<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="fr">
	<id>https://wiki-se.plil.fr/mediawiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Clemair1</id>
	<title>wiki-se.plil.fr - Contributions [fr]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki-se.plil.fr/mediawiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Clemair1"/>
	<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php/Sp%C3%A9cial:Contributions/Clemair1"/>
	<updated>2026-05-14T04:01:38Z</updated>
	<subtitle>Contributions</subtitle>
	<generator>MediaWiki 1.39.1</generator>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4763</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4763"/>
		<updated>2024-01-28T14:03:16Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /* Entrainement avec Scikit : */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Introduction Projet IE Delannoy - Lemaire &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadre la matière '''&amp;quot;Intelligence Embarquée&amp;quot;''' de l'UE &amp;quot;Module de Spécialité&amp;quot; des SE5 - Option Systèmes Communicants, nous avons dû concevoir un projet permettant de '''distribuer le calcul et le processus d'entrainement''' et d'utilisation d'un Intelligence Artificielle. Nous devrons distribuer le calcul à différents endroits du réseau afin d'être en mesure de proposer des pistes d'optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, nous allons mettre en oeuvre un réseau d'objets connectés à des passerelles et à un serveur. '''Les objets collecteront des données''' de l'environnemet et suivants les scénarios, traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Nous aurons à disposition :&lt;br /&gt;
&lt;br /&gt;
* Une machine virtuelle sur le serveur '''Chassiron''' en ''E304/306''&lt;br /&gt;
* Une '''Raspberry PI 4'''&lt;br /&gt;
* Un carte programmable '''STM32F401RE'''&lt;br /&gt;
* Un capteur à ultrason '''Nucleo-53L5A1'''&lt;br /&gt;
&lt;br /&gt;
Ce wiki est le compte-rendu du projet de '''Jason DELANNOY et Chloé LEMAIRE'''. Nous avons décider de développer une intelligence artificielle permettant de '''déterminer''' '''l'action faite par un joueur de Pierre-Feuille-Ciseau''' à l'aide du capteur à ultrason.&lt;br /&gt;
&lt;br /&gt;
Pour ce faire, nous allons développer notre IA de deux façons :&lt;br /&gt;
&lt;br /&gt;
* En utilisant '''NanoEdge Studio''' : Dans ce cas, le calcul serait fait par la carte programmable et envoyé au serveur via la Raspberry&lt;br /&gt;
* En utilisant '''un algorithme de machine learning ''': Ici, c'est le serveur qui fera le calcul et la Raspberry jouera le rôle de passerelle entre la carte programmable et le serveu&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Mise en oeuvre du réseau &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Création VM XEN ===&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]Notre VM est accessible en ssh à partir de son IPv6 : 2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la VM ===&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la borne WIFI Cisco ===&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251 (changement car besoin pour les PEIP) &lt;br /&gt;
&lt;br /&gt;
- dns-server: 193.48.57.33 (changement car problème avec le serveur DNS initial)&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Configuration de la Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadra du projet, nous avons à disposition une Raspberry PI 4 model B que nous allons configurer. Pour ce faire, nous utilisons le logiciel &amp;quot;Raspberry PI Imager&amp;quot; pour choisir notre OS.&lt;br /&gt;
[[Fichier:JCIE RPI Imager.png|centré|vignette|400x400px]]Maintenant que nous avons une carte SD prête pour la Raspberry, nous la configurons via sa liaison série en passant par minicom :&lt;br /&gt;
 root@zabeth18: / $ minicom -D /dev/ttyACM0 -b 9600&lt;br /&gt;
De plus, nous modifions le fichier /etc/network/interfaces pour pouvoir connecter notre carte au réseau wifi créé plus haut :&lt;br /&gt;
[[Fichier:Screen WiFi.png|centré|vignette|441x441px]]&lt;br /&gt;
Nous verifions ensuite que nous avons une adresse IP :&lt;br /&gt;
[[Fichier:Screenshot from 2023-12-04 17-17-05.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Capteur NUCLEO - 53L5A1 &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Pour ce projet, nous disposons d'une STM32 Nucléo F401RE muni d'un capteur à ultrason X-Nucleo-53L5A1.&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir entrainer notre IA, nous devons faire en sorte d'afficher et de ressortir sur la liaison série les données du capteur. Pour ce faire, nous utilisons le fichier example &amp;quot;'''''53L5A1_ThresholdDetection'''''&amp;quot;. Nous modifions la fonction print_result pour afficher 16 valeurs à la suite :&lt;br /&gt;
[[Fichier:ChifoumIA Print Result.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Après avoir téléversé, nous pouvons vérifier le bon fonctionnement du programme en nous connectant à la carte via minicom :&lt;br /&gt;
&lt;br /&gt;
 root@raspberrypi:/dev$ minicom -D ttyACM0 -b 460800&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Communication VM-Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Envoie de donnée : ===&lt;br /&gt;
&lt;br /&gt;
Dans notre projet, nous avons besoin de remonter les données de notre capteur branché en liaison série à la Raspberry sur le port &amp;quot;ttyACM0&amp;quot;. Nous allons donc passer par des requêtes API entre le serveur sur chassiron et notre Raspberry.&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Raspberry : ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Du côté Raspberry, nous programmons un script en python qui lit sur la liaison série les valeurs du capteurs et les envoie via une requête POST vers le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import requests&lt;br /&gt;
     import json&lt;br /&gt;
     import serial&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;Variable&lt;br /&gt;
     STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
     baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
     Serial_link = serial.Serial(STM32_port,baudrate,timeout=1)&lt;br /&gt;
     print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
     liste_mesures=[]&lt;br /&gt;
     for i in range(101):&lt;br /&gt;
          print(&amp;quot;Mesure&amp;quot;,i)&lt;br /&gt;
          mesure = Serial_link.readline().decode('utf-8')&lt;br /&gt;
          liste_mesures.append(mesure)&lt;br /&gt;
&lt;br /&gt;
     data_to_send = json.dumps(liste_mesures)&lt;br /&gt;
     url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080&amp;quot;&lt;br /&gt;
&lt;br /&gt;
     headers = {&lt;br /&gt;
          'Content-type':'application/json',&lt;br /&gt;
          'Accept':'application/json'&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     r = requests.post(&lt;br /&gt;
          url_request,&lt;br /&gt;
          json=data_to_send,&lt;br /&gt;
          headers=headers&lt;br /&gt;
     )&lt;br /&gt;
     print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Serveur : ====&lt;br /&gt;
La communication entre notre VM et la Raspberry est possible. Nous arrivons à effectuer un ping de l'une sur l'autre en passant par l'addresse IPv6.&lt;br /&gt;
&lt;br /&gt;
IPv6 VM :  2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
IPv6 Raspberry : 2001:660:4401:6050:da3a:ddff:fe59:4cb5&lt;br /&gt;
&lt;br /&gt;
Nous programmons ensuite une API sur notre VM en utilisant la libraire Flask.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import json&lt;br /&gt;
     from flask import Flask&lt;br /&gt;
     from flask import request&lt;br /&gt;
     from waitress import serve&lt;br /&gt;
     from flask import Response&lt;br /&gt;
     from flask_cors import CORS&lt;br /&gt;
     from flask_cors import cross_origin&lt;br /&gt;
&lt;br /&gt;
     app = Flask(__name__)&lt;br /&gt;
     cors = CORS(app, ressourceas={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;:&amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
     def compute_data(data):&lt;br /&gt;
          filename = input(&amp;quot;Nom du fichier :&amp;quot;)&lt;br /&gt;
          to_write = data.split(&amp;quot;\&amp;quot;&amp;quot;)[1:-1]&lt;br /&gt;
          with open(filename, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
               i = 0&lt;br /&gt;
               for elem in to_write:&lt;br /&gt;
                    if i == 0:&lt;br /&gt;
                         print(&amp;quot;We skip&amp;quot;)&lt;br /&gt;
                    else:&lt;br /&gt;
                         if (i%2) == 0:&lt;br /&gt;
                              print(&amp;quot;Data writed :&amp;quot;,elem[:-4])&lt;br /&gt;
                              f.write(elem[:-4])&lt;br /&gt;
                              f.write(&amp;quot;\n&amp;quot;)&lt;br /&gt;
                    i = i + 1&lt;br /&gt;
&lt;br /&gt;
     #Main&lt;br /&gt;
     @app.route('/',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
     @cross_origin()&lt;br /&gt;
     def hello():&lt;br /&gt;
          data = request.json&lt;br /&gt;
          compute_data(data)&lt;br /&gt;
          return data&lt;br /&gt;
&lt;br /&gt;
     if __name__ == '__main__':&lt;br /&gt;
          print(&amp;quot;Listening&amp;quot;)&lt;br /&gt;
          serve(app,host=&amp;quot;::&amp;quot;,port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Implémentation de l'IA : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant qu'on a une communication pour envoyer un fichier à notre serveur depuis la raspberry grâce à notre API, nous la modifions pour que la Raspberry puisse lire la valeur du capteur à ultrason, l'envoyer à notre serveur et recevoir en réponse, la prédiction de l'IA. Nous créons donc une route '''''/predict''''' sur notre API qui récupère les valeurs du capteurs données en paramètre et renvoie la prédiction de l'IA :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 @app.route('/predict',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
 def predict():&lt;br /&gt;
      data = request.json&lt;br /&gt;
      print(data)&lt;br /&gt;
      features = data['Features']&lt;br /&gt;
      print(features)&lt;br /&gt;
      features_splitted = features[0].split(&amp;quot;,&amp;quot;)&lt;br /&gt;
      features_int = [int(elem) for elem in features_splitted]&lt;br /&gt;
      loaded_model = joblib.load('model_entraine.pkl')&lt;br /&gt;
      predictios = loaded_model.predict(np.array(features_int).reshape(1,-1))&lt;br /&gt;
      return jsonify(predictions.tolist())&lt;br /&gt;
&amp;lt;/pre&amp;gt;Nous envoyons ensuite les données à analyser via des requêtes API :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 #Import Librairies&lt;br /&gt;
 import requests&lt;br /&gt;
 import json&lt;br /&gt;
 import serial&lt;br /&gt;
 from flask import jsonify&lt;br /&gt;
&lt;br /&gt;
 #Variable&lt;br /&gt;
 STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
 baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
 Serial_link = serial.Serial(STM32_port, baudrate, timeout=1)&lt;br /&gt;
 print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
 tab_to_send = []&lt;br /&gt;
&lt;br /&gt;
 while True:&lt;br /&gt;
      Serial_link.readline().decode('utf-8')&lt;br /&gt;
      tab_to_send.append(Serial_link.readline().decode('utf-8')&lt;br /&gt;
      if (tab_to_send != [&amp;quot;&amp;quot;]):&lt;br /&gt;
           print(&amp;quot;Data sended :&amp;quot;,tab_to_send)&lt;br /&gt;
           url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080/predict&amp;quot;&lt;br /&gt;
           headers = {&lt;br /&gt;
                'Content-type':'application/json',&lt;br /&gt;
                'Accept':'application/json'&lt;br /&gt;
           }&lt;br /&gt;
           r = requests.post(&lt;br /&gt;
                url_request,&lt;br /&gt;
                json = {&lt;br /&gt;
                     &amp;quot;Features&amp;quot;: tab_to_send&lt;br /&gt;
                },&lt;br /&gt;
                headers=headers&lt;br /&gt;
           )&lt;br /&gt;
           print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
           print(&amp;quot;Response :&amp;quot;,r.json())&lt;br /&gt;
      else:&lt;br /&gt;
           print(&amp;quot;Data skip:&amp;quot;,tab_to_send)&lt;br /&gt;
      tab_to_send.clear()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Entrainement de l'IA &amp;lt;/div&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec NanoEdge AI Studio : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour le projet, nous avons d'abord développé et entrainé notre IA sur la plateforme NanoEdge AI Studio. Pour ce faire, nous devons d'abord définir un projet de classification de n-class (&amp;quot;pierre&amp;quot;,&amp;quot;feuille&amp;quot;,&amp;quot;ciseau&amp;quot;) en utilisant un capteur générique à 16 axes. Pour ce faire, nous modifions le code de la STM32 pour qu'elle renvoie une ligne contenant 16*16 mesure en continue. Une fois le projet créé, nous ajoutons 3 signaux correspondant à nos dataset de &amp;quot;Pierre&amp;quot;, &amp;quot;Feuille&amp;quot; et &amp;quot;Ciseau&amp;quot;. Pour rajouter des valeurs dans notre dataset, nous utilisons la liaison série pour lire les valeurs de notre capteur.&lt;br /&gt;
=== Entrainement avec Scikit ===&lt;br /&gt;
&lt;br /&gt;
Pour la suite de notre projet, nous avons developpé et entrainé une IA avec Scikit.&lt;br /&gt;
&lt;br /&gt;
==== Construction du fichier d'entrainement ====&lt;br /&gt;
Pour commencer, nous avons du construire un fichier csv reprenant nos mesures sur un format de 16 valeurs. Pour chaque mesure, on ajoute en amont de la mesure la catégorie (feuille, ciseau ou pierre). &lt;br /&gt;
[[Fichier:Capture d’écran 2024-01-18 à 16.18.19.png|centré|vignette|500x500px|Fichier chifoumIA.csv]]&lt;br /&gt;
Pour construire ce fichier, nous avons assemblé trois fichiers csv de test que nous avons généré grâce à notre capteur : un fichier d'entrainement Pierre.csv, un fichier d'entrainement Ciseau.csv et un fichier d'entrainement Feuille.csv . &lt;br /&gt;
&lt;br /&gt;
Pour faire cette concaténation nous avons développer un programme python prenant en entrée nos fichiers d'entrainement et fournissant en sortie le fichier csv chifoumIA.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     line_feuille = []&lt;br /&gt;
     line_pierre = []&lt;br /&gt;
     line_ciseau = []&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Feuille.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_feuille = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Pierre.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_pierre = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Ciseau.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_ciseau = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;chifoumIA.csv&amp;quot;,&amp;quot;w&amp;quot;) as f:&lt;br /&gt;
          for elem in line_feuille:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;feuille,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_pierre:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;pierre,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_ciseau:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;ciseau,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Implémentation et Entrainement de notre IA ====&lt;br /&gt;
Maintenant que nous avons notre fichier d'entrainement, nous implémentons notre IA.&lt;br /&gt;
&lt;br /&gt;
Nous avons commencé par créer un tableau de données et un tableau de classes. &lt;br /&gt;
&lt;br /&gt;
Pour remplir ces tableaux, on va lire ligne par ligne le fichier chifoumIA.csv. Le premier élément de la ligne est stockée dans le tableau de classes et le reste de la ligne est stockée dans le tableau de données. &lt;br /&gt;
 chifoumi_data=[]&lt;br /&gt;
 chifoumi_classe=[]&lt;br /&gt;
 &lt;br /&gt;
 with open('chifoumIA.csv') as csv_file:&lt;br /&gt;
        csv_reader = csv.reader(csv_file,delimiter=',')&lt;br /&gt;
        for row in csv_reader:           &lt;br /&gt;
                 chifoumi_data.append([int(row[1]),int(row[2]),int(row[3]),int(row[4]),int(row[5]),int(row[6]),int(row[7]),int(row[8]),&lt;br /&gt;
                                       int(row[9]),int(row[10]),int(row[11]),int(row[12]),int(row[13]),int(row[14]),int(row[15]),int(row[16])])&lt;br /&gt;
                 chifoumi_classe.append(row[0])&lt;br /&gt;
  &lt;br /&gt;
A partir de ces deux tableaux, on construit un ensemble de données d'entraînement et un ensemble de données de tests.&lt;br /&gt;
&lt;br /&gt;
On choisi d'utiliser un réseau de neurone du type MLPClassifer. &lt;br /&gt;
&lt;br /&gt;
Le MLPClassifer est un type de réseau de neurones artificiels composés d'au minimum trois couches de neurones: une couche d'entrée, une ou plusieurs  couches cachées et une couche de sortie. &lt;br /&gt;
&lt;br /&gt;
Dans ce type de réseau, chaque neurone est connecté à l'ensemble des neurones de la couche suivante par un lien auquel est associé un poids. &lt;br /&gt;
&lt;br /&gt;
La classe MLPClassifer implémentée dans la bibliothèque Scikit-Learn dispose de nombreux paramètres. Pour notre projet, nous avons utilisé cette classe de façon très primaire. Les paramètres que nous avons utilisés sont :  &lt;br /&gt;
&lt;br /&gt;
- '''hidden_layer_sizes :''' ce paramètre est un tuple spécifiant le nombre de neurones dans chaque couche cachée. &lt;br /&gt;
&lt;br /&gt;
- '''max_iter :''' ce paramètre représente le nombre maximal d'époque. Il permet de contrôler également le temps d'entrainement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model=MLPClassifier(hidden_layer_sizes=(50,25),max_iter=100,solver='adam')&lt;br /&gt;
&lt;br /&gt;
model.fit(X_train,y_train)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;predictions = model.predict(X_test)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;print(f'Accuracy:{accuracy}')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Déploiement de notre IA ====&lt;br /&gt;
Pour pouvoir déployer notre IA, nous avons enregistré notre model d'entrainement et intégré un service web à notre code existant avec deux endpoint : &lt;br /&gt;
&lt;br /&gt;
- predict : pour effectuer des prédictions sur le model. &lt;br /&gt;
&lt;br /&gt;
- evaluate : pour évaluer les performances du model sur l'ensemble de tests.&lt;br /&gt;
&lt;br /&gt;
Malheureusement nous n'avons pas eu le temps d'entrainer suffisamment cette IA. Ces performances sont donc très faible un peu moins de 50% de fiabilité.&lt;br /&gt;
&lt;br /&gt;
==== Code complet ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import joblib&lt;br /&gt;
import pandas as pd &lt;br /&gt;
import csv&lt;br /&gt;
from flask import Flask, request,jsonify&lt;br /&gt;
from sklearn.model_selection import train_test_split&lt;br /&gt;
from sklearn.ensemble import RandomForestClassifier&lt;br /&gt;
from sklearn.metrics import accuracy_score,precision_score,recall_score,f1_score&lt;br /&gt;
from sklearn.neural_network import MLPClassifier&lt;br /&gt;
from waitress import serve&lt;br /&gt;
from flask import Response&lt;br /&gt;
from flask_cors import CORS&lt;br /&gt;
from flask_cors import cross_origin&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
chifoumi_data=[]&lt;br /&gt;
chifoumi_classe=[]&lt;br /&gt;
&lt;br /&gt;
with open('chifoumIA.csv') as csv_file:&lt;br /&gt;
	csv_reader = csv.reader(csv_file,delimiter=',')&lt;br /&gt;
	for row in csv_reader:&lt;br /&gt;
		chifoumi_data.append([int(row[1]),int(row[2]),int(row[3]),int(row[4]),int(row[5]),int(row[6]),int(row[7]),int(row[8]),int(row[9]),int(row[10]),int(row[11]),int(row[12]),int(row[13]),int(row[14]),int(row[15]),int(row[16])])&lt;br /&gt;
		chifoumi_classe.append(row[0])&lt;br /&gt;
&lt;br /&gt;
X_train,X_test,y_train,y_test= train_test_split(chifoumi_data,chifoumi_classe,test_size=0.2,random_state=42)&lt;br /&gt;
&lt;br /&gt;
model=MLPClassifier(hidden_layer_sizes=(50,25),max_iter=100,solver='adam')&lt;br /&gt;
model.fit(X_train,y_train)&lt;br /&gt;
#predictions = model.predict(X_test)&lt;br /&gt;
#accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
#print(f'Accuracy:{accuracy}')&lt;br /&gt;
&lt;br /&gt;
joblib.dump(model,'model_entraine.pkl')&lt;br /&gt;
&lt;br /&gt;
app = Flask(__name__)&lt;br /&gt;
cors = CORS(app,ressources={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;: &amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#Main&lt;br /&gt;
@app.route('/predict',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
#@cross_origin()&lt;br /&gt;
def predict():&lt;br /&gt;
	data = request.json&lt;br /&gt;
	print(data)&lt;br /&gt;
	features = data['Features']&lt;br /&gt;
	print(features)&lt;br /&gt;
	features_splitted = features[0].split(&amp;quot;,&amp;quot;)&lt;br /&gt;
	features_int = [int(elem) for elem in features_splitted]&lt;br /&gt;
	loaded_model=joblib.load('model_entraine.pkl')&lt;br /&gt;
	predictions = loaded_model.predict(np.array(features_int).reshape(1,-1))&lt;br /&gt;
	return jsonify(predictions.tolist())&lt;br /&gt;
&lt;br /&gt;
@app.route('/evaluate',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
def evaluate():&lt;br /&gt;
	loaded_model = joblib.load('model_entraine.pkl')&lt;br /&gt;
	predictions = loaded_model.predict(X_test)&lt;br /&gt;
	accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
	precision = precision_score(y_test,predictions)&lt;br /&gt;
	recall = recall_score(y_test,predictions)&lt;br /&gt;
	f1=f1_score(y_test,predictions)&lt;br /&gt;
	&lt;br /&gt;
	return jsonify({ 'Accuracy': accuracy,'Precision': precision,'Recall': recall,'F1 Score':f1})&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
	print(&amp;quot;listening&amp;quot;)&lt;br /&gt;
	serve(app,host=&amp;quot;::&amp;quot;, port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Performance et Sobriété Energétique&amp;lt;/div&amp;gt;==&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4762</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4762"/>
		<updated>2024-01-28T13:47:19Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /* Code complet */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Introduction Projet IE Delannoy - Lemaire &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadre la matière '''&amp;quot;Intelligence Embarquée&amp;quot;''' de l'UE &amp;quot;Module de Spécialité&amp;quot; des SE5 - Option Systèmes Communicants, nous avons dû concevoir un projet permettant de '''distribuer le calcul et le processus d'entrainement''' et d'utilisation d'un Intelligence Artificielle. Nous devrons distribuer le calcul à différents endroits du réseau afin d'être en mesure de proposer des pistes d'optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, nous allons mettre en oeuvre un réseau d'objets connectés à des passerelles et à un serveur. '''Les objets collecteront des données''' de l'environnemet et suivants les scénarios, traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Nous aurons à disposition :&lt;br /&gt;
&lt;br /&gt;
* Une machine virtuelle sur le serveur '''Chassiron''' en ''E304/306''&lt;br /&gt;
* Une '''Raspberry PI 4'''&lt;br /&gt;
* Un carte programmable '''STM32F401RE'''&lt;br /&gt;
* Un capteur à ultrason '''Nucleo-53L5A1'''&lt;br /&gt;
&lt;br /&gt;
Ce wiki est le compte-rendu du projet de '''Jason DELANNOY et Chloé LEMAIRE'''. Nous avons décider de développer une intelligence artificielle permettant de '''déterminer''' '''l'action faite par un joueur de Pierre-Feuille-Ciseau''' à l'aide du capteur à ultrason.&lt;br /&gt;
&lt;br /&gt;
Pour ce faire, nous allons développer notre IA de deux façons :&lt;br /&gt;
&lt;br /&gt;
* En utilisant '''NanoEdge Studio''' : Dans ce cas, le calcul serait fait par la carte programmable et envoyé au serveur via la Raspberry&lt;br /&gt;
* En utilisant '''un algorithme de machine learning ''': Ici, c'est le serveur qui fera le calcul et la Raspberry jouera le rôle de passerelle entre la carte programmable et le serveu&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Mise en oeuvre du réseau &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Création VM XEN ===&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]Notre VM est accessible en ssh à partir de son IPv6 : 2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la VM ===&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la borne WIFI Cisco ===&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251 (changement car besoin pour les PEIP) &lt;br /&gt;
&lt;br /&gt;
- dns-server: 193.48.57.33 (changement car problème avec le serveur DNS initial)&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Configuration de la Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadra du projet, nous avons à disposition une Raspberry PI 4 model B que nous allons configurer. Pour ce faire, nous utilisons le logiciel &amp;quot;Raspberry PI Imager&amp;quot; pour choisir notre OS.&lt;br /&gt;
[[Fichier:JCIE RPI Imager.png|centré|vignette|400x400px]]Maintenant que nous avons une carte SD prête pour la Raspberry, nous la configurons via sa liaison série en passant par minicom :&lt;br /&gt;
 root@zabeth18: / $ minicom -D /dev/ttyACM0 -b 9600&lt;br /&gt;
De plus, nous modifions le fichier /etc/network/interfaces pour pouvoir connecter notre carte au réseau wifi créé plus haut :&lt;br /&gt;
[[Fichier:Screen WiFi.png|centré|vignette|441x441px]]&lt;br /&gt;
Nous verifions ensuite que nous avons une adresse IP :&lt;br /&gt;
[[Fichier:Screenshot from 2023-12-04 17-17-05.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Capteur NUCLEO - 53L5A1 &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Pour ce projet, nous disposons d'une STM32 Nucléo F401RE muni d'un capteur à ultrason X-Nucleo-53L5A1.&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir entrainer notre IA, nous devons faire en sorte d'afficher et de ressortir sur la liaison série les données du capteur. Pour ce faire, nous utilisons le fichier example &amp;quot;'''''53L5A1_ThresholdDetection'''''&amp;quot;. Nous modifions la fonction print_result pour afficher 16 valeurs à la suite :&lt;br /&gt;
[[Fichier:ChifoumIA Print Result.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Après avoir téléversé, nous pouvons vérifier le bon fonctionnement du programme en nous connectant à la carte via minicom :&lt;br /&gt;
&lt;br /&gt;
 root@raspberrypi:/dev$ minicom -D ttyACM0 -b 460800&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Communication VM-Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Envoie de donnée : ===&lt;br /&gt;
&lt;br /&gt;
Dans notre projet, nous avons besoin de remonter les données de notre capteur branché en liaison série à la Raspberry sur le port &amp;quot;ttyACM0&amp;quot;. Nous allons donc passer par des requêtes API entre le serveur sur chassiron et notre Raspberry.&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Raspberry : ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Du côté Raspberry, nous programmons un script en python qui lit sur la liaison série les valeurs du capteurs et les envoie via une requête POST vers le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import requests&lt;br /&gt;
     import json&lt;br /&gt;
     import serial&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;Variable&lt;br /&gt;
     STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
     baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
     Serial_link = serial.Serial(STM32_port,baudrate,timeout=1)&lt;br /&gt;
     print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
     liste_mesures=[]&lt;br /&gt;
     for i in range(101):&lt;br /&gt;
          print(&amp;quot;Mesure&amp;quot;,i)&lt;br /&gt;
          mesure = Serial_link.readline().decode('utf-8')&lt;br /&gt;
          liste_mesures.append(mesure)&lt;br /&gt;
&lt;br /&gt;
     data_to_send = json.dumps(liste_mesures)&lt;br /&gt;
     url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080&amp;quot;&lt;br /&gt;
&lt;br /&gt;
     headers = {&lt;br /&gt;
          'Content-type':'application/json',&lt;br /&gt;
          'Accept':'application/json'&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     r = requests.post(&lt;br /&gt;
          url_request,&lt;br /&gt;
          json=data_to_send,&lt;br /&gt;
          headers=headers&lt;br /&gt;
     )&lt;br /&gt;
     print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Serveur : ====&lt;br /&gt;
La communication entre notre VM et la Raspberry est possible. Nous arrivons à effectuer un ping de l'une sur l'autre en passant par l'addresse IPv6.&lt;br /&gt;
&lt;br /&gt;
IPv6 VM :  2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
IPv6 Raspberry : 2001:660:4401:6050:da3a:ddff:fe59:4cb5&lt;br /&gt;
&lt;br /&gt;
Nous programmons ensuite une API sur notre VM en utilisant la libraire Flask.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import json&lt;br /&gt;
     from flask import Flask&lt;br /&gt;
     from flask import request&lt;br /&gt;
     from waitress import serve&lt;br /&gt;
     from flask import Response&lt;br /&gt;
     from flask_cors import CORS&lt;br /&gt;
     from flask_cors import cross_origin&lt;br /&gt;
&lt;br /&gt;
     app = Flask(__name__)&lt;br /&gt;
     cors = CORS(app, ressourceas={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;:&amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
     def compute_data(data):&lt;br /&gt;
          filename = input(&amp;quot;Nom du fichier :&amp;quot;)&lt;br /&gt;
          to_write = data.split(&amp;quot;\&amp;quot;&amp;quot;)[1:-1]&lt;br /&gt;
          with open(filename, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
               i = 0&lt;br /&gt;
               for elem in to_write:&lt;br /&gt;
                    if i == 0:&lt;br /&gt;
                         print(&amp;quot;We skip&amp;quot;)&lt;br /&gt;
                    else:&lt;br /&gt;
                         if (i%2) == 0:&lt;br /&gt;
                              print(&amp;quot;Data writed :&amp;quot;,elem[:-4])&lt;br /&gt;
                              f.write(elem[:-4])&lt;br /&gt;
                              f.write(&amp;quot;\n&amp;quot;)&lt;br /&gt;
                    i = i + 1&lt;br /&gt;
&lt;br /&gt;
     #Main&lt;br /&gt;
     @app.route('/',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
     @cross_origin()&lt;br /&gt;
     def hello():&lt;br /&gt;
          data = request.json&lt;br /&gt;
          compute_data(data)&lt;br /&gt;
          return data&lt;br /&gt;
&lt;br /&gt;
     if __name__ == '__main__':&lt;br /&gt;
          print(&amp;quot;Listening&amp;quot;)&lt;br /&gt;
          serve(app,host=&amp;quot;::&amp;quot;,port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Implémentation de l'IA : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant qu'on a une communication pour envoyer un fichier à notre serveur depuis la raspberry grâce à notre API, nous la modifions pour que la Raspberry puisse lire la valeur du capteur à ultrason, l'envoyer à notre serveur et recevoir en réponse, la prédiction de l'IA. Nous créons donc une route '''''/predict''''' sur notre API qui récupère les valeurs du capteurs données en paramètre et renvoie la prédiction de l'IA :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 @app.route('/predict',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
 def predict():&lt;br /&gt;
      data = request.json&lt;br /&gt;
      print(data)&lt;br /&gt;
      features = data['Features']&lt;br /&gt;
      print(features)&lt;br /&gt;
      features_splitted = features[0].split(&amp;quot;,&amp;quot;)&lt;br /&gt;
      features_int = [int(elem) for elem in features_splitted]&lt;br /&gt;
      loaded_model = joblib.load('model_entraine.pkl')&lt;br /&gt;
      predictios = loaded_model.predict(np.array(features_int).reshape(1,-1))&lt;br /&gt;
      return jsonify(predictions.tolist())&lt;br /&gt;
&amp;lt;/pre&amp;gt;Nous envoyons ensuite les données à analyser via des requêtes API :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 #Import Librairies&lt;br /&gt;
 import requests&lt;br /&gt;
 import json&lt;br /&gt;
 import serial&lt;br /&gt;
 from flask import jsonify&lt;br /&gt;
&lt;br /&gt;
 #Variable&lt;br /&gt;
 STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
 baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
 Serial_link = serial.Serial(STM32_port, baudrate, timeout=1)&lt;br /&gt;
 print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
 tab_to_send = []&lt;br /&gt;
&lt;br /&gt;
 while True:&lt;br /&gt;
      Serial_link.readline().decode('utf-8')&lt;br /&gt;
      tab_to_send.append(Serial_link.readline().decode('utf-8')&lt;br /&gt;
      if (tab_to_send != [&amp;quot;&amp;quot;]):&lt;br /&gt;
           print(&amp;quot;Data sended :&amp;quot;,tab_to_send)&lt;br /&gt;
           url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080/predict&amp;quot;&lt;br /&gt;
           headers = {&lt;br /&gt;
                'Content-type':'application/json',&lt;br /&gt;
                'Accept':'application/json'&lt;br /&gt;
           }&lt;br /&gt;
           r = requests.post(&lt;br /&gt;
                url_request,&lt;br /&gt;
                json = {&lt;br /&gt;
                     &amp;quot;Features&amp;quot;: tab_to_send&lt;br /&gt;
                },&lt;br /&gt;
                headers=headers&lt;br /&gt;
           )&lt;br /&gt;
           print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
           print(&amp;quot;Response :&amp;quot;,r.json())&lt;br /&gt;
      else:&lt;br /&gt;
           print(&amp;quot;Data skip:&amp;quot;,tab_to_send)&lt;br /&gt;
      tab_to_send.clear()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Entrainement de l'IA &amp;lt;/div&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec NanoEdge AI Studio : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour le projet, nous avons d'abord développé et entrainé notre IA sur la plateforme NanoEdge AI Studio. Pour ce faire, nous devons d'abord définir un projet de classification de n-class (&amp;quot;pierre&amp;quot;,&amp;quot;feuille&amp;quot;,&amp;quot;ciseau&amp;quot;) en utilisant un capteur générique à 16 axes. Pour ce faire, nous modifions le code de la STM32 pour qu'elle renvoie une ligne contenant 16*16 mesure en continue. Une fois le projet créé, nous ajoutons 3 signaux correspondant à nos dataset de &amp;quot;Pierre&amp;quot;, &amp;quot;Feuille&amp;quot; et &amp;quot;Ciseau&amp;quot;. Pour rajouter des valeurs dans notre dataset, nous utilisons la liaison série pour lire les valeurs de notre capteur.&lt;br /&gt;
=== Entrainement avec Scikit : ===&lt;br /&gt;
&lt;br /&gt;
Pour la suite de notre projet, nous avons developpé et entrainé une IA avec Scikit.&lt;br /&gt;
&lt;br /&gt;
==== Construction du fichier d'entrainement ====&lt;br /&gt;
Pour commencer, nous avons du construire un fichier csv reprenant nos mesures sur un format de 16 valeurs. Pour chaque mesure, on ajoute en amont de la mesure la catégorie (feuille, ciseau ou pierre). &lt;br /&gt;
[[Fichier:Capture d’écran 2024-01-18 à 16.18.19.png|centré|vignette|500x500px|Fichier chifoumIA.csv]]&lt;br /&gt;
Pour construire ce fichier, nous avons assemblé trois fichiers csv de test que nous avons généré grâce à notre capteur : un fichier d'entrainement Pierre.csv, un fichier d'entrainement Ciseau.csv et un fichier d'entrainement Feuille.csv . &lt;br /&gt;
&lt;br /&gt;
Pour faire cette concaténation nous avons développer un programme python prenant en entrée nos fichiers d'entrainement et fournissant en sortie le fichier csv chifoumIA.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     line_feuille = []&lt;br /&gt;
     line_pierre = []&lt;br /&gt;
     line_ciseau = []&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Feuille.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_feuille = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Pierre.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_pierre = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Ciseau.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_ciseau = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;chifoumIA.csv&amp;quot;,&amp;quot;w&amp;quot;) as f:&lt;br /&gt;
          for elem in line_feuille:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;feuille,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_pierre:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;pierre,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_ciseau:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;ciseau,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Implémentation et Entrainement de notre IA ====&lt;br /&gt;
Maintenant que nous avons notre fichier d'entrainement, nous implémentons notre IA.&lt;br /&gt;
&lt;br /&gt;
Nous avons commencé par créer un tableau de données et un tableau de classes. &lt;br /&gt;
&lt;br /&gt;
Pour remplir ces tableaux, on va lire ligne par ligne le fichier chifoumIA.csv. Le premier élément de la ligne est stockée dans le tableau de classes et le reste de la ligne est stockée dans le tableau de données. &lt;br /&gt;
 chifoumi_data=[]&lt;br /&gt;
 chifoumi_classe=[]&lt;br /&gt;
 &lt;br /&gt;
 with open('chifoumIA.csv') as csv_file:&lt;br /&gt;
        csv_reader = csv.reader(csv_file,delimiter=',')&lt;br /&gt;
        for row in csv_reader:           &lt;br /&gt;
                 chifoumi_data.append([int(row[1]),int(row[2]),int(row[3]),int(row[4]),int(row[5]),int(row[6]),int(row[7]),int(row[8]),&lt;br /&gt;
                                       int(row[9]),int(row[10]),int(row[11]),int(row[12]),int(row[13]),int(row[14]),int(row[15]),int(row[16])])&lt;br /&gt;
                 chifoumi_classe.append(row[0])&lt;br /&gt;
  &lt;br /&gt;
A partir de ces deux tableaux, on construit un ensemble de données d'entraînement et un ensemble de données de tests.&lt;br /&gt;
&lt;br /&gt;
On choisi d'utiliser un réseau de neurone du type MLPClassifer. &lt;br /&gt;
&lt;br /&gt;
Le MLPClassifer est un type de réseau de neurones artificiels composés d'au minimum trois couches de neurones: une couche d'entrée, une ou plusieurs  couches cachées et une couche de sortie. &lt;br /&gt;
&lt;br /&gt;
Dans ce type de réseau, chaque neurone est connecté à l'ensemble des neurones de la couche suivante par un lien auquel est associé un poids. &lt;br /&gt;
&lt;br /&gt;
La classe MLPClassifer implémentée dans la bibliothèque Scikit-Learn dispose de nombreux paramètres. Pour notre projet, nous avons utilisé cette classe de façon très primaire. Les paramètres que nous avons utilisés sont :  &lt;br /&gt;
&lt;br /&gt;
- '''hidden_layer_sizes :''' ce paramètre est un tuple spécifiant le nombre de neurones dans chaque couche cachée. &lt;br /&gt;
&lt;br /&gt;
- '''max_iter :''' ce paramètre représente le nombre maximal d'époque. Il permet de contrôler également le temps d'entrainement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model=MLPClassifier(hidden_layer_sizes=(50,25),max_iter=100,solver='adam')&lt;br /&gt;
&lt;br /&gt;
model.fit(X_train,y_train)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;predictions = model.predict(X_test)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;print(f'Accuracy:{accuracy}')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Déploiement de notre IA ====&lt;br /&gt;
Pour pouvoir déployer notre IA, nous avons enregistré notre model d'entrainement et intégré un service web à notre code existant avec deux endpoint : &lt;br /&gt;
&lt;br /&gt;
- predict : pour effectuer des prédictions sur le model. &lt;br /&gt;
&lt;br /&gt;
- evaluate : pour évaluer les performances du model sur l'ensemble de tests.&lt;br /&gt;
&lt;br /&gt;
Malheureusement nous n'avons pas eu le temps d'entrainer suffisamment cette IA. Ces performances sont donc très faible un peu moins de 50% de fiabilité.&lt;br /&gt;
&lt;br /&gt;
==== Code complet ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import joblib&lt;br /&gt;
import pandas as pd &lt;br /&gt;
import csv&lt;br /&gt;
from flask import Flask, request,jsonify&lt;br /&gt;
from sklearn.model_selection import train_test_split&lt;br /&gt;
from sklearn.ensemble import RandomForestClassifier&lt;br /&gt;
from sklearn.metrics import accuracy_score,precision_score,recall_score,f1_score&lt;br /&gt;
from sklearn.neural_network import MLPClassifier&lt;br /&gt;
from waitress import serve&lt;br /&gt;
from flask import Response&lt;br /&gt;
from flask_cors import CORS&lt;br /&gt;
from flask_cors import cross_origin&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
chifoumi_data=[]&lt;br /&gt;
chifoumi_classe=[]&lt;br /&gt;
&lt;br /&gt;
with open('chifoumIA.csv') as csv_file:&lt;br /&gt;
	csv_reader = csv.reader(csv_file,delimiter=',')&lt;br /&gt;
	for row in csv_reader:&lt;br /&gt;
		chifoumi_data.append([int(row[1]),int(row[2]),int(row[3]),int(row[4]),int(row[5]),int(row[6]),int(row[7]),int(row[8]),int(row[9]),int(row[10]),int(row[11]),int(row[12]),int(row[13]),int(row[14]),int(row[15]),int(row[16])])&lt;br /&gt;
		chifoumi_classe.append(row[0])&lt;br /&gt;
&lt;br /&gt;
X_train,X_test,y_train,y_test= train_test_split(chifoumi_data,chifoumi_classe,test_size=0.2,random_state=42)&lt;br /&gt;
&lt;br /&gt;
model=MLPClassifier(hidden_layer_sizes=(50,25),max_iter=100,solver='adam')&lt;br /&gt;
model.fit(X_train,y_train)&lt;br /&gt;
#predictions = model.predict(X_test)&lt;br /&gt;
#accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
#print(f'Accuracy:{accuracy}')&lt;br /&gt;
&lt;br /&gt;
joblib.dump(model,'model_entraine.pkl')&lt;br /&gt;
&lt;br /&gt;
app = Flask(__name__)&lt;br /&gt;
cors = CORS(app,ressources={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;: &amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#Main&lt;br /&gt;
@app.route('/predict',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
#@cross_origin()&lt;br /&gt;
def predict():&lt;br /&gt;
	data = request.json&lt;br /&gt;
	print(data)&lt;br /&gt;
	features = data['Features']&lt;br /&gt;
	print(features)&lt;br /&gt;
	features_splitted = features[0].split(&amp;quot;,&amp;quot;)&lt;br /&gt;
	features_int = [int(elem) for elem in features_splitted]&lt;br /&gt;
	loaded_model=joblib.load('model_entraine.pkl')&lt;br /&gt;
	predictions = loaded_model.predict(np.array(features_int).reshape(1,-1))&lt;br /&gt;
	return jsonify(predictions.tolist())&lt;br /&gt;
&lt;br /&gt;
@app.route('/evaluate',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
def evaluate():&lt;br /&gt;
	loaded_model = joblib.load('model_entraine.pkl')&lt;br /&gt;
	predictions = loaded_model.predict(X_test)&lt;br /&gt;
	accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
	precision = precision_score(y_test,predictions)&lt;br /&gt;
	recall = recall_score(y_test,predictions)&lt;br /&gt;
	f1=f1_score(y_test,predictions)&lt;br /&gt;
	&lt;br /&gt;
	return jsonify({ 'Accuracy': accuracy,'Precision': precision,'Recall': recall,'F1 Score':f1})&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
	print(&amp;quot;listening&amp;quot;)&lt;br /&gt;
	serve(app,host=&amp;quot;::&amp;quot;, port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Performance et Sobriété Energétique&amp;lt;/div&amp;gt;==&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4758</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4758"/>
		<updated>2024-01-28T13:44:28Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /*  Configuration de la Raspberry  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Introduction Projet IE Delannoy - Lemaire &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadre la matière '''&amp;quot;Intelligence Embarquée&amp;quot;''' de l'UE &amp;quot;Module de Spécialité&amp;quot; des SE5 - Option Systèmes Communicants, nous avons dû concevoir un projet permettant de '''distribuer le calcul et le processus d'entrainement''' et d'utilisation d'un Intelligence Artificielle. Nous devrons distribuer le calcul à différents endroits du réseau afin d'être en mesure de proposer des pistes d'optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, nous allons mettre en oeuvre un réseau d'objets connectés à des passerelles et à un serveur. '''Les objets collecteront des données''' de l'environnemet et suivants les scénarios, traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Nous aurons à disposition :&lt;br /&gt;
&lt;br /&gt;
* Une machine virtuelle sur le serveur '''Chassiron''' en ''E304/306''&lt;br /&gt;
* Une '''Raspberry PI 4'''&lt;br /&gt;
* Un carte programmable '''STM32F401RE'''&lt;br /&gt;
* Un capteur à ultrason '''Nucleo-53L5A1'''&lt;br /&gt;
&lt;br /&gt;
Ce wiki est le compte-rendu du projet de '''Jason DELANNOY et Chloé LEMAIRE'''. Nous avons décider de développer une intelligence artificielle permettant de '''déterminer''' '''l'action faite par un joueur de Pierre-Feuille-Ciseau''' à l'aide du capteur à ultrason.&lt;br /&gt;
&lt;br /&gt;
Pour ce faire, nous allons développer notre IA de deux façons :&lt;br /&gt;
&lt;br /&gt;
* En utilisant '''NanoEdge Studio''' : Dans ce cas, le calcul serait fait par la carte programmable et envoyé au serveur via la Raspberry&lt;br /&gt;
* En utilisant '''un algorithme de machine learning ''': Ici, c'est le serveur qui fera le calcul et la Raspberry jouera le rôle de passerelle entre la carte programmable et le serveu&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Mise en oeuvre du réseau &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Création VM XEN ===&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]Notre VM est accessible en ssh à partir de son IPv6 : 2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la VM ===&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la borne WIFI Cisco ===&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251 (changement car besoin pour les PEIP) &lt;br /&gt;
&lt;br /&gt;
- dns-server: 193.48.57.33 (changement car problème avec le serveur DNS initial)&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Configuration de la Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadra du projet, nous avons à disposition une Raspberry PI 4 model B que nous allons configurer. Pour ce faire, nous utilisons le logiciel &amp;quot;Raspberry PI Imager&amp;quot; pour choisir notre OS.&lt;br /&gt;
[[Fichier:JCIE RPI Imager.png|centré|vignette|400x400px]]Maintenant que nous avons une carte SD prête pour la Raspberry, nous la configurons via sa liaison série en passant par minicom :&lt;br /&gt;
 root@zabeth18: / $ minicom -D /dev/ttyACM0 -b 9600&lt;br /&gt;
De plus, nous modifions le fichier /etc/network/interfaces pour pouvoir connecter notre carte au réseau wifi créé plus haut :&lt;br /&gt;
[[Fichier:Screen WiFi.png|centré|vignette|441x441px]]&lt;br /&gt;
Nous verifions ensuite que nous avons une adresse IP :&lt;br /&gt;
[[Fichier:Screenshot from 2023-12-04 17-17-05.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Capteur NUCLEO - 53L5A1 &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Pour ce projet, nous disposons d'une STM32 Nucléo F401RE muni d'un capteur à ultrason X-Nucleo-53L5A1.&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir entrainer notre IA, nous devons faire en sorte d'afficher et de ressortir sur la liaison série les données du capteur. Pour ce faire, nous utilisons le fichier example &amp;quot;'''''53L5A1_ThresholdDetection'''''&amp;quot;. Nous modifions la fonction print_result pour afficher 16 valeurs à la suite :&lt;br /&gt;
[[Fichier:ChifoumIA Print Result.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Après avoir téléversé, nous pouvons vérifier le bon fonctionnement du programme en nous connectant à la carte via minicom :&lt;br /&gt;
&lt;br /&gt;
 root@raspberrypi:/dev$ minicom -D ttyACM0 -b 460800&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Communication VM-Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Envoie de donnée : ===&lt;br /&gt;
&lt;br /&gt;
Dans notre projet, nous avons besoin de remonter les données de notre capteur branché en liaison série à la Raspberry sur le port &amp;quot;ttyACM0&amp;quot;. Nous allons donc passer par des requêtes API entre le serveur sur chassiron et notre Raspberry.&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Raspberry : ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Du côté Raspberry, nous programmons un script en python qui lit sur la liaison série les valeurs du capteurs et les envoie via une requête POST vers le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import requests&lt;br /&gt;
     import json&lt;br /&gt;
     import serial&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;Variable&lt;br /&gt;
     STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
     baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
     Serial_link = serial.Serial(STM32_port,baudrate,timeout=1)&lt;br /&gt;
     print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
     liste_mesures=[]&lt;br /&gt;
     for i in range(101):&lt;br /&gt;
          print(&amp;quot;Mesure&amp;quot;,i)&lt;br /&gt;
          mesure = Serial_link.readline().decode('utf-8')&lt;br /&gt;
          liste_mesures.append(mesure)&lt;br /&gt;
&lt;br /&gt;
     data_to_send = json.dumps(liste_mesures)&lt;br /&gt;
     url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080&amp;quot;&lt;br /&gt;
&lt;br /&gt;
     headers = {&lt;br /&gt;
          'Content-type':'application/json',&lt;br /&gt;
          'Accept':'application/json'&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     r = requests.post(&lt;br /&gt;
          url_request,&lt;br /&gt;
          json=data_to_send,&lt;br /&gt;
          headers=headers&lt;br /&gt;
     )&lt;br /&gt;
     print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Serveur : ====&lt;br /&gt;
La communication entre notre VM et la Raspberry est possible. Nous arrivons à effectuer un ping de l'une sur l'autre en passant par l'addresse IPv6.&lt;br /&gt;
&lt;br /&gt;
IPv6 VM :  2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
IPv6 Raspberry : 2001:660:4401:6050:da3a:ddff:fe59:4cb5&lt;br /&gt;
&lt;br /&gt;
Nous programmons ensuite une API sur notre VM en utilisant la libraire Flask.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import json&lt;br /&gt;
     from flask import Flask&lt;br /&gt;
     from flask import request&lt;br /&gt;
     from waitress import serve&lt;br /&gt;
     from flask import Response&lt;br /&gt;
     from flask_cors import CORS&lt;br /&gt;
     from flask_cors import cross_origin&lt;br /&gt;
&lt;br /&gt;
     app = Flask(__name__)&lt;br /&gt;
     cors = CORS(app, ressourceas={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;:&amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
     def compute_data(data):&lt;br /&gt;
          filename = input(&amp;quot;Nom du fichier :&amp;quot;)&lt;br /&gt;
          to_write = data.split(&amp;quot;\&amp;quot;&amp;quot;)[1:-1]&lt;br /&gt;
          with open(filename, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
               i = 0&lt;br /&gt;
               for elem in to_write:&lt;br /&gt;
                    if i == 0:&lt;br /&gt;
                         print(&amp;quot;We skip&amp;quot;)&lt;br /&gt;
                    else:&lt;br /&gt;
                         if (i%2) == 0:&lt;br /&gt;
                              print(&amp;quot;Data writed :&amp;quot;,elem[:-4])&lt;br /&gt;
                              f.write(elem[:-4])&lt;br /&gt;
                              f.write(&amp;quot;\n&amp;quot;)&lt;br /&gt;
                    i = i + 1&lt;br /&gt;
&lt;br /&gt;
     #Main&lt;br /&gt;
     @app.route('/',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
     @cross_origin()&lt;br /&gt;
     def hello():&lt;br /&gt;
          data = request.json&lt;br /&gt;
          compute_data(data)&lt;br /&gt;
          return data&lt;br /&gt;
&lt;br /&gt;
     if __name__ == '__main__':&lt;br /&gt;
          print(&amp;quot;Listening&amp;quot;)&lt;br /&gt;
          serve(app,host=&amp;quot;::&amp;quot;,port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Implémentation de l'IA : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant qu'on a une communication pour envoyer un fichier à notre serveur depuis la raspberry grâce à notre API, nous la modifions pour que la Raspberry puisse lire la valeur du capteur à ultrason, l'envoyer à notre serveur et recevoir en réponse, la prédiction de l'IA. Nous créons donc une route '''''/predict''''' sur notre API qui récupère les valeurs du capteurs données en paramètre et renvoie la prédiction de l'IA :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 @app.route('/predict',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
 def predict():&lt;br /&gt;
      data = request.json&lt;br /&gt;
      print(data)&lt;br /&gt;
      features = data['Features']&lt;br /&gt;
      print(features)&lt;br /&gt;
      features_splitted = features[0].split(&amp;quot;,&amp;quot;)&lt;br /&gt;
      features_int = [int(elem) for elem in features_splitted]&lt;br /&gt;
      loaded_model = joblib.load('model_entraine.pkl')&lt;br /&gt;
      predictios = loaded_model.predict(np.array(features_int).reshape(1,-1))&lt;br /&gt;
      return jsonify(predictions.tolist())&lt;br /&gt;
&amp;lt;/pre&amp;gt;Nous envoyons ensuite les données à analyser via des requêtes API :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 #Import Librairies&lt;br /&gt;
 import requests&lt;br /&gt;
 import json&lt;br /&gt;
 import serial&lt;br /&gt;
 from flask import jsonify&lt;br /&gt;
&lt;br /&gt;
 #Variable&lt;br /&gt;
 STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
 baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
 Serial_link = serial.Serial(STM32_port, baudrate, timeout=1)&lt;br /&gt;
 print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
 tab_to_send = []&lt;br /&gt;
&lt;br /&gt;
 while True:&lt;br /&gt;
      Serial_link.readline().decode('utf-8')&lt;br /&gt;
      tab_to_send.append(Serial_link.readline().decode('utf-8')&lt;br /&gt;
      if (tab_to_send != [&amp;quot;&amp;quot;]):&lt;br /&gt;
           print(&amp;quot;Data sended :&amp;quot;,tab_to_send)&lt;br /&gt;
           url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080/predict&amp;quot;&lt;br /&gt;
           headers = {&lt;br /&gt;
                'Content-type':'application/json',&lt;br /&gt;
                'Accept':'application/json'&lt;br /&gt;
           }&lt;br /&gt;
           r = requests.post(&lt;br /&gt;
                url_request,&lt;br /&gt;
                json = {&lt;br /&gt;
                     &amp;quot;Features&amp;quot;: tab_to_send&lt;br /&gt;
                },&lt;br /&gt;
                headers=headers&lt;br /&gt;
           )&lt;br /&gt;
           print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
           print(&amp;quot;Response :&amp;quot;,r.json())&lt;br /&gt;
      else:&lt;br /&gt;
           print(&amp;quot;Data skip:&amp;quot;,tab_to_send)&lt;br /&gt;
      tab_to_send.clear()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Entrainement de l'IA &amp;lt;/div&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec NanoEdge AI Studio : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour le projet, nous avons d'abord développé et entrainé notre IA sur la plateforme NanoEdge AI Studio. Pour ce faire, nous devons d'abord définir un projet de classification de n-class (&amp;quot;pierre&amp;quot;,&amp;quot;feuille&amp;quot;,&amp;quot;ciseau&amp;quot;) en utilisant un capteur générique à 16 axes. Pour ce faire, nous modifions le code de la STM32 pour qu'elle renvoie une ligne contenant 16*16 mesure en continue. Une fois le projet créé, nous ajoutons 3 signaux correspondant à nos dataset de &amp;quot;Pierre&amp;quot;, &amp;quot;Feuille&amp;quot; et &amp;quot;Ciseau&amp;quot;. Pour rajouter des valeurs dans notre dataset, nous utilisons la liaison série pour lire les valeurs de notre capteur.&lt;br /&gt;
=== Entrainement avec Scikit : ===&lt;br /&gt;
&lt;br /&gt;
Pour la suite de notre projet, nous avons developpé et entrainé une IA avec Scikit.&lt;br /&gt;
&lt;br /&gt;
==== Construction du fichier d'entrainement ====&lt;br /&gt;
Pour commencer, nous avons du construire un fichier csv reprenant nos mesures sur un format de 16 valeurs. Pour chaque mesure, on ajoute en amont de la mesure la catégorie (feuille, ciseau ou pierre). &lt;br /&gt;
[[Fichier:Capture d’écran 2024-01-18 à 16.18.19.png|centré|vignette|500x500px|Fichier chifoumIA.csv]]&lt;br /&gt;
Pour construire ce fichier, nous avons assemblé trois fichiers csv de test que nous avons généré grâce à notre capteur : un fichier d'entrainement Pierre.csv, un fichier d'entrainement Ciseau.csv et un fichier d'entrainement Feuille.csv . &lt;br /&gt;
&lt;br /&gt;
Pour faire cette concaténation nous avons développer un programme python prenant en entrée nos fichiers d'entrainement et fournissant en sortie le fichier csv chifoumIA.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     line_feuille = []&lt;br /&gt;
     line_pierre = []&lt;br /&gt;
     line_ciseau = []&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Feuille.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_feuille = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Pierre.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_pierre = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Ciseau.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_ciseau = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;chifoumIA.csv&amp;quot;,&amp;quot;w&amp;quot;) as f:&lt;br /&gt;
          for elem in line_feuille:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;feuille,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_pierre:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;pierre,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_ciseau:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;ciseau,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Implémentation et Entrainement de notre IA ====&lt;br /&gt;
Maintenant que nous avons notre fichier d'entrainement, nous implémentons notre IA.&lt;br /&gt;
&lt;br /&gt;
Nous avons commencé par créer un tableau de données et un tableau de classes. &lt;br /&gt;
&lt;br /&gt;
Pour remplir ces tableaux, on va lire ligne par ligne le fichier chifoumIA.csv. Le premier élément de la ligne est stockée dans le tableau de classes et le reste de la ligne est stockée dans le tableau de données. &lt;br /&gt;
 chifoumi_data=[]&lt;br /&gt;
 chifoumi_classe=[]&lt;br /&gt;
 &lt;br /&gt;
 with open('chifoumIA.csv') as csv_file:&lt;br /&gt;
        csv_reader = csv.reader(csv_file,delimiter=',')&lt;br /&gt;
        for row in csv_reader:           &lt;br /&gt;
                 chifoumi_data.append([int(row[1]),int(row[2]),int(row[3]),int(row[4]),int(row[5]),int(row[6]),int(row[7]),int(row[8]),&lt;br /&gt;
                                       int(row[9]),int(row[10]),int(row[11]),int(row[12]),int(row[13]),int(row[14]),int(row[15]),int(row[16])])&lt;br /&gt;
                 chifoumi_classe.append(row[0])&lt;br /&gt;
  &lt;br /&gt;
A partir de ces deux tableaux, on construit un ensemble de données d'entraînement et un ensemble de données de tests.&lt;br /&gt;
&lt;br /&gt;
On choisi d'utiliser un réseau de neurone du type MLPClassifer. &lt;br /&gt;
&lt;br /&gt;
Le MLPClassifer est un type de réseau de neurones artificiels composés d'au minimum trois couches de neurones: une couche d'entrée, une ou plusieurs  couches cachées et une couche de sortie. &lt;br /&gt;
&lt;br /&gt;
Dans ce type de réseau, chaque neurone est connecté à l'ensemble des neurones de la couche suivante par un lien auquel est associé un poids. &lt;br /&gt;
&lt;br /&gt;
La classe MLPClassifer implémentée dans la bibliothèque Scikit-Learn dispose de nombreux paramètres. Pour notre projet, nous avons utilisé cette classe de façon très primaire. Les paramètres que nous avons utilisés sont :  &lt;br /&gt;
&lt;br /&gt;
- '''hidden_layer_sizes :''' ce paramètre est un tuple spécifiant le nombre de neurones dans chaque couche cachée. &lt;br /&gt;
&lt;br /&gt;
- '''max_iter :''' ce paramètre représente le nombre maximal d'époque. Il permet de contrôler également le temps d'entrainement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model=MLPClassifier(hidden_layer_sizes=(50,25),max_iter=100,solver='adam')&lt;br /&gt;
&lt;br /&gt;
model.fit(X_train,y_train)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;predictions = model.predict(X_test)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;print(f'Accuracy:{accuracy}')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Déploiement de notre IA ====&lt;br /&gt;
Pour pouvoir déployer notre IA, nous avons enregistré notre model d'entrainement et intégré un service web à notre code existant avec deux endpoint : &lt;br /&gt;
&lt;br /&gt;
- predict : pour effectuer des prédictions sur le model. &lt;br /&gt;
&lt;br /&gt;
- evaluate : pour évaluer les performances du model sur l'ensemble de tests.&lt;br /&gt;
&lt;br /&gt;
Malheureusement nous n'avons pas eu le temps d'entrainer suffisamment cette IA. Ces performances sont donc très faible un peu moins de 50% de fiabilité.&lt;br /&gt;
&lt;br /&gt;
==== Code complet ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import joblib&lt;br /&gt;
import pandas as pd &lt;br /&gt;
import csv&lt;br /&gt;
from flask import Flask, request,jsonify&lt;br /&gt;
from sklearn.model_selection import train_test_split&lt;br /&gt;
from sklearn.ensemble import RandomForestClassifier&lt;br /&gt;
from sklearn.metrics import accuracy_score,precision_score,recall_score,f1_score&lt;br /&gt;
from sklearn.neural_network import MLPClassifier&lt;br /&gt;
from waitress import serve&lt;br /&gt;
from flask import Response&lt;br /&gt;
from flask_cors import CORS&lt;br /&gt;
from flask_cors import cross_origin&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
chifoumi_data=[]&lt;br /&gt;
chifoumi_classe=[]&lt;br /&gt;
&lt;br /&gt;
with open('chifoumIA.csv') as csv_file:&lt;br /&gt;
	csv_reader = csv.reader(csv_file,delimiter=',')&lt;br /&gt;
	for row in csv_reader:&lt;br /&gt;
		chifoumi_data.append([int(row[1]),int(row[2]),int(row[3]),int(row[4]),int(row[5]),int(row[6]),int(row[7]),int(row[8]),int(row[9]),int(row[10]),int(row[11]),int(row[12]),int(row[13]),int(row[14]),int(row[15]),int(row[16])])&lt;br /&gt;
		chifoumi_classe.append(row[0])&lt;br /&gt;
&lt;br /&gt;
X_train,X_test,y_train,y_test= train_test_split(chifoumi_data,chifoumi_classe,test_size=0.2,random_state=42)&lt;br /&gt;
&lt;br /&gt;
model=MLPClassifier(hidden_layer_sizes=(50,25),max_iter=100,solver='adam')&lt;br /&gt;
model.fit(X_train,y_train)&lt;br /&gt;
#predictions = model.predict(X_test)&lt;br /&gt;
#accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
#print(f'Accuracy:{accuracy}')&lt;br /&gt;
&lt;br /&gt;
joblib.dump(model,'model_entraine.pkl')&lt;br /&gt;
&lt;br /&gt;
app = Flask(__name__)&lt;br /&gt;
cors = CORS(app,ressources={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;: &amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#Main&lt;br /&gt;
@app.route('/predict',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
#@cross_origin()&lt;br /&gt;
def predict():&lt;br /&gt;
	data = request.json&lt;br /&gt;
	print(data)&lt;br /&gt;
	features = data['Features']&lt;br /&gt;
	print(features)&lt;br /&gt;
	features_splitted = features[0].split(&amp;quot;,&amp;quot;)&lt;br /&gt;
	features_int = [int(elem) for elem in features_splitted]&lt;br /&gt;
	loaded_model=joblib.load('model_entraine.pkl')&lt;br /&gt;
	predictions = loaded_model.predict(np.array(features_int).reshape(1,-1))&lt;br /&gt;
	return jsonify(predictions.tolist())&lt;br /&gt;
&lt;br /&gt;
@app.route('/evaluate',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
def evaluate():&lt;br /&gt;
	loaded_model = joblib.load('model_entraine.pkl')&lt;br /&gt;
	predictions = loaded_model.predict(X_test)&lt;br /&gt;
	accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
	precision = precision_score(y_test,predictions)&lt;br /&gt;
	recall = recall_score(y_test,predictions)&lt;br /&gt;
	f1=f1_score(y_test,predictions)&lt;br /&gt;
	&lt;br /&gt;
	return jsonify({ 'Accuracy': accuracy,'Precision': precision,'Recall': recall,'F1 Score':f1})&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
	print(&amp;quot;listening&amp;quot;)&lt;br /&gt;
	serve(app,host=&amp;quot;::&amp;quot;, port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4757</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4757"/>
		<updated>2024-01-28T13:43:11Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /*  Introduction Projet IE Delannoy - Lemaire  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Introduction Projet IE Delannoy - Lemaire &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadre la matière '''&amp;quot;Intelligence Embarquée&amp;quot;''' de l'UE &amp;quot;Module de Spécialité&amp;quot; des SE5 - Option Systèmes Communicants, nous avons dû concevoir un projet permettant de '''distribuer le calcul et le processus d'entrainement''' et d'utilisation d'un Intelligence Artificielle. Nous devrons distribuer le calcul à différents endroits du réseau afin d'être en mesure de proposer des pistes d'optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, nous allons mettre en oeuvre un réseau d'objets connectés à des passerelles et à un serveur. '''Les objets collecteront des données''' de l'environnemet et suivants les scénarios, traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Nous aurons à disposition :&lt;br /&gt;
&lt;br /&gt;
* Une machine virtuelle sur le serveur '''Chassiron''' en ''E304/306''&lt;br /&gt;
* Une '''Raspberry PI 4'''&lt;br /&gt;
* Un carte programmable '''STM32F401RE'''&lt;br /&gt;
* Un capteur à ultrason '''Nucleo-53L5A1'''&lt;br /&gt;
&lt;br /&gt;
Ce wiki est le compte-rendu du projet de '''Jason DELANNOY et Chloé LEMAIRE'''. Nous avons décider de développer une intelligence artificielle permettant de '''déterminer''' '''l'action faite par un joueur de Pierre-Feuille-Ciseau''' à l'aide du capteur à ultrason.&lt;br /&gt;
&lt;br /&gt;
Pour ce faire, nous allons développer notre IA de deux façons :&lt;br /&gt;
&lt;br /&gt;
* En utilisant '''NanoEdge Studio''' : Dans ce cas, le calcul serait fait par la carte programmable et envoyé au serveur via la Raspberry&lt;br /&gt;
* En utilisant '''un algorithme de machine learning ''': Ici, c'est le serveur qui fera le calcul et la Raspberry jouera le rôle de passerelle entre la carte programmable et le serveu&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Mise en oeuvre du réseau &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Création VM XEN ===&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]Notre VM est accessible en ssh à partir de son IPv6 : 2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la VM ===&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la borne WIFI Cisco ===&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251 (changement car besoin pour les PEIP) &lt;br /&gt;
&lt;br /&gt;
- dns-server: 193.48.57.33 (changement car problème avec le serveur DNS initial)&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Configuration de la Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadra du projet, nous avons à disposition une Raspberry PI 4 model B que nous allons configurer. Pour ce faire, nous utilisons le logiciel le &amp;quot;Raspberry PI Imager&amp;quot; pour choisir notre OS.&lt;br /&gt;
[[Fichier:JCIE RPI Imager.png|centré|vignette|400x400px]]Maintenant que nous avons une carte SD prête pour la Raspberry, nous la configurons via sa liaison série en passant par minicom :&lt;br /&gt;
 root@zabeth18: / $ minicom -D /dev/ttyACM0 -b 9600&lt;br /&gt;
De plus, nous modifions le fichier /etc/network/interfaces pour pouvoir connecter notre carte au réseau wifi créé plus haut :&lt;br /&gt;
[[Fichier:Screen WiFi.png|centré|vignette|441x441px]]&lt;br /&gt;
Nous verifions ensuite que nous avons une adresse IP :&lt;br /&gt;
[[Fichier:Screenshot from 2023-12-04 17-17-05.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Capteur NUCLEO - 53L5A1 &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Pour ce projet, nous disposons d'une STM32 Nucléo F401RE muni d'un capteur à ultrason X-Nucleo-53L5A1.&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir entrainer notre IA, nous devons faire en sorte d'afficher et de ressortir sur la liaison série les données du capteur. Pour ce faire, nous utilisons le fichier example &amp;quot;'''''53L5A1_ThresholdDetection'''''&amp;quot;. Nous modifions la fonction print_result pour afficher 16 valeurs à la suite :&lt;br /&gt;
[[Fichier:ChifoumIA Print Result.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Après avoir téléversé, nous pouvons vérifier le bon fonctionnement du programme en nous connectant à la carte via minicom :&lt;br /&gt;
&lt;br /&gt;
 root@raspberrypi:/dev$ minicom -D ttyACM0 -b 460800&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Communication VM-Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Envoie de donnée : ===&lt;br /&gt;
&lt;br /&gt;
Dans notre projet, nous avons besoin de remonter les données de notre capteur branché en liaison série à la Raspberry sur le port &amp;quot;ttyACM0&amp;quot;. Nous allons donc passer par des requêtes API entre le serveur sur chassiron et notre Raspberry.&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Raspberry : ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Du côté Raspberry, nous programmons un script en python qui lit sur la liaison série les valeurs du capteurs et les envoie via une requête POST vers le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import requests&lt;br /&gt;
     import json&lt;br /&gt;
     import serial&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;Variable&lt;br /&gt;
     STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
     baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
     Serial_link = serial.Serial(STM32_port,baudrate,timeout=1)&lt;br /&gt;
     print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
     liste_mesures=[]&lt;br /&gt;
     for i in range(101):&lt;br /&gt;
          print(&amp;quot;Mesure&amp;quot;,i)&lt;br /&gt;
          mesure = Serial_link.readline().decode('utf-8')&lt;br /&gt;
          liste_mesures.append(mesure)&lt;br /&gt;
&lt;br /&gt;
     data_to_send = json.dumps(liste_mesures)&lt;br /&gt;
     url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080&amp;quot;&lt;br /&gt;
&lt;br /&gt;
     headers = {&lt;br /&gt;
          'Content-type':'application/json',&lt;br /&gt;
          'Accept':'application/json'&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     r = requests.post(&lt;br /&gt;
          url_request,&lt;br /&gt;
          json=data_to_send,&lt;br /&gt;
          headers=headers&lt;br /&gt;
     )&lt;br /&gt;
     print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Serveur : ====&lt;br /&gt;
La communication entre notre VM et la Raspberry est possible. Nous arrivons à effectuer un ping de l'une sur l'autre en passant par l'addresse IPv6.&lt;br /&gt;
&lt;br /&gt;
IPv6 VM :  2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
IPv6 Raspberry : 2001:660:4401:6050:da3a:ddff:fe59:4cb5&lt;br /&gt;
&lt;br /&gt;
Nous programmons ensuite une API sur notre VM en utilisant la libraire Flask.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import json&lt;br /&gt;
     from flask import Flask&lt;br /&gt;
     from flask import request&lt;br /&gt;
     from waitress import serve&lt;br /&gt;
     from flask import Response&lt;br /&gt;
     from flask_cors import CORS&lt;br /&gt;
     from flask_cors import cross_origin&lt;br /&gt;
&lt;br /&gt;
     app = Flask(__name__)&lt;br /&gt;
     cors = CORS(app, ressourceas={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;:&amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
     def compute_data(data):&lt;br /&gt;
          filename = input(&amp;quot;Nom du fichier :&amp;quot;)&lt;br /&gt;
          to_write = data.split(&amp;quot;\&amp;quot;&amp;quot;)[1:-1]&lt;br /&gt;
          with open(filename, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
               i = 0&lt;br /&gt;
               for elem in to_write:&lt;br /&gt;
                    if i == 0:&lt;br /&gt;
                         print(&amp;quot;We skip&amp;quot;)&lt;br /&gt;
                    else:&lt;br /&gt;
                         if (i%2) == 0:&lt;br /&gt;
                              print(&amp;quot;Data writed :&amp;quot;,elem[:-4])&lt;br /&gt;
                              f.write(elem[:-4])&lt;br /&gt;
                              f.write(&amp;quot;\n&amp;quot;)&lt;br /&gt;
                    i = i + 1&lt;br /&gt;
&lt;br /&gt;
     #Main&lt;br /&gt;
     @app.route('/',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
     @cross_origin()&lt;br /&gt;
     def hello():&lt;br /&gt;
          data = request.json&lt;br /&gt;
          compute_data(data)&lt;br /&gt;
          return data&lt;br /&gt;
&lt;br /&gt;
     if __name__ == '__main__':&lt;br /&gt;
          print(&amp;quot;Listening&amp;quot;)&lt;br /&gt;
          serve(app,host=&amp;quot;::&amp;quot;,port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Implémentation de l'IA : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant qu'on a une communication pour envoyer un fichier à notre serveur depuis la raspberry grâce à notre API, nous la modifions pour que la Raspberry puisse lire la valeur du capteur à ultrason, l'envoyer à notre serveur et recevoir en réponse, la prédiction de l'IA. Nous créons donc une route '''''/predict''''' sur notre API qui récupère les valeurs du capteurs données en paramètre et renvoie la prédiction de l'IA :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 @app.route('/predict',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
 def predict():&lt;br /&gt;
      data = request.json&lt;br /&gt;
      print(data)&lt;br /&gt;
      features = data['Features']&lt;br /&gt;
      print(features)&lt;br /&gt;
      features_splitted = features[0].split(&amp;quot;,&amp;quot;)&lt;br /&gt;
      features_int = [int(elem) for elem in features_splitted]&lt;br /&gt;
      loaded_model = joblib.load('model_entraine.pkl')&lt;br /&gt;
      predictios = loaded_model.predict(np.array(features_int).reshape(1,-1))&lt;br /&gt;
      return jsonify(predictions.tolist())&lt;br /&gt;
&amp;lt;/pre&amp;gt;Nous envoyons ensuite les données à analyser via des requêtes API :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 #Import Librairies&lt;br /&gt;
 import requests&lt;br /&gt;
 import json&lt;br /&gt;
 import serial&lt;br /&gt;
 from flask import jsonify&lt;br /&gt;
&lt;br /&gt;
 #Variable&lt;br /&gt;
 STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
 baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
 Serial_link = serial.Serial(STM32_port, baudrate, timeout=1)&lt;br /&gt;
 print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
 tab_to_send = []&lt;br /&gt;
&lt;br /&gt;
 while True:&lt;br /&gt;
      Serial_link.readline().decode('utf-8')&lt;br /&gt;
      tab_to_send.append(Serial_link.readline().decode('utf-8')&lt;br /&gt;
      if (tab_to_send != [&amp;quot;&amp;quot;]):&lt;br /&gt;
           print(&amp;quot;Data sended :&amp;quot;,tab_to_send)&lt;br /&gt;
           url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080/predict&amp;quot;&lt;br /&gt;
           headers = {&lt;br /&gt;
                'Content-type':'application/json',&lt;br /&gt;
                'Accept':'application/json'&lt;br /&gt;
           }&lt;br /&gt;
           r = requests.post(&lt;br /&gt;
                url_request,&lt;br /&gt;
                json = {&lt;br /&gt;
                     &amp;quot;Features&amp;quot;: tab_to_send&lt;br /&gt;
                },&lt;br /&gt;
                headers=headers&lt;br /&gt;
           )&lt;br /&gt;
           print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
           print(&amp;quot;Response :&amp;quot;,r.json())&lt;br /&gt;
      else:&lt;br /&gt;
           print(&amp;quot;Data skip:&amp;quot;,tab_to_send)&lt;br /&gt;
      tab_to_send.clear()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Entrainement de l'IA &amp;lt;/div&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec NanoEdge AI Studio : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour le projet, nous avons d'abord développé et entrainé notre IA sur la plateforme NanoEdge AI Studio. Pour ce faire, nous devons d'abord définir un projet de classification de n-class (&amp;quot;pierre&amp;quot;,&amp;quot;feuille&amp;quot;,&amp;quot;ciseau&amp;quot;) en utilisant un capteur générique à 16 axes. Pour ce faire, nous modifions le code de la STM32 pour qu'elle renvoie une ligne contenant 16*16 mesure en continue. Une fois le projet créé, nous ajoutons 3 signaux correspondant à nos dataset de &amp;quot;Pierre&amp;quot;, &amp;quot;Feuille&amp;quot; et &amp;quot;Ciseau&amp;quot;. Pour rajouter des valeurs dans notre dataset, nous utilisons la liaison série pour lire les valeurs de notre capteur.&lt;br /&gt;
=== Entrainement avec Scikit : ===&lt;br /&gt;
&lt;br /&gt;
Pour la suite de notre projet, nous avons developpé et entrainé une IA avec Scikit.&lt;br /&gt;
&lt;br /&gt;
==== Construction du fichier d'entrainement ====&lt;br /&gt;
Pour commencer, nous avons du construire un fichier csv reprenant nos mesures sur un format de 16 valeurs. Pour chaque mesure, on ajoute en amont de la mesure la catégorie (feuille, ciseau ou pierre). &lt;br /&gt;
[[Fichier:Capture d’écran 2024-01-18 à 16.18.19.png|centré|vignette|500x500px|Fichier chifoumIA.csv]]&lt;br /&gt;
Pour construire ce fichier, nous avons assemblé trois fichiers csv de test que nous avons généré grâce à notre capteur : un fichier d'entrainement Pierre.csv, un fichier d'entrainement Ciseau.csv et un fichier d'entrainement Feuille.csv . &lt;br /&gt;
&lt;br /&gt;
Pour faire cette concaténation nous avons développer un programme python prenant en entrée nos fichiers d'entrainement et fournissant en sortie le fichier csv chifoumIA.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     line_feuille = []&lt;br /&gt;
     line_pierre = []&lt;br /&gt;
     line_ciseau = []&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Feuille.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_feuille = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Pierre.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_pierre = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Ciseau.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_ciseau = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;chifoumIA.csv&amp;quot;,&amp;quot;w&amp;quot;) as f:&lt;br /&gt;
          for elem in line_feuille:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;feuille,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_pierre:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;pierre,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_ciseau:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;ciseau,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Implémentation et Entrainement de notre IA ====&lt;br /&gt;
Maintenant que nous avons notre fichier d'entrainement, nous implémentons notre IA.&lt;br /&gt;
&lt;br /&gt;
Nous avons commencé par créer un tableau de données et un tableau de classes. &lt;br /&gt;
&lt;br /&gt;
Pour remplir ces tableaux, on va lire ligne par ligne le fichier chifoumIA.csv. Le premier élément de la ligne est stockée dans le tableau de classes et le reste de la ligne est stockée dans le tableau de données. &lt;br /&gt;
 chifoumi_data=[]&lt;br /&gt;
 chifoumi_classe=[]&lt;br /&gt;
 &lt;br /&gt;
 with open('chifoumIA.csv') as csv_file:&lt;br /&gt;
        csv_reader = csv.reader(csv_file,delimiter=',')&lt;br /&gt;
        for row in csv_reader:           &lt;br /&gt;
                 chifoumi_data.append([int(row[1]),int(row[2]),int(row[3]),int(row[4]),int(row[5]),int(row[6]),int(row[7]),int(row[8]),&lt;br /&gt;
                                       int(row[9]),int(row[10]),int(row[11]),int(row[12]),int(row[13]),int(row[14]),int(row[15]),int(row[16])])&lt;br /&gt;
                 chifoumi_classe.append(row[0])&lt;br /&gt;
  &lt;br /&gt;
A partir de ces deux tableaux, on construit un ensemble de données d'entraînement et un ensemble de données de tests.&lt;br /&gt;
&lt;br /&gt;
On choisi d'utiliser un réseau de neurone du type MLPClassifer. &lt;br /&gt;
&lt;br /&gt;
Le MLPClassifer est un type de réseau de neurones artificiels composés d'au minimum trois couches de neurones: une couche d'entrée, une ou plusieurs  couches cachées et une couche de sortie. &lt;br /&gt;
&lt;br /&gt;
Dans ce type de réseau, chaque neurone est connecté à l'ensemble des neurones de la couche suivante par un lien auquel est associé un poids. &lt;br /&gt;
&lt;br /&gt;
La classe MLPClassifer implémentée dans la bibliothèque Scikit-Learn dispose de nombreux paramètres. Pour notre projet, nous avons utilisé cette classe de façon très primaire. Les paramètres que nous avons utilisés sont :  &lt;br /&gt;
&lt;br /&gt;
- '''hidden_layer_sizes :''' ce paramètre est un tuple spécifiant le nombre de neurones dans chaque couche cachée. &lt;br /&gt;
&lt;br /&gt;
- '''max_iter :''' ce paramètre représente le nombre maximal d'époque. Il permet de contrôler également le temps d'entrainement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model=MLPClassifier(hidden_layer_sizes=(50,25),max_iter=100,solver='adam')&lt;br /&gt;
&lt;br /&gt;
model.fit(X_train,y_train)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;predictions = model.predict(X_test)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;print(f'Accuracy:{accuracy}')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Déploiement de notre IA ====&lt;br /&gt;
Pour pouvoir déployer notre IA, nous avons enregistré notre model d'entrainement et intégré un service web à notre code existant avec deux endpoint : &lt;br /&gt;
&lt;br /&gt;
- predict : pour effectuer des prédictions sur le model. &lt;br /&gt;
&lt;br /&gt;
- evaluate : pour évaluer les performances du model sur l'ensemble de tests.&lt;br /&gt;
&lt;br /&gt;
Malheureusement nous n'avons pas eu le temps d'entrainer suffisamment cette IA. Ces performances sont donc très faible un peu moins de 50% de fiabilité.&lt;br /&gt;
&lt;br /&gt;
==== Code complet ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import joblib&lt;br /&gt;
import pandas as pd &lt;br /&gt;
import csv&lt;br /&gt;
from flask import Flask, request,jsonify&lt;br /&gt;
from sklearn.model_selection import train_test_split&lt;br /&gt;
from sklearn.ensemble import RandomForestClassifier&lt;br /&gt;
from sklearn.metrics import accuracy_score,precision_score,recall_score,f1_score&lt;br /&gt;
from sklearn.neural_network import MLPClassifier&lt;br /&gt;
from waitress import serve&lt;br /&gt;
from flask import Response&lt;br /&gt;
from flask_cors import CORS&lt;br /&gt;
from flask_cors import cross_origin&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
chifoumi_data=[]&lt;br /&gt;
chifoumi_classe=[]&lt;br /&gt;
&lt;br /&gt;
with open('chifoumIA.csv') as csv_file:&lt;br /&gt;
	csv_reader = csv.reader(csv_file,delimiter=',')&lt;br /&gt;
	for row in csv_reader:&lt;br /&gt;
		chifoumi_data.append([int(row[1]),int(row[2]),int(row[3]),int(row[4]),int(row[5]),int(row[6]),int(row[7]),int(row[8]),int(row[9]),int(row[10]),int(row[11]),int(row[12]),int(row[13]),int(row[14]),int(row[15]),int(row[16])])&lt;br /&gt;
		chifoumi_classe.append(row[0])&lt;br /&gt;
&lt;br /&gt;
X_train,X_test,y_train,y_test= train_test_split(chifoumi_data,chifoumi_classe,test_size=0.2,random_state=42)&lt;br /&gt;
&lt;br /&gt;
model=MLPClassifier(hidden_layer_sizes=(50,25),max_iter=100,solver='adam')&lt;br /&gt;
model.fit(X_train,y_train)&lt;br /&gt;
#predictions = model.predict(X_test)&lt;br /&gt;
#accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
#print(f'Accuracy:{accuracy}')&lt;br /&gt;
&lt;br /&gt;
joblib.dump(model,'model_entraine.pkl')&lt;br /&gt;
&lt;br /&gt;
app = Flask(__name__)&lt;br /&gt;
cors = CORS(app,ressources={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;: &amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#Main&lt;br /&gt;
@app.route('/predict',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
#@cross_origin()&lt;br /&gt;
def predict():&lt;br /&gt;
	data = request.json&lt;br /&gt;
	print(data)&lt;br /&gt;
	features = data['Features']&lt;br /&gt;
	print(features)&lt;br /&gt;
	features_splitted = features[0].split(&amp;quot;,&amp;quot;)&lt;br /&gt;
	features_int = [int(elem) for elem in features_splitted]&lt;br /&gt;
	loaded_model=joblib.load('model_entraine.pkl')&lt;br /&gt;
	predictions = loaded_model.predict(np.array(features_int).reshape(1,-1))&lt;br /&gt;
	return jsonify(predictions.tolist())&lt;br /&gt;
&lt;br /&gt;
@app.route('/evaluate',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
def evaluate():&lt;br /&gt;
	loaded_model = joblib.load('model_entraine.pkl')&lt;br /&gt;
	predictions = loaded_model.predict(X_test)&lt;br /&gt;
	accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
	precision = precision_score(y_test,predictions)&lt;br /&gt;
	recall = recall_score(y_test,predictions)&lt;br /&gt;
	f1=f1_score(y_test,predictions)&lt;br /&gt;
	&lt;br /&gt;
	return jsonify({ 'Accuracy': accuracy,'Precision': precision,'Recall': recall,'F1 Score':f1})&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
	print(&amp;quot;listening&amp;quot;)&lt;br /&gt;
	serve(app,host=&amp;quot;::&amp;quot;, port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4756</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4756"/>
		<updated>2024-01-28T13:35:31Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /*  Entrainement de l'IA  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Introduction Projet IE Delannoy - Lemaire &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadre la matière '''&amp;quot;Intelligence Embarquée&amp;quot;''' de l'UE &amp;quot;Module de Spécialité&amp;quot; des SE5 - Option Systèmes Communicants, nous avons dû concevoir un projet permettant de '''distribuer le calcul et le processus d'entrainement''' et d'utilisation d'un Intelligence Artificielle. Nous devrons distribuer le calcul à différents endroits du réseau afin d'être en mesure de proposer des pistes d'optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, nous allons mettre en oeuvre un réseau d'objets connectés à des passerelles et à un serveur. '''Les objets collecteront des données''' de l'environnemet et suivants les scénarios, traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Nous aurons à disposition :&lt;br /&gt;
&lt;br /&gt;
* Une machine virtuelle sur le serveur '''Chassiron''' en ''E304/306''&lt;br /&gt;
* Une '''Raspberry PI 4'''&lt;br /&gt;
* Un carte programmable '''STM32F401RE'''&lt;br /&gt;
* Un capteur à ultrason '''Nucleo-53L5A1'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ce wiki est le compte-rendu du projet de '''Jason DELANNOY et Chloé LEMAIRE'''. Nous avons décider de développer une intelligence artificielle permettant de '''déterminer''' '''l'action faite par un joueur de Pierre-Feuille-Ciseau''' à l'aide du capteur à ultrason.&lt;br /&gt;
&lt;br /&gt;
Pour ce faire, nous allons développer notre IA de deux façons :&lt;br /&gt;
&lt;br /&gt;
* En utilisant '''NanoEdge Studio''' : Dans ce cas, le calcul serait fait par la carte programmable et envoyé au serveur via la Raspberry&lt;br /&gt;
* En utilisant '''un algorithme de machine learning ''': Ici, c'est le serveur qui fera le calcul et la Raspberry jouera le rôle de passerelle entre la carte programmable et le serveu&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Mise en oeuvre du réseau &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Création VM XEN ===&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]Notre VM est accessible en ssh à partir de son IPv6 : 2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la VM ===&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la borne WIFI Cisco ===&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251 (changement car besoin pour les PEIP) &lt;br /&gt;
&lt;br /&gt;
- dns-server: 193.48.57.33 (changement car problème avec le serveur DNS initial)&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Configuration de la Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadra du projet, nous avons à disposition une Raspberry PI 4 model B que nous allons configurer. Pour ce faire, nous utilisons le logiciel le &amp;quot;Raspberry PI Imager&amp;quot; pour choisir notre OS.&lt;br /&gt;
[[Fichier:JCIE RPI Imager.png|centré|vignette|400x400px]]Maintenant que nous avons une carte SD prête pour la Raspberry, nous la configurons via sa liaison série en passant par minicom :&lt;br /&gt;
 root@zabeth18: / $ minicom -D /dev/ttyACM0 -b 9600&lt;br /&gt;
De plus, nous modifions le fichier /etc/network/interfaces pour pouvoir connecter notre carte au réseau wifi créé plus haut :&lt;br /&gt;
[[Fichier:Screen WiFi.png|centré|vignette|441x441px]]&lt;br /&gt;
Nous verifions ensuite que nous avons une adresse IP :&lt;br /&gt;
[[Fichier:Screenshot from 2023-12-04 17-17-05.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Capteur NUCLEO - 53L5A1 &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Pour ce projet, nous disposons d'une STM32 Nucléo F401RE muni d'un capteur à ultrason X-Nucleo-53L5A1.&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir entrainer notre IA, nous devons faire en sorte d'afficher et de ressortir sur la liaison série les données du capteur. Pour ce faire, nous utilisons le fichier example &amp;quot;'''''53L5A1_ThresholdDetection'''''&amp;quot;. Nous modifions la fonction print_result pour afficher 16 valeurs à la suite :&lt;br /&gt;
[[Fichier:ChifoumIA Print Result.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Après avoir téléversé, nous pouvons vérifier le bon fonctionnement du programme en nous connectant à la carte via minicom :&lt;br /&gt;
&lt;br /&gt;
 root@raspberrypi:/dev$ minicom -D ttyACM0 -b 460800&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Communication VM-Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Envoie de donnée : ===&lt;br /&gt;
&lt;br /&gt;
Dans notre projet, nous avons besoin de remonter les données de notre capteur branché en liaison série à la Raspberry sur le port &amp;quot;ttyACM0&amp;quot;. Nous allons donc passer par des requêtes API entre le serveur sur chassiron et notre Raspberry.&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Raspberry : ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Du côté Raspberry, nous programmons un script en python qui lit sur la liaison série les valeurs du capteurs et les envoie via une requête POST vers le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import requests&lt;br /&gt;
     import json&lt;br /&gt;
     import serial&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;Variable&lt;br /&gt;
     STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
     baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
     Serial_link = serial.Serial(STM32_port,baudrate,timeout=1)&lt;br /&gt;
     print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
     liste_mesures=[]&lt;br /&gt;
     for i in range(101):&lt;br /&gt;
          print(&amp;quot;Mesure&amp;quot;,i)&lt;br /&gt;
          mesure = Serial_link.readline().decode('utf-8')&lt;br /&gt;
          liste_mesures.append(mesure)&lt;br /&gt;
&lt;br /&gt;
     data_to_send = json.dumps(liste_mesures)&lt;br /&gt;
     url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080&amp;quot;&lt;br /&gt;
&lt;br /&gt;
     headers = {&lt;br /&gt;
          'Content-type':'application/json',&lt;br /&gt;
          'Accept':'application/json'&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     r = requests.post(&lt;br /&gt;
          url_request,&lt;br /&gt;
          json=data_to_send,&lt;br /&gt;
          headers=headers&lt;br /&gt;
     )&lt;br /&gt;
     print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Serveur : ====&lt;br /&gt;
La communication entre notre VM et la Raspberry est possible. Nous arrivons à effectuer un ping de l'une sur l'autre en passant par l'addresse IPv6.&lt;br /&gt;
&lt;br /&gt;
IPv6 VM :  2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
IPv6 Raspberry : 2001:660:4401:6050:da3a:ddff:fe59:4cb5&lt;br /&gt;
&lt;br /&gt;
Nous programmons ensuite une API sur notre VM en utilisant la libraire Flask.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import json&lt;br /&gt;
     from flask import Flask&lt;br /&gt;
     from flask import request&lt;br /&gt;
     from waitress import serve&lt;br /&gt;
     from flask import Response&lt;br /&gt;
     from flask_cors import CORS&lt;br /&gt;
     from flask_cors import cross_origin&lt;br /&gt;
&lt;br /&gt;
     app = Flask(__name__)&lt;br /&gt;
     cors = CORS(app, ressourceas={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;:&amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
     def compute_data(data):&lt;br /&gt;
          filename = input(&amp;quot;Nom du fichier :&amp;quot;)&lt;br /&gt;
          to_write = data.split(&amp;quot;\&amp;quot;&amp;quot;)[1:-1]&lt;br /&gt;
          with open(filename, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
               i = 0&lt;br /&gt;
               for elem in to_write:&lt;br /&gt;
                    if i == 0:&lt;br /&gt;
                         print(&amp;quot;We skip&amp;quot;)&lt;br /&gt;
                    else:&lt;br /&gt;
                         if (i%2) == 0:&lt;br /&gt;
                              print(&amp;quot;Data writed :&amp;quot;,elem[:-4])&lt;br /&gt;
                              f.write(elem[:-4])&lt;br /&gt;
                              f.write(&amp;quot;\n&amp;quot;)&lt;br /&gt;
                    i = i + 1&lt;br /&gt;
&lt;br /&gt;
     #Main&lt;br /&gt;
     @app.route('/',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
     @cross_origin()&lt;br /&gt;
     def hello():&lt;br /&gt;
          data = request.json&lt;br /&gt;
          compute_data(data)&lt;br /&gt;
          return data&lt;br /&gt;
&lt;br /&gt;
     if __name__ == '__main__':&lt;br /&gt;
          print(&amp;quot;Listening&amp;quot;)&lt;br /&gt;
          serve(app,host=&amp;quot;::&amp;quot;,port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Implémentation de l'IA : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant qu'on a une communication pour envoyer un fichier à notre serveur depuis la raspberry grâce à notre API, nous la modifions pour que la Raspberry puisse lire la valeur du capteur à ultrason, l'envoyer à notre serveur et recevoir en réponse, la prédiction de l'IA. Nous créons donc une route '''''/predict''''' sur notre API qui récupère les valeurs du capteurs données en paramètre et renvoie la prédiction de l'IA :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 @app.route('/predict',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
 def predict():&lt;br /&gt;
      data = request.json&lt;br /&gt;
      print(data)&lt;br /&gt;
      features = data['Features']&lt;br /&gt;
      print(features)&lt;br /&gt;
      features_splitted = features[0].split(&amp;quot;,&amp;quot;)&lt;br /&gt;
      features_int = [int(elem) for elem in features_splitted]&lt;br /&gt;
      loaded_model = joblib.load('model_entraine.pkl')&lt;br /&gt;
      predictios = loaded_model.predict(np.array(features_int).reshape(1,-1))&lt;br /&gt;
      return jsonify(predictions.tolist())&lt;br /&gt;
&amp;lt;/pre&amp;gt;Nous envoyons ensuite les données à analyser via des requêtes API :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 #Import Librairies&lt;br /&gt;
 import requests&lt;br /&gt;
 import json&lt;br /&gt;
 import serial&lt;br /&gt;
 from flask import jsonify&lt;br /&gt;
&lt;br /&gt;
 #Variable&lt;br /&gt;
 STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
 baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
 Serial_link = serial.Serial(STM32_port, baudrate, timeout=1)&lt;br /&gt;
 print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
 tab_to_send = []&lt;br /&gt;
&lt;br /&gt;
 while True:&lt;br /&gt;
      Serial_link.readline().decode('utf-8')&lt;br /&gt;
      tab_to_send.append(Serial_link.readline().decode('utf-8')&lt;br /&gt;
      if (tab_to_send != [&amp;quot;&amp;quot;]):&lt;br /&gt;
           print(&amp;quot;Data sended :&amp;quot;,tab_to_send)&lt;br /&gt;
           url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080/predict&amp;quot;&lt;br /&gt;
           headers = {&lt;br /&gt;
                'Content-type':'application/json',&lt;br /&gt;
                'Accept':'application/json'&lt;br /&gt;
           }&lt;br /&gt;
           r = requests.post(&lt;br /&gt;
                url_request,&lt;br /&gt;
                json = {&lt;br /&gt;
                     &amp;quot;Features&amp;quot;: tab_to_send&lt;br /&gt;
                },&lt;br /&gt;
                headers=headers&lt;br /&gt;
           )&lt;br /&gt;
           print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
           print(&amp;quot;Response :&amp;quot;,r.json())&lt;br /&gt;
      else:&lt;br /&gt;
           print(&amp;quot;Data skip:&amp;quot;,tab_to_send)&lt;br /&gt;
      tab_to_send.clear()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Entrainement de l'IA &amp;lt;/div&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec NanoEdge AI Studio : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour le projet, nous avons d'abord développé et entrainé notre IA sur la plateforme NanoEdge AI Studio. Pour ce faire, nous devons d'abord définir un projet de classification de n-class (&amp;quot;pierre&amp;quot;,&amp;quot;feuille&amp;quot;,&amp;quot;ciseau&amp;quot;) en utilisant un capteur générique à 16 axes. Pour ce faire, nous modifions le code de la STM32 pour qu'elle renvoie une ligne contenant 16*16 mesure en continue. Une fois le projet créé, nous ajoutons 3 signaux correspondant à nos dataset de &amp;quot;Pierre&amp;quot;, &amp;quot;Feuille&amp;quot; et &amp;quot;Ciseau&amp;quot;. Pour rajouter des valeurs dans notre dataset, nous utilisons la liaison série pour lire les valeurs de notre capteur.&lt;br /&gt;
=== Entrainement avec Scikit : ===&lt;br /&gt;
&lt;br /&gt;
Pour la suite de notre projet, nous avons developpé et entrainé une IA avec Scikit.&lt;br /&gt;
&lt;br /&gt;
==== Construction du fichier d'entrainement ====&lt;br /&gt;
Pour commencer, nous avons du construire un fichier csv reprenant nos mesures sur un format de 16 valeurs. Pour chaque mesure, on ajoute en amont de la mesure la catégorie (feuille, ciseau ou pierre). &lt;br /&gt;
[[Fichier:Capture d’écran 2024-01-18 à 16.18.19.png|centré|vignette|500x500px|Fichier chifoumIA.csv]]&lt;br /&gt;
Pour construire ce fichier, nous avons assemblé trois fichiers csv de test que nous avons généré grâce à notre capteur : un fichier d'entrainement Pierre.csv, un fichier d'entrainement Ciseau.csv et un fichier d'entrainement Feuille.csv . &lt;br /&gt;
&lt;br /&gt;
Pour faire cette concaténation nous avons développer un programme python prenant en entrée nos fichiers d'entrainement et fournissant en sortie le fichier csv chifoumIA.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     line_feuille = []&lt;br /&gt;
     line_pierre = []&lt;br /&gt;
     line_ciseau = []&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Feuille.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_feuille = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Pierre.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_pierre = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Ciseau.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_ciseau = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;chifoumIA.csv&amp;quot;,&amp;quot;w&amp;quot;) as f:&lt;br /&gt;
          for elem in line_feuille:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;feuille,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_pierre:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;pierre,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_ciseau:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;ciseau,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Implémentation et Entrainement de notre IA ====&lt;br /&gt;
Maintenant que nous avons notre fichier d'entrainement, nous implémentons notre IA.&lt;br /&gt;
&lt;br /&gt;
Nous avons commencé par créer un tableau de données et un tableau de classes. &lt;br /&gt;
&lt;br /&gt;
Pour remplir ces tableaux, on va lire ligne par ligne le fichier chifoumIA.csv. Le premier élément de la ligne est stockée dans le tableau de classes et le reste de la ligne est stockée dans le tableau de données. &lt;br /&gt;
 chifoumi_data=[]&lt;br /&gt;
 chifoumi_classe=[]&lt;br /&gt;
 &lt;br /&gt;
 with open('chifoumIA.csv') as csv_file:&lt;br /&gt;
        csv_reader = csv.reader(csv_file,delimiter=',')&lt;br /&gt;
        for row in csv_reader:           &lt;br /&gt;
                 chifoumi_data.append([int(row[1]),int(row[2]),int(row[3]),int(row[4]),int(row[5]),int(row[6]),int(row[7]),int(row[8]),&lt;br /&gt;
                                       int(row[9]),int(row[10]),int(row[11]),int(row[12]),int(row[13]),int(row[14]),int(row[15]),int(row[16])])&lt;br /&gt;
                 chifoumi_classe.append(row[0])&lt;br /&gt;
  &lt;br /&gt;
A partir de ces deux tableaux, on construit un ensemble de données d'entraînement et un ensemble de données de tests.&lt;br /&gt;
&lt;br /&gt;
On choisi d'utiliser un réseau de neurone du type MLPClassifer. &lt;br /&gt;
&lt;br /&gt;
Le MLPClassifer est un type de réseau de neurones artificiels composés d'au minimum trois couches de neurones: une couche d'entrée, une ou plusieurs  couches cachées et une couche de sortie. &lt;br /&gt;
&lt;br /&gt;
Dans ce type de réseau, chaque neurone est connecté à l'ensemble des neurones de la couche suivante par un lien auquel est associé un poids. &lt;br /&gt;
&lt;br /&gt;
La classe MLPClassifer implémentée dans la bibliothèque Scikit-Learn dispose de nombreux paramètres. Pour notre projet, nous avons utilisé cette classe de façon très primaire. Les paramètres que nous avons utilisés sont :  &lt;br /&gt;
&lt;br /&gt;
- '''hidden_layer_sizes :''' ce paramètre est un tuple spécifiant le nombre de neurones dans chaque couche cachée. &lt;br /&gt;
&lt;br /&gt;
- '''max_iter :''' ce paramètre représente le nombre maximal d'époque. Il permet de contrôler également le temps d'entrainement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model=MLPClassifier(hidden_layer_sizes=(50,25),max_iter=100,solver='adam')&lt;br /&gt;
&lt;br /&gt;
model.fit(X_train,y_train)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;predictions = model.predict(X_test)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;print(f'Accuracy:{accuracy}')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Déploiement de notre IA ====&lt;br /&gt;
Pour pouvoir déployer notre IA, nous avons enregistré notre model d'entrainement et intégré un service web à notre code existant avec deux endpoint : &lt;br /&gt;
&lt;br /&gt;
- predict : pour effectuer des prédictions sur le model. &lt;br /&gt;
&lt;br /&gt;
- evaluate : pour évaluer les performances du model sur l'ensemble de tests.&lt;br /&gt;
&lt;br /&gt;
Malheureusement nous n'avons pas eu le temps d'entrainer suffisamment cette IA. Ces performances sont donc très faible un peu moins de 50% de fiabilité.&lt;br /&gt;
&lt;br /&gt;
==== Code complet ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import joblib&lt;br /&gt;
import pandas as pd &lt;br /&gt;
import csv&lt;br /&gt;
from flask import Flask, request,jsonify&lt;br /&gt;
from sklearn.model_selection import train_test_split&lt;br /&gt;
from sklearn.ensemble import RandomForestClassifier&lt;br /&gt;
from sklearn.metrics import accuracy_score,precision_score,recall_score,f1_score&lt;br /&gt;
from sklearn.neural_network import MLPClassifier&lt;br /&gt;
from waitress import serve&lt;br /&gt;
from flask import Response&lt;br /&gt;
from flask_cors import CORS&lt;br /&gt;
from flask_cors import cross_origin&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
chifoumi_data=[]&lt;br /&gt;
chifoumi_classe=[]&lt;br /&gt;
&lt;br /&gt;
with open('chifoumIA.csv') as csv_file:&lt;br /&gt;
	csv_reader = csv.reader(csv_file,delimiter=',')&lt;br /&gt;
	for row in csv_reader:&lt;br /&gt;
		chifoumi_data.append([int(row[1]),int(row[2]),int(row[3]),int(row[4]),int(row[5]),int(row[6]),int(row[7]),int(row[8]),int(row[9]),int(row[10]),int(row[11]),int(row[12]),int(row[13]),int(row[14]),int(row[15]),int(row[16])])&lt;br /&gt;
		chifoumi_classe.append(row[0])&lt;br /&gt;
&lt;br /&gt;
X_train,X_test,y_train,y_test= train_test_split(chifoumi_data,chifoumi_classe,test_size=0.2,random_state=42)&lt;br /&gt;
&lt;br /&gt;
model=MLPClassifier(hidden_layer_sizes=(50,25),max_iter=100,solver='adam')&lt;br /&gt;
model.fit(X_train,y_train)&lt;br /&gt;
#predictions = model.predict(X_test)&lt;br /&gt;
#accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
#print(f'Accuracy:{accuracy}')&lt;br /&gt;
&lt;br /&gt;
joblib.dump(model,'model_entraine.pkl')&lt;br /&gt;
&lt;br /&gt;
app = Flask(__name__)&lt;br /&gt;
cors = CORS(app,ressources={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;: &amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#Main&lt;br /&gt;
@app.route('/predict',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
#@cross_origin()&lt;br /&gt;
def predict():&lt;br /&gt;
	data = request.json&lt;br /&gt;
	print(data)&lt;br /&gt;
	features = data['Features']&lt;br /&gt;
	print(features)&lt;br /&gt;
	features_splitted = features[0].split(&amp;quot;,&amp;quot;)&lt;br /&gt;
	features_int = [int(elem) for elem in features_splitted]&lt;br /&gt;
	loaded_model=joblib.load('model_entraine.pkl')&lt;br /&gt;
	predictions = loaded_model.predict(np.array(features_int).reshape(1,-1))&lt;br /&gt;
	return jsonify(predictions.tolist())&lt;br /&gt;
&lt;br /&gt;
@app.route('/evaluate',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
def evaluate():&lt;br /&gt;
	loaded_model = joblib.load('model_entraine.pkl')&lt;br /&gt;
	predictions = loaded_model.predict(X_test)&lt;br /&gt;
	accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
	precision = precision_score(y_test,predictions)&lt;br /&gt;
	recall = recall_score(y_test,predictions)&lt;br /&gt;
	f1=f1_score(y_test,predictions)&lt;br /&gt;
	&lt;br /&gt;
	return jsonify({ 'Accuracy': accuracy,'Precision': precision,'Recall': recall,'F1 Score':f1})&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
	print(&amp;quot;listening&amp;quot;)&lt;br /&gt;
	serve(app,host=&amp;quot;::&amp;quot;, port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4755</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4755"/>
		<updated>2024-01-28T13:34:44Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /*  Entrainement de l'IA  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Introduction Projet IE Delannoy - Lemaire &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadre la matière '''&amp;quot;Intelligence Embarquée&amp;quot;''' de l'UE &amp;quot;Module de Spécialité&amp;quot; des SE5 - Option Systèmes Communicants, nous avons dû concevoir un projet permettant de '''distribuer le calcul et le processus d'entrainement''' et d'utilisation d'un Intelligence Artificielle. Nous devrons distribuer le calcul à différents endroits du réseau afin d'être en mesure de proposer des pistes d'optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, nous allons mettre en oeuvre un réseau d'objets connectés à des passerelles et à un serveur. '''Les objets collecteront des données''' de l'environnemet et suivants les scénarios, traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Nous aurons à disposition :&lt;br /&gt;
&lt;br /&gt;
* Une machine virtuelle sur le serveur '''Chassiron''' en ''E304/306''&lt;br /&gt;
* Une '''Raspberry PI 4'''&lt;br /&gt;
* Un carte programmable '''STM32F401RE'''&lt;br /&gt;
* Un capteur à ultrason '''Nucleo-53L5A1'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ce wiki est le compte-rendu du projet de '''Jason DELANNOY et Chloé LEMAIRE'''. Nous avons décider de développer une intelligence artificielle permettant de '''déterminer''' '''l'action faite par un joueur de Pierre-Feuille-Ciseau''' à l'aide du capteur à ultrason.&lt;br /&gt;
&lt;br /&gt;
Pour ce faire, nous allons développer notre IA de deux façons :&lt;br /&gt;
&lt;br /&gt;
* En utilisant '''NanoEdge Studio''' : Dans ce cas, le calcul serait fait par la carte programmable et envoyé au serveur via la Raspberry&lt;br /&gt;
* En utilisant '''un algorithme de machine learning ''': Ici, c'est le serveur qui fera le calcul et la Raspberry jouera le rôle de passerelle entre la carte programmable et le serveu&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Mise en oeuvre du réseau &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Création VM XEN ===&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]Notre VM est accessible en ssh à partir de son IPv6 : 2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la VM ===&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la borne WIFI Cisco ===&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251 (changement car besoin pour les PEIP) &lt;br /&gt;
&lt;br /&gt;
- dns-server: 193.48.57.33 (changement car problème avec le serveur DNS initial)&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Configuration de la Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadra du projet, nous avons à disposition une Raspberry PI 4 model B que nous allons configurer. Pour ce faire, nous utilisons le logiciel le &amp;quot;Raspberry PI Imager&amp;quot; pour choisir notre OS.&lt;br /&gt;
[[Fichier:JCIE RPI Imager.png|centré|vignette|400x400px]]Maintenant que nous avons une carte SD prête pour la Raspberry, nous la configurons via sa liaison série en passant par minicom :&lt;br /&gt;
 root@zabeth18: / $ minicom -D /dev/ttyACM0 -b 9600&lt;br /&gt;
De plus, nous modifions le fichier /etc/network/interfaces pour pouvoir connecter notre carte au réseau wifi créé plus haut :&lt;br /&gt;
[[Fichier:Screen WiFi.png|centré|vignette|441x441px]]&lt;br /&gt;
Nous verifions ensuite que nous avons une adresse IP :&lt;br /&gt;
[[Fichier:Screenshot from 2023-12-04 17-17-05.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Capteur NUCLEO - 53L5A1 &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Pour ce projet, nous disposons d'une STM32 Nucléo F401RE muni d'un capteur à ultrason X-Nucleo-53L5A1.&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir entrainer notre IA, nous devons faire en sorte d'afficher et de ressortir sur la liaison série les données du capteur. Pour ce faire, nous utilisons le fichier example &amp;quot;'''''53L5A1_ThresholdDetection'''''&amp;quot;. Nous modifions la fonction print_result pour afficher 16 valeurs à la suite :&lt;br /&gt;
[[Fichier:ChifoumIA Print Result.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Après avoir téléversé, nous pouvons vérifier le bon fonctionnement du programme en nous connectant à la carte via minicom :&lt;br /&gt;
&lt;br /&gt;
 root@raspberrypi:/dev$ minicom -D ttyACM0 -b 460800&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Communication VM-Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Envoie de donnée : ===&lt;br /&gt;
&lt;br /&gt;
Dans notre projet, nous avons besoin de remonter les données de notre capteur branché en liaison série à la Raspberry sur le port &amp;quot;ttyACM0&amp;quot;. Nous allons donc passer par des requêtes API entre le serveur sur chassiron et notre Raspberry.&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Raspberry : ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Du côté Raspberry, nous programmons un script en python qui lit sur la liaison série les valeurs du capteurs et les envoie via une requête POST vers le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import requests&lt;br /&gt;
     import json&lt;br /&gt;
     import serial&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;Variable&lt;br /&gt;
     STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
     baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
     Serial_link = serial.Serial(STM32_port,baudrate,timeout=1)&lt;br /&gt;
     print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
     liste_mesures=[]&lt;br /&gt;
     for i in range(101):&lt;br /&gt;
          print(&amp;quot;Mesure&amp;quot;,i)&lt;br /&gt;
          mesure = Serial_link.readline().decode('utf-8')&lt;br /&gt;
          liste_mesures.append(mesure)&lt;br /&gt;
&lt;br /&gt;
     data_to_send = json.dumps(liste_mesures)&lt;br /&gt;
     url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080&amp;quot;&lt;br /&gt;
&lt;br /&gt;
     headers = {&lt;br /&gt;
          'Content-type':'application/json',&lt;br /&gt;
          'Accept':'application/json'&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     r = requests.post(&lt;br /&gt;
          url_request,&lt;br /&gt;
          json=data_to_send,&lt;br /&gt;
          headers=headers&lt;br /&gt;
     )&lt;br /&gt;
     print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Serveur : ====&lt;br /&gt;
La communication entre notre VM et la Raspberry est possible. Nous arrivons à effectuer un ping de l'une sur l'autre en passant par l'addresse IPv6.&lt;br /&gt;
&lt;br /&gt;
IPv6 VM :  2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
IPv6 Raspberry : 2001:660:4401:6050:da3a:ddff:fe59:4cb5&lt;br /&gt;
&lt;br /&gt;
Nous programmons ensuite une API sur notre VM en utilisant la libraire Flask.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import json&lt;br /&gt;
     from flask import Flask&lt;br /&gt;
     from flask import request&lt;br /&gt;
     from waitress import serve&lt;br /&gt;
     from flask import Response&lt;br /&gt;
     from flask_cors import CORS&lt;br /&gt;
     from flask_cors import cross_origin&lt;br /&gt;
&lt;br /&gt;
     app = Flask(__name__)&lt;br /&gt;
     cors = CORS(app, ressourceas={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;:&amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
     def compute_data(data):&lt;br /&gt;
          filename = input(&amp;quot;Nom du fichier :&amp;quot;)&lt;br /&gt;
          to_write = data.split(&amp;quot;\&amp;quot;&amp;quot;)[1:-1]&lt;br /&gt;
          with open(filename, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
               i = 0&lt;br /&gt;
               for elem in to_write:&lt;br /&gt;
                    if i == 0:&lt;br /&gt;
                         print(&amp;quot;We skip&amp;quot;)&lt;br /&gt;
                    else:&lt;br /&gt;
                         if (i%2) == 0:&lt;br /&gt;
                              print(&amp;quot;Data writed :&amp;quot;,elem[:-4])&lt;br /&gt;
                              f.write(elem[:-4])&lt;br /&gt;
                              f.write(&amp;quot;\n&amp;quot;)&lt;br /&gt;
                    i = i + 1&lt;br /&gt;
&lt;br /&gt;
     #Main&lt;br /&gt;
     @app.route('/',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
     @cross_origin()&lt;br /&gt;
     def hello():&lt;br /&gt;
          data = request.json&lt;br /&gt;
          compute_data(data)&lt;br /&gt;
          return data&lt;br /&gt;
&lt;br /&gt;
     if __name__ == '__main__':&lt;br /&gt;
          print(&amp;quot;Listening&amp;quot;)&lt;br /&gt;
          serve(app,host=&amp;quot;::&amp;quot;,port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Implémentation de l'IA : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant qu'on a une communication pour envoyer un fichier à notre serveur depuis la raspberry grâce à notre API, nous la modifions pour que la Raspberry puisse lire la valeur du capteur à ultrason, l'envoyer à notre serveur et recevoir en réponse, la prédiction de l'IA. Nous créons donc une route '''''/predict''''' sur notre API qui récupère les valeurs du capteurs données en paramètre et renvoie la prédiction de l'IA :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 @app.route('/predict',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
 def predict():&lt;br /&gt;
      data = request.json&lt;br /&gt;
      print(data)&lt;br /&gt;
      features = data['Features']&lt;br /&gt;
      print(features)&lt;br /&gt;
      features_splitted = features[0].split(&amp;quot;,&amp;quot;)&lt;br /&gt;
      features_int = [int(elem) for elem in features_splitted]&lt;br /&gt;
      loaded_model = joblib.load('model_entraine.pkl')&lt;br /&gt;
      predictios = loaded_model.predict(np.array(features_int).reshape(1,-1))&lt;br /&gt;
      return jsonify(predictions.tolist())&lt;br /&gt;
&amp;lt;/pre&amp;gt;Nous envoyons ensuite les données à analyser via des requêtes API :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 #Import Librairies&lt;br /&gt;
 import requests&lt;br /&gt;
 import json&lt;br /&gt;
 import serial&lt;br /&gt;
 from flask import jsonify&lt;br /&gt;
&lt;br /&gt;
 #Variable&lt;br /&gt;
 STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
 baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
 Serial_link = serial.Serial(STM32_port, baudrate, timeout=1)&lt;br /&gt;
 print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
 tab_to_send = []&lt;br /&gt;
&lt;br /&gt;
 while True:&lt;br /&gt;
      Serial_link.readline().decode('utf-8')&lt;br /&gt;
      tab_to_send.append(Serial_link.readline().decode('utf-8')&lt;br /&gt;
      if (tab_to_send != [&amp;quot;&amp;quot;]):&lt;br /&gt;
           print(&amp;quot;Data sended :&amp;quot;,tab_to_send)&lt;br /&gt;
           url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080/predict&amp;quot;&lt;br /&gt;
           headers = {&lt;br /&gt;
                'Content-type':'application/json',&lt;br /&gt;
                'Accept':'application/json'&lt;br /&gt;
           }&lt;br /&gt;
           r = requests.post(&lt;br /&gt;
                url_request,&lt;br /&gt;
                json = {&lt;br /&gt;
                     &amp;quot;Features&amp;quot;: tab_to_send&lt;br /&gt;
                },&lt;br /&gt;
                headers=headers&lt;br /&gt;
           )&lt;br /&gt;
           print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
           print(&amp;quot;Response :&amp;quot;,r.json())&lt;br /&gt;
      else:&lt;br /&gt;
           print(&amp;quot;Data skip:&amp;quot;,tab_to_send)&lt;br /&gt;
      tab_to_send.clear()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Entrainement de l'IA &amp;lt;/div&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec NanoEdge AI Studio : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour le projet, nous avons d'abord développé et entrainé notre IA sur la plateforme NanoEdge AI Studio. Pour ce faire, nous devons d'abord définir un projet de classification de n-class (&amp;quot;pierre&amp;quot;,&amp;quot;feuille&amp;quot;,&amp;quot;ciseau&amp;quot;) en utilisant un capteur générique à 16 axes. Pour ce faire, nous modifions le code de la STM32 pour qu'elle renvoie une ligne contenant 16*16 mesure en continue. Une fois le projet créé, nous ajoutons 3 signaux correspondant à nos dataset de &amp;quot;Pierre&amp;quot;, &amp;quot;Feuille&amp;quot; et &amp;quot;Ciseau&amp;quot;. Pour rajouter des valeurs dans notre dataset, nous utilisons la liaison série pour lire les valeurs de notre capteur.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec Scikit : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour la suite de notre projet, nous avons developpé et entrainé une IA avec Scikit.&lt;br /&gt;
&lt;br /&gt;
==== Construction du fichier d'entrainement ====&lt;br /&gt;
Pour commencer, nous avons du construire un fichier csv reprenant nos mesures sur un format de 16 valeurs. Pour chaque mesure, on ajoute en amont de la mesure la catégorie (feuille, ciseau ou pierre). &lt;br /&gt;
[[Fichier:Capture d’écran 2024-01-18 à 16.18.19.png|centré|vignette|500x500px|Fichier chifoumIA.csv]]&lt;br /&gt;
Pour construire ce fichier, nous avons assemblé trois fichiers csv de test que nous avons généré grâce à notre capteur : un fichier d'entrainement Pierre.csv, un fichier d'entrainement Ciseau.csv et un fichier d'entrainement Feuille.csv . &lt;br /&gt;
&lt;br /&gt;
Pour faire cette concaténation nous avons développer un programme python prenant en entrée nos fichiers d'entrainement et fournissant en sortie le fichier csv chifoumIA.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     line_feuille = []&lt;br /&gt;
     line_pierre = []&lt;br /&gt;
     line_ciseau = []&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Feuille.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_feuille = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Pierre.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_pierre = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Ciseau.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_ciseau = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;chifoumIA.csv&amp;quot;,&amp;quot;w&amp;quot;) as f:&lt;br /&gt;
          for elem in line_feuille:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;feuille,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_pierre:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;pierre,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_ciseau:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;ciseau,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Implémentation et Entrainement de notre IA ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant que nous avons notre fichier d'entrainement, nous implémentons notre IA. &lt;br /&gt;
&lt;br /&gt;
Nous avons commencé par créer un tableau de données et un tableau de classes. &lt;br /&gt;
&lt;br /&gt;
Pour remplir ces tableaux, on va lire ligne par ligne le fichier chifoumIA.csv. Le premier élément de la ligne est stockée dans le tableau de classes et le reste de la ligne est stockée dans le tableau de données. &lt;br /&gt;
 chifoumi_data=[]&lt;br /&gt;
 chifoumi_classe=[]&lt;br /&gt;
 &lt;br /&gt;
 with open('chifoumIA.csv') as csv_file:&lt;br /&gt;
        csv_reader = csv.reader(csv_file,delimiter=',')&lt;br /&gt;
        for row in csv_reader:           &lt;br /&gt;
                 chifoumi_data.append([int(row[1]),int(row[2]),int(row[3]),int(row[4]),int(row[5]),int(row[6]),int(row[7]),int(row[8]),&lt;br /&gt;
                                       int(row[9]),int(row[10]),int(row[11]),int(row[12]),int(row[13]),int(row[14]),int(row[15]),int(row[16])])&lt;br /&gt;
                 chifoumi_classe.append(row[0])&lt;br /&gt;
  &lt;br /&gt;
A partir de ces deux tableaux, on construit un ensemble de données d'entraînement et un ensemble de données de tests.&lt;br /&gt;
&lt;br /&gt;
On choisi d'utiliser un réseau de neurone du type MLPClassifer. &lt;br /&gt;
&lt;br /&gt;
Le MLPClassifer est un type de réseau de neurones artificiels composés d'au minimum trois couches de neurones: une couche d'entrée, une ou plusieurs  couches cachées et une couche de sortie. &lt;br /&gt;
&lt;br /&gt;
Dans ce type de réseau, chaque neurone est connecté à l'ensemble des neurones de la couche suivante par un lien auquel est associé un poids. &lt;br /&gt;
&lt;br /&gt;
La classe MLPClassifer implémentée dans la bibliothèque Scikit-Learn dispose de nombreux paramètres. Pour notre projet, nous avons utilisé cette classe de façon très primaire. Les paramètres que nous avons utilisés sont :  &lt;br /&gt;
&lt;br /&gt;
- '''hidden_layer_sizes :''' ce paramètre est un tuple spécifiant le nombre de neurones dans chaque couche cachée. &lt;br /&gt;
&lt;br /&gt;
- '''max_iter :''' ce paramètre représente le nombre maximal d'époque. Il permet de contrôler également le temps d'entrainement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model=MLPClassifier(hidden_layer_sizes=(50,25),max_iter=100,solver='adam')&lt;br /&gt;
&lt;br /&gt;
model.fit(X_train,y_train)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;predictions = model.predict(X_test)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;print(f'Accuracy:{accuracy}')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Déploiement de notre IA ====&lt;br /&gt;
Pour pouvoir déployer notre IA, nous avons enregistré notre model d'entrainement et intégré un service web à notre code existant avec deux endpoint : &lt;br /&gt;
&lt;br /&gt;
- predict : pour effectuer des prédictions sur le model. &lt;br /&gt;
&lt;br /&gt;
- evaluate : pour évaluer les performances du model sur l'ensemble de tests.&lt;br /&gt;
&lt;br /&gt;
Malheureusement nous n'avons pas eu le temps d'entrainer suffisamment cette IA. Ces performances sont donc très faible un peu moins de 50% de fiabilité.&lt;br /&gt;
&lt;br /&gt;
==== Code complet ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import joblib&lt;br /&gt;
import pandas as pd &lt;br /&gt;
import csv&lt;br /&gt;
from flask import Flask, request,jsonify&lt;br /&gt;
from sklearn.model_selection import train_test_split&lt;br /&gt;
from sklearn.ensemble import RandomForestClassifier&lt;br /&gt;
from sklearn.metrics import accuracy_score,precision_score,recall_score,f1_score&lt;br /&gt;
from sklearn.neural_network import MLPClassifier&lt;br /&gt;
from waitress import serve&lt;br /&gt;
from flask import Response&lt;br /&gt;
from flask_cors import CORS&lt;br /&gt;
from flask_cors import cross_origin&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
chifoumi_data=[]&lt;br /&gt;
chifoumi_classe=[]&lt;br /&gt;
&lt;br /&gt;
with open('chifoumIA.csv') as csv_file:&lt;br /&gt;
	csv_reader = csv.reader(csv_file,delimiter=',')&lt;br /&gt;
	for row in csv_reader:&lt;br /&gt;
		chifoumi_data.append([int(row[1]),int(row[2]),int(row[3]),int(row[4]),int(row[5]),int(row[6]),int(row[7]),int(row[8]),int(row[9]),int(row[10]),int(row[11]),int(row[12]),int(row[13]),int(row[14]),int(row[15]),int(row[16])])&lt;br /&gt;
		chifoumi_classe.append(row[0])&lt;br /&gt;
&lt;br /&gt;
X_train,X_test,y_train,y_test= train_test_split(chifoumi_data,chifoumi_classe,test_size=0.2,random_state=42)&lt;br /&gt;
&lt;br /&gt;
model=MLPClassifier(hidden_layer_sizes=(50,25),max_iter=100,solver='adam')&lt;br /&gt;
model.fit(X_train,y_train)&lt;br /&gt;
#predictions = model.predict(X_test)&lt;br /&gt;
#accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
#print(f'Accuracy:{accuracy}')&lt;br /&gt;
&lt;br /&gt;
joblib.dump(model,'model_entraine.pkl')&lt;br /&gt;
&lt;br /&gt;
app = Flask(__name__)&lt;br /&gt;
cors = CORS(app,ressources={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;: &amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#Main&lt;br /&gt;
@app.route('/predict',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
#@cross_origin()&lt;br /&gt;
def predict():&lt;br /&gt;
	data = request.json&lt;br /&gt;
	print(data)&lt;br /&gt;
	features = data['Features']&lt;br /&gt;
	print(features)&lt;br /&gt;
	features_splitted = features[0].split(&amp;quot;,&amp;quot;)&lt;br /&gt;
	features_int = [int(elem) for elem in features_splitted]&lt;br /&gt;
	loaded_model=joblib.load('model_entraine.pkl')&lt;br /&gt;
	predictions = loaded_model.predict(np.array(features_int).reshape(1,-1))&lt;br /&gt;
	return jsonify(predictions.tolist())&lt;br /&gt;
&lt;br /&gt;
@app.route('/evaluate',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
def evaluate():&lt;br /&gt;
	loaded_model = joblib.load('model_entraine.pkl')&lt;br /&gt;
	predictions = loaded_model.predict(X_test)&lt;br /&gt;
	accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
	precision = precision_score(y_test,predictions)&lt;br /&gt;
	recall = recall_score(y_test,predictions)&lt;br /&gt;
	f1=f1_score(y_test,predictions)&lt;br /&gt;
	&lt;br /&gt;
	return jsonify({ 'Accuracy': accuracy,'Precision': precision,'Recall': recall,'F1 Score':f1})&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
	print(&amp;quot;listening&amp;quot;)&lt;br /&gt;
	serve(app,host=&amp;quot;::&amp;quot;, port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4754</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4754"/>
		<updated>2024-01-28T13:33:15Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /* Entrainement avec Scikit : */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Introduction Projet IE Delannoy - Lemaire &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadre la matière '''&amp;quot;Intelligence Embarquée&amp;quot;''' de l'UE &amp;quot;Module de Spécialité&amp;quot; des SE5 - Option Systèmes Communicants, nous avons dû concevoir un projet permettant de '''distribuer le calcul et le processus d'entrainement''' et d'utilisation d'un Intelligence Artificielle. Nous devrons distribuer le calcul à différents endroits du réseau afin d'être en mesure de proposer des pistes d'optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, nous allons mettre en oeuvre un réseau d'objets connectés à des passerelles et à un serveur. '''Les objets collecteront des données''' de l'environnemet et suivants les scénarios, traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Nous aurons à disposition :&lt;br /&gt;
&lt;br /&gt;
* Une machine virtuelle sur le serveur '''Chassiron''' en ''E304/306''&lt;br /&gt;
* Une '''Raspberry PI 4'''&lt;br /&gt;
* Un carte programmable '''STM32F401RE'''&lt;br /&gt;
* Un capteur à ultrason '''Nucleo-53L5A1'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ce wiki est le compte-rendu du projet de '''Jason DELANNOY et Chloé LEMAIRE'''. Nous avons décider de développer une intelligence artificielle permettant de '''déterminer''' '''l'action faite par un joueur de Pierre-Feuille-Ciseau''' à l'aide du capteur à ultrason.&lt;br /&gt;
&lt;br /&gt;
Pour ce faire, nous allons développer notre IA de deux façons :&lt;br /&gt;
&lt;br /&gt;
* En utilisant '''NanoEdge Studio''' : Dans ce cas, le calcul serait fait par la carte programmable et envoyé au serveur via la Raspberry&lt;br /&gt;
* En utilisant '''un algorithme de machine learning ''': Ici, c'est le serveur qui fera le calcul et la Raspberry jouera le rôle de passerelle entre la carte programmable et le serveu&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Mise en oeuvre du réseau &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Création VM XEN ===&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]Notre VM est accessible en ssh à partir de son IPv6 : 2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la VM ===&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la borne WIFI Cisco ===&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251 (changement car besoin pour les PEIP) &lt;br /&gt;
&lt;br /&gt;
- dns-server: 193.48.57.33 (changement car problème avec le serveur DNS initial)&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Configuration de la Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadra du projet, nous avons à disposition une Raspberry PI 4 model B que nous allons configurer. Pour ce faire, nous utilisons le logiciel le &amp;quot;Raspberry PI Imager&amp;quot; pour choisir notre OS.&lt;br /&gt;
[[Fichier:JCIE RPI Imager.png|centré|vignette|400x400px]]Maintenant que nous avons une carte SD prête pour la Raspberry, nous la configurons via sa liaison série en passant par minicom :&lt;br /&gt;
 root@zabeth18: / $ minicom -D /dev/ttyACM0 -b 9600&lt;br /&gt;
De plus, nous modifions le fichier /etc/network/interfaces pour pouvoir connecter notre carte au réseau wifi créé plus haut :&lt;br /&gt;
[[Fichier:Screen WiFi.png|centré|vignette|441x441px]]&lt;br /&gt;
Nous verifions ensuite que nous avons une adresse IP :&lt;br /&gt;
[[Fichier:Screenshot from 2023-12-04 17-17-05.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Capteur NUCLEO - 53L5A1 &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Pour ce projet, nous disposons d'une STM32 Nucléo F401RE muni d'un capteur à ultrason X-Nucleo-53L5A1.&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir entrainer notre IA, nous devons faire en sorte d'afficher et de ressortir sur la liaison série les données du capteur. Pour ce faire, nous utilisons le fichier example &amp;quot;'''''53L5A1_ThresholdDetection'''''&amp;quot;. Nous modifions la fonction print_result pour afficher 16 valeurs à la suite :&lt;br /&gt;
[[Fichier:ChifoumIA Print Result.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Après avoir téléversé, nous pouvons vérifier le bon fonctionnement du programme en nous connectant à la carte via minicom :&lt;br /&gt;
&lt;br /&gt;
 root@raspberrypi:/dev$ minicom -D ttyACM0 -b 460800&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Communication VM-Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Envoie de donnée : ===&lt;br /&gt;
&lt;br /&gt;
Dans notre projet, nous avons besoin de remonter les données de notre capteur branché en liaison série à la Raspberry sur le port &amp;quot;ttyACM0&amp;quot;. Nous allons donc passer par des requêtes API entre le serveur sur chassiron et notre Raspberry.&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Raspberry : ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Du côté Raspberry, nous programmons un script en python qui lit sur la liaison série les valeurs du capteurs et les envoie via une requête POST vers le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import requests&lt;br /&gt;
     import json&lt;br /&gt;
     import serial&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;Variable&lt;br /&gt;
     STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
     baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
     Serial_link = serial.Serial(STM32_port,baudrate,timeout=1)&lt;br /&gt;
     print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
     liste_mesures=[]&lt;br /&gt;
     for i in range(101):&lt;br /&gt;
          print(&amp;quot;Mesure&amp;quot;,i)&lt;br /&gt;
          mesure = Serial_link.readline().decode('utf-8')&lt;br /&gt;
          liste_mesures.append(mesure)&lt;br /&gt;
&lt;br /&gt;
     data_to_send = json.dumps(liste_mesures)&lt;br /&gt;
     url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080&amp;quot;&lt;br /&gt;
&lt;br /&gt;
     headers = {&lt;br /&gt;
          'Content-type':'application/json',&lt;br /&gt;
          'Accept':'application/json'&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     r = requests.post(&lt;br /&gt;
          url_request,&lt;br /&gt;
          json=data_to_send,&lt;br /&gt;
          headers=headers&lt;br /&gt;
     )&lt;br /&gt;
     print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Serveur : ====&lt;br /&gt;
La communication entre notre VM et la Raspberry est possible. Nous arrivons à effectuer un ping de l'une sur l'autre en passant par l'addresse IPv6.&lt;br /&gt;
&lt;br /&gt;
IPv6 VM :  2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
IPv6 Raspberry : 2001:660:4401:6050:da3a:ddff:fe59:4cb5&lt;br /&gt;
&lt;br /&gt;
Nous programmons ensuite une API sur notre VM en utilisant la libraire Flask.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import json&lt;br /&gt;
     from flask import Flask&lt;br /&gt;
     from flask import request&lt;br /&gt;
     from waitress import serve&lt;br /&gt;
     from flask import Response&lt;br /&gt;
     from flask_cors import CORS&lt;br /&gt;
     from flask_cors import cross_origin&lt;br /&gt;
&lt;br /&gt;
     app = Flask(__name__)&lt;br /&gt;
     cors = CORS(app, ressourceas={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;:&amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
     def compute_data(data):&lt;br /&gt;
          filename = input(&amp;quot;Nom du fichier :&amp;quot;)&lt;br /&gt;
          to_write = data.split(&amp;quot;\&amp;quot;&amp;quot;)[1:-1]&lt;br /&gt;
          with open(filename, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
               i = 0&lt;br /&gt;
               for elem in to_write:&lt;br /&gt;
                    if i == 0:&lt;br /&gt;
                         print(&amp;quot;We skip&amp;quot;)&lt;br /&gt;
                    else:&lt;br /&gt;
                         if (i%2) == 0:&lt;br /&gt;
                              print(&amp;quot;Data writed :&amp;quot;,elem[:-4])&lt;br /&gt;
                              f.write(elem[:-4])&lt;br /&gt;
                              f.write(&amp;quot;\n&amp;quot;)&lt;br /&gt;
                    i = i + 1&lt;br /&gt;
&lt;br /&gt;
     #Main&lt;br /&gt;
     @app.route('/',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
     @cross_origin()&lt;br /&gt;
     def hello():&lt;br /&gt;
          data = request.json&lt;br /&gt;
          compute_data(data)&lt;br /&gt;
          return data&lt;br /&gt;
&lt;br /&gt;
     if __name__ == '__main__':&lt;br /&gt;
          print(&amp;quot;Listening&amp;quot;)&lt;br /&gt;
          serve(app,host=&amp;quot;::&amp;quot;,port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Implémentation de l'IA : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant qu'on a une communication pour envoyer un fichier à notre serveur depuis la raspberry grâce à notre API, nous la modifions pour que la Raspberry puisse lire la valeur du capteur à ultrason, l'envoyer à notre serveur et recevoir en réponse, la prédiction de l'IA. Nous créons donc une route '''''/predict''''' sur notre API qui récupère les valeurs du capteurs données en paramètre et renvoie la prédiction de l'IA :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 @app.route('/predict',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
 def predict():&lt;br /&gt;
      data = request.json&lt;br /&gt;
      print(data)&lt;br /&gt;
      features = data['Features']&lt;br /&gt;
      print(features)&lt;br /&gt;
      features_splitted = features[0].split(&amp;quot;,&amp;quot;)&lt;br /&gt;
      features_int = [int(elem) for elem in features_splitted]&lt;br /&gt;
      loaded_model = joblib.load('model_entraine.pkl')&lt;br /&gt;
      predictios = loaded_model.predict(np.array(features_int).reshape(1,-1))&lt;br /&gt;
      return jsonify(predictions.tolist())&lt;br /&gt;
&amp;lt;/pre&amp;gt;Nous envoyons ensuite les données à analyser via des requêtes API :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 #Import Librairies&lt;br /&gt;
 import requests&lt;br /&gt;
 import json&lt;br /&gt;
 import serial&lt;br /&gt;
 from flask import jsonify&lt;br /&gt;
&lt;br /&gt;
 #Variable&lt;br /&gt;
 STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
 baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
 Serial_link = serial.Serial(STM32_port, baudrate, timeout=1)&lt;br /&gt;
 print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
 tab_to_send = []&lt;br /&gt;
&lt;br /&gt;
 while True:&lt;br /&gt;
      Serial_link.readline().decode('utf-8')&lt;br /&gt;
      tab_to_send.append(Serial_link.readline().decode('utf-8')&lt;br /&gt;
      if (tab_to_send != [&amp;quot;&amp;quot;]):&lt;br /&gt;
           print(&amp;quot;Data sended :&amp;quot;,tab_to_send)&lt;br /&gt;
           url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080/predict&amp;quot;&lt;br /&gt;
           headers = {&lt;br /&gt;
                'Content-type':'application/json',&lt;br /&gt;
                'Accept':'application/json'&lt;br /&gt;
           }&lt;br /&gt;
           r = requests.post(&lt;br /&gt;
                url_request,&lt;br /&gt;
                json = {&lt;br /&gt;
                     &amp;quot;Features&amp;quot;: tab_to_send&lt;br /&gt;
                },&lt;br /&gt;
                headers=headers&lt;br /&gt;
           )&lt;br /&gt;
           print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
           print(&amp;quot;Response :&amp;quot;,r.json())&lt;br /&gt;
      else:&lt;br /&gt;
           print(&amp;quot;Data skip:&amp;quot;,tab_to_send)&lt;br /&gt;
      tab_to_send.clear()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Entrainement de l'IA &amp;lt;/div&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec NanoEdge AI Studio : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour le projet, nous avons d'abord développé et entrainé notre IA sur la plateforme NanoEdge AI Studio. Pour ce faire, nous devons d'abord définir un projet de classification de n-class (&amp;quot;pierre&amp;quot;,&amp;quot;feuille&amp;quot;,&amp;quot;ciseau&amp;quot;) en utilisant un capteur générique à 16 axes. Pour ce faire, nous modifions le code de la STM32 pour qu'elle renvoie une ligne contenant 16*16 mesure en continue. Une fois le projet créé, nous ajoutons 3 signaux correspondant à nos dataset de &amp;quot;Pierre&amp;quot;, &amp;quot;Feuille&amp;quot; et &amp;quot;Ciseau&amp;quot;. Pour rajouter des valeurs dans notre dataset, nous utilisons la liaison série pour lire les valeurs de notre capteur.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec Scikit : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour la suite de notre projet, nous avons developpé et entrainé une IA avec Scikit.&lt;br /&gt;
&lt;br /&gt;
==== Construction du fichier d'entrainement ====&lt;br /&gt;
Pour commencer, nous avons du construire un fichier csv reprenant nos mesures sur un format de 16 valeurs. Pour chaque mesure, on ajoute en amont de la mesure la catégorie (feuille, ciseau ou pierre). &lt;br /&gt;
[[Fichier:Capture d’écran 2024-01-18 à 16.18.19.png|centré|vignette|500x500px|Fichier chifoumIA.csv]]&lt;br /&gt;
Pour construire ce fichier, nous avons assemblé trois fichiers csv de test que nous avons généré grâce à notre capteur : un fichier d'entrainement Pierre.csv, un fichier d'entrainement Ciseau.csv et un fichier d'entrainement Feuille.csv . &lt;br /&gt;
&lt;br /&gt;
Pour faire cette concaténation nous avons développer un programme python prenant en entrée nos fichiers d'entrainement et fournissant en sortie le fichier csv chifoumIA.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     line_feuille = []&lt;br /&gt;
     line_pierre = []&lt;br /&gt;
     line_ciseau = []&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Feuille.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_feuille = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Pierre.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_pierre = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Ciseau.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_ciseau = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;chifoumIA.csv&amp;quot;,&amp;quot;w&amp;quot;) as f:&lt;br /&gt;
          for elem in line_feuille:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;feuille,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_pierre:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;pierre,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_ciseau:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;ciseau,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Implémentation et Entrainement de notre IA ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant que nous avons notre fichier d'entrainement, nous implémentons notre IA. &lt;br /&gt;
&lt;br /&gt;
Nous avons commencé par créer un tableau de données et un tableau de classes. &lt;br /&gt;
&lt;br /&gt;
Pour remplir ces tableaux, on va lire ligne par ligne le fichier chifoumIA.csv. Le premier élément de la ligne est stockée dans le tableau de classes et le reste de la ligne est stockée dans le tableau de données. &lt;br /&gt;
 chifoumi_data=[]&lt;br /&gt;
 chifoumi_classe=[]&lt;br /&gt;
 &lt;br /&gt;
 with open('chifoumIA.csv') as csv_file:&lt;br /&gt;
        csv_reader = csv.reader(csv_file,delimiter=',')&lt;br /&gt;
        for row in csv_reader:           &lt;br /&gt;
                 chifoumi_data.append([int(row[1]),int(row[2]),int(row[3]),int(row[4]),int(row[5]),int(row[6]),int(row[7]),int(row[8]),&lt;br /&gt;
                                       int(row[9]),int(row[10]),int(row[11]),int(row[12]),int(row[13]),int(row[14]),int(row[15]),int(row[16])])&lt;br /&gt;
                 chifoumi_classe.append(row[0])&lt;br /&gt;
  &lt;br /&gt;
A partir de ces deux tableaux, on construit un ensemble de données d'entraînement et un ensemble de données de tests.&lt;br /&gt;
&lt;br /&gt;
On choisi d'utiliser un réseau de neurone du type MLPClassifer. &lt;br /&gt;
&lt;br /&gt;
Le MLPClassifer est un type de réseau de neurones artificiels composés d'au minimum trois couches de neurones: une couche d'entrée, une ou plusieurs  couches cachées et une couche de sortie. &lt;br /&gt;
&lt;br /&gt;
Dans ce type de réseau, chaque neurone est connecté à l'ensemble des neurones de la couche suivante par un lien auquel est associé un poids. &lt;br /&gt;
&lt;br /&gt;
La classe MLPClassifer implémentée dans la bibliothèque Scikit-Learn dispose de nombreux paramètres. Pour notre projet, nous avons utilisé cette classe de façon très primaire. Les paramètres que nous avons utilisés sont :  &lt;br /&gt;
&lt;br /&gt;
- '''hidden_layer_sizes :''' ce paramètre est un tuple spécifiant le nombre de neurones dans chaque couche cachée. &lt;br /&gt;
&lt;br /&gt;
- '''max_iter :''' ce paramètre représente le nombre maximal d'époque. Il permet de contrôler également le temps d'entrainement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model=MLPClassifier(hidden_layer_sizes=(50,25),max_iter=100,solver='adam')&lt;br /&gt;
&lt;br /&gt;
model.fit(X_train,y_train)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;predictions = model.predict(X_test)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;print(f'Accuracy:{accuracy}')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Déploiement de notre IA ====&lt;br /&gt;
Pour pouvoir déployer notre IA, nous avons enregistré notre model d'entrainement et intégré un service web à notre code existant avec deux endpoint : &lt;br /&gt;
&lt;br /&gt;
- predict : pour effectuer des prédictions sur le model. &lt;br /&gt;
&lt;br /&gt;
- evaluate : pour évaluer les performances du model sur l'ensemble de tests.&lt;br /&gt;
&lt;br /&gt;
Malheureusement nous n'avons pas eu le temps d'entrainer suffisamment cette IA. Ces performances sont donc très faible un peu moins de 50% de fiabilité.&lt;br /&gt;
&lt;br /&gt;
==== Code complet ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import joblib&lt;br /&gt;
import pandas as pd &lt;br /&gt;
import csv&lt;br /&gt;
from flask import Flask, request,jsonify&lt;br /&gt;
from sklearn.model_selection import train_test_split&lt;br /&gt;
from sklearn.ensemble import RandomForestClassifier&lt;br /&gt;
from sklearn.metrics import accuracy_score,precision_score,recall_score,f1_score&lt;br /&gt;
from sklearn.neural_network import MLPClassifier&lt;br /&gt;
from waitress import serve&lt;br /&gt;
from flask import Response&lt;br /&gt;
from flask_cors import CORS&lt;br /&gt;
from flask_cors import cross_origin&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
chifoumi_data=[]&lt;br /&gt;
chifoumi_classe=[]&lt;br /&gt;
&lt;br /&gt;
with open('chifoumIA.csv') as csv_file:&lt;br /&gt;
	csv_reader = csv.reader(csv_file,delimiter=',')&lt;br /&gt;
	for row in csv_reader:&lt;br /&gt;
		chifoumi_data.append([int(row[1]),int(row[2]),int(row[3]),int(row[4]),int(row[5]),int(row[6]),int(row[7]),int(row[8]),int(row[9]),int(row[10]),int(row[11]),int(row[12]),int(row[13]),int(row[14]),int(row[15]),int(row[16])])&lt;br /&gt;
		chifoumi_classe.append(row[0])&lt;br /&gt;
&lt;br /&gt;
X_train,X_test,y_train,y_test= train_test_split(chifoumi_data,chifoumi_classe,test_size=0.2,random_state=42)&lt;br /&gt;
&lt;br /&gt;
model=MLPClassifier(hidden_layer_sizes=(50,25),max_iter=100,solver='adam')&lt;br /&gt;
model.fit(X_train,y_train)&lt;br /&gt;
#predictions = model.predict(X_test)&lt;br /&gt;
#accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
#print(f'Accuracy:{accuracy}')&lt;br /&gt;
&lt;br /&gt;
joblib.dump(model,'model_entraine.pkl')&lt;br /&gt;
&lt;br /&gt;
app = Flask(__name__)&lt;br /&gt;
cors = CORS(app,ressources={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;: &amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#Main&lt;br /&gt;
@app.route('/predict',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
#@cross_origin()&lt;br /&gt;
def predict():&lt;br /&gt;
	data = request.json&lt;br /&gt;
	print(data)&lt;br /&gt;
	features = data['Features']&lt;br /&gt;
	print(features)&lt;br /&gt;
	features_splitted = features[0].split(&amp;quot;,&amp;quot;)&lt;br /&gt;
	features_int = [int(elem) for elem in features_splitted]&lt;br /&gt;
	loaded_model=joblib.load('model_entraine.pkl')&lt;br /&gt;
	predictions = loaded_model.predict(np.array(features_int).reshape(1,-1))&lt;br /&gt;
	return jsonify(predictions.tolist())&lt;br /&gt;
&lt;br /&gt;
@app.route('/evaluate',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
def evaluate():&lt;br /&gt;
	loaded_model = joblib.load('model_entraine.pkl')&lt;br /&gt;
	predictions = loaded_model.predict(X_test)&lt;br /&gt;
	accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
	precision = precision_score(y_test,predictions)&lt;br /&gt;
	recall = recall_score(y_test,predictions)&lt;br /&gt;
	f1=f1_score(y_test,predictions)&lt;br /&gt;
	&lt;br /&gt;
	return jsonify({ 'Accuracy': accuracy,'Precision': precision,'Recall': recall,'F1 Score':f1})&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
	print(&amp;quot;listening&amp;quot;)&lt;br /&gt;
	serve(app,host=&amp;quot;::&amp;quot;, port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4753</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4753"/>
		<updated>2024-01-28T13:26:53Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /* Création VM XEN */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Introduction Projet IE Delannoy - Lemaire &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadre la matière '''&amp;quot;Intelligence Embarquée&amp;quot;''' de l'UE &amp;quot;Module de Spécialité&amp;quot; des SE5 - Option Systèmes Communicants, nous avons dû concevoir un projet permettant de '''distribuer le calcul et le processus d'entrainement''' et d'utilisation d'un Intelligence Artificielle. Nous devrons distribuer le calcul à différents endroits du réseau afin d'être en mesure de proposer des pistes d'optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, nous allons mettre en oeuvre un réseau d'objets connectés à des passerelles et à un serveur. '''Les objets collecteront des données''' de l'environnemet et suivants les scénarios, traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Nous aurons à disposition :&lt;br /&gt;
&lt;br /&gt;
* Une machine virtuelle sur le serveur '''Chassiron''' en ''E304/306''&lt;br /&gt;
* Une '''Raspberry PI 4'''&lt;br /&gt;
* Un carte programmable '''STM32F401RE'''&lt;br /&gt;
* Un capteur à ultrason '''Nucleo-53L5A1'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ce wiki est le compte-rendu du projet de '''Jason DELANNOY et Chloé LEMAIRE'''. Nous avons décider de développer une intelligence artificielle permettant de '''déterminer''' '''l'action faite par un joueur de Pierre-Feuille-Ciseau''' à l'aide du capteur à ultrason.&lt;br /&gt;
&lt;br /&gt;
Pour ce faire, nous allons développer notre IA de deux façons :&lt;br /&gt;
&lt;br /&gt;
* En utilisant '''NanoEdge Studio''' : Dans ce cas, le calcul serait fait par la carte programmable et envoyé au serveur via la Raspberry&lt;br /&gt;
* En utilisant '''un algorithme de machine learning ''': Ici, c'est le serveur qui fera le calcul et la Raspberry jouera le rôle de passerelle entre la carte programmable et le serveu&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Mise en oeuvre du réseau &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Création VM XEN ===&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]Notre VM est accessible en ssh à partir de son IPv6 : 2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la VM ===&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la borne WIFI Cisco ===&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251 (changement car besoin pour les PEIP) &lt;br /&gt;
&lt;br /&gt;
- dns-server: 193.48.57.33 (changement car problème avec le serveur DNS initial)&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Configuration de la Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadra du projet, nous avons à disposition une Raspberry PI 4 model B que nous allons configurer. Pour ce faire, nous utilisons le logiciel le &amp;quot;Raspberry PI Imager&amp;quot; pour choisir notre OS.&lt;br /&gt;
[[Fichier:JCIE RPI Imager.png|centré|vignette|400x400px]]Maintenant que nous avons une carte SD prête pour la Raspberry, nous la configurons via sa liaison série en passant par minicom :&lt;br /&gt;
 root@zabeth18: / $ minicom -D /dev/ttyACM0 -b 9600&lt;br /&gt;
De plus, nous modifions le fichier /etc/network/interfaces pour pouvoir connecter notre carte au réseau wifi créé plus haut :&lt;br /&gt;
[[Fichier:Screen WiFi.png|centré|vignette|441x441px]]&lt;br /&gt;
Nous verifions ensuite que nous avons une adresse IP :&lt;br /&gt;
[[Fichier:Screenshot from 2023-12-04 17-17-05.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Capteur NUCLEO - 53L5A1 &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Pour ce projet, nous disposons d'une STM32 Nucléo F401RE muni d'un capteur à ultrason X-Nucleo-53L5A1.&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir entrainer notre IA, nous devons faire en sorte d'afficher et de ressortir sur la liaison série les données du capteur. Pour ce faire, nous utilisons le fichier example &amp;quot;'''''53L5A1_ThresholdDetection'''''&amp;quot;. Nous modifions la fonction print_result pour afficher 16 valeurs à la suite :&lt;br /&gt;
[[Fichier:ChifoumIA Print Result.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Après avoir téléversé, nous pouvons vérifier le bon fonctionnement du programme en nous connectant à la carte via minicom :&lt;br /&gt;
&lt;br /&gt;
 root@raspberrypi:/dev$ minicom -D ttyACM0 -b 460800&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Communication VM-Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Envoie de donnée : ===&lt;br /&gt;
&lt;br /&gt;
Dans notre projet, nous avons besoin de remonter les données de notre capteur branché en liaison série à la Raspberry sur le port &amp;quot;ttyACM0&amp;quot;. Nous allons donc passer par des requêtes API entre le serveur sur chassiron et notre Raspberry.&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Raspberry : ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Du côté Raspberry, nous programmons un script en python qui lit sur la liaison série les valeurs du capteurs et les envoie via une requête POST vers le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import requests&lt;br /&gt;
     import json&lt;br /&gt;
     import serial&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;Variable&lt;br /&gt;
     STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
     baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
     Serial_link = serial.Serial(STM32_port,baudrate,timeout=1)&lt;br /&gt;
     print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
     liste_mesures=[]&lt;br /&gt;
     for i in range(101):&lt;br /&gt;
          print(&amp;quot;Mesure&amp;quot;,i)&lt;br /&gt;
          mesure = Serial_link.readline().decode('utf-8')&lt;br /&gt;
          liste_mesures.append(mesure)&lt;br /&gt;
&lt;br /&gt;
     data_to_send = json.dumps(liste_mesures)&lt;br /&gt;
     url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080&amp;quot;&lt;br /&gt;
&lt;br /&gt;
     headers = {&lt;br /&gt;
          'Content-type':'application/json',&lt;br /&gt;
          'Accept':'application/json'&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     r = requests.post(&lt;br /&gt;
          url_request,&lt;br /&gt;
          json=data_to_send,&lt;br /&gt;
          headers=headers&lt;br /&gt;
     )&lt;br /&gt;
     print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Serveur : ====&lt;br /&gt;
La communication entre notre VM et la Raspberry est possible. Nous arrivons à effectuer un ping de l'une sur l'autre en passant par l'addresse IPv6.&lt;br /&gt;
&lt;br /&gt;
IPv6 VM :  2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
IPv6 Raspberry : 2001:660:4401:6050:da3a:ddff:fe59:4cb5&lt;br /&gt;
&lt;br /&gt;
Nous programmons ensuite une API sur notre VM en utilisant la libraire Flask.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import json&lt;br /&gt;
     from flask import Flask&lt;br /&gt;
     from flask import request&lt;br /&gt;
     from waitress import serve&lt;br /&gt;
     from flask import Response&lt;br /&gt;
     from flask_cors import CORS&lt;br /&gt;
     from flask_cors import cross_origin&lt;br /&gt;
&lt;br /&gt;
     app = Flask(__name__)&lt;br /&gt;
     cors = CORS(app, ressourceas={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;:&amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
     def compute_data(data):&lt;br /&gt;
          filename = input(&amp;quot;Nom du fichier :&amp;quot;)&lt;br /&gt;
          to_write = data.split(&amp;quot;\&amp;quot;&amp;quot;)[1:-1]&lt;br /&gt;
          with open(filename, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
               i = 0&lt;br /&gt;
               for elem in to_write:&lt;br /&gt;
                    if i == 0:&lt;br /&gt;
                         print(&amp;quot;We skip&amp;quot;)&lt;br /&gt;
                    else:&lt;br /&gt;
                         if (i%2) == 0:&lt;br /&gt;
                              print(&amp;quot;Data writed :&amp;quot;,elem[:-4])&lt;br /&gt;
                              f.write(elem[:-4])&lt;br /&gt;
                              f.write(&amp;quot;\n&amp;quot;)&lt;br /&gt;
                    i = i + 1&lt;br /&gt;
&lt;br /&gt;
     #Main&lt;br /&gt;
     @app.route('/',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
     @cross_origin()&lt;br /&gt;
     def hello():&lt;br /&gt;
          data = request.json&lt;br /&gt;
          compute_data(data)&lt;br /&gt;
          return data&lt;br /&gt;
&lt;br /&gt;
     if __name__ == '__main__':&lt;br /&gt;
          print(&amp;quot;Listening&amp;quot;)&lt;br /&gt;
          serve(app,host=&amp;quot;::&amp;quot;,port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Implémentation de l'IA : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant qu'on a une communication pour envoyer un fichier à notre serveur depuis la raspberry grâce à notre API, nous la modifions pour que la Raspberry puisse lire la valeur du capteur à ultrason, l'envoyer à notre serveur et recevoir en réponse, la prédiction de l'IA. Nous créons donc une route '''''/predict''''' sur notre API qui récupère les valeurs du capteurs données en paramètre et renvoie la prédiction de l'IA :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 @app.route('/predict',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
 def predict():&lt;br /&gt;
      data = request.json&lt;br /&gt;
      print(data)&lt;br /&gt;
      features = data['Features']&lt;br /&gt;
      print(features)&lt;br /&gt;
      features_splitted = features[0].split(&amp;quot;,&amp;quot;)&lt;br /&gt;
      features_int = [int(elem) for elem in features_splitted]&lt;br /&gt;
      loaded_model = joblib.load('model_entraine.pkl')&lt;br /&gt;
      predictios = loaded_model.predict(np.array(features_int).reshape(1,-1))&lt;br /&gt;
      return jsonify(predictions.tolist())&lt;br /&gt;
&amp;lt;/pre&amp;gt;Nous envoyons ensuite les données à analyser via des requêtes API :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 #Import Librairies&lt;br /&gt;
 import requests&lt;br /&gt;
 import json&lt;br /&gt;
 import serial&lt;br /&gt;
 from flask import jsonify&lt;br /&gt;
&lt;br /&gt;
 #Variable&lt;br /&gt;
 STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
 baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
 Serial_link = serial.Serial(STM32_port, baudrate, timeout=1)&lt;br /&gt;
 print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
 tab_to_send = []&lt;br /&gt;
&lt;br /&gt;
 while True:&lt;br /&gt;
      Serial_link.readline().decode('utf-8')&lt;br /&gt;
      tab_to_send.append(Serial_link.readline().decode('utf-8')&lt;br /&gt;
      if (tab_to_send != [&amp;quot;&amp;quot;]):&lt;br /&gt;
           print(&amp;quot;Data sended :&amp;quot;,tab_to_send)&lt;br /&gt;
           url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080/predict&amp;quot;&lt;br /&gt;
           headers = {&lt;br /&gt;
                'Content-type':'application/json',&lt;br /&gt;
                'Accept':'application/json'&lt;br /&gt;
           }&lt;br /&gt;
           r = requests.post(&lt;br /&gt;
                url_request,&lt;br /&gt;
                json = {&lt;br /&gt;
                     &amp;quot;Features&amp;quot;: tab_to_send&lt;br /&gt;
                },&lt;br /&gt;
                headers=headers&lt;br /&gt;
           )&lt;br /&gt;
           print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
           print(&amp;quot;Response :&amp;quot;,r.json())&lt;br /&gt;
      else:&lt;br /&gt;
           print(&amp;quot;Data skip:&amp;quot;,tab_to_send)&lt;br /&gt;
      tab_to_send.clear()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Entrainement de l'IA &amp;lt;/div&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec NanoEdge AI Studio : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour le projet, nous avons d'abord développé et entrainé notre IA sur la plateforme NanoEdge AI Studio. Pour ce faire, nous devons d'abord définir un projet de classification de n-class (&amp;quot;pierre&amp;quot;,&amp;quot;feuille&amp;quot;,&amp;quot;ciseau&amp;quot;) en utilisant un capteur générique à 16 axes. Pour ce faire, nous modifions le code de la STM32 pour qu'elle renvoie une ligne contenant 16*16 mesure en continue. Une fois le projet créé, nous ajoutons 3 signaux correspondant à nos dataset de &amp;quot;Pierre&amp;quot;, &amp;quot;Feuille&amp;quot; et &amp;quot;Ciseau&amp;quot;. Pour rajouter des valeurs dans notre dataset, nous utilisons la liaison série pour lire les valeurs de notre capteur.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec Scikit : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour la suite de notre projet, nous avons developpé et entrainé une IA avec Scikit.&lt;br /&gt;
&lt;br /&gt;
==== Construction du fichier d'entrainement ====&lt;br /&gt;
Pour commencer, nous avons du construire un fichier csv reprenant nos mesures sur un format de 16 valeurs. Pour chaque mesure, on ajoute en amont de la mesure la catégorie (feuille, ciseau ou pierre). &lt;br /&gt;
[[Fichier:Capture d’écran 2024-01-18 à 16.18.19.png|centré|vignette|500x500px|Fichier chifoumIA.csv]]&lt;br /&gt;
Pour construire ce fichier, nous avons assemblé trois fichiers csv de test que nous avons généré grâce à notre capteur : un fichier d'entrainement Pierre.csv, un fichier d'entrainement Ciseau.csv et un fichier d'entrainement Feuille.csv . &lt;br /&gt;
&lt;br /&gt;
Pour faire cette concaténation nous avons développer un programme python prenant en entrée nos fichiers d'entrainement et fournissant en sortie le fichier csv chifoumIA.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     line_feuille = []&lt;br /&gt;
     line_pierre = []&lt;br /&gt;
     line_ciseau = []&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Feuille.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_feuille = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Pierre.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_pierre = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Ciseau.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_ciseau = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;chifoumIA.csv&amp;quot;,&amp;quot;w&amp;quot;) as f:&lt;br /&gt;
          for elem in line_feuille:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;feuille,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_pierre:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;pierre,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_ciseau:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;ciseau,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Implémentation et Entrainement de notre IA ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant que nous avons notre fichier d'entrainement, nous implémentons notre IA. &lt;br /&gt;
&lt;br /&gt;
Nous avons commencé par créer un tableau de données et un tableau de classes. &lt;br /&gt;
&lt;br /&gt;
Pour remplir ces tableaux, on va lire ligne par ligne le fichier chifoumIA.csv. Le premier élément de la ligne est stockée dans le tableau de classes et le reste de la ligne est stockée dans le tableau de données. &lt;br /&gt;
 chifoumi_data=[]&lt;br /&gt;
 chifoumi_classe=[]&lt;br /&gt;
 &lt;br /&gt;
 with open('chifoumIA.csv') as csv_file:&lt;br /&gt;
        csv_reader = csv.reader(csv_file,delimiter=',')&lt;br /&gt;
        for row in csv_reader:           &lt;br /&gt;
                 chifoumi_data.append([int(row[1]),int(row[2]),int(row[3]),int(row[4]),int(row[5]),int(row[6]),int(row[7]),int(row[8]),&lt;br /&gt;
                                       int(row[9]),int(row[10]),int(row[11]),int(row[12]),int(row[13]),int(row[14]),int(row[15]),int(row[16])])&lt;br /&gt;
                 chifoumi_classe.append(row[0])&lt;br /&gt;
  &lt;br /&gt;
A partir de ces deux tableaux, on construit un ensemble de données d'entraînement et un ensemble de données de tests.&lt;br /&gt;
&lt;br /&gt;
On choisi d'utiliser un réseau de neurone du type MLPClassifer. &lt;br /&gt;
&lt;br /&gt;
Le MLPClassifer est un type de réseau de neurones artificiels composés d'au minimum trois couches de neurones: une couche d'entrée, une ou plusieurs  couches cachées et une couche de sortie. &lt;br /&gt;
&lt;br /&gt;
Dans ce type de réseau, chaque neurone est connecté à l'ensemble des neurones de la couche suivante par un lien auquel est associé un poids. &lt;br /&gt;
&lt;br /&gt;
La classe MLPClassifer implémentée dans la bibliothèque Scikit-Learn dispose de nombreux paramètres. Pour notre projet, nous avons utilisé cette classe de façon très primaire. Les paramètres que nous avons utilisés sont :  &lt;br /&gt;
&lt;br /&gt;
- '''hidden_layer_sizes :''' ce paramètre est un tuple spécifiant le nombre de neurones dans chaque couche cachée. &lt;br /&gt;
&lt;br /&gt;
- '''max_iter :''' ce paramètre représente le nombre maximal d'époque. Il permet de contrôler également le temps d'entrainement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model=MLPClassifier(hidden_layer_sizes=(50,25),max_iter=100,solver='adam')&lt;br /&gt;
&lt;br /&gt;
model.fit(X_train,y_train)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;predictions = model.predict(X_test)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;print(f'Accuracy:{accuracy}')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Déploiement de notre IA ====&lt;br /&gt;
Pour pouvoir déployer notre IA, nous avons enregistré notre model d'entrainement et intégré un service web à notre code existant avec deux endpoint : &lt;br /&gt;
&lt;br /&gt;
- predict : pour effectuer des prédictions sur le model. &lt;br /&gt;
&lt;br /&gt;
- evaluate : pour évaluer les performances du model sur l'ensemble de tests.&lt;br /&gt;
&lt;br /&gt;
==== Code complet ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import joblib&lt;br /&gt;
import pandas as pd &lt;br /&gt;
import csv&lt;br /&gt;
from flask import Flask, request,jsonify&lt;br /&gt;
from sklearn.model_selection import train_test_split&lt;br /&gt;
from sklearn.ensemble import RandomForestClassifier&lt;br /&gt;
from sklearn.metrics import accuracy_score,precision_score,recall_score,f1_score&lt;br /&gt;
from sklearn.neural_network import MLPClassifier&lt;br /&gt;
from waitress import serve&lt;br /&gt;
from flask import Response&lt;br /&gt;
from flask_cors import CORS&lt;br /&gt;
from flask_cors import cross_origin&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
chifoumi_data=[]&lt;br /&gt;
chifoumi_classe=[]&lt;br /&gt;
&lt;br /&gt;
with open('chifoumIA.csv') as csv_file:&lt;br /&gt;
	csv_reader = csv.reader(csv_file,delimiter=',')&lt;br /&gt;
	for row in csv_reader:&lt;br /&gt;
		chifoumi_data.append([int(row[1]),int(row[2]),int(row[3]),int(row[4]),int(row[5]),int(row[6]),int(row[7]),int(row[8]),int(row[9]),int(row[10]),int(row[11]),int(row[12]),int(row[13]),int(row[14]),int(row[15]),int(row[16])])&lt;br /&gt;
		chifoumi_classe.append(row[0])&lt;br /&gt;
&lt;br /&gt;
X_train,X_test,y_train,y_test= train_test_split(chifoumi_data,chifoumi_classe,test_size=0.2,random_state=42)&lt;br /&gt;
&lt;br /&gt;
model=MLPClassifier(hidden_layer_sizes=(50,25),max_iter=100,solver='adam')&lt;br /&gt;
model.fit(X_train,y_train)&lt;br /&gt;
#predictions = model.predict(X_test)&lt;br /&gt;
#accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
#print(f'Accuracy:{accuracy}')&lt;br /&gt;
&lt;br /&gt;
joblib.dump(model,'model_entraine.pkl')&lt;br /&gt;
&lt;br /&gt;
app = Flask(__name__)&lt;br /&gt;
cors = CORS(app,ressources={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;: &amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#Main&lt;br /&gt;
@app.route('/predict',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
#@cross_origin()&lt;br /&gt;
def predict():&lt;br /&gt;
	data = request.json&lt;br /&gt;
	print(data)&lt;br /&gt;
	features = data['Features']&lt;br /&gt;
	print(features)&lt;br /&gt;
	features_splitted = features[0].split(&amp;quot;,&amp;quot;)&lt;br /&gt;
	features_int = [int(elem) for elem in features_splitted]&lt;br /&gt;
	loaded_model=joblib.load('model_entraine.pkl')&lt;br /&gt;
	predictions = loaded_model.predict(np.array(features_int).reshape(1,-1))&lt;br /&gt;
	return jsonify(predictions.tolist())&lt;br /&gt;
&lt;br /&gt;
@app.route('/evaluate',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
def evaluate():&lt;br /&gt;
	loaded_model = joblib.load('model_entraine.pkl')&lt;br /&gt;
	predictions = loaded_model.predict(X_test)&lt;br /&gt;
	accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
	precision = precision_score(y_test,predictions)&lt;br /&gt;
	recall = recall_score(y_test,predictions)&lt;br /&gt;
	f1=f1_score(y_test,predictions)&lt;br /&gt;
	&lt;br /&gt;
	return jsonify({ 'Accuracy': accuracy,'Precision': precision,'Recall': recall,'F1 Score':f1})&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
	print(&amp;quot;listening&amp;quot;)&lt;br /&gt;
	serve(app,host=&amp;quot;::&amp;quot;, port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4752</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4752"/>
		<updated>2024-01-28T13:21:56Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /* Code complet */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Introduction Projet IE Delannoy - Lemaire &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadre la matière '''&amp;quot;Intelligence Embarquée&amp;quot;''' de l'UE &amp;quot;Module de Spécialité&amp;quot; des SE5 - Option Systèmes Communicants, nous avons dû concevoir un projet permettant de '''distribuer le calcul et le processus d'entrainement''' et d'utilisation d'un Intelligence Artificielle. Nous devrons distribuer le calcul à différents endroits du réseau afin d'être en mesure de proposer des pistes d'optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, nous allons mettre en oeuvre un réseau d'objets connectés à des passerelles et à un serveur. '''Les objets collecteront des données''' de l'environnemet et suivants les scénarios, traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Nous aurons à disposition :&lt;br /&gt;
&lt;br /&gt;
* Une machine virtuelle sur le serveur '''Chassiron''' en ''E304/306''&lt;br /&gt;
* Une '''Raspberry PI 4'''&lt;br /&gt;
* Un carte programmable '''STM32F401RE'''&lt;br /&gt;
* Un capteur à ultrason '''Nucleo-53L5A1'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ce wiki est le compte-rendu du projet de '''Jason DELANNOY et Chloé LEMAIRE'''. Nous avons décider de développer une intelligence artificielle permettant de '''déterminer''' '''l'action faite par un joueur de Pierre-Feuille-Ciseau''' à l'aide du capteur à ultrason.&lt;br /&gt;
&lt;br /&gt;
Pour ce faire, nous allons développer notre IA de deux façons :&lt;br /&gt;
&lt;br /&gt;
* En utilisant '''NanoEdge Studio''' : Dans ce cas, le calcul serait fait par la carte programmable et envoyé au serveur via la Raspberry&lt;br /&gt;
* En utilisant '''un algorithme de machine learning ''': Ici, c'est le serveur qui fera le calcul et la Raspberry jouera le rôle de passerelle entre la carte programmable et le serveu&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Mise en oeuvre du réseau &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Création VM XEN ===&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la VM ===&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la borne WIFI Cisco ===&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251 (changement car besoin pour les PEIP) &lt;br /&gt;
&lt;br /&gt;
- dns-server: 193.48.57.33 (changement car problème avec le serveur DNS initial)&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Configuration de la Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadra du projet, nous avons à disposition une Raspberry PI 4 model B que nous allons configurer. Pour ce faire, nous utilisons le logiciel le &amp;quot;Raspberry PI Imager&amp;quot; pour choisir notre OS.&lt;br /&gt;
[[Fichier:JCIE RPI Imager.png|centré|vignette|400x400px]]Maintenant que nous avons une carte SD prête pour la Raspberry, nous la configurons via sa liaison série en passant par minicom :&lt;br /&gt;
 root@zabeth18: / $ minicom -D /dev/ttyACM0 -b 9600&lt;br /&gt;
De plus, nous modifions le fichier /etc/network/interfaces pour pouvoir connecter notre carte au réseau wifi créé plus haut :&lt;br /&gt;
[[Fichier:Screen WiFi.png|centré|vignette|441x441px]]&lt;br /&gt;
Nous verifions ensuite que nous avons une adresse IP :&lt;br /&gt;
[[Fichier:Screenshot from 2023-12-04 17-17-05.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Capteur NUCLEO - 53L5A1 &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Pour ce projet, nous disposons d'une STM32 Nucléo F401RE muni d'un capteur à ultrason X-Nucleo-53L5A1.&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir entrainer notre IA, nous devons faire en sorte d'afficher et de ressortir sur la liaison série les données du capteur. Pour ce faire, nous utilisons le fichier example &amp;quot;'''''53L5A1_ThresholdDetection'''''&amp;quot;. Nous modifions la fonction print_result pour afficher 16 valeurs à la suite :&lt;br /&gt;
[[Fichier:ChifoumIA Print Result.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Après avoir téléversé, nous pouvons vérifier le bon fonctionnement du programme en nous connectant à la carte via minicom :&lt;br /&gt;
&lt;br /&gt;
 root@raspberrypi:/dev$ minicom -D ttyACM0 -b 460800&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Communication VM-Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Envoie de donnée : ===&lt;br /&gt;
&lt;br /&gt;
Dans notre projet, nous avons besoin de remonter les données de notre capteur branché en liaison série à la Raspberry sur le port &amp;quot;ttyACM0&amp;quot;. Nous allons donc passer par des requêtes API entre le serveur sur chassiron et notre Raspberry.&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Raspberry : ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Du côté Raspberry, nous programmons un script en python qui lit sur la liaison série les valeurs du capteurs et les envoie via une requête POST vers le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import requests&lt;br /&gt;
     import json&lt;br /&gt;
     import serial&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;Variable&lt;br /&gt;
     STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
     baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
     Serial_link = serial.Serial(STM32_port,baudrate,timeout=1)&lt;br /&gt;
     print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
     liste_mesures=[]&lt;br /&gt;
     for i in range(101):&lt;br /&gt;
          print(&amp;quot;Mesure&amp;quot;,i)&lt;br /&gt;
          mesure = Serial_link.readline().decode('utf-8')&lt;br /&gt;
          liste_mesures.append(mesure)&lt;br /&gt;
&lt;br /&gt;
     data_to_send = json.dumps(liste_mesures)&lt;br /&gt;
     url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080&amp;quot;&lt;br /&gt;
&lt;br /&gt;
     headers = {&lt;br /&gt;
          'Content-type':'application/json',&lt;br /&gt;
          'Accept':'application/json'&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     r = requests.post(&lt;br /&gt;
          url_request,&lt;br /&gt;
          json=data_to_send,&lt;br /&gt;
          headers=headers&lt;br /&gt;
     )&lt;br /&gt;
     print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Serveur : ====&lt;br /&gt;
La communication entre notre VM et la Raspberry est possible. Nous arrivons à effectuer un ping de l'une sur l'autre en passant par l'addresse IPv6.&lt;br /&gt;
&lt;br /&gt;
IPv6 VM :  2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
IPv6 Raspberry : 2001:660:4401:6050:da3a:ddff:fe59:4cb5&lt;br /&gt;
&lt;br /&gt;
Nous programmons ensuite une API sur notre VM en utilisant la libraire Flask.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import json&lt;br /&gt;
     from flask import Flask&lt;br /&gt;
     from flask import request&lt;br /&gt;
     from waitress import serve&lt;br /&gt;
     from flask import Response&lt;br /&gt;
     from flask_cors import CORS&lt;br /&gt;
     from flask_cors import cross_origin&lt;br /&gt;
&lt;br /&gt;
     app = Flask(__name__)&lt;br /&gt;
     cors = CORS(app, ressourceas={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;:&amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
     def compute_data(data):&lt;br /&gt;
          filename = input(&amp;quot;Nom du fichier :&amp;quot;)&lt;br /&gt;
          to_write = data.split(&amp;quot;\&amp;quot;&amp;quot;)[1:-1]&lt;br /&gt;
          with open(filename, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
               i = 0&lt;br /&gt;
               for elem in to_write:&lt;br /&gt;
                    if i == 0:&lt;br /&gt;
                         print(&amp;quot;We skip&amp;quot;)&lt;br /&gt;
                    else:&lt;br /&gt;
                         if (i%2) == 0:&lt;br /&gt;
                              print(&amp;quot;Data writed :&amp;quot;,elem[:-4])&lt;br /&gt;
                              f.write(elem[:-4])&lt;br /&gt;
                              f.write(&amp;quot;\n&amp;quot;)&lt;br /&gt;
                    i = i + 1&lt;br /&gt;
&lt;br /&gt;
     #Main&lt;br /&gt;
     @app.route('/',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
     @cross_origin()&lt;br /&gt;
     def hello():&lt;br /&gt;
          data = request.json&lt;br /&gt;
          compute_data(data)&lt;br /&gt;
          return data&lt;br /&gt;
&lt;br /&gt;
     if __name__ == '__main__':&lt;br /&gt;
          print(&amp;quot;Listening&amp;quot;)&lt;br /&gt;
          serve(app,host=&amp;quot;::&amp;quot;,port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Implémentation de l'IA : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant qu'on a une communication pour envoyer un fichier à notre serveur depuis la raspberry grâce à notre API, nous la modifions pour que la Raspberry puisse lire la valeur du capteur à ultrason, l'envoyer à notre serveur et recevoir en réponse, la prédiction de l'IA. Nous créons donc une route '''''/predict''''' sur notre API qui récupère les valeurs du capteurs données en paramètre et renvoie la prédiction de l'IA :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 @app.route('/predict',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
 def predict():&lt;br /&gt;
      data = request.json&lt;br /&gt;
      print(data)&lt;br /&gt;
      features = data['Features']&lt;br /&gt;
      print(features)&lt;br /&gt;
      features_splitted = features[0].split(&amp;quot;,&amp;quot;)&lt;br /&gt;
      features_int = [int(elem) for elem in features_splitted]&lt;br /&gt;
      loaded_model = joblib.load('model_entraine.pkl')&lt;br /&gt;
      predictios = loaded_model.predict(np.array(features_int).reshape(1,-1))&lt;br /&gt;
      return jsonify(predictions.tolist())&lt;br /&gt;
&amp;lt;/pre&amp;gt;Nous envoyons ensuite les données à analyser via des requêtes API :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 #Import Librairies&lt;br /&gt;
 import requests&lt;br /&gt;
 import json&lt;br /&gt;
 import serial&lt;br /&gt;
 from flask import jsonify&lt;br /&gt;
&lt;br /&gt;
 #Variable&lt;br /&gt;
 STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
 baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
 Serial_link = serial.Serial(STM32_port, baudrate, timeout=1)&lt;br /&gt;
 print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
 tab_to_send = []&lt;br /&gt;
&lt;br /&gt;
 while True:&lt;br /&gt;
      Serial_link.readline().decode('utf-8')&lt;br /&gt;
      tab_to_send.append(Serial_link.readline().decode('utf-8')&lt;br /&gt;
      if (tab_to_send != [&amp;quot;&amp;quot;]):&lt;br /&gt;
           print(&amp;quot;Data sended :&amp;quot;,tab_to_send)&lt;br /&gt;
           url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080/predict&amp;quot;&lt;br /&gt;
           headers = {&lt;br /&gt;
                'Content-type':'application/json',&lt;br /&gt;
                'Accept':'application/json'&lt;br /&gt;
           }&lt;br /&gt;
           r = requests.post(&lt;br /&gt;
                url_request,&lt;br /&gt;
                json = {&lt;br /&gt;
                     &amp;quot;Features&amp;quot;: tab_to_send&lt;br /&gt;
                },&lt;br /&gt;
                headers=headers&lt;br /&gt;
           )&lt;br /&gt;
           print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
           print(&amp;quot;Response :&amp;quot;,r.json())&lt;br /&gt;
      else:&lt;br /&gt;
           print(&amp;quot;Data skip:&amp;quot;,tab_to_send)&lt;br /&gt;
      tab_to_send.clear()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Entrainement de l'IA &amp;lt;/div&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec NanoEdge AI Studio : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour le projet, nous avons d'abord développé et entrainé notre IA sur la plateforme NanoEdge AI Studio. Pour ce faire, nous devons d'abord définir un projet de classification de n-class (&amp;quot;pierre&amp;quot;,&amp;quot;feuille&amp;quot;,&amp;quot;ciseau&amp;quot;) en utilisant un capteur générique à 16 axes. Pour ce faire, nous modifions le code de la STM32 pour qu'elle renvoie une ligne contenant 16*16 mesure en continue. Une fois le projet créé, nous ajoutons 3 signaux correspondant à nos dataset de &amp;quot;Pierre&amp;quot;, &amp;quot;Feuille&amp;quot; et &amp;quot;Ciseau&amp;quot;. Pour rajouter des valeurs dans notre dataset, nous utilisons la liaison série pour lire les valeurs de notre capteur.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec Scikit : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour la suite de notre projet, nous avons developpé et entrainé une IA avec Scikit.&lt;br /&gt;
&lt;br /&gt;
==== Construction du fichier d'entrainement ====&lt;br /&gt;
Pour commencer, nous avons du construire un fichier csv reprenant nos mesures sur un format de 16 valeurs. Pour chaque mesure, on ajoute en amont de la mesure la catégorie (feuille, ciseau ou pierre). &lt;br /&gt;
[[Fichier:Capture d’écran 2024-01-18 à 16.18.19.png|centré|vignette|500x500px|Fichier chifoumIA.csv]]&lt;br /&gt;
Pour construire ce fichier, nous avons assemblé trois fichiers csv de test que nous avons généré grâce à notre capteur : un fichier d'entrainement Pierre.csv, un fichier d'entrainement Ciseau.csv et un fichier d'entrainement Feuille.csv . &lt;br /&gt;
&lt;br /&gt;
Pour faire cette concaténation nous avons développer un programme python prenant en entrée nos fichiers d'entrainement et fournissant en sortie le fichier csv chifoumIA.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     line_feuille = []&lt;br /&gt;
     line_pierre = []&lt;br /&gt;
     line_ciseau = []&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Feuille.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_feuille = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Pierre.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_pierre = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Ciseau.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_ciseau = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;chifoumIA.csv&amp;quot;,&amp;quot;w&amp;quot;) as f:&lt;br /&gt;
          for elem in line_feuille:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;feuille,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_pierre:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;pierre,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_ciseau:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;ciseau,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Implémentation et Entrainement de notre IA ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant que nous avons notre fichier d'entrainement, nous implémentons notre IA. &lt;br /&gt;
&lt;br /&gt;
Nous avons commencé par créer un tableau de données et un tableau de classes. &lt;br /&gt;
&lt;br /&gt;
Pour remplir ces tableaux, on va lire ligne par ligne le fichier chifoumIA.csv. Le premier élément de la ligne est stockée dans le tableau de classes et le reste de la ligne est stockée dans le tableau de données. &lt;br /&gt;
 chifoumi_data=[]&lt;br /&gt;
 chifoumi_classe=[]&lt;br /&gt;
 &lt;br /&gt;
 with open('chifoumIA.csv') as csv_file:&lt;br /&gt;
        csv_reader = csv.reader(csv_file,delimiter=',')&lt;br /&gt;
        for row in csv_reader:           &lt;br /&gt;
                 chifoumi_data.append([int(row[1]),int(row[2]),int(row[3]),int(row[4]),int(row[5]),int(row[6]),int(row[7]),int(row[8]),&lt;br /&gt;
                                       int(row[9]),int(row[10]),int(row[11]),int(row[12]),int(row[13]),int(row[14]),int(row[15]),int(row[16])])&lt;br /&gt;
                 chifoumi_classe.append(row[0])&lt;br /&gt;
  &lt;br /&gt;
A partir de ces deux tableaux, on construit un ensemble de données d'entraînement et un ensemble de données de tests.&lt;br /&gt;
&lt;br /&gt;
On choisi d'utiliser un réseau de neurone du type MLPClassifer. &lt;br /&gt;
&lt;br /&gt;
Le MLPClassifer est un type de réseau de neurones artificiels composés d'au minimum trois couches de neurones: une couche d'entrée, une ou plusieurs  couches cachées et une couche de sortie. &lt;br /&gt;
&lt;br /&gt;
Dans ce type de réseau, chaque neurone est connecté à l'ensemble des neurones de la couche suivante par un lien auquel est associé un poids. &lt;br /&gt;
&lt;br /&gt;
La classe MLPClassifer implémentée dans la bibliothèque Scikit-Learn dispose de nombreux paramètres. Pour notre projet, nous avons utilisé cette classe de façon très primaire. Les paramètres que nous avons utilisés sont :  &lt;br /&gt;
&lt;br /&gt;
- '''hidden_layer_sizes :''' ce paramètre est un tuple spécifiant le nombre de neurones dans chaque couche cachée. &lt;br /&gt;
&lt;br /&gt;
- '''max_iter :''' ce paramètre représente le nombre maximal d'époque. Il permet de contrôler également le temps d'entrainement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model=MLPClassifier(hidden_layer_sizes=(50,25),max_iter=100,solver='adam')&lt;br /&gt;
&lt;br /&gt;
model.fit(X_train,y_train)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;predictions = model.predict(X_test)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;print(f'Accuracy:{accuracy}')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Déploiement de notre IA ====&lt;br /&gt;
Pour pouvoir déployer notre IA, nous avons enregistré notre model d'entrainement et intégré un service web à notre code existant avec deux endpoint : &lt;br /&gt;
&lt;br /&gt;
- predict : pour effectuer des prédictions sur le model. &lt;br /&gt;
&lt;br /&gt;
- evaluate : pour évaluer les performances du model sur l'ensemble de tests.&lt;br /&gt;
&lt;br /&gt;
==== Code complet ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import joblib&lt;br /&gt;
import pandas as pd &lt;br /&gt;
import csv&lt;br /&gt;
from flask import Flask, request,jsonify&lt;br /&gt;
from sklearn.model_selection import train_test_split&lt;br /&gt;
from sklearn.ensemble import RandomForestClassifier&lt;br /&gt;
from sklearn.metrics import accuracy_score,precision_score,recall_score,f1_score&lt;br /&gt;
from sklearn.neural_network import MLPClassifier&lt;br /&gt;
from waitress import serve&lt;br /&gt;
from flask import Response&lt;br /&gt;
from flask_cors import CORS&lt;br /&gt;
from flask_cors import cross_origin&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
chifoumi_data=[]&lt;br /&gt;
chifoumi_classe=[]&lt;br /&gt;
&lt;br /&gt;
with open('chifoumIA.csv') as csv_file:&lt;br /&gt;
	csv_reader = csv.reader(csv_file,delimiter=',')&lt;br /&gt;
	for row in csv_reader:&lt;br /&gt;
		chifoumi_data.append([int(row[1]),int(row[2]),int(row[3]),int(row[4]),int(row[5]),int(row[6]),int(row[7]),int(row[8]),int(row[9]),int(row[10]),int(row[11]),int(row[12]),int(row[13]),int(row[14]),int(row[15]),int(row[16])])&lt;br /&gt;
		chifoumi_classe.append(row[0])&lt;br /&gt;
&lt;br /&gt;
X_train,X_test,y_train,y_test= train_test_split(chifoumi_data,chifoumi_classe,test_size=0.2,random_state=42)&lt;br /&gt;
&lt;br /&gt;
model=MLPClassifier(hidden_layer_sizes=(50,25),max_iter=100,solver='adam')&lt;br /&gt;
model.fit(X_train,y_train)&lt;br /&gt;
#predictions = model.predict(X_test)&lt;br /&gt;
#accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
#print(f'Accuracy:{accuracy}')&lt;br /&gt;
&lt;br /&gt;
joblib.dump(model,'model_entraine.pkl')&lt;br /&gt;
&lt;br /&gt;
app = Flask(__name__)&lt;br /&gt;
cors = CORS(app,ressources={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;: &amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#Main&lt;br /&gt;
@app.route('/predict',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
#@cross_origin()&lt;br /&gt;
def predict():&lt;br /&gt;
	data = request.json&lt;br /&gt;
	print(data)&lt;br /&gt;
	features = data['Features']&lt;br /&gt;
	print(features)&lt;br /&gt;
	features_splitted = features[0].split(&amp;quot;,&amp;quot;)&lt;br /&gt;
	features_int = [int(elem) for elem in features_splitted]&lt;br /&gt;
	loaded_model=joblib.load('model_entraine.pkl')&lt;br /&gt;
	predictions = loaded_model.predict(np.array(features_int).reshape(1,-1))&lt;br /&gt;
	return jsonify(predictions.tolist())&lt;br /&gt;
&lt;br /&gt;
@app.route('/evaluate',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
def evaluate():&lt;br /&gt;
	loaded_model = joblib.load('model_entraine.pkl')&lt;br /&gt;
	predictions = loaded_model.predict(X_test)&lt;br /&gt;
	accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
	precision = precision_score(y_test,predictions)&lt;br /&gt;
	recall = recall_score(y_test,predictions)&lt;br /&gt;
	f1=f1_score(y_test,predictions)&lt;br /&gt;
	&lt;br /&gt;
	return jsonify({ 'Accuracy': accuracy,'Precision': precision,'Recall': recall,'F1 Score':f1})&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
	print(&amp;quot;listening&amp;quot;)&lt;br /&gt;
	serve(app,host=&amp;quot;::&amp;quot;, port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====  ipv6 jcie : 2001:660:4401:6050:216:3eff:fe68:8176 ====&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4751</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4751"/>
		<updated>2024-01-28T13:21:32Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /* Entrainement avec Scikit : */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Introduction Projet IE Delannoy - Lemaire &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadre la matière '''&amp;quot;Intelligence Embarquée&amp;quot;''' de l'UE &amp;quot;Module de Spécialité&amp;quot; des SE5 - Option Systèmes Communicants, nous avons dû concevoir un projet permettant de '''distribuer le calcul et le processus d'entrainement''' et d'utilisation d'un Intelligence Artificielle. Nous devrons distribuer le calcul à différents endroits du réseau afin d'être en mesure de proposer des pistes d'optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, nous allons mettre en oeuvre un réseau d'objets connectés à des passerelles et à un serveur. '''Les objets collecteront des données''' de l'environnemet et suivants les scénarios, traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Nous aurons à disposition :&lt;br /&gt;
&lt;br /&gt;
* Une machine virtuelle sur le serveur '''Chassiron''' en ''E304/306''&lt;br /&gt;
* Une '''Raspberry PI 4'''&lt;br /&gt;
* Un carte programmable '''STM32F401RE'''&lt;br /&gt;
* Un capteur à ultrason '''Nucleo-53L5A1'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ce wiki est le compte-rendu du projet de '''Jason DELANNOY et Chloé LEMAIRE'''. Nous avons décider de développer une intelligence artificielle permettant de '''déterminer''' '''l'action faite par un joueur de Pierre-Feuille-Ciseau''' à l'aide du capteur à ultrason.&lt;br /&gt;
&lt;br /&gt;
Pour ce faire, nous allons développer notre IA de deux façons :&lt;br /&gt;
&lt;br /&gt;
* En utilisant '''NanoEdge Studio''' : Dans ce cas, le calcul serait fait par la carte programmable et envoyé au serveur via la Raspberry&lt;br /&gt;
* En utilisant '''un algorithme de machine learning ''': Ici, c'est le serveur qui fera le calcul et la Raspberry jouera le rôle de passerelle entre la carte programmable et le serveu&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Mise en oeuvre du réseau &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Création VM XEN ===&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la VM ===&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la borne WIFI Cisco ===&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251 (changement car besoin pour les PEIP) &lt;br /&gt;
&lt;br /&gt;
- dns-server: 193.48.57.33 (changement car problème avec le serveur DNS initial)&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Configuration de la Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadra du projet, nous avons à disposition une Raspberry PI 4 model B que nous allons configurer. Pour ce faire, nous utilisons le logiciel le &amp;quot;Raspberry PI Imager&amp;quot; pour choisir notre OS.&lt;br /&gt;
[[Fichier:JCIE RPI Imager.png|centré|vignette|400x400px]]Maintenant que nous avons une carte SD prête pour la Raspberry, nous la configurons via sa liaison série en passant par minicom :&lt;br /&gt;
 root@zabeth18: / $ minicom -D /dev/ttyACM0 -b 9600&lt;br /&gt;
De plus, nous modifions le fichier /etc/network/interfaces pour pouvoir connecter notre carte au réseau wifi créé plus haut :&lt;br /&gt;
[[Fichier:Screen WiFi.png|centré|vignette|441x441px]]&lt;br /&gt;
Nous verifions ensuite que nous avons une adresse IP :&lt;br /&gt;
[[Fichier:Screenshot from 2023-12-04 17-17-05.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Capteur NUCLEO - 53L5A1 &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Pour ce projet, nous disposons d'une STM32 Nucléo F401RE muni d'un capteur à ultrason X-Nucleo-53L5A1.&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir entrainer notre IA, nous devons faire en sorte d'afficher et de ressortir sur la liaison série les données du capteur. Pour ce faire, nous utilisons le fichier example &amp;quot;'''''53L5A1_ThresholdDetection'''''&amp;quot;. Nous modifions la fonction print_result pour afficher 16 valeurs à la suite :&lt;br /&gt;
[[Fichier:ChifoumIA Print Result.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Après avoir téléversé, nous pouvons vérifier le bon fonctionnement du programme en nous connectant à la carte via minicom :&lt;br /&gt;
&lt;br /&gt;
 root@raspberrypi:/dev$ minicom -D ttyACM0 -b 460800&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Communication VM-Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Envoie de donnée : ===&lt;br /&gt;
&lt;br /&gt;
Dans notre projet, nous avons besoin de remonter les données de notre capteur branché en liaison série à la Raspberry sur le port &amp;quot;ttyACM0&amp;quot;. Nous allons donc passer par des requêtes API entre le serveur sur chassiron et notre Raspberry.&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Raspberry : ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Du côté Raspberry, nous programmons un script en python qui lit sur la liaison série les valeurs du capteurs et les envoie via une requête POST vers le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import requests&lt;br /&gt;
     import json&lt;br /&gt;
     import serial&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;Variable&lt;br /&gt;
     STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
     baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
     Serial_link = serial.Serial(STM32_port,baudrate,timeout=1)&lt;br /&gt;
     print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
     liste_mesures=[]&lt;br /&gt;
     for i in range(101):&lt;br /&gt;
          print(&amp;quot;Mesure&amp;quot;,i)&lt;br /&gt;
          mesure = Serial_link.readline().decode('utf-8')&lt;br /&gt;
          liste_mesures.append(mesure)&lt;br /&gt;
&lt;br /&gt;
     data_to_send = json.dumps(liste_mesures)&lt;br /&gt;
     url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080&amp;quot;&lt;br /&gt;
&lt;br /&gt;
     headers = {&lt;br /&gt;
          'Content-type':'application/json',&lt;br /&gt;
          'Accept':'application/json'&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     r = requests.post(&lt;br /&gt;
          url_request,&lt;br /&gt;
          json=data_to_send,&lt;br /&gt;
          headers=headers&lt;br /&gt;
     )&lt;br /&gt;
     print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Serveur : ====&lt;br /&gt;
La communication entre notre VM et la Raspberry est possible. Nous arrivons à effectuer un ping de l'une sur l'autre en passant par l'addresse IPv6.&lt;br /&gt;
&lt;br /&gt;
IPv6 VM :  2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
IPv6 Raspberry : 2001:660:4401:6050:da3a:ddff:fe59:4cb5&lt;br /&gt;
&lt;br /&gt;
Nous programmons ensuite une API sur notre VM en utilisant la libraire Flask.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import json&lt;br /&gt;
     from flask import Flask&lt;br /&gt;
     from flask import request&lt;br /&gt;
     from waitress import serve&lt;br /&gt;
     from flask import Response&lt;br /&gt;
     from flask_cors import CORS&lt;br /&gt;
     from flask_cors import cross_origin&lt;br /&gt;
&lt;br /&gt;
     app = Flask(__name__)&lt;br /&gt;
     cors = CORS(app, ressourceas={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;:&amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
     def compute_data(data):&lt;br /&gt;
          filename = input(&amp;quot;Nom du fichier :&amp;quot;)&lt;br /&gt;
          to_write = data.split(&amp;quot;\&amp;quot;&amp;quot;)[1:-1]&lt;br /&gt;
          with open(filename, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
               i = 0&lt;br /&gt;
               for elem in to_write:&lt;br /&gt;
                    if i == 0:&lt;br /&gt;
                         print(&amp;quot;We skip&amp;quot;)&lt;br /&gt;
                    else:&lt;br /&gt;
                         if (i%2) == 0:&lt;br /&gt;
                              print(&amp;quot;Data writed :&amp;quot;,elem[:-4])&lt;br /&gt;
                              f.write(elem[:-4])&lt;br /&gt;
                              f.write(&amp;quot;\n&amp;quot;)&lt;br /&gt;
                    i = i + 1&lt;br /&gt;
&lt;br /&gt;
     #Main&lt;br /&gt;
     @app.route('/',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
     @cross_origin()&lt;br /&gt;
     def hello():&lt;br /&gt;
          data = request.json&lt;br /&gt;
          compute_data(data)&lt;br /&gt;
          return data&lt;br /&gt;
&lt;br /&gt;
     if __name__ == '__main__':&lt;br /&gt;
          print(&amp;quot;Listening&amp;quot;)&lt;br /&gt;
          serve(app,host=&amp;quot;::&amp;quot;,port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Implémentation de l'IA : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant qu'on a une communication pour envoyer un fichier à notre serveur depuis la raspberry grâce à notre API, nous la modifions pour que la Raspberry puisse lire la valeur du capteur à ultrason, l'envoyer à notre serveur et recevoir en réponse, la prédiction de l'IA. Nous créons donc une route '''''/predict''''' sur notre API qui récupère les valeurs du capteurs données en paramètre et renvoie la prédiction de l'IA :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 @app.route('/predict',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
 def predict():&lt;br /&gt;
      data = request.json&lt;br /&gt;
      print(data)&lt;br /&gt;
      features = data['Features']&lt;br /&gt;
      print(features)&lt;br /&gt;
      features_splitted = features[0].split(&amp;quot;,&amp;quot;)&lt;br /&gt;
      features_int = [int(elem) for elem in features_splitted]&lt;br /&gt;
      loaded_model = joblib.load('model_entraine.pkl')&lt;br /&gt;
      predictios = loaded_model.predict(np.array(features_int).reshape(1,-1))&lt;br /&gt;
      return jsonify(predictions.tolist())&lt;br /&gt;
&amp;lt;/pre&amp;gt;Nous envoyons ensuite les données à analyser via des requêtes API :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 #Import Librairies&lt;br /&gt;
 import requests&lt;br /&gt;
 import json&lt;br /&gt;
 import serial&lt;br /&gt;
 from flask import jsonify&lt;br /&gt;
&lt;br /&gt;
 #Variable&lt;br /&gt;
 STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
 baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
 Serial_link = serial.Serial(STM32_port, baudrate, timeout=1)&lt;br /&gt;
 print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
 tab_to_send = []&lt;br /&gt;
&lt;br /&gt;
 while True:&lt;br /&gt;
      Serial_link.readline().decode('utf-8')&lt;br /&gt;
      tab_to_send.append(Serial_link.readline().decode('utf-8')&lt;br /&gt;
      if (tab_to_send != [&amp;quot;&amp;quot;]):&lt;br /&gt;
           print(&amp;quot;Data sended :&amp;quot;,tab_to_send)&lt;br /&gt;
           url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080/predict&amp;quot;&lt;br /&gt;
           headers = {&lt;br /&gt;
                'Content-type':'application/json',&lt;br /&gt;
                'Accept':'application/json'&lt;br /&gt;
           }&lt;br /&gt;
           r = requests.post(&lt;br /&gt;
                url_request,&lt;br /&gt;
                json = {&lt;br /&gt;
                     &amp;quot;Features&amp;quot;: tab_to_send&lt;br /&gt;
                },&lt;br /&gt;
                headers=headers&lt;br /&gt;
           )&lt;br /&gt;
           print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
           print(&amp;quot;Response :&amp;quot;,r.json())&lt;br /&gt;
      else:&lt;br /&gt;
           print(&amp;quot;Data skip:&amp;quot;,tab_to_send)&lt;br /&gt;
      tab_to_send.clear()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Entrainement de l'IA &amp;lt;/div&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec NanoEdge AI Studio : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour le projet, nous avons d'abord développé et entrainé notre IA sur la plateforme NanoEdge AI Studio. Pour ce faire, nous devons d'abord définir un projet de classification de n-class (&amp;quot;pierre&amp;quot;,&amp;quot;feuille&amp;quot;,&amp;quot;ciseau&amp;quot;) en utilisant un capteur générique à 16 axes. Pour ce faire, nous modifions le code de la STM32 pour qu'elle renvoie une ligne contenant 16*16 mesure en continue. Une fois le projet créé, nous ajoutons 3 signaux correspondant à nos dataset de &amp;quot;Pierre&amp;quot;, &amp;quot;Feuille&amp;quot; et &amp;quot;Ciseau&amp;quot;. Pour rajouter des valeurs dans notre dataset, nous utilisons la liaison série pour lire les valeurs de notre capteur.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec Scikit : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour la suite de notre projet, nous avons developpé et entrainé une IA avec Scikit.&lt;br /&gt;
&lt;br /&gt;
==== Construction du fichier d'entrainement ====&lt;br /&gt;
Pour commencer, nous avons du construire un fichier csv reprenant nos mesures sur un format de 16 valeurs. Pour chaque mesure, on ajoute en amont de la mesure la catégorie (feuille, ciseau ou pierre). &lt;br /&gt;
[[Fichier:Capture d’écran 2024-01-18 à 16.18.19.png|centré|vignette|500x500px|Fichier chifoumIA.csv]]&lt;br /&gt;
Pour construire ce fichier, nous avons assemblé trois fichiers csv de test que nous avons généré grâce à notre capteur : un fichier d'entrainement Pierre.csv, un fichier d'entrainement Ciseau.csv et un fichier d'entrainement Feuille.csv . &lt;br /&gt;
&lt;br /&gt;
Pour faire cette concaténation nous avons développer un programme python prenant en entrée nos fichiers d'entrainement et fournissant en sortie le fichier csv chifoumIA.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     line_feuille = []&lt;br /&gt;
     line_pierre = []&lt;br /&gt;
     line_ciseau = []&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Feuille.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_feuille = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Pierre.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_pierre = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Ciseau.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_ciseau = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;chifoumIA.csv&amp;quot;,&amp;quot;w&amp;quot;) as f:&lt;br /&gt;
          for elem in line_feuille:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;feuille,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_pierre:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;pierre,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_ciseau:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;ciseau,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Implémentation et Entrainement de notre IA ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant que nous avons notre fichier d'entrainement, nous implémentons notre IA. &lt;br /&gt;
&lt;br /&gt;
Nous avons commencé par créer un tableau de données et un tableau de classes. &lt;br /&gt;
&lt;br /&gt;
Pour remplir ces tableaux, on va lire ligne par ligne le fichier chifoumIA.csv. Le premier élément de la ligne est stockée dans le tableau de classes et le reste de la ligne est stockée dans le tableau de données. &lt;br /&gt;
 chifoumi_data=[]&lt;br /&gt;
 chifoumi_classe=[]&lt;br /&gt;
 &lt;br /&gt;
 with open('chifoumIA.csv') as csv_file:&lt;br /&gt;
        csv_reader = csv.reader(csv_file,delimiter=',')&lt;br /&gt;
        for row in csv_reader:           &lt;br /&gt;
                 chifoumi_data.append([int(row[1]),int(row[2]),int(row[3]),int(row[4]),int(row[5]),int(row[6]),int(row[7]),int(row[8]),&lt;br /&gt;
                                       int(row[9]),int(row[10]),int(row[11]),int(row[12]),int(row[13]),int(row[14]),int(row[15]),int(row[16])])&lt;br /&gt;
                 chifoumi_classe.append(row[0])&lt;br /&gt;
  &lt;br /&gt;
A partir de ces deux tableaux, on construit un ensemble de données d'entraînement et un ensemble de données de tests.&lt;br /&gt;
&lt;br /&gt;
On choisi d'utiliser un réseau de neurone du type MLPClassifer. &lt;br /&gt;
&lt;br /&gt;
Le MLPClassifer est un type de réseau de neurones artificiels composés d'au minimum trois couches de neurones: une couche d'entrée, une ou plusieurs  couches cachées et une couche de sortie. &lt;br /&gt;
&lt;br /&gt;
Dans ce type de réseau, chaque neurone est connecté à l'ensemble des neurones de la couche suivante par un lien auquel est associé un poids. &lt;br /&gt;
&lt;br /&gt;
La classe MLPClassifer implémentée dans la bibliothèque Scikit-Learn dispose de nombreux paramètres. Pour notre projet, nous avons utilisé cette classe de façon très primaire. Les paramètres que nous avons utilisés sont :  &lt;br /&gt;
&lt;br /&gt;
- '''hidden_layer_sizes :''' ce paramètre est un tuple spécifiant le nombre de neurones dans chaque couche cachée. &lt;br /&gt;
&lt;br /&gt;
- '''max_iter :''' ce paramètre représente le nombre maximal d'époque. Il permet de contrôler également le temps d'entrainement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model=MLPClassifier(hidden_layer_sizes=(50,25),max_iter=100,solver='adam')&lt;br /&gt;
&lt;br /&gt;
model.fit(X_train,y_train)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;predictions = model.predict(X_test)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;print(f'Accuracy:{accuracy}')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Déploiement de notre IA ====&lt;br /&gt;
Pour pouvoir déployer notre IA, nous avons enregistré notre model d'entrainement et intégré un service web à notre code existant avec deux endpoint : &lt;br /&gt;
&lt;br /&gt;
- predict : pour effectuer des prédictions sur le model. &lt;br /&gt;
&lt;br /&gt;
- evaluate : pour évaluer les performances du model sur l'ensemble de tests.&lt;br /&gt;
&lt;br /&gt;
==== Code complet ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import joblib&lt;br /&gt;
import pandas as pd &lt;br /&gt;
import csv&lt;br /&gt;
from flask import Flask, request,jsonify&lt;br /&gt;
from sklearn.model_selection import train_test_split&lt;br /&gt;
from sklearn.ensemble import RandomForestClassifier&lt;br /&gt;
from sklearn.metrics import accuracy_score,precision_score,recall_score,f1_score&lt;br /&gt;
from sklearn.neural_network import MLPClassifier&lt;br /&gt;
from waitress import serve&lt;br /&gt;
from flask import Response&lt;br /&gt;
from flask_cors import CORS&lt;br /&gt;
from flask_cors import cross_origin&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
chifoumi_data=[]&lt;br /&gt;
chifoumi_classe=[]&lt;br /&gt;
&lt;br /&gt;
with open('chifoumIA.csv') as csv_file:&lt;br /&gt;
	csv_reader = csv.reader(csv_file,delimiter=',')&lt;br /&gt;
	for row in csv_reader:&lt;br /&gt;
		chifoumi_data.append([int(row[1]),int(row[2]),int(row[3]),int(row[4]),int(row[5]),int(row[6]),int(row[7]),int(row[8]),int(row[9]),int(row[10]),int(row[11]),int(row[12]),int(row[13]),int(row[14]),int(row[15]),int(row[16])])&lt;br /&gt;
		chifoumi_classe.append(row[0])&lt;br /&gt;
&lt;br /&gt;
X_train,X_test,y_train,y_test= train_test_split(chifoumi_data,chifoumi_classe,test_size=0.2,random_state=42)&lt;br /&gt;
&lt;br /&gt;
model=MLPClassifier(hidden_layer_sizes=(50,25),max_iter=100,solver='adam')&lt;br /&gt;
model.fit(X_train,y_train)&lt;br /&gt;
#predictions = model.predict(X_test)&lt;br /&gt;
#accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
#print(f'Accuracy:{accuracy}')&lt;br /&gt;
&lt;br /&gt;
joblib.dump(model,'model_entraine.pkl')&lt;br /&gt;
&lt;br /&gt;
app = Flask(__name__)&lt;br /&gt;
cors = CORS(app,ressources={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;: &amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#Main&lt;br /&gt;
@app.route('/predict',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
#@cross_origin()&lt;br /&gt;
def predict():&lt;br /&gt;
	data = request.json&lt;br /&gt;
	print(data)&lt;br /&gt;
	features = data['Features']&lt;br /&gt;
	print(features)&lt;br /&gt;
	features_splitted = features[0].split(&amp;quot;,&amp;quot;)&lt;br /&gt;
	features_int = [int(elem) for elem in features_splitted]&lt;br /&gt;
	loaded_model=joblib.load('model_entraine.pkl')&lt;br /&gt;
	predictions = loaded_model.predict(np.array(features_int).reshape(1,-1))&lt;br /&gt;
	return jsonify(predictions.tolist())&lt;br /&gt;
&lt;br /&gt;
@app.route('/evaluate',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
def evaluate():&lt;br /&gt;
	loaded_model = joblib.load('model_entraine.pkl')&lt;br /&gt;
	predictions = loaded_model.predict(X_test)&lt;br /&gt;
	accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
	precision = precision_score(y_test,predictions)&lt;br /&gt;
	recall = recall_score(y_test,predictions)&lt;br /&gt;
	f1=f1_score(y_test,predictions)&lt;br /&gt;
	&lt;br /&gt;
	return jsonify({ 'Accuracy': accuracy,'Precision': precision,'Recall': recall,'F1 Score':f1})&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
	print(&amp;quot;listening&amp;quot;)&lt;br /&gt;
	serve(app,host=&amp;quot;::&amp;quot;, port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;pre/&amp;gt;&lt;br /&gt;
====  ipv6 jcie : 2001:660:4401:6050:216:3eff:fe68:8176 ====&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4750</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4750"/>
		<updated>2024-01-28T13:20:45Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /* Entrainement avec Scikit : */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Introduction Projet IE Delannoy - Lemaire &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadre la matière '''&amp;quot;Intelligence Embarquée&amp;quot;''' de l'UE &amp;quot;Module de Spécialité&amp;quot; des SE5 - Option Systèmes Communicants, nous avons dû concevoir un projet permettant de '''distribuer le calcul et le processus d'entrainement''' et d'utilisation d'un Intelligence Artificielle. Nous devrons distribuer le calcul à différents endroits du réseau afin d'être en mesure de proposer des pistes d'optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, nous allons mettre en oeuvre un réseau d'objets connectés à des passerelles et à un serveur. '''Les objets collecteront des données''' de l'environnemet et suivants les scénarios, traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Nous aurons à disposition :&lt;br /&gt;
&lt;br /&gt;
* Une machine virtuelle sur le serveur '''Chassiron''' en ''E304/306''&lt;br /&gt;
* Une '''Raspberry PI 4'''&lt;br /&gt;
* Un carte programmable '''STM32F401RE'''&lt;br /&gt;
* Un capteur à ultrason '''Nucleo-53L5A1'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ce wiki est le compte-rendu du projet de '''Jason DELANNOY et Chloé LEMAIRE'''. Nous avons décider de développer une intelligence artificielle permettant de '''déterminer''' '''l'action faite par un joueur de Pierre-Feuille-Ciseau''' à l'aide du capteur à ultrason.&lt;br /&gt;
&lt;br /&gt;
Pour ce faire, nous allons développer notre IA de deux façons :&lt;br /&gt;
&lt;br /&gt;
* En utilisant '''NanoEdge Studio''' : Dans ce cas, le calcul serait fait par la carte programmable et envoyé au serveur via la Raspberry&lt;br /&gt;
* En utilisant '''un algorithme de machine learning ''': Ici, c'est le serveur qui fera le calcul et la Raspberry jouera le rôle de passerelle entre la carte programmable et le serveu&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Mise en oeuvre du réseau &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Création VM XEN ===&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la VM ===&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la borne WIFI Cisco ===&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251 (changement car besoin pour les PEIP) &lt;br /&gt;
&lt;br /&gt;
- dns-server: 193.48.57.33 (changement car problème avec le serveur DNS initial)&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Configuration de la Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadra du projet, nous avons à disposition une Raspberry PI 4 model B que nous allons configurer. Pour ce faire, nous utilisons le logiciel le &amp;quot;Raspberry PI Imager&amp;quot; pour choisir notre OS.&lt;br /&gt;
[[Fichier:JCIE RPI Imager.png|centré|vignette|400x400px]]Maintenant que nous avons une carte SD prête pour la Raspberry, nous la configurons via sa liaison série en passant par minicom :&lt;br /&gt;
 root@zabeth18: / $ minicom -D /dev/ttyACM0 -b 9600&lt;br /&gt;
De plus, nous modifions le fichier /etc/network/interfaces pour pouvoir connecter notre carte au réseau wifi créé plus haut :&lt;br /&gt;
[[Fichier:Screen WiFi.png|centré|vignette|441x441px]]&lt;br /&gt;
Nous verifions ensuite que nous avons une adresse IP :&lt;br /&gt;
[[Fichier:Screenshot from 2023-12-04 17-17-05.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Capteur NUCLEO - 53L5A1 &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Pour ce projet, nous disposons d'une STM32 Nucléo F401RE muni d'un capteur à ultrason X-Nucleo-53L5A1.&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir entrainer notre IA, nous devons faire en sorte d'afficher et de ressortir sur la liaison série les données du capteur. Pour ce faire, nous utilisons le fichier example &amp;quot;'''''53L5A1_ThresholdDetection'''''&amp;quot;. Nous modifions la fonction print_result pour afficher 16 valeurs à la suite :&lt;br /&gt;
[[Fichier:ChifoumIA Print Result.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Après avoir téléversé, nous pouvons vérifier le bon fonctionnement du programme en nous connectant à la carte via minicom :&lt;br /&gt;
&lt;br /&gt;
 root@raspberrypi:/dev$ minicom -D ttyACM0 -b 460800&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Communication VM-Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Envoie de donnée : ===&lt;br /&gt;
&lt;br /&gt;
Dans notre projet, nous avons besoin de remonter les données de notre capteur branché en liaison série à la Raspberry sur le port &amp;quot;ttyACM0&amp;quot;. Nous allons donc passer par des requêtes API entre le serveur sur chassiron et notre Raspberry.&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Raspberry : ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Du côté Raspberry, nous programmons un script en python qui lit sur la liaison série les valeurs du capteurs et les envoie via une requête POST vers le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import requests&lt;br /&gt;
     import json&lt;br /&gt;
     import serial&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;Variable&lt;br /&gt;
     STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
     baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
     Serial_link = serial.Serial(STM32_port,baudrate,timeout=1)&lt;br /&gt;
     print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
     liste_mesures=[]&lt;br /&gt;
     for i in range(101):&lt;br /&gt;
          print(&amp;quot;Mesure&amp;quot;,i)&lt;br /&gt;
          mesure = Serial_link.readline().decode('utf-8')&lt;br /&gt;
          liste_mesures.append(mesure)&lt;br /&gt;
&lt;br /&gt;
     data_to_send = json.dumps(liste_mesures)&lt;br /&gt;
     url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080&amp;quot;&lt;br /&gt;
&lt;br /&gt;
     headers = {&lt;br /&gt;
          'Content-type':'application/json',&lt;br /&gt;
          'Accept':'application/json'&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     r = requests.post(&lt;br /&gt;
          url_request,&lt;br /&gt;
          json=data_to_send,&lt;br /&gt;
          headers=headers&lt;br /&gt;
     )&lt;br /&gt;
     print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Serveur : ====&lt;br /&gt;
La communication entre notre VM et la Raspberry est possible. Nous arrivons à effectuer un ping de l'une sur l'autre en passant par l'addresse IPv6.&lt;br /&gt;
&lt;br /&gt;
IPv6 VM :  2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
IPv6 Raspberry : 2001:660:4401:6050:da3a:ddff:fe59:4cb5&lt;br /&gt;
&lt;br /&gt;
Nous programmons ensuite une API sur notre VM en utilisant la libraire Flask.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import json&lt;br /&gt;
     from flask import Flask&lt;br /&gt;
     from flask import request&lt;br /&gt;
     from waitress import serve&lt;br /&gt;
     from flask import Response&lt;br /&gt;
     from flask_cors import CORS&lt;br /&gt;
     from flask_cors import cross_origin&lt;br /&gt;
&lt;br /&gt;
     app = Flask(__name__)&lt;br /&gt;
     cors = CORS(app, ressourceas={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;:&amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
     def compute_data(data):&lt;br /&gt;
          filename = input(&amp;quot;Nom du fichier :&amp;quot;)&lt;br /&gt;
          to_write = data.split(&amp;quot;\&amp;quot;&amp;quot;)[1:-1]&lt;br /&gt;
          with open(filename, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
               i = 0&lt;br /&gt;
               for elem in to_write:&lt;br /&gt;
                    if i == 0:&lt;br /&gt;
                         print(&amp;quot;We skip&amp;quot;)&lt;br /&gt;
                    else:&lt;br /&gt;
                         if (i%2) == 0:&lt;br /&gt;
                              print(&amp;quot;Data writed :&amp;quot;,elem[:-4])&lt;br /&gt;
                              f.write(elem[:-4])&lt;br /&gt;
                              f.write(&amp;quot;\n&amp;quot;)&lt;br /&gt;
                    i = i + 1&lt;br /&gt;
&lt;br /&gt;
     #Main&lt;br /&gt;
     @app.route('/',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
     @cross_origin()&lt;br /&gt;
     def hello():&lt;br /&gt;
          data = request.json&lt;br /&gt;
          compute_data(data)&lt;br /&gt;
          return data&lt;br /&gt;
&lt;br /&gt;
     if __name__ == '__main__':&lt;br /&gt;
          print(&amp;quot;Listening&amp;quot;)&lt;br /&gt;
          serve(app,host=&amp;quot;::&amp;quot;,port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Implémentation de l'IA : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant qu'on a une communication pour envoyer un fichier à notre serveur depuis la raspberry grâce à notre API, nous la modifions pour que la Raspberry puisse lire la valeur du capteur à ultrason, l'envoyer à notre serveur et recevoir en réponse, la prédiction de l'IA. Nous créons donc une route '''''/predict''''' sur notre API qui récupère les valeurs du capteurs données en paramètre et renvoie la prédiction de l'IA :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 @app.route('/predict',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
 def predict():&lt;br /&gt;
      data = request.json&lt;br /&gt;
      print(data)&lt;br /&gt;
      features = data['Features']&lt;br /&gt;
      print(features)&lt;br /&gt;
      features_splitted = features[0].split(&amp;quot;,&amp;quot;)&lt;br /&gt;
      features_int = [int(elem) for elem in features_splitted]&lt;br /&gt;
      loaded_model = joblib.load('model_entraine.pkl')&lt;br /&gt;
      predictios = loaded_model.predict(np.array(features_int).reshape(1,-1))&lt;br /&gt;
      return jsonify(predictions.tolist())&lt;br /&gt;
&amp;lt;/pre&amp;gt;Nous envoyons ensuite les données à analyser via des requêtes API :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 #Import Librairies&lt;br /&gt;
 import requests&lt;br /&gt;
 import json&lt;br /&gt;
 import serial&lt;br /&gt;
 from flask import jsonify&lt;br /&gt;
&lt;br /&gt;
 #Variable&lt;br /&gt;
 STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
 baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
 Serial_link = serial.Serial(STM32_port, baudrate, timeout=1)&lt;br /&gt;
 print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
 tab_to_send = []&lt;br /&gt;
&lt;br /&gt;
 while True:&lt;br /&gt;
      Serial_link.readline().decode('utf-8')&lt;br /&gt;
      tab_to_send.append(Serial_link.readline().decode('utf-8')&lt;br /&gt;
      if (tab_to_send != [&amp;quot;&amp;quot;]):&lt;br /&gt;
           print(&amp;quot;Data sended :&amp;quot;,tab_to_send)&lt;br /&gt;
           url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080/predict&amp;quot;&lt;br /&gt;
           headers = {&lt;br /&gt;
                'Content-type':'application/json',&lt;br /&gt;
                'Accept':'application/json'&lt;br /&gt;
           }&lt;br /&gt;
           r = requests.post(&lt;br /&gt;
                url_request,&lt;br /&gt;
                json = {&lt;br /&gt;
                     &amp;quot;Features&amp;quot;: tab_to_send&lt;br /&gt;
                },&lt;br /&gt;
                headers=headers&lt;br /&gt;
           )&lt;br /&gt;
           print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
           print(&amp;quot;Response :&amp;quot;,r.json())&lt;br /&gt;
      else:&lt;br /&gt;
           print(&amp;quot;Data skip:&amp;quot;,tab_to_send)&lt;br /&gt;
      tab_to_send.clear()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Entrainement de l'IA &amp;lt;/div&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec NanoEdge AI Studio : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour le projet, nous avons d'abord développé et entrainé notre IA sur la plateforme NanoEdge AI Studio. Pour ce faire, nous devons d'abord définir un projet de classification de n-class (&amp;quot;pierre&amp;quot;,&amp;quot;feuille&amp;quot;,&amp;quot;ciseau&amp;quot;) en utilisant un capteur générique à 16 axes. Pour ce faire, nous modifions le code de la STM32 pour qu'elle renvoie une ligne contenant 16*16 mesure en continue. Une fois le projet créé, nous ajoutons 3 signaux correspondant à nos dataset de &amp;quot;Pierre&amp;quot;, &amp;quot;Feuille&amp;quot; et &amp;quot;Ciseau&amp;quot;. Pour rajouter des valeurs dans notre dataset, nous utilisons la liaison série pour lire les valeurs de notre capteur.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec Scikit : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour la suite de notre projet, nous avons developpé et entrainé une IA avec Scikit.&lt;br /&gt;
&lt;br /&gt;
==== Construction du fichier d'entrainement ====&lt;br /&gt;
Pour commencer, nous avons du construire un fichier csv reprenant nos mesures sur un format de 16 valeurs. Pour chaque mesure, on ajoute en amont de la mesure la catégorie (feuille, ciseau ou pierre). &lt;br /&gt;
[[Fichier:Capture d’écran 2024-01-18 à 16.18.19.png|centré|vignette|500x500px|Fichier chifoumIA.csv]]&lt;br /&gt;
Pour construire ce fichier, nous avons assemblé trois fichiers csv de test que nous avons généré grâce à notre capteur : un fichier d'entrainement Pierre.csv, un fichier d'entrainement Ciseau.csv et un fichier d'entrainement Feuille.csv . &lt;br /&gt;
&lt;br /&gt;
Pour faire cette concaténation nous avons développer un programme python prenant en entrée nos fichiers d'entrainement et fournissant en sortie le fichier csv chifoumIA.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     line_feuille = []&lt;br /&gt;
     line_pierre = []&lt;br /&gt;
     line_ciseau = []&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Feuille.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_feuille = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Pierre.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_pierre = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Ciseau.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_ciseau = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;chifoumIA.csv&amp;quot;,&amp;quot;w&amp;quot;) as f:&lt;br /&gt;
          for elem in line_feuille:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;feuille,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_pierre:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;pierre,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_ciseau:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;ciseau,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Implémentation et Entrainement de notre IA ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant que nous avons notre fichier d'entrainement, nous implémentons notre IA. &lt;br /&gt;
&lt;br /&gt;
Nous avons commencé par créer un tableau de données et un tableau de classes. &lt;br /&gt;
&lt;br /&gt;
Pour remplir ces tableaux, on va lire ligne par ligne le fichier chifoumIA.csv. Le premier élément de la ligne est stockée dans le tableau de classes et le reste de la ligne est stockée dans le tableau de données. &lt;br /&gt;
 chifoumi_data=[]&lt;br /&gt;
 chifoumi_classe=[]&lt;br /&gt;
 &lt;br /&gt;
 with open('chifoumIA.csv') as csv_file:&lt;br /&gt;
        csv_reader = csv.reader(csv_file,delimiter=',')&lt;br /&gt;
        for row in csv_reader:           &lt;br /&gt;
                 chifoumi_data.append([int(row[1]),int(row[2]),int(row[3]),int(row[4]),int(row[5]),int(row[6]),int(row[7]),int(row[8]),&lt;br /&gt;
                                       int(row[9]),int(row[10]),int(row[11]),int(row[12]),int(row[13]),int(row[14]),int(row[15]),int(row[16])])&lt;br /&gt;
                 chifoumi_classe.append(row[0])&lt;br /&gt;
  &lt;br /&gt;
A partir de ces deux tableaux, on construit un ensemble de données d'entraînement et un ensemble de données de tests.&lt;br /&gt;
&lt;br /&gt;
On choisi d'utiliser un réseau de neurone du type MLPClassifer. &lt;br /&gt;
&lt;br /&gt;
Le MLPClassifer est un type de réseau de neurones artificiels composés d'au minimum trois couches de neurones: une couche d'entrée, une ou plusieurs  couches cachées et une couche de sortie. &lt;br /&gt;
&lt;br /&gt;
Dans ce type de réseau, chaque neurone est connecté à l'ensemble des neurones de la couche suivante par un lien auquel est associé un poids. &lt;br /&gt;
&lt;br /&gt;
La classe MLPClassifer implémentée dans la bibliothèque Scikit-Learn dispose de nombreux paramètres. Pour notre projet, nous avons utilisé cette classe de façon très primaire. Les paramètres que nous avons utilisés sont :  &lt;br /&gt;
&lt;br /&gt;
- '''hidden_layer_sizes :''' ce paramètre est un tuple spécifiant le nombre de neurones dans chaque couche cachée. &lt;br /&gt;
&lt;br /&gt;
- '''max_iter :''' ce paramètre représente le nombre maximal d'époque. Il permet de contrôler également le temps d'entrainement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model=MLPClassifier(hidden_layer_sizes=(50,25),max_iter=100,solver='adam')&lt;br /&gt;
&lt;br /&gt;
model.fit(X_train,y_train)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;predictions = model.predict(X_test)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;print(f'Accuracy:{accuracy}')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Déploiement de notre IA ====&lt;br /&gt;
Pour pouvoir déployer notre IA, nous avons enregistré notre model d'entrainement et intégré un service web à notre code existant avec deux endpoint : &lt;br /&gt;
&lt;br /&gt;
- predict : pour effectuer des prédictions sur le model. &lt;br /&gt;
&lt;br /&gt;
- evaluate : pour évaluer les performances du model sur l'ensemble de tests.&lt;br /&gt;
&lt;br /&gt;
==== Code complet ====&lt;br /&gt;
&lt;br /&gt;
====  ipv6 jcie : 2001:660:4401:6050:216:3eff:fe68:8176 ====&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4743</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4743"/>
		<updated>2024-01-28T12:58:15Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /* Implémentation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Introduction Projet IE Delannoy - Lemaire &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadre la matière '''&amp;quot;Intelligence Embarquée&amp;quot;''' de l'UE &amp;quot;Module de Spécialité&amp;quot; des SE5 - Option Systèmes Communicants, nous avons dû concevoir un projet permettant de '''distribuer le calcul et le processus d'entrainement''' et d'utilisation d'un Intelligence Artificielle. Nous devrons distribuer le calcul à différents endroits du réseau afin d'être en mesure de proposer des pistes d'optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, nous allons mettre en oeuvre un réseau d'objets connectés à des passerelles et à un serveur. '''Les objets collecteront des données''' de l'environnemet et suivants les scénarios, traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Nous aurons à disposition :&lt;br /&gt;
&lt;br /&gt;
* Une machine virtuelle sur le serveur '''Chassiron''' en ''E304/306''&lt;br /&gt;
* Une '''Raspberry PI 4'''&lt;br /&gt;
* Un carte programmable '''STM32F401RE'''&lt;br /&gt;
* Un capteur à ultrason '''Nucleo-53L5A1'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ce wiki est le compte-rendu du projet de '''Jason DELANNOY et Chloé LEMAIRE'''. Nous avons décider de développer une intelligence artificielle permettant de '''déterminer''' '''l'action faite par un joueur de Pierre-Feuille-Ciseau''' à l'aide du capteur à ultrason.&lt;br /&gt;
&lt;br /&gt;
Pour ce faire, nous allons développer notre IA de deux façons :&lt;br /&gt;
&lt;br /&gt;
* En utilisant '''NanoEdge Studio''' : Dans ce cas, le calcul serait fait par la carte programmable et envoyé au serveur via la Raspberry&lt;br /&gt;
* En utilisant '''un algorithme de machine learning ''': Ici, c'est le serveur qui fera le calcul et la Raspberry jouera le rôle de passerelle entre la carte programmable et le serveu&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Mise en oeuvre du réseau &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Création VM XEN ===&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la VM ===&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la borne WIFI Cisco ===&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251 (changement car besoin pour les PEIP) &lt;br /&gt;
&lt;br /&gt;
- dns-server: 193.48.57.33 (changement car problème avec le serveur DNS initial)&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Configuration de la Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadra du projet, nous avons à disposition une Raspberry PI 4 model B que nous allons configurer. Pour ce faire, nous utilisons le logiciel le &amp;quot;Raspberry PI Imager&amp;quot; pour choisir notre OS.&lt;br /&gt;
[[Fichier:JCIE RPI Imager.png|centré|vignette|400x400px]]Maintenant que nous avons une carte SD prête pour la Raspberry, nous la configurons via sa liaison série en passant par minicom :&lt;br /&gt;
 root@zabeth18: / $ minicom -D /dev/ttyACM0 -b 9600&lt;br /&gt;
De plus, nous modifions le fichier /etc/network/interfaces pour pouvoir connecter notre carte au réseau wifi créé plus haut :&lt;br /&gt;
[[Fichier:Screen WiFi.png|centré|vignette|441x441px]]&lt;br /&gt;
Nous verifions ensuite que nous avons une adresse IP :&lt;br /&gt;
[[Fichier:Screenshot from 2023-12-04 17-17-05.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Capteur NUCLEO - 53L5A1 &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Pour ce projet, nous disposons d'une STM32 Nucléo F401RE muni d'un capteur à ultrason X-Nucleo-53L5A1.&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir entrainer notre IA, nous devons faire en sorte d'afficher et de ressortir sur la liaison série les données du capteur. Pour ce faire, nous utilisons le fichier example &amp;quot;'''''53L5A1_ThresholdDetection'''''&amp;quot;. Nous modifions la fonction print_result pour afficher 16 valeurs à la suite :&lt;br /&gt;
[[Fichier:ChifoumIA Print Result.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Après avoir téléversé, nous pouvons vérifier le bon fonctionnement du programme en nous connectant à la carte via minicom :&lt;br /&gt;
&lt;br /&gt;
 root@raspberrypi:/dev$ minicom -D ttyACM0 -b 460800&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Communication VM-Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Envoie de donnée : ===&lt;br /&gt;
&lt;br /&gt;
Dans notre projet, nous avons besoin de remonter les données de notre capteur branché en liaison série à la Raspberry sur le port &amp;quot;ttyACM0&amp;quot;. Nous allons donc passer par des requêtes API entre le serveur sur chassiron et notre Raspberry.&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Raspberry : ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Du côté Raspberry, nous programmons un script en python qui lit sur la liaison série les valeurs du capteurs et les envoie via une requête POST vers le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import requests&lt;br /&gt;
     import json&lt;br /&gt;
     import serial&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;Variable&lt;br /&gt;
     STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
     baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
     Serial_link = serial.Serial(STM32_port,baudrate,timeout=1)&lt;br /&gt;
     print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
     liste_mesures=[]&lt;br /&gt;
     for i in range(101):&lt;br /&gt;
          print(&amp;quot;Mesure&amp;quot;,i)&lt;br /&gt;
          mesure = Serial_link.readline().decode('utf-8')&lt;br /&gt;
          liste_mesures.append(mesure)&lt;br /&gt;
&lt;br /&gt;
     data_to_send = json.dumps(liste_mesures)&lt;br /&gt;
     url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080&amp;quot;&lt;br /&gt;
&lt;br /&gt;
     headers = {&lt;br /&gt;
          'Content-type':'application/json',&lt;br /&gt;
          'Accept':'application/json'&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     r = requests.post(&lt;br /&gt;
          url_request,&lt;br /&gt;
          json=data_to_send,&lt;br /&gt;
          headers=headers&lt;br /&gt;
     )&lt;br /&gt;
     print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Serveur : ====&lt;br /&gt;
La communication entre notre VM et la Raspberry est possible. Nous arrivons à effectuer un ping de l'une sur l'autre en passant par l'addresse IPv6.&lt;br /&gt;
&lt;br /&gt;
IPv6 VM :  2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
IPv6 Raspberry : 2001:660:4401:6050:da3a:ddff:fe59:4cb5&lt;br /&gt;
&lt;br /&gt;
Nous programmons ensuite une API sur notre VM en utilisant la libraire Flask.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import json&lt;br /&gt;
     from flask import Flask&lt;br /&gt;
     from flask import request&lt;br /&gt;
     from waitress import serve&lt;br /&gt;
     from flask import Response&lt;br /&gt;
     from flask_cors import CORS&lt;br /&gt;
     from flask_cors import cross_origin&lt;br /&gt;
&lt;br /&gt;
     app = Flask(__name__)&lt;br /&gt;
     cors = CORS(app, ressourceas={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;:&amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
     def compute_data(data):&lt;br /&gt;
          filename = input(&amp;quot;Nom du fichier :&amp;quot;)&lt;br /&gt;
          to_write = data.split(&amp;quot;\&amp;quot;&amp;quot;)[1:-1]&lt;br /&gt;
          with open(filename, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
               i = 0&lt;br /&gt;
               for elem in to_write:&lt;br /&gt;
                    if i == 0:&lt;br /&gt;
                         print(&amp;quot;We skip&amp;quot;)&lt;br /&gt;
                    else:&lt;br /&gt;
                         if (i%2) == 0:&lt;br /&gt;
                              print(&amp;quot;Data writed :&amp;quot;,elem[:-4])&lt;br /&gt;
                              f.write(elem[:-4])&lt;br /&gt;
                              f.write(&amp;quot;\n&amp;quot;)&lt;br /&gt;
                    i = i + 1&lt;br /&gt;
&lt;br /&gt;
     #Main&lt;br /&gt;
     @app.route('/',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
     @cross_origin()&lt;br /&gt;
     def hello():&lt;br /&gt;
          data = request.json&lt;br /&gt;
          compute_data(data)&lt;br /&gt;
          return data&lt;br /&gt;
&lt;br /&gt;
     if __name__ == '__main__':&lt;br /&gt;
          print(&amp;quot;Listening&amp;quot;)&lt;br /&gt;
          serve(app,host=&amp;quot;::&amp;quot;,port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Implémentation de l'IA : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant qu'on a une communication pour envoyer un fichier à notre serveur depuis la raspberry grâce à notre API, nous la modifions pour que la Raspberry puisse lire la valeur du capteur à ultrason, l'envoyer à notre serveur et recevoir en réponse, la prédiction de l'IA. Nous créons donc une route '''''/predict''''' sur notre API qui récupère les valeurs du capteurs données en paramètre et renvoie la prédiction de l'IA :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 @app.route('/predict',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
 def predict():&lt;br /&gt;
      data = request.json&lt;br /&gt;
      print(data)&lt;br /&gt;
      features = data['Features']&lt;br /&gt;
      print(features)&lt;br /&gt;
      features_splitted = features[0].split(&amp;quot;,&amp;quot;)&lt;br /&gt;
      features_int = [int(elem) for elem in features_splitted]&lt;br /&gt;
      loaded_model = joblib.load('model_entraine.pkl')&lt;br /&gt;
      predictios = loaded_model.predict(np.array(features_int).reshape(1,-1))&lt;br /&gt;
      return jsonify(predictions.tolist())&lt;br /&gt;
&amp;lt;/pre&amp;gt;Nous envoyons ensuite les données à analyser via des requêtes API :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 #Import Librairies&lt;br /&gt;
 import requests&lt;br /&gt;
 import json&lt;br /&gt;
 import serial&lt;br /&gt;
 from flask import jsonify&lt;br /&gt;
&lt;br /&gt;
 #Variable&lt;br /&gt;
 STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
 baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
 Serial_link = serial.Serial(STM32_port, baudrate, timeout=1)&lt;br /&gt;
 print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
 tab_to_send = []&lt;br /&gt;
&lt;br /&gt;
 while True:&lt;br /&gt;
      Serial_link.readline().decode('utf-8')&lt;br /&gt;
      tab_to_send.append(Serial_link.readline().decode('utf-8')&lt;br /&gt;
      if (tab_to_send != [&amp;quot;&amp;quot;]):&lt;br /&gt;
           print(&amp;quot;Data sended :&amp;quot;,tab_to_send)&lt;br /&gt;
           url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080/predict&amp;quot;&lt;br /&gt;
           headers = {&lt;br /&gt;
                'Content-type':'application/json',&lt;br /&gt;
                'Accept':'application/json'&lt;br /&gt;
           }&lt;br /&gt;
           r = requests.post(&lt;br /&gt;
                url_request,&lt;br /&gt;
                json = {&lt;br /&gt;
                     &amp;quot;Features&amp;quot;: tab_to_send&lt;br /&gt;
                },&lt;br /&gt;
                headers=headers&lt;br /&gt;
           )&lt;br /&gt;
           print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
           print(&amp;quot;Response :&amp;quot;,r.json())&lt;br /&gt;
      else:&lt;br /&gt;
           print(&amp;quot;Data skip:&amp;quot;,tab_to_send)&lt;br /&gt;
      tab_to_send.clear()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Entrainement de l'IA &amp;lt;/div&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec NanoEdge AI Studio : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour le projet, nous avons d'abord développé et entrainé notre IA sur la plateforme NanoEdge AI Studio. Pour ce faire, nous devons d'abord définir un projet de classification de n-class (&amp;quot;pierre&amp;quot;,&amp;quot;feuille&amp;quot;,&amp;quot;ciseau&amp;quot;) en utilisant un capteur générique à 16 axes. Pour ce faire, nous modifions le code de la STM32 pour qu'elle renvoie une ligne contenant 16*16 mesure en continue. Une fois le projet créé, nous ajoutons 3 signaux correspondant à nos dataset de &amp;quot;Pierre&amp;quot;, &amp;quot;Feuille&amp;quot; et &amp;quot;Ciseau&amp;quot;. Pour rajouter des valeurs dans notre dataset, nous utilisons la liaison série pour lire les valeurs de notre capteur.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec Scikit : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour la suite de notre projet, nous avons developpé et entrainé une IA avec Scikit.&lt;br /&gt;
&lt;br /&gt;
==== Construction du fichier d'entrainement ====&lt;br /&gt;
Pour commencer, nous avons du construire un fichier csv reprenant nos mesures sur un format de 16 valeurs. Pour chaque mesure, on ajoute en amont de la mesure la catégorie (feuille, ciseau ou pierre). &lt;br /&gt;
[[Fichier:Capture d’écran 2024-01-18 à 16.18.19.png|centré|vignette|500x500px|Fichier chifoumIA.csv]]&lt;br /&gt;
Pour construire ce fichier, nous avons assemblé trois fichiers csv de test que nous avons généré grâce à notre capteur : un fichier d'entrainement Pierre.csv, un fichier d'entrainement Ciseau.csv et un fichier d'entrainement Feuille.csv . &lt;br /&gt;
&lt;br /&gt;
Pour faire cette concaténation nous avons développer un programme python prenant en entrée nos fichiers d'entrainement et fournissant en sortie le fichier csv chifoumIA.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     line_feuille = []&lt;br /&gt;
     line_pierre = []&lt;br /&gt;
     line_ciseau = []&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Feuille.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_feuille = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Pierre.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_pierre = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Ciseau.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_ciseau = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;chifoumIA.csv&amp;quot;,&amp;quot;w&amp;quot;) as f:&lt;br /&gt;
          for elem in line_feuille:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;feuille,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_pierre:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;pierre,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_ciseau:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;ciseau,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Implémentation et Entrainement de notre IA ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant que nous avons notre fichier d'entrainement, nous implémentons notre IA. &lt;br /&gt;
&lt;br /&gt;
Nous avons commencé par créer un tableau de données et un tableau de classes. &lt;br /&gt;
&lt;br /&gt;
Pour remplir ces tableaux, on va lire ligne par ligne le fichier chifoumIA.csv. Le premier élément de la ligne est stockée dans le tableau de classes et le reste de la ligne est stockée dans le tableau de données. &lt;br /&gt;
 chifoumi_data=[]&lt;br /&gt;
 chifoumi_classe=[]&lt;br /&gt;
 &lt;br /&gt;
 with open('chifoumIA.csv') as csv_file:&lt;br /&gt;
        csv_reader = csv.reader(csv_file,delimiter=',')&lt;br /&gt;
        for row in csv_reader:           &lt;br /&gt;
                 chifoumi_data.append([int(row[1]),int(row[2]),int(row[3]),int(row[4]),int(row[5]),int(row[6]),int(row[7]),int(row[8]),&lt;br /&gt;
                                       int(row[9]),int(row[10]),int(row[11]),int(row[12]),int(row[13]),int(row[14]),int(row[15]),int(row[16])])&lt;br /&gt;
                 chifoumi_classe.append(row[0])&lt;br /&gt;
  &lt;br /&gt;
A partir de ces deux tableaux, on construit un ensemble de données d'entraînement et un ensemble de données de tests.&lt;br /&gt;
&lt;br /&gt;
On choisi d'utiliser un réseau de neurone du type MLPClassifer. &lt;br /&gt;
&lt;br /&gt;
Le MLPClassifer est un type de réseau de neurones artificiels composés d'au minimum trois couches de neurones: une couche d'entrée, une ou plusieurs  couches cachées et une couche de sortie. &lt;br /&gt;
&lt;br /&gt;
Dans ce type de réseau, chaque neurone est connecté à l'ensemble des neurones de la couche suivante par un lien auquel est associé un poids. &lt;br /&gt;
&lt;br /&gt;
La classe MLPClassifer implémentée dans la bibliothèque Scikit-Learn dispose de nombreux paramètres. Pour notre projet, nous avons utilisé cette classe de façon très primaire. Les paramètres que nous avons utilisés sont :  &lt;br /&gt;
&lt;br /&gt;
- '''hidden_layer_sizes :''' ce paramètre est un tuple spécifiant le nombre de neurones dans chaque couche cachée. &lt;br /&gt;
&lt;br /&gt;
- '''max_iter :''' ce paramètre représente le nombre maximal d'époque. Il permet de contrôler également le temps d'entrainement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model=MLPClassifier(hidden_layer_sizes=(50,25),max_iter=100,solver='adam')&lt;br /&gt;
&lt;br /&gt;
model.fit(X_train,y_train)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;predictions = model.predict(X_test)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;print(f'Accuracy:{accuracy}')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ipv6 jcie : 2001:660:4401:6050:216:3eff:fe68:8176&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4742</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4742"/>
		<updated>2024-01-28T12:47:55Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /* MLPClassifer */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Introduction Projet IE Delannoy - Lemaire &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadre la matière '''&amp;quot;Intelligence Embarquée&amp;quot;''' de l'UE &amp;quot;Module de Spécialité&amp;quot; des SE5 - Option Systèmes Communicants, nous avons dû concevoir un projet permettant de '''distribuer le calcul et le processus d'entrainement''' et d'utilisation d'un Intelligence Artificielle. Nous devrons distribuer le calcul à différents endroits du réseau afin d'être en mesure de proposer des pistes d'optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, nous allons mettre en oeuvre un réseau d'objets connectés à des passerelles et à un serveur. '''Les objets collecteront des données''' de l'environnemet et suivants les scénarios, traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Nous aurons à disposition :&lt;br /&gt;
&lt;br /&gt;
* Une machine virtuelle sur le serveur '''Chassiron''' en ''E304/306''&lt;br /&gt;
* Une '''Raspberry PI 4'''&lt;br /&gt;
* Un carte programmable '''STM32F401RE'''&lt;br /&gt;
* Un capteur à ultrason '''Nucleo-53L5A1'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ce wiki est le compte-rendu du projet de '''Jason DELANNOY et Chloé LEMAIRE'''. Nous avons décider de développer une intelligence artificielle permettant de '''déterminer''' '''l'action faite par un joueur de Pierre-Feuille-Ciseau''' à l'aide du capteur à ultrason.&lt;br /&gt;
&lt;br /&gt;
Pour ce faire, nous allons développer notre IA de deux façons :&lt;br /&gt;
&lt;br /&gt;
* En utilisant '''NanoEdge Studio''' : Dans ce cas, le calcul serait fait par la carte programmable et envoyé au serveur via la Raspberry&lt;br /&gt;
* En utilisant '''un algorithme de machine learning ''': Ici, c'est le serveur qui fera le calcul et la Raspberry jouera le rôle de passerelle entre la carte programmable et le serveu&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Mise en oeuvre du réseau &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Création VM XEN ===&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la VM ===&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la borne WIFI Cisco ===&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251 (changement car besoin pour les PEIP) &lt;br /&gt;
&lt;br /&gt;
- dns-server: 193.48.57.33 (changement car problème avec le serveur DNS initial)&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Configuration de la Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadra du projet, nous avons à disposition une Raspberry PI 4 model B que nous allons configurer. Pour ce faire, nous utilisons le logiciel le &amp;quot;Raspberry PI Imager&amp;quot; pour choisir notre OS.&lt;br /&gt;
[[Fichier:JCIE RPI Imager.png|centré|vignette|400x400px]]Maintenant que nous avons une carte SD prête pour la Raspberry, nous la configurons via sa liaison série en passant par minicom :&lt;br /&gt;
 root@zabeth18: / $ minicom -D /dev/ttyACM0 -b 9600&lt;br /&gt;
De plus, nous modifions le fichier /etc/network/interfaces pour pouvoir connecter notre carte au réseau wifi créé plus haut :&lt;br /&gt;
[[Fichier:Screen WiFi.png|centré|vignette|441x441px]]&lt;br /&gt;
Nous verifions ensuite que nous avons une adresse IP :&lt;br /&gt;
[[Fichier:Screenshot from 2023-12-04 17-17-05.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Capteur NUCLEO - 53L5A1 &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Pour ce projet, nous disposons d'une STM32 Nucléo F401RE muni d'un capteur à ultrason X-Nucleo-53L5A1.&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir entrainer notre IA, nous devons faire en sorte d'afficher et de ressortir sur la liaison série les données du capteur. Pour ce faire, nous utilisons le fichier example &amp;quot;'''''53L5A1_ThresholdDetection'''''&amp;quot;. Nous modifions la fonction print_result pour afficher 16 valeurs à la suite :&lt;br /&gt;
[[Fichier:ChifoumIA Print Result.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Après avoir téléversé, nous pouvons vérifier le bon fonctionnement du programme en nous connectant à la carte via minicom :&lt;br /&gt;
&lt;br /&gt;
 root@raspberrypi:/dev$ minicom -D ttyACM0 -b 460800&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Communication VM-Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Envoie de donnée : ===&lt;br /&gt;
&lt;br /&gt;
Dans notre projet, nous avons besoin de remonter les données de notre capteur branché en liaison série à la Raspberry sur le port &amp;quot;ttyACM0&amp;quot;. Nous allons donc passer par des requêtes API entre le serveur sur chassiron et notre Raspberry.&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Raspberry : ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Du côté Raspberry, nous programmons un script en python qui lit sur la liaison série les valeurs du capteurs et les envoie via une requête POST vers le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import requests&lt;br /&gt;
     import json&lt;br /&gt;
     import serial&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;Variable&lt;br /&gt;
     STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
     baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
     Serial_link = serial.Serial(STM32_port,baudrate,timeout=1)&lt;br /&gt;
     print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
     liste_mesures=[]&lt;br /&gt;
     for i in range(101):&lt;br /&gt;
          print(&amp;quot;Mesure&amp;quot;,i)&lt;br /&gt;
          mesure = Serial_link.readline().decode('utf-8')&lt;br /&gt;
          liste_mesures.append(mesure)&lt;br /&gt;
&lt;br /&gt;
     data_to_send = json.dumps(liste_mesures)&lt;br /&gt;
     url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080&amp;quot;&lt;br /&gt;
&lt;br /&gt;
     headers = {&lt;br /&gt;
          'Content-type':'application/json',&lt;br /&gt;
          'Accept':'application/json'&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     r = requests.post(&lt;br /&gt;
          url_request,&lt;br /&gt;
          json=data_to_send,&lt;br /&gt;
          headers=headers&lt;br /&gt;
     )&lt;br /&gt;
     print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Serveur : ====&lt;br /&gt;
La communication entre notre VM et la Raspberry est possible. Nous arrivons à effectuer un ping de l'une sur l'autre en passant par l'addresse IPv6.&lt;br /&gt;
&lt;br /&gt;
IPv6 VM :  2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
IPv6 Raspberry : 2001:660:4401:6050:da3a:ddff:fe59:4cb5&lt;br /&gt;
&lt;br /&gt;
Nous programmons ensuite une API sur notre VM en utilisant la libraire Flask.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import json&lt;br /&gt;
     from flask import Flask&lt;br /&gt;
     from flask import request&lt;br /&gt;
     from waitress import serve&lt;br /&gt;
     from flask import Response&lt;br /&gt;
     from flask_cors import CORS&lt;br /&gt;
     from flask_cors import cross_origin&lt;br /&gt;
&lt;br /&gt;
     app = Flask(__name__)&lt;br /&gt;
     cors = CORS(app, ressourceas={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;:&amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
     def compute_data(data):&lt;br /&gt;
          filename = input(&amp;quot;Nom du fichier :&amp;quot;)&lt;br /&gt;
          to_write = data.split(&amp;quot;\&amp;quot;&amp;quot;)[1:-1]&lt;br /&gt;
          with open(filename, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
               i = 0&lt;br /&gt;
               for elem in to_write:&lt;br /&gt;
                    if i == 0:&lt;br /&gt;
                         print(&amp;quot;We skip&amp;quot;)&lt;br /&gt;
                    else:&lt;br /&gt;
                         if (i%2) == 0:&lt;br /&gt;
                              print(&amp;quot;Data writed :&amp;quot;,elem[:-4])&lt;br /&gt;
                              f.write(elem[:-4])&lt;br /&gt;
                              f.write(&amp;quot;\n&amp;quot;)&lt;br /&gt;
                    i = i + 1&lt;br /&gt;
&lt;br /&gt;
     #Main&lt;br /&gt;
     @app.route('/',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
     @cross_origin()&lt;br /&gt;
     def hello():&lt;br /&gt;
          data = request.json&lt;br /&gt;
          compute_data(data)&lt;br /&gt;
          return data&lt;br /&gt;
&lt;br /&gt;
     if __name__ == '__main__':&lt;br /&gt;
          print(&amp;quot;Listening&amp;quot;)&lt;br /&gt;
          serve(app,host=&amp;quot;::&amp;quot;,port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Implémentation de l'IA : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant qu'on a une communication pour envoyer un fichier à notre serveur depuis la raspberry grâce à notre API, nous la modifions pour que la Raspberry puisse lire la valeur du capteur à ultrason, l'envoyer à notre serveur et recevoir en réponse, la prédiction de l'IA. Nous créons donc une route '''''/predict''''' sur notre API qui récupère les valeurs du capteurs données en paramètre et renvoie la prédiction de l'IA :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 @app.route('/predict',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
 def predict():&lt;br /&gt;
      data = request.json&lt;br /&gt;
      print(data)&lt;br /&gt;
      features = data['Features']&lt;br /&gt;
      print(features)&lt;br /&gt;
      features_splitted = features[0].split(&amp;quot;,&amp;quot;)&lt;br /&gt;
      features_int = [int(elem) for elem in features_splitted]&lt;br /&gt;
      loaded_model = joblib.load('model_entraine.pkl')&lt;br /&gt;
      predictios = loaded_model.predict(np.array(features_int).reshape(1,-1))&lt;br /&gt;
      return jsonify(predictions.tolist())&lt;br /&gt;
&amp;lt;/pre&amp;gt;Nous envoyons ensuite les données à analyser via des requêtes API :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 #Import Librairies&lt;br /&gt;
 import requests&lt;br /&gt;
 import json&lt;br /&gt;
 import serial&lt;br /&gt;
 from flask import jsonify&lt;br /&gt;
&lt;br /&gt;
 #Variable&lt;br /&gt;
 STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
 baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
 Serial_link = serial.Serial(STM32_port, baudrate, timeout=1)&lt;br /&gt;
 print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
 tab_to_send = []&lt;br /&gt;
&lt;br /&gt;
 while True:&lt;br /&gt;
      Serial_link.readline().decode('utf-8')&lt;br /&gt;
      tab_to_send.append(Serial_link.readline().decode('utf-8')&lt;br /&gt;
      if (tab_to_send != [&amp;quot;&amp;quot;]):&lt;br /&gt;
           print(&amp;quot;Data sended :&amp;quot;,tab_to_send)&lt;br /&gt;
           url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080/predict&amp;quot;&lt;br /&gt;
           headers = {&lt;br /&gt;
                'Content-type':'application/json',&lt;br /&gt;
                'Accept':'application/json'&lt;br /&gt;
           }&lt;br /&gt;
           r = requests.post(&lt;br /&gt;
                url_request,&lt;br /&gt;
                json = {&lt;br /&gt;
                     &amp;quot;Features&amp;quot;: tab_to_send&lt;br /&gt;
                },&lt;br /&gt;
                headers=headers&lt;br /&gt;
           )&lt;br /&gt;
           print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
           print(&amp;quot;Response :&amp;quot;,r.json())&lt;br /&gt;
      else:&lt;br /&gt;
           print(&amp;quot;Data skip:&amp;quot;,tab_to_send)&lt;br /&gt;
      tab_to_send.clear()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Entrainement de l'IA &amp;lt;/div&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec NanoEdge AI Studio : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour le projet, nous avons d'abord développé et entrainé notre IA sur la plateforme NanoEdge AI Studio. Pour ce faire, nous devons d'abord définir un projet de classification de n-class (&amp;quot;pierre&amp;quot;,&amp;quot;feuille&amp;quot;,&amp;quot;ciseau&amp;quot;) en utilisant un capteur générique à 16 axes. Pour ce faire, nous modifions le code de la STM32 pour qu'elle renvoie une ligne contenant 16*16 mesure en continue. Une fois le projet créé, nous ajoutons 3 signaux correspondant à nos dataset de &amp;quot;Pierre&amp;quot;, &amp;quot;Feuille&amp;quot; et &amp;quot;Ciseau&amp;quot;. Pour rajouter des valeurs dans notre dataset, nous utilisons la liaison série pour lire les valeurs de notre capteur.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec Scikit : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour la suite de notre projet, nous avons developpé et entrainé une IA avec Scikit.&lt;br /&gt;
&lt;br /&gt;
==== Construction du fichier d'entrainement ====&lt;br /&gt;
Pour commencer, nous avons du construire un fichier csv reprenant nos mesures sur un format de 16 valeurs. Pour chaque mesure, on ajoute en amont de la mesure la catégorie (feuille, ciseau ou pierre). &lt;br /&gt;
[[Fichier:Capture d’écran 2024-01-18 à 16.18.19.png|centré|vignette|500x500px|Fichier chifoumIA.csv]]&lt;br /&gt;
Pour construire ce fichier, nous avons assemblé trois fichiers csv de test que nous avons généré grâce à notre capteur : un fichier d'entrainement Pierre.csv, un fichier d'entrainement Ciseau.csv et un fichier d'entrainement Feuille.csv . &lt;br /&gt;
&lt;br /&gt;
Pour faire cette concaténation nous avons développer un programme python prenant en entrée nos fichiers d'entrainement et fournissant en sortie le fichier csv chifoumIA.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     line_feuille = []&lt;br /&gt;
     line_pierre = []&lt;br /&gt;
     line_ciseau = []&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Feuille.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_feuille = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Pierre.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_pierre = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Ciseau.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_ciseau = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;chifoumIA.csv&amp;quot;,&amp;quot;w&amp;quot;) as f:&lt;br /&gt;
          for elem in line_feuille:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;feuille,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_pierre:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;pierre,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_ciseau:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;ciseau,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Implémentation et Entrainement de notre IA ====&lt;br /&gt;
&lt;br /&gt;
===== Implémentation =====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant que nous avons notre fichier d'entrainement, nous implémentons notre IA. &lt;br /&gt;
&lt;br /&gt;
Nous avons commencé par créer un tableau de données et un tableau de classes. &lt;br /&gt;
&lt;br /&gt;
Pour remplir ces tableaux, on va lire ligne par ligne le fichier chifoumIA.csv. Le premier élément de la ligne est stockée dans le tableau de classes et le reste de la ligne est stockée dans le tableau de données. &lt;br /&gt;
 chifoumi_data=[]&lt;br /&gt;
 chifoumi_classe=[]&lt;br /&gt;
 &lt;br /&gt;
 with open('chifoumIA.csv') as csv_file:&lt;br /&gt;
        csv_reader = csv.reader(csv_file,delimiter=',')&lt;br /&gt;
        for row in csv_reader:           &lt;br /&gt;
                 chifoumi_data.append([int(row[1]),int(row[2]),int(row[3]),int(row[4]),int(row[5]),int(row[6]),int(row[7]),int(row[8]),&lt;br /&gt;
                                       int(row[9]),int(row[10]),int(row[11]),int(row[12]),int(row[13]),int(row[14]),int(row[15]),int(row[16])])&lt;br /&gt;
                 chifoumi_classe.append(row[0])&lt;br /&gt;
  &lt;br /&gt;
A partir de ces deux tableaux, on construit un ensemble de données d'entraînement et un ensemble de données de tests.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On choisi d'utiliser un réseau de neurone du type MLPClassifer. &lt;br /&gt;
&lt;br /&gt;
====== MLPClassifer ======&lt;br /&gt;
Le MLPClassifer est un type de réseau de neurones artificiels composés d'au minimum trois couches de neurones: une couche d'entrée, une ou plusieurs  couches cachées et une couche de sortie. &lt;br /&gt;
&lt;br /&gt;
Dans ce type de réseau, chaque neurone est connecté à l'ensemble des neurones de la couche suivante par un lien auquel est associé un poids. &lt;br /&gt;
&lt;br /&gt;
La classe MLPClassifer implémentée dans la bibliothèque Scikit-Learn dispose de nombreux paramètres. Pour notre projet, nous avons utilisé cette classe de façon très primaire. Les paramètres que nous avons utilisés sont :  &lt;br /&gt;
&lt;br /&gt;
- '''hidden_layer_sizes :''' ce paramètre est un tuple spécifiant le nombre de neurones dans chaque couche cachée. &lt;br /&gt;
&lt;br /&gt;
- '''max_iter :''' ce paramètre représente le nombre maximal d'époque. Il permet de contrôler également le temps d'entrainement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model=MLPClassifier(hidden_layer_sizes=(50,25),max_iter=100,solver='adam')&lt;br /&gt;
&lt;br /&gt;
model.fit(X_train,y_train)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;predictions = model.predict(X_test)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;print(f'Accuracy:{accuracy}')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ipv6 jcie : 2001:660:4401:6050:216:3eff:fe68:8176&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4740</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4740"/>
		<updated>2024-01-28T12:46:24Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /* MLPClassifer */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Introduction Projet IE Delannoy - Lemaire &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadre la matière '''&amp;quot;Intelligence Embarquée&amp;quot;''' de l'UE &amp;quot;Module de Spécialité&amp;quot; des SE5 - Option Systèmes Communicants, nous avons dû concevoir un projet permettant de '''distribuer le calcul et le processus d'entrainement''' et d'utilisation d'un Intelligence Artificielle. Nous devrons distribuer le calcul à différents endroits du réseau afin d'être en mesure de proposer des pistes d'optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, nous allons mettre en oeuvre un réseau d'objets connectés à des passerelles et à un serveur. '''Les objets collecteront des données''' de l'environnemet et suivants les scénarios, traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Nous aurons à disposition :&lt;br /&gt;
&lt;br /&gt;
* Une machine virtuelle sur le serveur '''Chassiron''' en ''E304/306''&lt;br /&gt;
* Une '''Raspberry PI 4'''&lt;br /&gt;
* Un carte programmable '''STM32F401RE'''&lt;br /&gt;
* Un capteur à ultrason '''Nucleo-53L5A1'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ce wiki est le compte-rendu du projet de '''Jason DELANNOY et Chloé LEMAIRE'''. Nous avons décider de développer une intelligence artificielle permettant de '''déterminer''' '''l'action faite par un joueur de Pierre-Feuille-Ciseau''' à l'aide du capteur à ultrason.&lt;br /&gt;
&lt;br /&gt;
Pour ce faire, nous allons développer notre IA de deux façons :&lt;br /&gt;
&lt;br /&gt;
* En utilisant '''NanoEdge Studio''' : Dans ce cas, le calcul serait fait par la carte programmable et envoyé au serveur via la Raspberry&lt;br /&gt;
* En utilisant '''un algorithme de machine learning ''': Ici, c'est le serveur qui fera le calcul et la Raspberry jouera le rôle de passerelle entre la carte programmable et le serveu&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Mise en oeuvre du réseau &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Création VM XEN ===&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la VM ===&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la borne WIFI Cisco ===&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251 (changement car besoin pour les PEIP) &lt;br /&gt;
&lt;br /&gt;
- dns-server: 193.48.57.33 (changement car problème avec le serveur DNS initial)&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Configuration de la Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadra du projet, nous avons à disposition une Raspberry PI 4 model B que nous allons configurer. Pour ce faire, nous utilisons le logiciel le &amp;quot;Raspberry PI Imager&amp;quot; pour choisir notre OS.&lt;br /&gt;
[[Fichier:JCIE RPI Imager.png|centré|vignette|400x400px]]Maintenant que nous avons une carte SD prête pour la Raspberry, nous la configurons via sa liaison série en passant par minicom :&lt;br /&gt;
 root@zabeth18: / $ minicom -D /dev/ttyACM0 -b 9600&lt;br /&gt;
De plus, nous modifions le fichier /etc/network/interfaces pour pouvoir connecter notre carte au réseau wifi créé plus haut :&lt;br /&gt;
[[Fichier:Screen WiFi.png|centré|vignette|441x441px]]&lt;br /&gt;
Nous verifions ensuite que nous avons une adresse IP :&lt;br /&gt;
[[Fichier:Screenshot from 2023-12-04 17-17-05.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Capteur NUCLEO - 53L5A1 &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Pour ce projet, nous disposons d'une STM32 Nucléo F401RE muni d'un capteur à ultrason X-Nucleo-53L5A1.&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir entrainer notre IA, nous devons faire en sorte d'afficher et de ressortir sur la liaison série les données du capteur. Pour ce faire, nous utilisons le fichier example &amp;quot;'''''53L5A1_ThresholdDetection'''''&amp;quot;. Nous modifions la fonction print_result pour afficher 16 valeurs à la suite :&lt;br /&gt;
[[Fichier:ChifoumIA Print Result.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Après avoir téléversé, nous pouvons vérifier le bon fonctionnement du programme en nous connectant à la carte via minicom :&lt;br /&gt;
&lt;br /&gt;
 root@raspberrypi:/dev$ minicom -D ttyACM0 -b 460800&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Communication VM-Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Envoie de donnée : ===&lt;br /&gt;
&lt;br /&gt;
Dans notre projet, nous avons besoin de remonter les données de notre capteur branché en liaison série à la Raspberry sur le port &amp;quot;ttyACM0&amp;quot;. Nous allons donc passer par des requêtes API entre le serveur sur chassiron et notre Raspberry.&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Raspberry : ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Du côté Raspberry, nous programmons un script en python qui lit sur la liaison série les valeurs du capteurs et les envoie via une requête POST vers le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import requests&lt;br /&gt;
     import json&lt;br /&gt;
     import serial&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;Variable&lt;br /&gt;
     STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
     baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
     Serial_link = serial.Serial(STM32_port,baudrate,timeout=1)&lt;br /&gt;
     print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
     liste_mesures=[]&lt;br /&gt;
     for i in range(101):&lt;br /&gt;
          print(&amp;quot;Mesure&amp;quot;,i)&lt;br /&gt;
          mesure = Serial_link.readline().decode('utf-8')&lt;br /&gt;
          liste_mesures.append(mesure)&lt;br /&gt;
&lt;br /&gt;
     data_to_send = json.dumps(liste_mesures)&lt;br /&gt;
     url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080&amp;quot;&lt;br /&gt;
&lt;br /&gt;
     headers = {&lt;br /&gt;
          'Content-type':'application/json',&lt;br /&gt;
          'Accept':'application/json'&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     r = requests.post(&lt;br /&gt;
          url_request,&lt;br /&gt;
          json=data_to_send,&lt;br /&gt;
          headers=headers&lt;br /&gt;
     )&lt;br /&gt;
     print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Serveur : ====&lt;br /&gt;
La communication entre notre VM et la Raspberry est possible. Nous arrivons à effectuer un ping de l'une sur l'autre en passant par l'addresse IPv6.&lt;br /&gt;
&lt;br /&gt;
IPv6 VM :  2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
IPv6 Raspberry : 2001:660:4401:6050:da3a:ddff:fe59:4cb5&lt;br /&gt;
&lt;br /&gt;
Nous programmons ensuite une API sur notre VM en utilisant la libraire Flask.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import json&lt;br /&gt;
     from flask import Flask&lt;br /&gt;
     from flask import request&lt;br /&gt;
     from waitress import serve&lt;br /&gt;
     from flask import Response&lt;br /&gt;
     from flask_cors import CORS&lt;br /&gt;
     from flask_cors import cross_origin&lt;br /&gt;
&lt;br /&gt;
     app = Flask(__name__)&lt;br /&gt;
     cors = CORS(app, ressourceas={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;:&amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
     def compute_data(data):&lt;br /&gt;
          filename = input(&amp;quot;Nom du fichier :&amp;quot;)&lt;br /&gt;
          to_write = data.split(&amp;quot;\&amp;quot;&amp;quot;)[1:-1]&lt;br /&gt;
          with open(filename, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
               i = 0&lt;br /&gt;
               for elem in to_write:&lt;br /&gt;
                    if i == 0:&lt;br /&gt;
                         print(&amp;quot;We skip&amp;quot;)&lt;br /&gt;
                    else:&lt;br /&gt;
                         if (i%2) == 0:&lt;br /&gt;
                              print(&amp;quot;Data writed :&amp;quot;,elem[:-4])&lt;br /&gt;
                              f.write(elem[:-4])&lt;br /&gt;
                              f.write(&amp;quot;\n&amp;quot;)&lt;br /&gt;
                    i = i + 1&lt;br /&gt;
&lt;br /&gt;
     #Main&lt;br /&gt;
     @app.route('/',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
     @cross_origin()&lt;br /&gt;
     def hello():&lt;br /&gt;
          data = request.json&lt;br /&gt;
          compute_data(data)&lt;br /&gt;
          return data&lt;br /&gt;
&lt;br /&gt;
     if __name__ == '__main__':&lt;br /&gt;
          print(&amp;quot;Listening&amp;quot;)&lt;br /&gt;
          serve(app,host=&amp;quot;::&amp;quot;,port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Implémentation de l'IA : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant qu'on a une communication pour envoyer un fichier à notre serveur depuis la raspberry grâce à notre API, nous la modifions pour que la Raspberry puisse lire la valeur du capteur à ultrason, l'envoyer à notre serveur et recevoir en réponse, la prédiction de l'IA. Nous créons donc une route '''''/predict''''' sur notre API qui récupère les valeurs du capteurs données en paramètre et renvoie la prédiction de l'IA :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 @app.route('/predict',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
 def predict():&lt;br /&gt;
      data = request.json&lt;br /&gt;
      print(data)&lt;br /&gt;
      features = data['Features']&lt;br /&gt;
      print(features)&lt;br /&gt;
      features_splitted = features[0].split(&amp;quot;,&amp;quot;)&lt;br /&gt;
      features_int = [int(elem) for elem in features_splitted]&lt;br /&gt;
      loaded_model = joblib.load('model_entraine.pkl')&lt;br /&gt;
      predictios = loaded_model.predict(np.array(features_int).reshape(1,-1))&lt;br /&gt;
      return jsonify(predictions.tolist())&lt;br /&gt;
&amp;lt;/pre&amp;gt;Nous envoyons ensuite les données à analyser via des requêtes API :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 #Import Librairies&lt;br /&gt;
 import requests&lt;br /&gt;
 import json&lt;br /&gt;
 import serial&lt;br /&gt;
 from flask import jsonify&lt;br /&gt;
&lt;br /&gt;
 #Variable&lt;br /&gt;
 STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
 baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
 Serial_link = serial.Serial(STM32_port, baudrate, timeout=1)&lt;br /&gt;
 print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
 tab_to_send = []&lt;br /&gt;
&lt;br /&gt;
 while True:&lt;br /&gt;
      Serial_link.readline().decode('utf-8')&lt;br /&gt;
      tab_to_send.append(Serial_link.readline().decode('utf-8')&lt;br /&gt;
      if (tab_to_send != [&amp;quot;&amp;quot;]):&lt;br /&gt;
           print(&amp;quot;Data sended :&amp;quot;,tab_to_send)&lt;br /&gt;
           url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080/predict&amp;quot;&lt;br /&gt;
           headers = {&lt;br /&gt;
                'Content-type':'application/json',&lt;br /&gt;
                'Accept':'application/json'&lt;br /&gt;
           }&lt;br /&gt;
           r = requests.post(&lt;br /&gt;
                url_request,&lt;br /&gt;
                json = {&lt;br /&gt;
                     &amp;quot;Features&amp;quot;: tab_to_send&lt;br /&gt;
                },&lt;br /&gt;
                headers=headers&lt;br /&gt;
           )&lt;br /&gt;
           print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
           print(&amp;quot;Response :&amp;quot;,r.json())&lt;br /&gt;
      else:&lt;br /&gt;
           print(&amp;quot;Data skip:&amp;quot;,tab_to_send)&lt;br /&gt;
      tab_to_send.clear()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Entrainement de l'IA &amp;lt;/div&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec NanoEdge AI Studio : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour le projet, nous avons d'abord développé et entrainé notre IA sur la plateforme NanoEdge AI Studio. Pour ce faire, nous devons d'abord définir un projet de classification de n-class (&amp;quot;pierre&amp;quot;,&amp;quot;feuille&amp;quot;,&amp;quot;ciseau&amp;quot;) en utilisant un capteur générique à 16 axes. Pour ce faire, nous modifions le code de la STM32 pour qu'elle renvoie une ligne contenant 16*16 mesure en continue. Une fois le projet créé, nous ajoutons 3 signaux correspondant à nos dataset de &amp;quot;Pierre&amp;quot;, &amp;quot;Feuille&amp;quot; et &amp;quot;Ciseau&amp;quot;. Pour rajouter des valeurs dans notre dataset, nous utilisons la liaison série pour lire les valeurs de notre capteur.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec Scikit : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour la suite de notre projet, nous avons developpé et entrainé une IA avec Scikit.&lt;br /&gt;
&lt;br /&gt;
==== Construction du fichier d'entrainement ====&lt;br /&gt;
Pour commencer, nous avons du construire un fichier csv reprenant nos mesures sur un format de 16 valeurs. Pour chaque mesure, on ajoute en amont de la mesure la catégorie (feuille, ciseau ou pierre). &lt;br /&gt;
[[Fichier:Capture d’écran 2024-01-18 à 16.18.19.png|centré|vignette|500x500px|Fichier chifoumIA.csv]]&lt;br /&gt;
Pour construire ce fichier, nous avons assemblé trois fichiers csv de test que nous avons généré grâce à notre capteur : un fichier d'entrainement Pierre.csv, un fichier d'entrainement Ciseau.csv et un fichier d'entrainement Feuille.csv . &lt;br /&gt;
&lt;br /&gt;
Pour faire cette concaténation nous avons développer un programme python prenant en entrée nos fichiers d'entrainement et fournissant en sortie le fichier csv chifoumIA.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     line_feuille = []&lt;br /&gt;
     line_pierre = []&lt;br /&gt;
     line_ciseau = []&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Feuille.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_feuille = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Pierre.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_pierre = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Ciseau.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_ciseau = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;chifoumIA.csv&amp;quot;,&amp;quot;w&amp;quot;) as f:&lt;br /&gt;
          for elem in line_feuille:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;feuille,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_pierre:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;pierre,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_ciseau:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;ciseau,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Implémentation et Entrainement de notre IA ====&lt;br /&gt;
&lt;br /&gt;
===== Implémentation =====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant que nous avons notre fichier d'entrainement, nous implémentons notre IA. &lt;br /&gt;
&lt;br /&gt;
Nous avons commencé par créer un tableau de données et un tableau de classes. &lt;br /&gt;
&lt;br /&gt;
Pour remplir ces tableaux, on va lire ligne par ligne le fichier chifoumIA.csv. Le premier élément de la ligne est stockée dans le tableau de classes et le reste de la ligne est stockée dans le tableau de données. &lt;br /&gt;
 chifoumi_data=[]&lt;br /&gt;
 chifoumi_classe=[]&lt;br /&gt;
 &lt;br /&gt;
 with open('chifoumIA.csv') as csv_file:&lt;br /&gt;
        csv_reader = csv.reader(csv_file,delimiter=',')&lt;br /&gt;
        for row in csv_reader:           &lt;br /&gt;
                 chifoumi_data.append([int(row[1]),int(row[2]),int(row[3]),int(row[4]),int(row[5]),int(row[6]),int(row[7]),int(row[8]),&lt;br /&gt;
                                       int(row[9]),int(row[10]),int(row[11]),int(row[12]),int(row[13]),int(row[14]),int(row[15]),int(row[16])])&lt;br /&gt;
                 chifoumi_classe.append(row[0])&lt;br /&gt;
  &lt;br /&gt;
A partir de ces deux tableaux, on construit un ensemble de données d'entraînement et un ensemble de données de tests.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On choisi d'utiliser un réseau de neurone du type MLPClassifer. &lt;br /&gt;
&lt;br /&gt;
====== MLPClassifer ======&lt;br /&gt;
Le MLPClassifer est un type de réseau de neurones artificiels composés d'au minimum trois couches de neurones: une couche d'entrée, une ou plusieurs  couches cachées et une couche de sortie. &lt;br /&gt;
&lt;br /&gt;
Dans ce type de réseau, chaque neurone est connecté à l'ensemble des neurones de la couche suivante par un lien auquel est associé un poids. &lt;br /&gt;
&lt;br /&gt;
La classe MLPClassifer implémentée dans la bibliothèque Scikit-Learn dispose de nombreux paramètres. Pour notre projet, nous avons utilisé cette classe de façon très primaire. Les paramètres que nous avons utilisés sont :  &lt;br /&gt;
&lt;br /&gt;
- '''hidden_layer_sizes :''' ce paramètre est un tuple spécifiant le nombre de neurones dans chaque couche cachée. &lt;br /&gt;
&lt;br /&gt;
- '''max_iter :''' ce paramètre représente le nombre maximal d'époque. Il permet de contrôler également le temps d'entrainement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre/&amp;gt;&lt;br /&gt;
model=MLPClassifier(hidden_layer_sizes=(50,25),max_iter=100,solver='adam')&lt;br /&gt;
&lt;br /&gt;
model.fit(X_train,y_train)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;predictions = model.predict(X_test)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;print(f'Accuracy:{accuracy}')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ipv6 jcie : 2001:660:4401:6050:216:3eff:fe68:8176&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4739</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4739"/>
		<updated>2024-01-28T12:45:42Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /* MLPClassifer */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Introduction Projet IE Delannoy - Lemaire &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadre la matière '''&amp;quot;Intelligence Embarquée&amp;quot;''' de l'UE &amp;quot;Module de Spécialité&amp;quot; des SE5 - Option Systèmes Communicants, nous avons dû concevoir un projet permettant de '''distribuer le calcul et le processus d'entrainement''' et d'utilisation d'un Intelligence Artificielle. Nous devrons distribuer le calcul à différents endroits du réseau afin d'être en mesure de proposer des pistes d'optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, nous allons mettre en oeuvre un réseau d'objets connectés à des passerelles et à un serveur. '''Les objets collecteront des données''' de l'environnemet et suivants les scénarios, traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Nous aurons à disposition :&lt;br /&gt;
&lt;br /&gt;
* Une machine virtuelle sur le serveur '''Chassiron''' en ''E304/306''&lt;br /&gt;
* Une '''Raspberry PI 4'''&lt;br /&gt;
* Un carte programmable '''STM32F401RE'''&lt;br /&gt;
* Un capteur à ultrason '''Nucleo-53L5A1'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ce wiki est le compte-rendu du projet de '''Jason DELANNOY et Chloé LEMAIRE'''. Nous avons décider de développer une intelligence artificielle permettant de '''déterminer''' '''l'action faite par un joueur de Pierre-Feuille-Ciseau''' à l'aide du capteur à ultrason.&lt;br /&gt;
&lt;br /&gt;
Pour ce faire, nous allons développer notre IA de deux façons :&lt;br /&gt;
&lt;br /&gt;
* En utilisant '''NanoEdge Studio''' : Dans ce cas, le calcul serait fait par la carte programmable et envoyé au serveur via la Raspberry&lt;br /&gt;
* En utilisant '''un algorithme de machine learning ''': Ici, c'est le serveur qui fera le calcul et la Raspberry jouera le rôle de passerelle entre la carte programmable et le serveu&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Mise en oeuvre du réseau &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Création VM XEN ===&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la VM ===&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la borne WIFI Cisco ===&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251 (changement car besoin pour les PEIP) &lt;br /&gt;
&lt;br /&gt;
- dns-server: 193.48.57.33 (changement car problème avec le serveur DNS initial)&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Configuration de la Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadra du projet, nous avons à disposition une Raspberry PI 4 model B que nous allons configurer. Pour ce faire, nous utilisons le logiciel le &amp;quot;Raspberry PI Imager&amp;quot; pour choisir notre OS.&lt;br /&gt;
[[Fichier:JCIE RPI Imager.png|centré|vignette|400x400px]]Maintenant que nous avons une carte SD prête pour la Raspberry, nous la configurons via sa liaison série en passant par minicom :&lt;br /&gt;
 root@zabeth18: / $ minicom -D /dev/ttyACM0 -b 9600&lt;br /&gt;
De plus, nous modifions le fichier /etc/network/interfaces pour pouvoir connecter notre carte au réseau wifi créé plus haut :&lt;br /&gt;
[[Fichier:Screen WiFi.png|centré|vignette|441x441px]]&lt;br /&gt;
Nous verifions ensuite que nous avons une adresse IP :&lt;br /&gt;
[[Fichier:Screenshot from 2023-12-04 17-17-05.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Capteur NUCLEO - 53L5A1 &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Pour ce projet, nous disposons d'une STM32 Nucléo F401RE muni d'un capteur à ultrason X-Nucleo-53L5A1.&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir entrainer notre IA, nous devons faire en sorte d'afficher et de ressortir sur la liaison série les données du capteur. Pour ce faire, nous utilisons le fichier example &amp;quot;'''''53L5A1_ThresholdDetection'''''&amp;quot;. Nous modifions la fonction print_result pour afficher 16 valeurs à la suite :&lt;br /&gt;
[[Fichier:ChifoumIA Print Result.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Après avoir téléversé, nous pouvons vérifier le bon fonctionnement du programme en nous connectant à la carte via minicom :&lt;br /&gt;
&lt;br /&gt;
 root@raspberrypi:/dev$ minicom -D ttyACM0 -b 460800&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Communication VM-Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Envoie de donnée : ===&lt;br /&gt;
&lt;br /&gt;
Dans notre projet, nous avons besoin de remonter les données de notre capteur branché en liaison série à la Raspberry sur le port &amp;quot;ttyACM0&amp;quot;. Nous allons donc passer par des requêtes API entre le serveur sur chassiron et notre Raspberry.&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Raspberry : ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Du côté Raspberry, nous programmons un script en python qui lit sur la liaison série les valeurs du capteurs et les envoie via une requête POST vers le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import requests&lt;br /&gt;
     import json&lt;br /&gt;
     import serial&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;Variable&lt;br /&gt;
     STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
     baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
     Serial_link = serial.Serial(STM32_port,baudrate,timeout=1)&lt;br /&gt;
     print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
     liste_mesures=[]&lt;br /&gt;
     for i in range(101):&lt;br /&gt;
          print(&amp;quot;Mesure&amp;quot;,i)&lt;br /&gt;
          mesure = Serial_link.readline().decode('utf-8')&lt;br /&gt;
          liste_mesures.append(mesure)&lt;br /&gt;
&lt;br /&gt;
     data_to_send = json.dumps(liste_mesures)&lt;br /&gt;
     url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080&amp;quot;&lt;br /&gt;
&lt;br /&gt;
     headers = {&lt;br /&gt;
          'Content-type':'application/json',&lt;br /&gt;
          'Accept':'application/json'&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     r = requests.post(&lt;br /&gt;
          url_request,&lt;br /&gt;
          json=data_to_send,&lt;br /&gt;
          headers=headers&lt;br /&gt;
     )&lt;br /&gt;
     print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Serveur : ====&lt;br /&gt;
La communication entre notre VM et la Raspberry est possible. Nous arrivons à effectuer un ping de l'une sur l'autre en passant par l'addresse IPv6.&lt;br /&gt;
&lt;br /&gt;
IPv6 VM :  2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
IPv6 Raspberry : 2001:660:4401:6050:da3a:ddff:fe59:4cb5&lt;br /&gt;
&lt;br /&gt;
Nous programmons ensuite une API sur notre VM en utilisant la libraire Flask.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import json&lt;br /&gt;
     from flask import Flask&lt;br /&gt;
     from flask import request&lt;br /&gt;
     from waitress import serve&lt;br /&gt;
     from flask import Response&lt;br /&gt;
     from flask_cors import CORS&lt;br /&gt;
     from flask_cors import cross_origin&lt;br /&gt;
&lt;br /&gt;
     app = Flask(__name__)&lt;br /&gt;
     cors = CORS(app, ressourceas={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;:&amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
     def compute_data(data):&lt;br /&gt;
          filename = input(&amp;quot;Nom du fichier :&amp;quot;)&lt;br /&gt;
          to_write = data.split(&amp;quot;\&amp;quot;&amp;quot;)[1:-1]&lt;br /&gt;
          with open(filename, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
               i = 0&lt;br /&gt;
               for elem in to_write:&lt;br /&gt;
                    if i == 0:&lt;br /&gt;
                         print(&amp;quot;We skip&amp;quot;)&lt;br /&gt;
                    else:&lt;br /&gt;
                         if (i%2) == 0:&lt;br /&gt;
                              print(&amp;quot;Data writed :&amp;quot;,elem[:-4])&lt;br /&gt;
                              f.write(elem[:-4])&lt;br /&gt;
                              f.write(&amp;quot;\n&amp;quot;)&lt;br /&gt;
                    i = i + 1&lt;br /&gt;
&lt;br /&gt;
     #Main&lt;br /&gt;
     @app.route('/',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
     @cross_origin()&lt;br /&gt;
     def hello():&lt;br /&gt;
          data = request.json&lt;br /&gt;
          compute_data(data)&lt;br /&gt;
          return data&lt;br /&gt;
&lt;br /&gt;
     if __name__ == '__main__':&lt;br /&gt;
          print(&amp;quot;Listening&amp;quot;)&lt;br /&gt;
          serve(app,host=&amp;quot;::&amp;quot;,port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Implémentation de l'IA : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant qu'on a une communication pour envoyer un fichier à notre serveur depuis la raspberry grâce à notre API, nous la modifions pour que la Raspberry puisse lire la valeur du capteur à ultrason, l'envoyer à notre serveur et recevoir en réponse, la prédiction de l'IA. Nous créons donc une route '''''/predict''''' sur notre API qui récupère les valeurs du capteurs données en paramètre et renvoie la prédiction de l'IA :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 @app.route('/predict',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
 def predict():&lt;br /&gt;
      data = request.json&lt;br /&gt;
      print(data)&lt;br /&gt;
      features = data['Features']&lt;br /&gt;
      print(features)&lt;br /&gt;
      features_splitted = features[0].split(&amp;quot;,&amp;quot;)&lt;br /&gt;
      features_int = [int(elem) for elem in features_splitted]&lt;br /&gt;
      loaded_model = joblib.load('model_entraine.pkl')&lt;br /&gt;
      predictios = loaded_model.predict(np.array(features_int).reshape(1,-1))&lt;br /&gt;
      return jsonify(predictions.tolist())&lt;br /&gt;
&amp;lt;/pre&amp;gt;Nous envoyons ensuite les données à analyser via des requêtes API :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 #Import Librairies&lt;br /&gt;
 import requests&lt;br /&gt;
 import json&lt;br /&gt;
 import serial&lt;br /&gt;
 from flask import jsonify&lt;br /&gt;
&lt;br /&gt;
 #Variable&lt;br /&gt;
 STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
 baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
 Serial_link = serial.Serial(STM32_port, baudrate, timeout=1)&lt;br /&gt;
 print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
 tab_to_send = []&lt;br /&gt;
&lt;br /&gt;
 while True:&lt;br /&gt;
      Serial_link.readline().decode('utf-8')&lt;br /&gt;
      tab_to_send.append(Serial_link.readline().decode('utf-8')&lt;br /&gt;
      if (tab_to_send != [&amp;quot;&amp;quot;]):&lt;br /&gt;
           print(&amp;quot;Data sended :&amp;quot;,tab_to_send)&lt;br /&gt;
           url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080/predict&amp;quot;&lt;br /&gt;
           headers = {&lt;br /&gt;
                'Content-type':'application/json',&lt;br /&gt;
                'Accept':'application/json'&lt;br /&gt;
           }&lt;br /&gt;
           r = requests.post(&lt;br /&gt;
                url_request,&lt;br /&gt;
                json = {&lt;br /&gt;
                     &amp;quot;Features&amp;quot;: tab_to_send&lt;br /&gt;
                },&lt;br /&gt;
                headers=headers&lt;br /&gt;
           )&lt;br /&gt;
           print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
           print(&amp;quot;Response :&amp;quot;,r.json())&lt;br /&gt;
      else:&lt;br /&gt;
           print(&amp;quot;Data skip:&amp;quot;,tab_to_send)&lt;br /&gt;
      tab_to_send.clear()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Entrainement de l'IA &amp;lt;/div&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec NanoEdge AI Studio : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour le projet, nous avons d'abord développé et entrainé notre IA sur la plateforme NanoEdge AI Studio. Pour ce faire, nous devons d'abord définir un projet de classification de n-class (&amp;quot;pierre&amp;quot;,&amp;quot;feuille&amp;quot;,&amp;quot;ciseau&amp;quot;) en utilisant un capteur générique à 16 axes. Pour ce faire, nous modifions le code de la STM32 pour qu'elle renvoie une ligne contenant 16*16 mesure en continue. Une fois le projet créé, nous ajoutons 3 signaux correspondant à nos dataset de &amp;quot;Pierre&amp;quot;, &amp;quot;Feuille&amp;quot; et &amp;quot;Ciseau&amp;quot;. Pour rajouter des valeurs dans notre dataset, nous utilisons la liaison série pour lire les valeurs de notre capteur.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec Scikit : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour la suite de notre projet, nous avons developpé et entrainé une IA avec Scikit.&lt;br /&gt;
&lt;br /&gt;
==== Construction du fichier d'entrainement ====&lt;br /&gt;
Pour commencer, nous avons du construire un fichier csv reprenant nos mesures sur un format de 16 valeurs. Pour chaque mesure, on ajoute en amont de la mesure la catégorie (feuille, ciseau ou pierre). &lt;br /&gt;
[[Fichier:Capture d’écran 2024-01-18 à 16.18.19.png|centré|vignette|500x500px|Fichier chifoumIA.csv]]&lt;br /&gt;
Pour construire ce fichier, nous avons assemblé trois fichiers csv de test que nous avons généré grâce à notre capteur : un fichier d'entrainement Pierre.csv, un fichier d'entrainement Ciseau.csv et un fichier d'entrainement Feuille.csv . &lt;br /&gt;
&lt;br /&gt;
Pour faire cette concaténation nous avons développer un programme python prenant en entrée nos fichiers d'entrainement et fournissant en sortie le fichier csv chifoumIA.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     line_feuille = []&lt;br /&gt;
     line_pierre = []&lt;br /&gt;
     line_ciseau = []&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Feuille.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_feuille = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Pierre.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_pierre = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Ciseau.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_ciseau = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;chifoumIA.csv&amp;quot;,&amp;quot;w&amp;quot;) as f:&lt;br /&gt;
          for elem in line_feuille:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;feuille,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_pierre:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;pierre,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_ciseau:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;ciseau,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Implémentation et Entrainement de notre IA ====&lt;br /&gt;
&lt;br /&gt;
===== Implémentation =====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant que nous avons notre fichier d'entrainement, nous implémentons notre IA. &lt;br /&gt;
&lt;br /&gt;
Nous avons commencé par créer un tableau de données et un tableau de classes. &lt;br /&gt;
&lt;br /&gt;
Pour remplir ces tableaux, on va lire ligne par ligne le fichier chifoumIA.csv. Le premier élément de la ligne est stockée dans le tableau de classes et le reste de la ligne est stockée dans le tableau de données. &lt;br /&gt;
 chifoumi_data=[]&lt;br /&gt;
 chifoumi_classe=[]&lt;br /&gt;
 &lt;br /&gt;
 with open('chifoumIA.csv') as csv_file:&lt;br /&gt;
        csv_reader = csv.reader(csv_file,delimiter=',')&lt;br /&gt;
        for row in csv_reader:           &lt;br /&gt;
                 chifoumi_data.append([int(row[1]),int(row[2]),int(row[3]),int(row[4]),int(row[5]),int(row[6]),int(row[7]),int(row[8]),&lt;br /&gt;
                                       int(row[9]),int(row[10]),int(row[11]),int(row[12]),int(row[13]),int(row[14]),int(row[15]),int(row[16])])&lt;br /&gt;
                 chifoumi_classe.append(row[0])&lt;br /&gt;
  &lt;br /&gt;
A partir de ces deux tableaux, on construit un ensemble de données d'entraînement et un ensemble de données de tests.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On choisi d'utiliser un réseau de neurone du type MLPClassifer. &lt;br /&gt;
&lt;br /&gt;
====== MLPClassifer ======&lt;br /&gt;
Le MLPClassifer est un type de réseau de neurones artificiels composés d'au minimum trois couches de neurones: une couche d'entrée, une ou plusieurs  couches cachées et une couche de sortie. &lt;br /&gt;
&lt;br /&gt;
Dans ce type de réseau, chaque neurone est connecté à l'ensemble des neurones de la couche suivante par un lien auquel est associé un poids. &lt;br /&gt;
&lt;br /&gt;
La classe MLPClassifer implémentée dans la bibliothèque Scikit-Learn dispose de nombreux paramètres. Pour notre projet, nous avons utilisé cette classe de façon très primaire. Les paramètres que nous avons utilisés sont :  &lt;br /&gt;
&lt;br /&gt;
- '''hidden_layer_sizes :''' ce paramètre est un tuple spécifiant le nombre de neurones dans chaque couche cachée. &lt;br /&gt;
&lt;br /&gt;
- '''max_iter :''' ce paramètre représente le nombre maximal d'époque. Il permet de contrôler également le temps d'entrainement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
model=MLPClassifier(hidden_layer_sizes=(50,25),max_iter=100,solver='adam')&lt;br /&gt;
&lt;br /&gt;
model.fit(X_train,y_train)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;predictions = model.predict(X_test)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;print(f'Accuracy:{accuracy}')&lt;br /&gt;
&amp;lt;pre/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ipv6 jcie : 2001:660:4401:6050:216:3eff:fe68:8176&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4738</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4738"/>
		<updated>2024-01-28T12:45:13Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /* MLPClassifer */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Introduction Projet IE Delannoy - Lemaire &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadre la matière '''&amp;quot;Intelligence Embarquée&amp;quot;''' de l'UE &amp;quot;Module de Spécialité&amp;quot; des SE5 - Option Systèmes Communicants, nous avons dû concevoir un projet permettant de '''distribuer le calcul et le processus d'entrainement''' et d'utilisation d'un Intelligence Artificielle. Nous devrons distribuer le calcul à différents endroits du réseau afin d'être en mesure de proposer des pistes d'optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, nous allons mettre en oeuvre un réseau d'objets connectés à des passerelles et à un serveur. '''Les objets collecteront des données''' de l'environnemet et suivants les scénarios, traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Nous aurons à disposition :&lt;br /&gt;
&lt;br /&gt;
* Une machine virtuelle sur le serveur '''Chassiron''' en ''E304/306''&lt;br /&gt;
* Une '''Raspberry PI 4'''&lt;br /&gt;
* Un carte programmable '''STM32F401RE'''&lt;br /&gt;
* Un capteur à ultrason '''Nucleo-53L5A1'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ce wiki est le compte-rendu du projet de '''Jason DELANNOY et Chloé LEMAIRE'''. Nous avons décider de développer une intelligence artificielle permettant de '''déterminer''' '''l'action faite par un joueur de Pierre-Feuille-Ciseau''' à l'aide du capteur à ultrason.&lt;br /&gt;
&lt;br /&gt;
Pour ce faire, nous allons développer notre IA de deux façons :&lt;br /&gt;
&lt;br /&gt;
* En utilisant '''NanoEdge Studio''' : Dans ce cas, le calcul serait fait par la carte programmable et envoyé au serveur via la Raspberry&lt;br /&gt;
* En utilisant '''un algorithme de machine learning ''': Ici, c'est le serveur qui fera le calcul et la Raspberry jouera le rôle de passerelle entre la carte programmable et le serveu&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Mise en oeuvre du réseau &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Création VM XEN ===&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la VM ===&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la borne WIFI Cisco ===&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251 (changement car besoin pour les PEIP) &lt;br /&gt;
&lt;br /&gt;
- dns-server: 193.48.57.33 (changement car problème avec le serveur DNS initial)&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Configuration de la Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadra du projet, nous avons à disposition une Raspberry PI 4 model B que nous allons configurer. Pour ce faire, nous utilisons le logiciel le &amp;quot;Raspberry PI Imager&amp;quot; pour choisir notre OS.&lt;br /&gt;
[[Fichier:JCIE RPI Imager.png|centré|vignette|400x400px]]Maintenant que nous avons une carte SD prête pour la Raspberry, nous la configurons via sa liaison série en passant par minicom :&lt;br /&gt;
 root@zabeth18: / $ minicom -D /dev/ttyACM0 -b 9600&lt;br /&gt;
De plus, nous modifions le fichier /etc/network/interfaces pour pouvoir connecter notre carte au réseau wifi créé plus haut :&lt;br /&gt;
[[Fichier:Screen WiFi.png|centré|vignette|441x441px]]&lt;br /&gt;
Nous verifions ensuite que nous avons une adresse IP :&lt;br /&gt;
[[Fichier:Screenshot from 2023-12-04 17-17-05.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Capteur NUCLEO - 53L5A1 &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Pour ce projet, nous disposons d'une STM32 Nucléo F401RE muni d'un capteur à ultrason X-Nucleo-53L5A1.&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir entrainer notre IA, nous devons faire en sorte d'afficher et de ressortir sur la liaison série les données du capteur. Pour ce faire, nous utilisons le fichier example &amp;quot;'''''53L5A1_ThresholdDetection'''''&amp;quot;. Nous modifions la fonction print_result pour afficher 16 valeurs à la suite :&lt;br /&gt;
[[Fichier:ChifoumIA Print Result.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Après avoir téléversé, nous pouvons vérifier le bon fonctionnement du programme en nous connectant à la carte via minicom :&lt;br /&gt;
&lt;br /&gt;
 root@raspberrypi:/dev$ minicom -D ttyACM0 -b 460800&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Communication VM-Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Envoie de donnée : ===&lt;br /&gt;
&lt;br /&gt;
Dans notre projet, nous avons besoin de remonter les données de notre capteur branché en liaison série à la Raspberry sur le port &amp;quot;ttyACM0&amp;quot;. Nous allons donc passer par des requêtes API entre le serveur sur chassiron et notre Raspberry.&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Raspberry : ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Du côté Raspberry, nous programmons un script en python qui lit sur la liaison série les valeurs du capteurs et les envoie via une requête POST vers le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import requests&lt;br /&gt;
     import json&lt;br /&gt;
     import serial&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;Variable&lt;br /&gt;
     STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
     baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
     Serial_link = serial.Serial(STM32_port,baudrate,timeout=1)&lt;br /&gt;
     print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
     liste_mesures=[]&lt;br /&gt;
     for i in range(101):&lt;br /&gt;
          print(&amp;quot;Mesure&amp;quot;,i)&lt;br /&gt;
          mesure = Serial_link.readline().decode('utf-8')&lt;br /&gt;
          liste_mesures.append(mesure)&lt;br /&gt;
&lt;br /&gt;
     data_to_send = json.dumps(liste_mesures)&lt;br /&gt;
     url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080&amp;quot;&lt;br /&gt;
&lt;br /&gt;
     headers = {&lt;br /&gt;
          'Content-type':'application/json',&lt;br /&gt;
          'Accept':'application/json'&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     r = requests.post(&lt;br /&gt;
          url_request,&lt;br /&gt;
          json=data_to_send,&lt;br /&gt;
          headers=headers&lt;br /&gt;
     )&lt;br /&gt;
     print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Serveur : ====&lt;br /&gt;
La communication entre notre VM et la Raspberry est possible. Nous arrivons à effectuer un ping de l'une sur l'autre en passant par l'addresse IPv6.&lt;br /&gt;
&lt;br /&gt;
IPv6 VM :  2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
IPv6 Raspberry : 2001:660:4401:6050:da3a:ddff:fe59:4cb5&lt;br /&gt;
&lt;br /&gt;
Nous programmons ensuite une API sur notre VM en utilisant la libraire Flask.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import json&lt;br /&gt;
     from flask import Flask&lt;br /&gt;
     from flask import request&lt;br /&gt;
     from waitress import serve&lt;br /&gt;
     from flask import Response&lt;br /&gt;
     from flask_cors import CORS&lt;br /&gt;
     from flask_cors import cross_origin&lt;br /&gt;
&lt;br /&gt;
     app = Flask(__name__)&lt;br /&gt;
     cors = CORS(app, ressourceas={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;:&amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
     def compute_data(data):&lt;br /&gt;
          filename = input(&amp;quot;Nom du fichier :&amp;quot;)&lt;br /&gt;
          to_write = data.split(&amp;quot;\&amp;quot;&amp;quot;)[1:-1]&lt;br /&gt;
          with open(filename, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
               i = 0&lt;br /&gt;
               for elem in to_write:&lt;br /&gt;
                    if i == 0:&lt;br /&gt;
                         print(&amp;quot;We skip&amp;quot;)&lt;br /&gt;
                    else:&lt;br /&gt;
                         if (i%2) == 0:&lt;br /&gt;
                              print(&amp;quot;Data writed :&amp;quot;,elem[:-4])&lt;br /&gt;
                              f.write(elem[:-4])&lt;br /&gt;
                              f.write(&amp;quot;\n&amp;quot;)&lt;br /&gt;
                    i = i + 1&lt;br /&gt;
&lt;br /&gt;
     #Main&lt;br /&gt;
     @app.route('/',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
     @cross_origin()&lt;br /&gt;
     def hello():&lt;br /&gt;
          data = request.json&lt;br /&gt;
          compute_data(data)&lt;br /&gt;
          return data&lt;br /&gt;
&lt;br /&gt;
     if __name__ == '__main__':&lt;br /&gt;
          print(&amp;quot;Listening&amp;quot;)&lt;br /&gt;
          serve(app,host=&amp;quot;::&amp;quot;,port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Implémentation de l'IA : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant qu'on a une communication pour envoyer un fichier à notre serveur depuis la raspberry grâce à notre API, nous la modifions pour que la Raspberry puisse lire la valeur du capteur à ultrason, l'envoyer à notre serveur et recevoir en réponse, la prédiction de l'IA. Nous créons donc une route '''''/predict''''' sur notre API qui récupère les valeurs du capteurs données en paramètre et renvoie la prédiction de l'IA :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 @app.route('/predict',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
 def predict():&lt;br /&gt;
      data = request.json&lt;br /&gt;
      print(data)&lt;br /&gt;
      features = data['Features']&lt;br /&gt;
      print(features)&lt;br /&gt;
      features_splitted = features[0].split(&amp;quot;,&amp;quot;)&lt;br /&gt;
      features_int = [int(elem) for elem in features_splitted]&lt;br /&gt;
      loaded_model = joblib.load('model_entraine.pkl')&lt;br /&gt;
      predictios = loaded_model.predict(np.array(features_int).reshape(1,-1))&lt;br /&gt;
      return jsonify(predictions.tolist())&lt;br /&gt;
&amp;lt;/pre&amp;gt;Nous envoyons ensuite les données à analyser via des requêtes API :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 #Import Librairies&lt;br /&gt;
 import requests&lt;br /&gt;
 import json&lt;br /&gt;
 import serial&lt;br /&gt;
 from flask import jsonify&lt;br /&gt;
&lt;br /&gt;
 #Variable&lt;br /&gt;
 STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
 baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
 Serial_link = serial.Serial(STM32_port, baudrate, timeout=1)&lt;br /&gt;
 print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
 tab_to_send = []&lt;br /&gt;
&lt;br /&gt;
 while True:&lt;br /&gt;
      Serial_link.readline().decode('utf-8')&lt;br /&gt;
      tab_to_send.append(Serial_link.readline().decode('utf-8')&lt;br /&gt;
      if (tab_to_send != [&amp;quot;&amp;quot;]):&lt;br /&gt;
           print(&amp;quot;Data sended :&amp;quot;,tab_to_send)&lt;br /&gt;
           url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080/predict&amp;quot;&lt;br /&gt;
           headers = {&lt;br /&gt;
                'Content-type':'application/json',&lt;br /&gt;
                'Accept':'application/json'&lt;br /&gt;
           }&lt;br /&gt;
           r = requests.post(&lt;br /&gt;
                url_request,&lt;br /&gt;
                json = {&lt;br /&gt;
                     &amp;quot;Features&amp;quot;: tab_to_send&lt;br /&gt;
                },&lt;br /&gt;
                headers=headers&lt;br /&gt;
           )&lt;br /&gt;
           print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
           print(&amp;quot;Response :&amp;quot;,r.json())&lt;br /&gt;
      else:&lt;br /&gt;
           print(&amp;quot;Data skip:&amp;quot;,tab_to_send)&lt;br /&gt;
      tab_to_send.clear()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Entrainement de l'IA &amp;lt;/div&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec NanoEdge AI Studio : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour le projet, nous avons d'abord développé et entrainé notre IA sur la plateforme NanoEdge AI Studio. Pour ce faire, nous devons d'abord définir un projet de classification de n-class (&amp;quot;pierre&amp;quot;,&amp;quot;feuille&amp;quot;,&amp;quot;ciseau&amp;quot;) en utilisant un capteur générique à 16 axes. Pour ce faire, nous modifions le code de la STM32 pour qu'elle renvoie une ligne contenant 16*16 mesure en continue. Une fois le projet créé, nous ajoutons 3 signaux correspondant à nos dataset de &amp;quot;Pierre&amp;quot;, &amp;quot;Feuille&amp;quot; et &amp;quot;Ciseau&amp;quot;. Pour rajouter des valeurs dans notre dataset, nous utilisons la liaison série pour lire les valeurs de notre capteur.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec Scikit : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour la suite de notre projet, nous avons developpé et entrainé une IA avec Scikit.&lt;br /&gt;
&lt;br /&gt;
==== Construction du fichier d'entrainement ====&lt;br /&gt;
Pour commencer, nous avons du construire un fichier csv reprenant nos mesures sur un format de 16 valeurs. Pour chaque mesure, on ajoute en amont de la mesure la catégorie (feuille, ciseau ou pierre). &lt;br /&gt;
[[Fichier:Capture d’écran 2024-01-18 à 16.18.19.png|centré|vignette|500x500px|Fichier chifoumIA.csv]]&lt;br /&gt;
Pour construire ce fichier, nous avons assemblé trois fichiers csv de test que nous avons généré grâce à notre capteur : un fichier d'entrainement Pierre.csv, un fichier d'entrainement Ciseau.csv et un fichier d'entrainement Feuille.csv . &lt;br /&gt;
&lt;br /&gt;
Pour faire cette concaténation nous avons développer un programme python prenant en entrée nos fichiers d'entrainement et fournissant en sortie le fichier csv chifoumIA.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     line_feuille = []&lt;br /&gt;
     line_pierre = []&lt;br /&gt;
     line_ciseau = []&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Feuille.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_feuille = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Pierre.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_pierre = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Ciseau.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_ciseau = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;chifoumIA.csv&amp;quot;,&amp;quot;w&amp;quot;) as f:&lt;br /&gt;
          for elem in line_feuille:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;feuille,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_pierre:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;pierre,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_ciseau:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;ciseau,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Implémentation et Entrainement de notre IA ====&lt;br /&gt;
&lt;br /&gt;
===== Implémentation =====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant que nous avons notre fichier d'entrainement, nous implémentons notre IA. &lt;br /&gt;
&lt;br /&gt;
Nous avons commencé par créer un tableau de données et un tableau de classes. &lt;br /&gt;
&lt;br /&gt;
Pour remplir ces tableaux, on va lire ligne par ligne le fichier chifoumIA.csv. Le premier élément de la ligne est stockée dans le tableau de classes et le reste de la ligne est stockée dans le tableau de données. &lt;br /&gt;
 chifoumi_data=[]&lt;br /&gt;
 chifoumi_classe=[]&lt;br /&gt;
 &lt;br /&gt;
 with open('chifoumIA.csv') as csv_file:&lt;br /&gt;
        csv_reader = csv.reader(csv_file,delimiter=',')&lt;br /&gt;
        for row in csv_reader:           &lt;br /&gt;
                 chifoumi_data.append([int(row[1]),int(row[2]),int(row[3]),int(row[4]),int(row[5]),int(row[6]),int(row[7]),int(row[8]),&lt;br /&gt;
                                       int(row[9]),int(row[10]),int(row[11]),int(row[12]),int(row[13]),int(row[14]),int(row[15]),int(row[16])])&lt;br /&gt;
                 chifoumi_classe.append(row[0])&lt;br /&gt;
  &lt;br /&gt;
A partir de ces deux tableaux, on construit un ensemble de données d'entraînement et un ensemble de données de tests.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On choisi d'utiliser un réseau de neurone du type MLPClassifer. &lt;br /&gt;
&lt;br /&gt;
====== MLPClassifer ======&lt;br /&gt;
Le MLPClassifer est un type de réseau de neurones artificiels composés d'au minimum trois couches de neurones: une couche d'entrée, une ou plusieurs  couches cachées et une couche de sortie. &lt;br /&gt;
&lt;br /&gt;
Dans ce type de réseau, chaque neurone est connecté à l'ensemble des neurones de la couche suivante par un lien auquel est associé un poids. &lt;br /&gt;
&lt;br /&gt;
La classe MLPClassifer implémentée dans la bibliothèque Scikit-Learn dispose de nombreux paramètres. Pour notre projet, nous avons utilisé cette classe de façon très primaire. Les paramètres que nous avons utilisés sont :  &lt;br /&gt;
&lt;br /&gt;
- '''hidden_layer_sizes :''' ce paramètre est un tuple spécifiant le nombre de neurones dans chaque couche cachée. &lt;br /&gt;
&lt;br /&gt;
- '''max_iter :''' ce paramètre représente le nombre maximal d'époque. Il permet de contrôler également le temps d'entrainement.    &lt;br /&gt;
&lt;br /&gt;
model=MLPClassifier(hidden_layer_sizes=(50,25),max_iter=100,solver='adam')&lt;br /&gt;
&lt;br /&gt;
model.fit(X_train,y_train)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;predictions = model.predict(X_test)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;print(f'Accuracy:{accuracy}')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ipv6 jcie : 2001:660:4401:6050:216:3eff:fe68:8176&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4736</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4736"/>
		<updated>2024-01-28T12:44:05Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /* MLPClassifer */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Introduction Projet IE Delannoy - Lemaire &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadre la matière '''&amp;quot;Intelligence Embarquée&amp;quot;''' de l'UE &amp;quot;Module de Spécialité&amp;quot; des SE5 - Option Systèmes Communicants, nous avons dû concevoir un projet permettant de '''distribuer le calcul et le processus d'entrainement''' et d'utilisation d'un Intelligence Artificielle. Nous devrons distribuer le calcul à différents endroits du réseau afin d'être en mesure de proposer des pistes d'optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, nous allons mettre en oeuvre un réseau d'objets connectés à des passerelles et à un serveur. '''Les objets collecteront des données''' de l'environnemet et suivants les scénarios, traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Nous aurons à disposition :&lt;br /&gt;
&lt;br /&gt;
* Une machine virtuelle sur le serveur '''Chassiron''' en ''E304/306''&lt;br /&gt;
* Une '''Raspberry PI 4'''&lt;br /&gt;
* Un carte programmable '''STM32F401RE'''&lt;br /&gt;
* Un capteur à ultrason '''Nucleo-53L5A1'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ce wiki est le compte-rendu du projet de '''Jason DELANNOY et Chloé LEMAIRE'''. Nous avons décider de développer une intelligence artificielle permettant de '''déterminer''' '''l'action faite par un joueur de Pierre-Feuille-Ciseau''' à l'aide du capteur à ultrason.&lt;br /&gt;
&lt;br /&gt;
Pour ce faire, nous allons développer notre IA de deux façons :&lt;br /&gt;
&lt;br /&gt;
* En utilisant '''NanoEdge Studio''' : Dans ce cas, le calcul serait fait par la carte programmable et envoyé au serveur via la Raspberry&lt;br /&gt;
* En utilisant '''un algorithme de machine learning ''': Ici, c'est le serveur qui fera le calcul et la Raspberry jouera le rôle de passerelle entre la carte programmable et le serveu&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Mise en oeuvre du réseau &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Création VM XEN ===&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la VM ===&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la borne WIFI Cisco ===&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251 (changement car besoin pour les PEIP) &lt;br /&gt;
&lt;br /&gt;
- dns-server: 193.48.57.33 (changement car problème avec le serveur DNS initial)&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Configuration de la Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadra du projet, nous avons à disposition une Raspberry PI 4 model B que nous allons configurer. Pour ce faire, nous utilisons le logiciel le &amp;quot;Raspberry PI Imager&amp;quot; pour choisir notre OS.&lt;br /&gt;
[[Fichier:JCIE RPI Imager.png|centré|vignette|400x400px]]Maintenant que nous avons une carte SD prête pour la Raspberry, nous la configurons via sa liaison série en passant par minicom :&lt;br /&gt;
 root@zabeth18: / $ minicom -D /dev/ttyACM0 -b 9600&lt;br /&gt;
De plus, nous modifions le fichier /etc/network/interfaces pour pouvoir connecter notre carte au réseau wifi créé plus haut :&lt;br /&gt;
[[Fichier:Screen WiFi.png|centré|vignette|441x441px]]&lt;br /&gt;
Nous verifions ensuite que nous avons une adresse IP :&lt;br /&gt;
[[Fichier:Screenshot from 2023-12-04 17-17-05.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Capteur NUCLEO - 53L5A1 &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Pour ce projet, nous disposons d'une STM32 Nucléo F401RE muni d'un capteur à ultrason X-Nucleo-53L5A1.&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir entrainer notre IA, nous devons faire en sorte d'afficher et de ressortir sur la liaison série les données du capteur. Pour ce faire, nous utilisons le fichier example &amp;quot;'''''53L5A1_ThresholdDetection'''''&amp;quot;. Nous modifions la fonction print_result pour afficher 16 valeurs à la suite :&lt;br /&gt;
[[Fichier:ChifoumIA Print Result.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Après avoir téléversé, nous pouvons vérifier le bon fonctionnement du programme en nous connectant à la carte via minicom :&lt;br /&gt;
&lt;br /&gt;
 root@raspberrypi:/dev$ minicom -D ttyACM0 -b 460800&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Communication VM-Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Envoie de donnée : ===&lt;br /&gt;
&lt;br /&gt;
Dans notre projet, nous avons besoin de remonter les données de notre capteur branché en liaison série à la Raspberry sur le port &amp;quot;ttyACM0&amp;quot;. Nous allons donc passer par des requêtes API entre le serveur sur chassiron et notre Raspberry.&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Raspberry : ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Du côté Raspberry, nous programmons un script en python qui lit sur la liaison série les valeurs du capteurs et les envoie via une requête POST vers le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import requests&lt;br /&gt;
     import json&lt;br /&gt;
     import serial&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;Variable&lt;br /&gt;
     STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
     baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
     Serial_link = serial.Serial(STM32_port,baudrate,timeout=1)&lt;br /&gt;
     print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
     liste_mesures=[]&lt;br /&gt;
     for i in range(101):&lt;br /&gt;
          print(&amp;quot;Mesure&amp;quot;,i)&lt;br /&gt;
          mesure = Serial_link.readline().decode('utf-8')&lt;br /&gt;
          liste_mesures.append(mesure)&lt;br /&gt;
&lt;br /&gt;
     data_to_send = json.dumps(liste_mesures)&lt;br /&gt;
     url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080&amp;quot;&lt;br /&gt;
&lt;br /&gt;
     headers = {&lt;br /&gt;
          'Content-type':'application/json',&lt;br /&gt;
          'Accept':'application/json'&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     r = requests.post(&lt;br /&gt;
          url_request,&lt;br /&gt;
          json=data_to_send,&lt;br /&gt;
          headers=headers&lt;br /&gt;
     )&lt;br /&gt;
     print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Serveur : ====&lt;br /&gt;
La communication entre notre VM et la Raspberry est possible. Nous arrivons à effectuer un ping de l'une sur l'autre en passant par l'addresse IPv6.&lt;br /&gt;
&lt;br /&gt;
IPv6 VM :  2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
IPv6 Raspberry : 2001:660:4401:6050:da3a:ddff:fe59:4cb5&lt;br /&gt;
&lt;br /&gt;
Nous programmons ensuite une API sur notre VM en utilisant la libraire Flask.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import json&lt;br /&gt;
     from flask import Flask&lt;br /&gt;
     from flask import request&lt;br /&gt;
     from waitress import serve&lt;br /&gt;
     from flask import Response&lt;br /&gt;
     from flask_cors import CORS&lt;br /&gt;
     from flask_cors import cross_origin&lt;br /&gt;
&lt;br /&gt;
     app = Flask(__name__)&lt;br /&gt;
     cors = CORS(app, ressourceas={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;:&amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
     def compute_data(data):&lt;br /&gt;
          filename = input(&amp;quot;Nom du fichier :&amp;quot;)&lt;br /&gt;
          to_write = data.split(&amp;quot;\&amp;quot;&amp;quot;)[1:-1]&lt;br /&gt;
          with open(filename, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
               i = 0&lt;br /&gt;
               for elem in to_write:&lt;br /&gt;
                    if i == 0:&lt;br /&gt;
                         print(&amp;quot;We skip&amp;quot;)&lt;br /&gt;
                    else:&lt;br /&gt;
                         if (i%2) == 0:&lt;br /&gt;
                              print(&amp;quot;Data writed :&amp;quot;,elem[:-4])&lt;br /&gt;
                              f.write(elem[:-4])&lt;br /&gt;
                              f.write(&amp;quot;\n&amp;quot;)&lt;br /&gt;
                    i = i + 1&lt;br /&gt;
&lt;br /&gt;
     #Main&lt;br /&gt;
     @app.route('/',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
     @cross_origin()&lt;br /&gt;
     def hello():&lt;br /&gt;
          data = request.json&lt;br /&gt;
          compute_data(data)&lt;br /&gt;
          return data&lt;br /&gt;
&lt;br /&gt;
     if __name__ == '__main__':&lt;br /&gt;
          print(&amp;quot;Listening&amp;quot;)&lt;br /&gt;
          serve(app,host=&amp;quot;::&amp;quot;,port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Implémentation de l'IA : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant qu'on a une communication pour envoyer un fichier à notre serveur depuis la raspberry grâce à notre API, nous la modifions pour que la Raspberry puisse lire la valeur du capteur à ultrason, l'envoyer à notre serveur et recevoir en réponse, la prédiction de l'IA. Nous créons donc une route '''''/predict''''' sur notre API qui récupère les valeurs du capteurs données en paramètre et renvoie la prédiction de l'IA :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 @app.route('/predict',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
 def predict():&lt;br /&gt;
      data = request.json&lt;br /&gt;
      print(data)&lt;br /&gt;
      features = data['Features']&lt;br /&gt;
      print(features)&lt;br /&gt;
      features_splitted = features[0].split(&amp;quot;,&amp;quot;)&lt;br /&gt;
      features_int = [int(elem) for elem in features_splitted]&lt;br /&gt;
      loaded_model = joblib.load('model_entraine.pkl')&lt;br /&gt;
      predictios = loaded_model.predict(np.array(features_int).reshape(1,-1))&lt;br /&gt;
      return jsonify(predictions.tolist())&lt;br /&gt;
&amp;lt;/pre&amp;gt;Nous envoyons ensuite les données à analyser via des requêtes API :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 #Import Librairies&lt;br /&gt;
 import requests&lt;br /&gt;
 import json&lt;br /&gt;
 import serial&lt;br /&gt;
 from flask import jsonify&lt;br /&gt;
&lt;br /&gt;
 #Variable&lt;br /&gt;
 STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
 baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
 Serial_link = serial.Serial(STM32_port, baudrate, timeout=1)&lt;br /&gt;
 print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
 tab_to_send = []&lt;br /&gt;
&lt;br /&gt;
 while True:&lt;br /&gt;
      Serial_link.readline().decode('utf-8')&lt;br /&gt;
      tab_to_send.append(Serial_link.readline().decode('utf-8')&lt;br /&gt;
      if (tab_to_send != [&amp;quot;&amp;quot;]):&lt;br /&gt;
           print(&amp;quot;Data sended :&amp;quot;,tab_to_send)&lt;br /&gt;
           url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080/predict&amp;quot;&lt;br /&gt;
           headers = {&lt;br /&gt;
                'Content-type':'application/json',&lt;br /&gt;
                'Accept':'application/json'&lt;br /&gt;
           }&lt;br /&gt;
           r = requests.post(&lt;br /&gt;
                url_request,&lt;br /&gt;
                json = {&lt;br /&gt;
                     &amp;quot;Features&amp;quot;: tab_to_send&lt;br /&gt;
                },&lt;br /&gt;
                headers=headers&lt;br /&gt;
           )&lt;br /&gt;
           print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
           print(&amp;quot;Response :&amp;quot;,r.json())&lt;br /&gt;
      else:&lt;br /&gt;
           print(&amp;quot;Data skip:&amp;quot;,tab_to_send)&lt;br /&gt;
      tab_to_send.clear()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Entrainement de l'IA &amp;lt;/div&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec NanoEdge AI Studio : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour le projet, nous avons d'abord développé et entrainé notre IA sur la plateforme NanoEdge AI Studio. Pour ce faire, nous devons d'abord définir un projet de classification de n-class (&amp;quot;pierre&amp;quot;,&amp;quot;feuille&amp;quot;,&amp;quot;ciseau&amp;quot;) en utilisant un capteur générique à 16 axes. Pour ce faire, nous modifions le code de la STM32 pour qu'elle renvoie une ligne contenant 16*16 mesure en continue. Une fois le projet créé, nous ajoutons 3 signaux correspondant à nos dataset de &amp;quot;Pierre&amp;quot;, &amp;quot;Feuille&amp;quot; et &amp;quot;Ciseau&amp;quot;. Pour rajouter des valeurs dans notre dataset, nous utilisons la liaison série pour lire les valeurs de notre capteur.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec Scikit : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour la suite de notre projet, nous avons developpé et entrainé une IA avec Scikit.&lt;br /&gt;
&lt;br /&gt;
==== Construction du fichier d'entrainement ====&lt;br /&gt;
Pour commencer, nous avons du construire un fichier csv reprenant nos mesures sur un format de 16 valeurs. Pour chaque mesure, on ajoute en amont de la mesure la catégorie (feuille, ciseau ou pierre). &lt;br /&gt;
[[Fichier:Capture d’écran 2024-01-18 à 16.18.19.png|centré|vignette|500x500px|Fichier chifoumIA.csv]]&lt;br /&gt;
Pour construire ce fichier, nous avons assemblé trois fichiers csv de test que nous avons généré grâce à notre capteur : un fichier d'entrainement Pierre.csv, un fichier d'entrainement Ciseau.csv et un fichier d'entrainement Feuille.csv . &lt;br /&gt;
&lt;br /&gt;
Pour faire cette concaténation nous avons développer un programme python prenant en entrée nos fichiers d'entrainement et fournissant en sortie le fichier csv chifoumIA.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     line_feuille = []&lt;br /&gt;
     line_pierre = []&lt;br /&gt;
     line_ciseau = []&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Feuille.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_feuille = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Pierre.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_pierre = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Ciseau.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_ciseau = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;chifoumIA.csv&amp;quot;,&amp;quot;w&amp;quot;) as f:&lt;br /&gt;
          for elem in line_feuille:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;feuille,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_pierre:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;pierre,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_ciseau:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;ciseau,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Implémentation et Entrainement de notre IA ====&lt;br /&gt;
&lt;br /&gt;
===== Implémentation =====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant que nous avons notre fichier d'entrainement, nous implémentons notre IA. &lt;br /&gt;
&lt;br /&gt;
Nous avons commencé par créer un tableau de données et un tableau de classes. &lt;br /&gt;
&lt;br /&gt;
Pour remplir ces tableaux, on va lire ligne par ligne le fichier chifoumIA.csv. Le premier élément de la ligne est stockée dans le tableau de classes et le reste de la ligne est stockée dans le tableau de données. &lt;br /&gt;
 chifoumi_data=[]&lt;br /&gt;
 chifoumi_classe=[]&lt;br /&gt;
 &lt;br /&gt;
 with open('chifoumIA.csv') as csv_file:&lt;br /&gt;
        csv_reader = csv.reader(csv_file,delimiter=',')&lt;br /&gt;
        for row in csv_reader:           &lt;br /&gt;
                 chifoumi_data.append([int(row[1]),int(row[2]),int(row[3]),int(row[4]),int(row[5]),int(row[6]),int(row[7]),int(row[8]),&lt;br /&gt;
                                       int(row[9]),int(row[10]),int(row[11]),int(row[12]),int(row[13]),int(row[14]),int(row[15]),int(row[16])])&lt;br /&gt;
                 chifoumi_classe.append(row[0])&lt;br /&gt;
  &lt;br /&gt;
A partir de ces deux tableaux, on construit un ensemble de données d'entraînement et un ensemble de données de tests.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On choisi d'utiliser un réseau de neurone du type MLPClassifer. &lt;br /&gt;
&lt;br /&gt;
====== MLPClassifer ======&lt;br /&gt;
Le MLPClassifer est un type de réseau de neurones artificiels composés d'au minimum trois couches de neurones: une couche d'entrée, une ou plusieurs  couches cachées et une couche de sortie. &lt;br /&gt;
&lt;br /&gt;
Dans ce type de réseau, chaque neurone est connecté à l'ensemble des neurones de la couche suivante par un lien auquel est associé un poids. &lt;br /&gt;
&lt;br /&gt;
La classe MLPClassifer implémentée dans la bibliothèque Scikit-Learn dispose de nombreux paramètres. Pour notre projet, nous avons utilisé cette classe de façon très primaire. Les paramètres que nous avons utilisés sont :  &lt;br /&gt;
&lt;br /&gt;
- '''hidden_layer_sizes :''' ce paramètre est un tuple spécifiant le nombre de neurones dans chaque couche cachée. &lt;br /&gt;
&lt;br /&gt;
- '''max_iter :''' ce paramètre représente le nombre maximal d'époque. Il permet de contrôler également le temps d'entrainement.    &lt;br /&gt;
&lt;br /&gt;
 model=MLPClassifier(hidden_layer_sizes=(50,25),max_iter=100,solver='adam')&lt;br /&gt;
&lt;br /&gt;
 model.fit(X_train,y_train)&lt;br /&gt;
&lt;br /&gt;
 #predictions = model.predict(X_test)&lt;br /&gt;
&lt;br /&gt;
 #accuracy = accuracy_score(y_test,predictions)&lt;br /&gt;
&lt;br /&gt;
 #print(f'Accuracy:{accuracy}')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ipv6 jcie : 2001:660:4401:6050:216:3eff:fe68:8176&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4735</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4735"/>
		<updated>2024-01-28T12:41:31Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /* Implémentation et Entrainement de notre IA */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Introduction Projet IE Delannoy - Lemaire &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadre la matière '''&amp;quot;Intelligence Embarquée&amp;quot;''' de l'UE &amp;quot;Module de Spécialité&amp;quot; des SE5 - Option Systèmes Communicants, nous avons dû concevoir un projet permettant de '''distribuer le calcul et le processus d'entrainement''' et d'utilisation d'un Intelligence Artificielle. Nous devrons distribuer le calcul à différents endroits du réseau afin d'être en mesure de proposer des pistes d'optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, nous allons mettre en oeuvre un réseau d'objets connectés à des passerelles et à un serveur. '''Les objets collecteront des données''' de l'environnemet et suivants les scénarios, traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Nous aurons à disposition :&lt;br /&gt;
&lt;br /&gt;
* Une machine virtuelle sur le serveur '''Chassiron''' en ''E304/306''&lt;br /&gt;
* Une '''Raspberry PI 4'''&lt;br /&gt;
* Un carte programmable '''STM32F401RE'''&lt;br /&gt;
* Un capteur à ultrason '''Nucleo-53L5A1'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ce wiki est le compte-rendu du projet de '''Jason DELANNOY et Chloé LEMAIRE'''. Nous avons décider de développer une intelligence artificielle permettant de '''déterminer''' '''l'action faite par un joueur de Pierre-Feuille-Ciseau''' à l'aide du capteur à ultrason.&lt;br /&gt;
&lt;br /&gt;
Pour ce faire, nous allons développer notre IA de deux façons :&lt;br /&gt;
&lt;br /&gt;
* En utilisant '''NanoEdge Studio''' : Dans ce cas, le calcul serait fait par la carte programmable et envoyé au serveur via la Raspberry&lt;br /&gt;
* En utilisant '''un algorithme de machine learning ''': Ici, c'est le serveur qui fera le calcul et la Raspberry jouera le rôle de passerelle entre la carte programmable et le serveu&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Mise en oeuvre du réseau &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Création VM XEN ===&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la VM ===&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la borne WIFI Cisco ===&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251 (changement car besoin pour les PEIP) &lt;br /&gt;
&lt;br /&gt;
- dns-server: 193.48.57.33 (changement car problème avec le serveur DNS initial)&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Configuration de la Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadra du projet, nous avons à disposition une Raspberry PI 4 model B que nous allons configurer. Pour ce faire, nous utilisons le logiciel le &amp;quot;Raspberry PI Imager&amp;quot; pour choisir notre OS.&lt;br /&gt;
[[Fichier:JCIE RPI Imager.png|centré|vignette|400x400px]]Maintenant que nous avons une carte SD prête pour la Raspberry, nous la configurons via sa liaison série en passant par minicom :&lt;br /&gt;
 root@zabeth18: / $ minicom -D /dev/ttyACM0 -b 9600&lt;br /&gt;
De plus, nous modifions le fichier /etc/network/interfaces pour pouvoir connecter notre carte au réseau wifi créé plus haut :&lt;br /&gt;
[[Fichier:Screen WiFi.png|centré|vignette|441x441px]]&lt;br /&gt;
Nous verifions ensuite que nous avons une adresse IP :&lt;br /&gt;
[[Fichier:Screenshot from 2023-12-04 17-17-05.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Capteur NUCLEO - 53L5A1 &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Pour ce projet, nous disposons d'une STM32 Nucléo F401RE muni d'un capteur à ultrason X-Nucleo-53L5A1.&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir entrainer notre IA, nous devons faire en sorte d'afficher et de ressortir sur la liaison série les données du capteur. Pour ce faire, nous utilisons le fichier example &amp;quot;'''''53L5A1_ThresholdDetection'''''&amp;quot;. Nous modifions la fonction print_result pour afficher 16 valeurs à la suite :&lt;br /&gt;
[[Fichier:ChifoumIA Print Result.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Après avoir téléversé, nous pouvons vérifier le bon fonctionnement du programme en nous connectant à la carte via minicom :&lt;br /&gt;
&lt;br /&gt;
 root@raspberrypi:/dev$ minicom -D ttyACM0 -b 460800&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Communication VM-Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Envoie de donnée : ===&lt;br /&gt;
&lt;br /&gt;
Dans notre projet, nous avons besoin de remonter les données de notre capteur branché en liaison série à la Raspberry sur le port &amp;quot;ttyACM0&amp;quot;. Nous allons donc passer par des requêtes API entre le serveur sur chassiron et notre Raspberry.&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Raspberry : ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Du côté Raspberry, nous programmons un script en python qui lit sur la liaison série les valeurs du capteurs et les envoie via une requête POST vers le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import requests&lt;br /&gt;
     import json&lt;br /&gt;
     import serial&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;Variable&lt;br /&gt;
     STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
     baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
     Serial_link = serial.Serial(STM32_port,baudrate,timeout=1)&lt;br /&gt;
     print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
     liste_mesures=[]&lt;br /&gt;
     for i in range(101):&lt;br /&gt;
          print(&amp;quot;Mesure&amp;quot;,i)&lt;br /&gt;
          mesure = Serial_link.readline().decode('utf-8')&lt;br /&gt;
          liste_mesures.append(mesure)&lt;br /&gt;
&lt;br /&gt;
     data_to_send = json.dumps(liste_mesures)&lt;br /&gt;
     url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080&amp;quot;&lt;br /&gt;
&lt;br /&gt;
     headers = {&lt;br /&gt;
          'Content-type':'application/json',&lt;br /&gt;
          'Accept':'application/json'&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     r = requests.post(&lt;br /&gt;
          url_request,&lt;br /&gt;
          json=data_to_send,&lt;br /&gt;
          headers=headers&lt;br /&gt;
     )&lt;br /&gt;
     print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Serveur : ====&lt;br /&gt;
La communication entre notre VM et la Raspberry est possible. Nous arrivons à effectuer un ping de l'une sur l'autre en passant par l'addresse IPv6.&lt;br /&gt;
&lt;br /&gt;
IPv6 VM :  2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
IPv6 Raspberry : 2001:660:4401:6050:da3a:ddff:fe59:4cb5&lt;br /&gt;
&lt;br /&gt;
Nous programmons ensuite une API sur notre VM en utilisant la libraire Flask.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import json&lt;br /&gt;
     from flask import Flask&lt;br /&gt;
     from flask import request&lt;br /&gt;
     from waitress import serve&lt;br /&gt;
     from flask import Response&lt;br /&gt;
     from flask_cors import CORS&lt;br /&gt;
     from flask_cors import cross_origin&lt;br /&gt;
&lt;br /&gt;
     app = Flask(__name__)&lt;br /&gt;
     cors = CORS(app, ressourceas={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;:&amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
     def compute_data(data):&lt;br /&gt;
          filename = input(&amp;quot;Nom du fichier :&amp;quot;)&lt;br /&gt;
          to_write = data.split(&amp;quot;\&amp;quot;&amp;quot;)[1:-1]&lt;br /&gt;
          with open(filename, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
               i = 0&lt;br /&gt;
               for elem in to_write:&lt;br /&gt;
                    if i == 0:&lt;br /&gt;
                         print(&amp;quot;We skip&amp;quot;)&lt;br /&gt;
                    else:&lt;br /&gt;
                         if (i%2) == 0:&lt;br /&gt;
                              print(&amp;quot;Data writed :&amp;quot;,elem[:-4])&lt;br /&gt;
                              f.write(elem[:-4])&lt;br /&gt;
                              f.write(&amp;quot;\n&amp;quot;)&lt;br /&gt;
                    i = i + 1&lt;br /&gt;
&lt;br /&gt;
     #Main&lt;br /&gt;
     @app.route('/',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
     @cross_origin()&lt;br /&gt;
     def hello():&lt;br /&gt;
          data = request.json&lt;br /&gt;
          compute_data(data)&lt;br /&gt;
          return data&lt;br /&gt;
&lt;br /&gt;
     if __name__ == '__main__':&lt;br /&gt;
          print(&amp;quot;Listening&amp;quot;)&lt;br /&gt;
          serve(app,host=&amp;quot;::&amp;quot;,port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Implémentation de l'IA : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant qu'on a une communication pour envoyer un fichier à notre serveur depuis la raspberry grâce à notre API, nous la modifions pour que la Raspberry puisse lire la valeur du capteur à ultrason, l'envoyer à notre serveur et recevoir en réponse, la prédiction de l'IA. Nous créons donc une route '''''/predict''''' sur notre API qui récupère les valeurs du capteurs données en paramètre et renvoie la prédiction de l'IA :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 @app.route('/predict',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
 def predict():&lt;br /&gt;
      data = request.json&lt;br /&gt;
      print(data)&lt;br /&gt;
      features = data['Features']&lt;br /&gt;
      print(features)&lt;br /&gt;
      features_splitted = features[0].split(&amp;quot;,&amp;quot;)&lt;br /&gt;
      features_int = [int(elem) for elem in features_splitted]&lt;br /&gt;
      loaded_model = joblib.load('model_entraine.pkl')&lt;br /&gt;
      predictios = loaded_model.predict(np.array(features_int).reshape(1,-1))&lt;br /&gt;
      return jsonify(predictions.tolist())&lt;br /&gt;
&amp;lt;/pre&amp;gt;Nous envoyons ensuite les données à analyser via des requêtes API :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 #Import Librairies&lt;br /&gt;
 import requests&lt;br /&gt;
 import json&lt;br /&gt;
 import serial&lt;br /&gt;
 from flask import jsonify&lt;br /&gt;
&lt;br /&gt;
 #Variable&lt;br /&gt;
 STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
 baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
 Serial_link = serial.Serial(STM32_port, baudrate, timeout=1)&lt;br /&gt;
 print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
 tab_to_send = []&lt;br /&gt;
&lt;br /&gt;
 while True:&lt;br /&gt;
      Serial_link.readline().decode('utf-8')&lt;br /&gt;
      tab_to_send.append(Serial_link.readline().decode('utf-8')&lt;br /&gt;
      if (tab_to_send != [&amp;quot;&amp;quot;]):&lt;br /&gt;
           print(&amp;quot;Data sended :&amp;quot;,tab_to_send)&lt;br /&gt;
           url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080/predict&amp;quot;&lt;br /&gt;
           headers = {&lt;br /&gt;
                'Content-type':'application/json',&lt;br /&gt;
                'Accept':'application/json'&lt;br /&gt;
           }&lt;br /&gt;
           r = requests.post(&lt;br /&gt;
                url_request,&lt;br /&gt;
                json = {&lt;br /&gt;
                     &amp;quot;Features&amp;quot;: tab_to_send&lt;br /&gt;
                },&lt;br /&gt;
                headers=headers&lt;br /&gt;
           )&lt;br /&gt;
           print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
           print(&amp;quot;Response :&amp;quot;,r.json())&lt;br /&gt;
      else:&lt;br /&gt;
           print(&amp;quot;Data skip:&amp;quot;,tab_to_send)&lt;br /&gt;
      tab_to_send.clear()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Entrainement de l'IA &amp;lt;/div&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec NanoEdge AI Studio : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour le projet, nous avons d'abord développé et entrainé notre IA sur la plateforme NanoEdge AI Studio. Pour ce faire, nous devons d'abord définir un projet de classification de n-class (&amp;quot;pierre&amp;quot;,&amp;quot;feuille&amp;quot;,&amp;quot;ciseau&amp;quot;) en utilisant un capteur générique à 16 axes. Pour ce faire, nous modifions le code de la STM32 pour qu'elle renvoie une ligne contenant 16*16 mesure en continue. Une fois le projet créé, nous ajoutons 3 signaux correspondant à nos dataset de &amp;quot;Pierre&amp;quot;, &amp;quot;Feuille&amp;quot; et &amp;quot;Ciseau&amp;quot;. Pour rajouter des valeurs dans notre dataset, nous utilisons la liaison série pour lire les valeurs de notre capteur.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec Scikit : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour la suite de notre projet, nous avons developpé et entrainé une IA avec Scikit.&lt;br /&gt;
&lt;br /&gt;
==== Construction du fichier d'entrainement ====&lt;br /&gt;
Pour commencer, nous avons du construire un fichier csv reprenant nos mesures sur un format de 16 valeurs. Pour chaque mesure, on ajoute en amont de la mesure la catégorie (feuille, ciseau ou pierre). &lt;br /&gt;
[[Fichier:Capture d’écran 2024-01-18 à 16.18.19.png|centré|vignette|500x500px|Fichier chifoumIA.csv]]&lt;br /&gt;
Pour construire ce fichier, nous avons assemblé trois fichiers csv de test que nous avons généré grâce à notre capteur : un fichier d'entrainement Pierre.csv, un fichier d'entrainement Ciseau.csv et un fichier d'entrainement Feuille.csv . &lt;br /&gt;
&lt;br /&gt;
Pour faire cette concaténation nous avons développer un programme python prenant en entrée nos fichiers d'entrainement et fournissant en sortie le fichier csv chifoumIA.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     line_feuille = []&lt;br /&gt;
     line_pierre = []&lt;br /&gt;
     line_ciseau = []&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Feuille.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_feuille = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Pierre.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_pierre = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Ciseau.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_ciseau = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;chifoumIA.csv&amp;quot;,&amp;quot;w&amp;quot;) as f:&lt;br /&gt;
          for elem in line_feuille:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;feuille,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_pierre:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;pierre,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_ciseau:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;ciseau,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Implémentation et Entrainement de notre IA ====&lt;br /&gt;
&lt;br /&gt;
===== Implémentation =====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant que nous avons notre fichier d'entrainement, nous implémentons notre IA. &lt;br /&gt;
&lt;br /&gt;
Nous avons commencé par créer un tableau de données et un tableau de classes. &lt;br /&gt;
&lt;br /&gt;
Pour remplir ces tableaux, on va lire ligne par ligne le fichier chifoumIA.csv. Le premier élément de la ligne est stockée dans le tableau de classes et le reste de la ligne est stockée dans le tableau de données. &lt;br /&gt;
 chifoumi_data=[]&lt;br /&gt;
 chifoumi_classe=[]&lt;br /&gt;
 &lt;br /&gt;
 with open('chifoumIA.csv') as csv_file:&lt;br /&gt;
        csv_reader = csv.reader(csv_file,delimiter=',')&lt;br /&gt;
        for row in csv_reader:           &lt;br /&gt;
                 chifoumi_data.append([int(row[1]),int(row[2]),int(row[3]),int(row[4]),int(row[5]),int(row[6]),int(row[7]),int(row[8]),&lt;br /&gt;
                                       int(row[9]),int(row[10]),int(row[11]),int(row[12]),int(row[13]),int(row[14]),int(row[15]),int(row[16])])&lt;br /&gt;
                 chifoumi_classe.append(row[0])&lt;br /&gt;
  &lt;br /&gt;
A partir de ces deux tableaux, on construit un ensemble de données d'entraînement et un ensemble de données de tests.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On choisi d'utiliser un réseau de neurone du type MLPClassifer. &lt;br /&gt;
&lt;br /&gt;
====== MLPClassifer ======&lt;br /&gt;
Le MLPClassifer est un type de réseau de neurones artificiels composés d'au minimum trois couches de neurones: une couche d'entrée, une ou plusieurs  couches cachées et une couche de sortie. &lt;br /&gt;
&lt;br /&gt;
Dans ce type de réseau, chaque neurone est connecté à l'ensemble des neurones de la couche suivante par un lien auquel est associé un poids. &lt;br /&gt;
&lt;br /&gt;
La classe MLPClassifer implémentée dans la bibliothèque Scikit-Learn dispose de nombreux paramètres. Pour notre projet, nous avons utilisé cette classe de façon très primaire. Les paramètres que nous avons utilisés sont :  &lt;br /&gt;
&lt;br /&gt;
- '''hidden_layer_sizes :''' ce paramètre est un tuple spécifiant le nombre de neurones dans chaque couche cachée. &lt;br /&gt;
&lt;br /&gt;
- '''max_iter :''' ce paramètre représente le nombre maximal d'époque. Il permet de contrôler également le temps d'entrainement.  &lt;br /&gt;
  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ipv6 jcie : 2001:660:4401:6050:216:3eff:fe68:8176&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4734</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4734"/>
		<updated>2024-01-28T11:29:17Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /* Implémentation et Entrainement de notre IA */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Introduction Projet IE Delannoy - Lemaire &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadre la matière '''&amp;quot;Intelligence Embarquée&amp;quot;''' de l'UE &amp;quot;Module de Spécialité&amp;quot; des SE5 - Option Systèmes Communicants, nous avons dû concevoir un projet permettant de '''distribuer le calcul et le processus d'entrainement''' et d'utilisation d'un Intelligence Artificielle. Nous devrons distribuer le calcul à différents endroits du réseau afin d'être en mesure de proposer des pistes d'optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, nous allons mettre en oeuvre un réseau d'objets connectés à des passerelles et à un serveur. '''Les objets collecteront des données''' de l'environnemet et suivants les scénarios, traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Nous aurons à disposition :&lt;br /&gt;
&lt;br /&gt;
* Une machine virtuelle sur le serveur '''Chassiron''' en ''E304/306''&lt;br /&gt;
* Une '''Raspberry PI 4'''&lt;br /&gt;
* Un carte programmable '''STM32F401RE'''&lt;br /&gt;
* Un capteur à ultrason '''Nucleo-53L5A1'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ce wiki est le compte-rendu du projet de '''Jason DELANNOY et Chloé LEMAIRE'''. Nous avons décider de développer une intelligence artificielle permettant de '''déterminer''' '''l'action faite par un joueur de Pierre-Feuille-Ciseau''' à l'aide du capteur à ultrason.&lt;br /&gt;
&lt;br /&gt;
Pour ce faire, nous allons développer notre IA de deux façons :&lt;br /&gt;
&lt;br /&gt;
* En utilisant '''NanoEdge Studio''' : Dans ce cas, le calcul serait fait par la carte programmable et envoyé au serveur via la Raspberry&lt;br /&gt;
* En utilisant '''un algorithme de machine learning ''': Ici, c'est le serveur qui fera le calcul et la Raspberry jouera le rôle de passerelle entre la carte programmable et le serveu&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Mise en oeuvre du réseau &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Création VM XEN ===&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la VM ===&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la borne WIFI Cisco ===&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251 (changement car besoin pour les PEIP) &lt;br /&gt;
&lt;br /&gt;
- dns-server: 193.48.57.33 (changement car problème avec le serveur DNS initial)&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Configuration de la Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadra du projet, nous avons à disposition une Raspberry PI 4 model B que nous allons configurer. Pour ce faire, nous utilisons le logiciel le &amp;quot;Raspberry PI Imager&amp;quot; pour choisir notre OS.&lt;br /&gt;
[[Fichier:JCIE RPI Imager.png|centré|vignette|400x400px]]Maintenant que nous avons une carte SD prête pour la Raspberry, nous la configurons via sa liaison série en passant par minicom :&lt;br /&gt;
 root@zabeth18: / $ minicom -D /dev/ttyACM0 -b 9600&lt;br /&gt;
De plus, nous modifions le fichier /etc/network/interfaces pour pouvoir connecter notre carte au réseau wifi créé plus haut :&lt;br /&gt;
[[Fichier:Screen WiFi.png|centré|vignette|441x441px]]&lt;br /&gt;
Nous verifions ensuite que nous avons une adresse IP :&lt;br /&gt;
[[Fichier:Screenshot from 2023-12-04 17-17-05.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Capteur NUCLEO - 53L5A1 &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Pour ce projet, nous disposons d'une STM32 Nucléo F401RE muni d'un capteur à ultrason X-Nucleo-53L5A1.&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir entrainer notre IA, nous devons faire en sorte d'afficher et de ressortir sur la liaison série les données du capteur. Pour ce faire, nous utilisons le fichier example &amp;quot;'''''53L5A1_ThresholdDetection'''''&amp;quot;. Nous modifions la fonction print_result pour afficher 16 valeurs à la suite :&lt;br /&gt;
[[Fichier:ChifoumIA Print Result.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Après avoir téléversé, nous pouvons vérifier le bon fonctionnement du programme en nous connectant à la carte via minicom :&lt;br /&gt;
&lt;br /&gt;
 root@raspberrypi:/dev$ minicom -D ttyACM0 -b 460800&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Communication VM-Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Envoie de donnée : ===&lt;br /&gt;
&lt;br /&gt;
Dans notre projet, nous avons besoin de remonter les données de notre capteur branché en liaison série à la Raspberry sur le port &amp;quot;ttyACM0&amp;quot;. Nous allons donc passer par des requêtes API entre le serveur sur chassiron et notre Raspberry.&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Raspberry : ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Du côté Raspberry, nous programmons un script en python qui lit sur la liaison série les valeurs du capteurs et les envoie via une requête POST vers le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import requests&lt;br /&gt;
     import json&lt;br /&gt;
     import serial&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;Variable&lt;br /&gt;
     STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
     baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
     Serial_link = serial.Serial(STM32_port,baudrate,timeout=1)&lt;br /&gt;
     print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
     liste_mesures=[]&lt;br /&gt;
     for i in range(101):&lt;br /&gt;
          print(&amp;quot;Mesure&amp;quot;,i)&lt;br /&gt;
          mesure = Serial_link.readline().decode('utf-8')&lt;br /&gt;
          liste_mesures.append(mesure)&lt;br /&gt;
&lt;br /&gt;
     data_to_send = json.dumps(liste_mesures)&lt;br /&gt;
     url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080&amp;quot;&lt;br /&gt;
&lt;br /&gt;
     headers = {&lt;br /&gt;
          'Content-type':'application/json',&lt;br /&gt;
          'Accept':'application/json'&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     r = requests.post(&lt;br /&gt;
          url_request,&lt;br /&gt;
          json=data_to_send,&lt;br /&gt;
          headers=headers&lt;br /&gt;
     )&lt;br /&gt;
     print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Serveur : ====&lt;br /&gt;
La communication entre notre VM et la Raspberry est possible. Nous arrivons à effectuer un ping de l'une sur l'autre en passant par l'addresse IPv6.&lt;br /&gt;
&lt;br /&gt;
IPv6 VM :  2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
IPv6 Raspberry : 2001:660:4401:6050:da3a:ddff:fe59:4cb5&lt;br /&gt;
&lt;br /&gt;
Nous programmons ensuite une API sur notre VM en utilisant la libraire Flask.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import json&lt;br /&gt;
     from flask import Flask&lt;br /&gt;
     from flask import request&lt;br /&gt;
     from waitress import serve&lt;br /&gt;
     from flask import Response&lt;br /&gt;
     from flask_cors import CORS&lt;br /&gt;
     from flask_cors import cross_origin&lt;br /&gt;
&lt;br /&gt;
     app = Flask(__name__)&lt;br /&gt;
     cors = CORS(app, ressourceas={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;:&amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
     def compute_data(data):&lt;br /&gt;
          filename = input(&amp;quot;Nom du fichier :&amp;quot;)&lt;br /&gt;
          to_write = data.split(&amp;quot;\&amp;quot;&amp;quot;)[1:-1]&lt;br /&gt;
          with open(filename, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
               i = 0&lt;br /&gt;
               for elem in to_write:&lt;br /&gt;
                    if i == 0:&lt;br /&gt;
                         print(&amp;quot;We skip&amp;quot;)&lt;br /&gt;
                    else:&lt;br /&gt;
                         if (i%2) == 0:&lt;br /&gt;
                              print(&amp;quot;Data writed :&amp;quot;,elem[:-4])&lt;br /&gt;
                              f.write(elem[:-4])&lt;br /&gt;
                              f.write(&amp;quot;\n&amp;quot;)&lt;br /&gt;
                    i = i + 1&lt;br /&gt;
&lt;br /&gt;
     #Main&lt;br /&gt;
     @app.route('/',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
     @cross_origin()&lt;br /&gt;
     def hello():&lt;br /&gt;
          data = request.json&lt;br /&gt;
          compute_data(data)&lt;br /&gt;
          return data&lt;br /&gt;
&lt;br /&gt;
     if __name__ == '__main__':&lt;br /&gt;
          print(&amp;quot;Listening&amp;quot;)&lt;br /&gt;
          serve(app,host=&amp;quot;::&amp;quot;,port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Implémentation de l'IA : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant qu'on a une communication pour envoyer un fichier à notre serveur depuis la raspberry grâce à notre API, nous la modifions pour que la Raspberry puisse lire la valeur du capteur à ultrason, l'envoyer à notre serveur et recevoir en réponse, la prédiction de l'IA. Nous créons donc une route '''''/predict''''' sur notre API qui récupère les valeurs du capteurs données en paramètre et renvoie la prédiction de l'IA :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 @app.route('/predict',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
 def predict():&lt;br /&gt;
      data = request.json&lt;br /&gt;
      print(data)&lt;br /&gt;
      features = data['Features']&lt;br /&gt;
      print(features)&lt;br /&gt;
      features_splitted = features[0].split(&amp;quot;,&amp;quot;)&lt;br /&gt;
      features_int = [int(elem) for elem in features_splitted]&lt;br /&gt;
      loaded_model = joblib.load('model_entraine.pkl')&lt;br /&gt;
      predictios = loaded_model.predict(np.array(features_int).reshape(1,-1))&lt;br /&gt;
      return jsonify(predictions.tolist())&lt;br /&gt;
&amp;lt;/pre&amp;gt;Nous envoyons ensuite les données à analyser via des requêtes API :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 #Import Librairies&lt;br /&gt;
 import requests&lt;br /&gt;
 import json&lt;br /&gt;
 import serial&lt;br /&gt;
 from flask import jsonify&lt;br /&gt;
&lt;br /&gt;
 #Variable&lt;br /&gt;
 STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
 baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
 Serial_link = serial.Serial(STM32_port, baudrate, timeout=1)&lt;br /&gt;
 print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
 tab_to_send = []&lt;br /&gt;
&lt;br /&gt;
 while True:&lt;br /&gt;
      Serial_link.readline().decode('utf-8')&lt;br /&gt;
      tab_to_send.append(Serial_link.readline().decode('utf-8')&lt;br /&gt;
      if (tab_to_send != [&amp;quot;&amp;quot;]):&lt;br /&gt;
           print(&amp;quot;Data sended :&amp;quot;,tab_to_send)&lt;br /&gt;
           url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080/predict&amp;quot;&lt;br /&gt;
           headers = {&lt;br /&gt;
                'Content-type':'application/json',&lt;br /&gt;
                'Accept':'application/json'&lt;br /&gt;
           }&lt;br /&gt;
           r = requests.post(&lt;br /&gt;
                url_request,&lt;br /&gt;
                json = {&lt;br /&gt;
                     &amp;quot;Features&amp;quot;: tab_to_send&lt;br /&gt;
                },&lt;br /&gt;
                headers=headers&lt;br /&gt;
           )&lt;br /&gt;
           print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
           print(&amp;quot;Response :&amp;quot;,r.json())&lt;br /&gt;
      else:&lt;br /&gt;
           print(&amp;quot;Data skip:&amp;quot;,tab_to_send)&lt;br /&gt;
      tab_to_send.clear()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Entrainement de l'IA &amp;lt;/div&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec NanoEdge AI Studio : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour le projet, nous avons d'abord développé et entrainé notre IA sur la plateforme NanoEdge AI Studio. Pour ce faire, nous devons d'abord définir un projet de classification de n-class (&amp;quot;pierre&amp;quot;,&amp;quot;feuille&amp;quot;,&amp;quot;ciseau&amp;quot;) en utilisant un capteur générique à 16 axes. Pour ce faire, nous modifions le code de la STM32 pour qu'elle renvoie une ligne contenant 16*16 mesure en continue. Une fois le projet créé, nous ajoutons 3 signaux correspondant à nos dataset de &amp;quot;Pierre&amp;quot;, &amp;quot;Feuille&amp;quot; et &amp;quot;Ciseau&amp;quot;. Pour rajouter des valeurs dans notre dataset, nous utilisons la liaison série pour lire les valeurs de notre capteur.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec Scikit : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour la suite de notre projet, nous avons developpé et entrainé une IA avec Scikit.&lt;br /&gt;
&lt;br /&gt;
==== Construction du fichier d'entrainement ====&lt;br /&gt;
Pour commencer, nous avons du construire un fichier csv reprenant nos mesures sur un format de 16 valeurs. Pour chaque mesure, on ajoute en amont de la mesure la catégorie (feuille, ciseau ou pierre). &lt;br /&gt;
[[Fichier:Capture d’écran 2024-01-18 à 16.18.19.png|centré|vignette|500x500px|Fichier chifoumIA.csv]]&lt;br /&gt;
Pour construire ce fichier, nous avons assemblé trois fichiers csv de test que nous avons généré grâce à notre capteur : un fichier d'entrainement Pierre.csv, un fichier d'entrainement Ciseau.csv et un fichier d'entrainement Feuille.csv . &lt;br /&gt;
&lt;br /&gt;
Pour faire cette concaténation nous avons développer un programme python prenant en entrée nos fichiers d'entrainement et fournissant en sortie le fichier csv chifoumIA.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     line_feuille = []&lt;br /&gt;
     line_pierre = []&lt;br /&gt;
     line_ciseau = []&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Feuille.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_feuille = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Pierre.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_pierre = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Ciseau.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_ciseau = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;chifoumIA.csv&amp;quot;,&amp;quot;w&amp;quot;) as f:&lt;br /&gt;
          for elem in line_feuille:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;feuille,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_pierre:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;pierre,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_ciseau:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;ciseau,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Implémentation et Entrainement de notre IA ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant que nous avons notre fichier d'entrainement, nous implémentons notre IA. &lt;br /&gt;
&lt;br /&gt;
Nous avons commencé par créer un tableau de données et un tableau de classes. &lt;br /&gt;
&lt;br /&gt;
Pour remplir ces tableaux, on va lire ligne par ligne le fichier chifoumIA.csv. Le premier élément de la ligne est stockée dans le tableau de classes et le reste de la ligne est stockée dans le tableau de données. &lt;br /&gt;
 chifoumi_data=[]&lt;br /&gt;
 chifoumi_classe=[]&lt;br /&gt;
 &lt;br /&gt;
 with open('chifoumIA.csv') as csv_file:&lt;br /&gt;
        csv_reader = csv.reader(csv_file,delimiter=',')&lt;br /&gt;
        for row in csv_reader:           &lt;br /&gt;
                 chifoumi_data.append([int(row[1]),int(row[2]),int(row[3]),int(row[4]),int(row[5]),int(row[6]),int(row[7]),int(row[8]),&lt;br /&gt;
                                       int(row[9]),int(row[10]),int(row[11]),int(row[12]),int(row[13]),int(row[14]),int(row[15]),int(row[16])])&lt;br /&gt;
                 chifoumi_classe.append(row[0])&lt;br /&gt;
  &lt;br /&gt;
A partir de ces deux tableaux, on construit un ensemble de données d'entraînement et un ensemble de données de tests.&lt;br /&gt;
&lt;br /&gt;
On choisi d'utiliser un réseau de neurone du type MLPClassifer. &lt;br /&gt;
&lt;br /&gt;
Le MLPClassifer est un type de réseau de neurones artificiels composés d'au minimum trois couches de neurones : une couche d'entrée, une couche cachée et une couche de sortie. &lt;br /&gt;
&lt;br /&gt;
Dans ce type de réseau, chaque neurone est connecté à l'ensemble des neurones de la couche suivante par un lien auquel est associé un poids. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ipv6 jcie : 2001:660:4401:6050:216:3eff:fe68:8176&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4733</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=4733"/>
		<updated>2024-01-28T11:18:23Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /* Implémentation et Entrainement de notre IA */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Introduction Projet IE Delannoy - Lemaire &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadre la matière '''&amp;quot;Intelligence Embarquée&amp;quot;''' de l'UE &amp;quot;Module de Spécialité&amp;quot; des SE5 - Option Systèmes Communicants, nous avons dû concevoir un projet permettant de '''distribuer le calcul et le processus d'entrainement''' et d'utilisation d'un Intelligence Artificielle. Nous devrons distribuer le calcul à différents endroits du réseau afin d'être en mesure de proposer des pistes d'optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, nous allons mettre en oeuvre un réseau d'objets connectés à des passerelles et à un serveur. '''Les objets collecteront des données''' de l'environnemet et suivants les scénarios, traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Nous aurons à disposition :&lt;br /&gt;
&lt;br /&gt;
* Une machine virtuelle sur le serveur '''Chassiron''' en ''E304/306''&lt;br /&gt;
* Une '''Raspberry PI 4'''&lt;br /&gt;
* Un carte programmable '''STM32F401RE'''&lt;br /&gt;
* Un capteur à ultrason '''Nucleo-53L5A1'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ce wiki est le compte-rendu du projet de '''Jason DELANNOY et Chloé LEMAIRE'''. Nous avons décider de développer une intelligence artificielle permettant de '''déterminer''' '''l'action faite par un joueur de Pierre-Feuille-Ciseau''' à l'aide du capteur à ultrason.&lt;br /&gt;
&lt;br /&gt;
Pour ce faire, nous allons développer notre IA de deux façons :&lt;br /&gt;
&lt;br /&gt;
* En utilisant '''NanoEdge Studio''' : Dans ce cas, le calcul serait fait par la carte programmable et envoyé au serveur via la Raspberry&lt;br /&gt;
* En utilisant '''un algorithme de machine learning ''': Ici, c'est le serveur qui fera le calcul et la Raspberry jouera le rôle de passerelle entre la carte programmable et le serveu&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Mise en oeuvre du réseau &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Création VM XEN ===&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la VM ===&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la borne WIFI Cisco ===&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251 (changement car besoin pour les PEIP) &lt;br /&gt;
&lt;br /&gt;
- dns-server: 193.48.57.33 (changement car problème avec le serveur DNS initial)&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Configuration de la Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadra du projet, nous avons à disposition une Raspberry PI 4 model B que nous allons configurer. Pour ce faire, nous utilisons le logiciel le &amp;quot;Raspberry PI Imager&amp;quot; pour choisir notre OS.&lt;br /&gt;
[[Fichier:JCIE RPI Imager.png|centré|vignette|400x400px]]Maintenant que nous avons une carte SD prête pour la Raspberry, nous la configurons via sa liaison série en passant par minicom :&lt;br /&gt;
 root@zabeth18: / $ minicom -D /dev/ttyACM0 -b 9600&lt;br /&gt;
De plus, nous modifions le fichier /etc/network/interfaces pour pouvoir connecter notre carte au réseau wifi créé plus haut :&lt;br /&gt;
[[Fichier:Screen WiFi.png|centré|vignette|441x441px]]&lt;br /&gt;
Nous verifions ensuite que nous avons une adresse IP :&lt;br /&gt;
[[Fichier:Screenshot from 2023-12-04 17-17-05.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Capteur NUCLEO - 53L5A1 &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Pour ce projet, nous disposons d'une STM32 Nucléo F401RE muni d'un capteur à ultrason X-Nucleo-53L5A1.&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir entrainer notre IA, nous devons faire en sorte d'afficher et de ressortir sur la liaison série les données du capteur. Pour ce faire, nous utilisons le fichier example &amp;quot;'''''53L5A1_ThresholdDetection'''''&amp;quot;. Nous modifions la fonction print_result pour afficher 16 valeurs à la suite :&lt;br /&gt;
[[Fichier:ChifoumIA Print Result.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Après avoir téléversé, nous pouvons vérifier le bon fonctionnement du programme en nous connectant à la carte via minicom :&lt;br /&gt;
&lt;br /&gt;
 root@raspberrypi:/dev$ minicom -D ttyACM0 -b 460800&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Communication VM-Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Envoie de donnée : ===&lt;br /&gt;
&lt;br /&gt;
Dans notre projet, nous avons besoin de remonter les données de notre capteur branché en liaison série à la Raspberry sur le port &amp;quot;ttyACM0&amp;quot;. Nous allons donc passer par des requêtes API entre le serveur sur chassiron et notre Raspberry.&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Raspberry : ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Du côté Raspberry, nous programmons un script en python qui lit sur la liaison série les valeurs du capteurs et les envoie via une requête POST vers le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import requests&lt;br /&gt;
     import json&lt;br /&gt;
     import serial&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;Variable&lt;br /&gt;
     STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
     baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
     Serial_link = serial.Serial(STM32_port,baudrate,timeout=1)&lt;br /&gt;
     print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
     liste_mesures=[]&lt;br /&gt;
     for i in range(101):&lt;br /&gt;
          print(&amp;quot;Mesure&amp;quot;,i)&lt;br /&gt;
          mesure = Serial_link.readline().decode('utf-8')&lt;br /&gt;
          liste_mesures.append(mesure)&lt;br /&gt;
&lt;br /&gt;
     data_to_send = json.dumps(liste_mesures)&lt;br /&gt;
     url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080&amp;quot;&lt;br /&gt;
&lt;br /&gt;
     headers = {&lt;br /&gt;
          'Content-type':'application/json',&lt;br /&gt;
          'Accept':'application/json'&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     r = requests.post(&lt;br /&gt;
          url_request,&lt;br /&gt;
          json=data_to_send,&lt;br /&gt;
          headers=headers&lt;br /&gt;
     )&lt;br /&gt;
     print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Serveur : ====&lt;br /&gt;
La communication entre notre VM et la Raspberry est possible. Nous arrivons à effectuer un ping de l'une sur l'autre en passant par l'addresse IPv6.&lt;br /&gt;
&lt;br /&gt;
IPv6 VM :  2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
IPv6 Raspberry : 2001:660:4401:6050:da3a:ddff:fe59:4cb5&lt;br /&gt;
&lt;br /&gt;
Nous programmons ensuite une API sur notre VM en utilisant la libraire Flask.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import json&lt;br /&gt;
     from flask import Flask&lt;br /&gt;
     from flask import request&lt;br /&gt;
     from waitress import serve&lt;br /&gt;
     from flask import Response&lt;br /&gt;
     from flask_cors import CORS&lt;br /&gt;
     from flask_cors import cross_origin&lt;br /&gt;
&lt;br /&gt;
     app = Flask(__name__)&lt;br /&gt;
     cors = CORS(app, ressourceas={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;:&amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
     def compute_data(data):&lt;br /&gt;
          filename = input(&amp;quot;Nom du fichier :&amp;quot;)&lt;br /&gt;
          to_write = data.split(&amp;quot;\&amp;quot;&amp;quot;)[1:-1]&lt;br /&gt;
          with open(filename, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
               i = 0&lt;br /&gt;
               for elem in to_write:&lt;br /&gt;
                    if i == 0:&lt;br /&gt;
                         print(&amp;quot;We skip&amp;quot;)&lt;br /&gt;
                    else:&lt;br /&gt;
                         if (i%2) == 0:&lt;br /&gt;
                              print(&amp;quot;Data writed :&amp;quot;,elem[:-4])&lt;br /&gt;
                              f.write(elem[:-4])&lt;br /&gt;
                              f.write(&amp;quot;\n&amp;quot;)&lt;br /&gt;
                    i = i + 1&lt;br /&gt;
&lt;br /&gt;
     #Main&lt;br /&gt;
     @app.route('/',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
     @cross_origin()&lt;br /&gt;
     def hello():&lt;br /&gt;
          data = request.json&lt;br /&gt;
          compute_data(data)&lt;br /&gt;
          return data&lt;br /&gt;
&lt;br /&gt;
     if __name__ == '__main__':&lt;br /&gt;
          print(&amp;quot;Listening&amp;quot;)&lt;br /&gt;
          serve(app,host=&amp;quot;::&amp;quot;,port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Implémentation de l'IA : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant qu'on a une communication pour envoyer un fichier à notre serveur depuis la raspberry grâce à notre API, nous la modifions pour que la Raspberry puisse lire la valeur du capteur à ultrason, l'envoyer à notre serveur et recevoir en réponse, la prédiction de l'IA. Nous créons donc une route '''''/predict''''' sur notre API qui récupère les valeurs du capteurs données en paramètre et renvoie la prédiction de l'IA :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 @app.route('/predict',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
 def predict():&lt;br /&gt;
      data = request.json&lt;br /&gt;
      print(data)&lt;br /&gt;
      features = data['Features']&lt;br /&gt;
      print(features)&lt;br /&gt;
      features_splitted = features[0].split(&amp;quot;,&amp;quot;)&lt;br /&gt;
      features_int = [int(elem) for elem in features_splitted]&lt;br /&gt;
      loaded_model = joblib.load('model_entraine.pkl')&lt;br /&gt;
      predictios = loaded_model.predict(np.array(features_int).reshape(1,-1))&lt;br /&gt;
      return jsonify(predictions.tolist())&lt;br /&gt;
&amp;lt;/pre&amp;gt;Nous envoyons ensuite les données à analyser via des requêtes API :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 #Import Librairies&lt;br /&gt;
 import requests&lt;br /&gt;
 import json&lt;br /&gt;
 import serial&lt;br /&gt;
 from flask import jsonify&lt;br /&gt;
&lt;br /&gt;
 #Variable&lt;br /&gt;
 STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
 baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
 Serial_link = serial.Serial(STM32_port, baudrate, timeout=1)&lt;br /&gt;
 print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
 tab_to_send = []&lt;br /&gt;
&lt;br /&gt;
 while True:&lt;br /&gt;
      Serial_link.readline().decode('utf-8')&lt;br /&gt;
      tab_to_send.append(Serial_link.readline().decode('utf-8')&lt;br /&gt;
      if (tab_to_send != [&amp;quot;&amp;quot;]):&lt;br /&gt;
           print(&amp;quot;Data sended :&amp;quot;,tab_to_send)&lt;br /&gt;
           url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080/predict&amp;quot;&lt;br /&gt;
           headers = {&lt;br /&gt;
                'Content-type':'application/json',&lt;br /&gt;
                'Accept':'application/json'&lt;br /&gt;
           }&lt;br /&gt;
           r = requests.post(&lt;br /&gt;
                url_request,&lt;br /&gt;
                json = {&lt;br /&gt;
                     &amp;quot;Features&amp;quot;: tab_to_send&lt;br /&gt;
                },&lt;br /&gt;
                headers=headers&lt;br /&gt;
           )&lt;br /&gt;
           print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
           print(&amp;quot;Response :&amp;quot;,r.json())&lt;br /&gt;
      else:&lt;br /&gt;
           print(&amp;quot;Data skip:&amp;quot;,tab_to_send)&lt;br /&gt;
      tab_to_send.clear()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Entrainement de l'IA &amp;lt;/div&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec NanoEdge AI Studio : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour le projet, nous avons d'abord développé et entrainé notre IA sur la plateforme NanoEdge AI Studio. Pour ce faire, nous devons d'abord définir un projet de classification de n-class (&amp;quot;pierre&amp;quot;,&amp;quot;feuille&amp;quot;,&amp;quot;ciseau&amp;quot;) en utilisant un capteur générique à 16 axes. Pour ce faire, nous modifions le code de la STM32 pour qu'elle renvoie une ligne contenant 16*16 mesure en continue. Une fois le projet créé, nous ajoutons 3 signaux correspondant à nos dataset de &amp;quot;Pierre&amp;quot;, &amp;quot;Feuille&amp;quot; et &amp;quot;Ciseau&amp;quot;. Pour rajouter des valeurs dans notre dataset, nous utilisons la liaison série pour lire les valeurs de notre capteur.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec Scikit : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour la suite de notre projet, nous avons developpé et entrainé une IA avec Scikit.&lt;br /&gt;
&lt;br /&gt;
==== Construction du fichier d'entrainement ====&lt;br /&gt;
Pour commencer, nous avons du construire un fichier csv reprenant nos mesures sur un format de 16 valeurs. Pour chaque mesure, on ajoute en amont de la mesure la catégorie (feuille, ciseau ou pierre). &lt;br /&gt;
[[Fichier:Capture d’écran 2024-01-18 à 16.18.19.png|centré|vignette|500x500px|Fichier chifoumIA.csv]]&lt;br /&gt;
Pour construire ce fichier, nous avons assemblé trois fichiers csv de test que nous avons généré grâce à notre capteur : un fichier d'entrainement Pierre.csv, un fichier d'entrainement Ciseau.csv et un fichier d'entrainement Feuille.csv . &lt;br /&gt;
&lt;br /&gt;
Pour faire cette concaténation nous avons développer un programme python prenant en entrée nos fichiers d'entrainement et fournissant en sortie le fichier csv chifoumIA.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     line_feuille = []&lt;br /&gt;
     line_pierre = []&lt;br /&gt;
     line_ciseau = []&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Feuille.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_feuille = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Pierre.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_pierre = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Ciseau.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_ciseau = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;chifoumIA.csv&amp;quot;,&amp;quot;w&amp;quot;) as f:&lt;br /&gt;
          for elem in line_feuille:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;feuille,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_pierre:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;pierre,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_ciseau:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;ciseau,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Implémentation et Entrainement de notre IA ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant que nous avons notre fichier d'entrainement, nous implémentons notre IA. &lt;br /&gt;
&lt;br /&gt;
Nous avons commencé par créer un tableau de données et un tableau de classes. &lt;br /&gt;
&lt;br /&gt;
Pour remplir ces tableaux, on va lire ligne par ligne le fichier chifoumIA.csv. Le premier élément de la ligne est stockée dans le tableau de classes et le reste de la ligne est stockée dans le tableau de données. &lt;br /&gt;
 chifoumi_data=[]&lt;br /&gt;
 chifoumi_classe=[]&lt;br /&gt;
 &lt;br /&gt;
 with open('chifoumIA.csv') as csv_file:&lt;br /&gt;
        csv_reader = csv.reader(csv_file,delimiter=',')&lt;br /&gt;
        for row in csv_reader:           &lt;br /&gt;
                 chifoumi_data.append([int(row[1]),int(row[2]),int(row[3]),int(row[4]),int(row[5]),int(row[6]),int(row[7]),int(row[8]),&lt;br /&gt;
                                       int(row[9]),int(row[10]),int(row[11]),int(row[12]),int(row[13]),int(row[14]),int(row[15]),int(row[16])])&lt;br /&gt;
                 chifoumi_classe.append(row[0])&lt;br /&gt;
  &lt;br /&gt;
A partir de ces deux tableaux, on construit un ensemble de données d'entraînement et un ensemble de données de tests.&lt;br /&gt;
&lt;br /&gt;
On choisi d'utiliser un réseau de neurone du type MLPClassifer. &lt;br /&gt;
&lt;br /&gt;
Le MLPClassifer est un type de réseau de neurones artificiels composés d'au minimum trois couches de neurones : une couche d'entrée, une couche cachée et une couche de sortie. &lt;br /&gt;
&lt;br /&gt;
ipv6 jcie : 2001:660:4401:6050:216:3eff:fe68:8176&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3976</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3976"/>
		<updated>2024-01-18T16:05:50Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /* Implémentation et Entrainement de notre IA */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Introduction Projet IE Delannoy - Lemaire &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadre la matière '''&amp;quot;Intelligence Embarquée&amp;quot;''' de l'UE &amp;quot;Module de Spécialité&amp;quot; des SE5 - Option Systèmes Communicants, nous avons dû concevoir un projet permettant de '''distribuer le calcul et le processus d'entrainement''' et d'utilisation d'un Intelligence Artificielle. Nous devrons distribuer le calcul à différents endroits du réseau afin d'être en mesure de proposer des pistes d'optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, nous allons mettre en oeuvre un réseau d'objets connectés à des passerelles et à un serveur. '''Les objets collecteront des données''' de l'environnemet et suivants les scénarios, traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Nous aurons à disposition :&lt;br /&gt;
&lt;br /&gt;
* Une machine virtuelle sur le serveur '''Chassiron''' en ''E304/306''&lt;br /&gt;
* Une '''Raspberry PI 4'''&lt;br /&gt;
* Un carte programmable '''STM32F401RE'''&lt;br /&gt;
* Un capteur à ultrason '''Nucleo-53L5A1'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ce wiki est le compte-rendu du projet de '''Jason DELANNOY et Chloé LEMAIRE'''. Nous avons décider de développer une intelligence artificielle permettant de '''déterminer''' '''l'action faite par un joueur de Pierre-Feuille-Ciseau''' à l'aide du capteur à ultrason.&lt;br /&gt;
&lt;br /&gt;
Pour ce faire, nous allons développer notre IA de deux façons :&lt;br /&gt;
&lt;br /&gt;
* En utilisant '''NanoEdge Studio''' : Dans ce cas, le calcul serait fait par la carte programmable et envoyé au serveur via la Raspberry&lt;br /&gt;
* En utilisant '''un algorithme de machine learning ''': Ici, c'est le serveur qui fera le calcul et la Raspberry jouera le rôle de passerelle entre la carte programmable et le serveu&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Mise en oeuvre du réseau &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Création VM XEN ===&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la VM ===&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la borne WIFI Cisco ===&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251 (changement car besoin pour les PEIP) &lt;br /&gt;
&lt;br /&gt;
- dns-server: 193.48.57.33 (changement car problème avec le serveur DNS initial)&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Configuration de la Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadra du projet, nous avons à disposition une Raspberry PI 4 model B que nous allons configurer. Pour ce faire, nous utilisons le logiciel le &amp;quot;Raspberry PI Imager&amp;quot; pour choisir notre OS.&lt;br /&gt;
[[Fichier:JCIE RPI Imager.png|centré|vignette|400x400px]]Maintenant que nous avons une carte SD prête pour la Raspberry, nous la configurons via sa liaison série en passant par minicom :&lt;br /&gt;
 root@zabeth18: / $ minicom -D /dev/ttyACM0 -b 9600&lt;br /&gt;
De plus, nous modifions le fichier /etc/network/interfaces pour pouvoir connecter notre carte au réseau wifi créé plus haut :&lt;br /&gt;
[[Fichier:Screen WiFi.png|centré|vignette|441x441px]]&lt;br /&gt;
Nous verifions ensuite que nous avons une adresse IP :&lt;br /&gt;
[[Fichier:Screenshot from 2023-12-04 17-17-05.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Capteur NUCLEO - 53L5A1 &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Pour ce projet, nous disposons d'une STM32 Nucléo F401RE muni d'un capteur à ultrason X-Nucleo-53L5A1.&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir entrainer notre IA, nous devons faire en sorte d'afficher et de ressortir sur la liaison série les données du capteur. Pour ce faire, nous utilisons le fichier example &amp;quot;'''''53L5A1_ThresholdDetection'''''&amp;quot;. Nous modifions la fonction print_result pour afficher 16 valeurs à la suite :&lt;br /&gt;
[[Fichier:ChifoumIA Print Result.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Après avoir téléversé, nous pouvons vérifier le bon fonctionnement du programme en nous connectant à la carte via minicom :&lt;br /&gt;
&lt;br /&gt;
 root@raspberrypi:/dev$ minicom -D ttyACM0 -b 460800&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Communication VM-Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Envoie de donnée : ===&lt;br /&gt;
&lt;br /&gt;
Dans notre projet, nous avons besoin de remonter les données de notre capteur branché en liaison série à la Raspberry sur le port &amp;quot;ttyACM0&amp;quot;. Nous allons donc passer par des requêtes API entre le serveur sur chassiron et notre Raspberry.&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Raspberry : ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Du côté Raspberry, nous programmons un script en python qui lit sur la liaison série les valeurs du capteurs et les envoie via une requête POST vers le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import requests&lt;br /&gt;
     import json&lt;br /&gt;
     import serial&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;Variable&lt;br /&gt;
     STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
     baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
     Serial_link = serial.Serial(STM32_port,baudrate,timeout=1)&lt;br /&gt;
     print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
     liste_mesures=[]&lt;br /&gt;
     for i in range(101):&lt;br /&gt;
          print(&amp;quot;Mesure&amp;quot;,i)&lt;br /&gt;
          mesure = Serial_link.readline().decode('utf-8')&lt;br /&gt;
          liste_mesures.append(mesure)&lt;br /&gt;
&lt;br /&gt;
     data_to_send = json.dumps(liste_mesures)&lt;br /&gt;
     url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080&amp;quot;&lt;br /&gt;
&lt;br /&gt;
     headers = {&lt;br /&gt;
          'Content-type':'application/json',&lt;br /&gt;
          'Accept':'application/json'&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     r = requests.post(&lt;br /&gt;
          url_request,&lt;br /&gt;
          json=data_to_send,&lt;br /&gt;
          headers=headers&lt;br /&gt;
     )&lt;br /&gt;
     print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Serveur : ====&lt;br /&gt;
La communication entre notre VM et la Raspberry est possible. Nous arrivons à effectuer un ping de l'une sur l'autre en passant par l'addresse IPv6.&lt;br /&gt;
&lt;br /&gt;
IPv6 VM :  2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
IPv6 Raspberry : 2001:660:4401:6050:da3a:ddff:fe59:4cb5&lt;br /&gt;
&lt;br /&gt;
Nous programmons ensuite une API sur notre VM en utilisant la libraire Flask.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import json&lt;br /&gt;
     from flask import Flask&lt;br /&gt;
     from flask import request&lt;br /&gt;
     from waitress import serve&lt;br /&gt;
     from flask import Response&lt;br /&gt;
     from flask_cors import CORS&lt;br /&gt;
     from flask_cors import cross_origin&lt;br /&gt;
&lt;br /&gt;
     app = Flask(__name__)&lt;br /&gt;
     cors = CORS(app, ressourceas={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;:&amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
     def compute_data(data):&lt;br /&gt;
          filename = input(&amp;quot;Nom du fichier :&amp;quot;)&lt;br /&gt;
          to_write = data.split(&amp;quot;\&amp;quot;&amp;quot;)[1:-1]&lt;br /&gt;
          with open(filename, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
               i = 0&lt;br /&gt;
               for elem in to_write:&lt;br /&gt;
                    if i == 0:&lt;br /&gt;
                         print(&amp;quot;We skip&amp;quot;)&lt;br /&gt;
                    else:&lt;br /&gt;
                         if (i%2) == 0:&lt;br /&gt;
                              print(&amp;quot;Data writed :&amp;quot;,elem[:-4])&lt;br /&gt;
                              f.write(elem[:-4])&lt;br /&gt;
                              f.write(&amp;quot;\n&amp;quot;)&lt;br /&gt;
                    i = i + 1&lt;br /&gt;
&lt;br /&gt;
     #Main&lt;br /&gt;
     @app.route('/',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
     @cross_origin()&lt;br /&gt;
     def hello():&lt;br /&gt;
          data = request.json&lt;br /&gt;
          compute_data(data)&lt;br /&gt;
          return data&lt;br /&gt;
&lt;br /&gt;
     if __name__ == '__main__':&lt;br /&gt;
          print(&amp;quot;Listening&amp;quot;)&lt;br /&gt;
          serve(app,host=&amp;quot;::&amp;quot;,port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Implémentation de l'IA : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant qu'on a une communication pour envoyer un fichier à notre serveur depuis la raspberry grâce à notre API, nous la modifions pour que la Raspberry puisse lire la valeur du capteur à ultrason, l'envoyer à notre serveur et recevoir en réponse, la prédiction de l'IA. Nous créons donc une route '''''/predict''''' sur notre API qui récupère les valeurs du capteurs données en paramètre et renvoie la prédiction de l'IA :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 @app.route('/predict',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
 def predict():&lt;br /&gt;
      data = request.json&lt;br /&gt;
      print(data)&lt;br /&gt;
      features = data['Features']&lt;br /&gt;
      print(features)&lt;br /&gt;
      features_splitted = features[0].split(&amp;quot;,&amp;quot;)&lt;br /&gt;
      features_int = [int(elem) for elem in features_splitted]&lt;br /&gt;
      loaded_model = joblib.load('model_entraine.pkl')&lt;br /&gt;
      predictios = loaded_model.predict(np.array(features_int).reshape(1,-1))&lt;br /&gt;
      return jsonify(predictions.tolist())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Entrainement de l'IA &amp;lt;/div&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec NanoEdge AI Studio : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour le projet, nous avons d'abord développé et entrainé notre IA sur la plateforme NanoEdge AI Studio. Pour ce faire, nous devons d'abord définir un projet de classification de n-class (&amp;quot;pierre&amp;quot;,&amp;quot;feuille&amp;quot;,&amp;quot;ciseau&amp;quot;) en utilisant un capteur générique à 16 axes. Pour ce faire, nous modifions le code de la STM32 pour qu'elle renvoie une ligne contenant 16*16 mesure en continue. Une fois le projet créé, nous ajoutons 3 signaux correspondant à nos dataset de &amp;quot;Pierre&amp;quot;, &amp;quot;Feuille&amp;quot; et &amp;quot;Ciseau&amp;quot;. Pour rajouter des valeurs dans notre dataset, nous utilisons la liaison série pour lire les valeurs de notre capteur.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec Scikit : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour la suite de notre projet, nous avons developpé et entrainé une IA avec Scikit.&lt;br /&gt;
&lt;br /&gt;
==== Construction du fichier d'entrainement ====&lt;br /&gt;
Pour commencer, nous avons du construire un fichier csv reprenant nos mesures sur un format de 16 valeurs. Pour chaque mesure, on ajoute en amont de la mesure la catégorie (feuille, ciseau ou pierre). &lt;br /&gt;
[[Fichier:Capture d’écran 2024-01-18 à 16.18.19.png|centré|vignette|500x500px|Fichier chifoumIA.csv]]&lt;br /&gt;
Pour construire ce fichier, nous avons assemblé trois fichiers csv de test que nous avons généré grâce à notre capteur : un fichier d'entrainement Pierre.csv, un fichier d'entrainement Ciseau.csv et un fichier d'entrainement Feuille.csv . &lt;br /&gt;
&lt;br /&gt;
Pour faire cette concaténation nous avons développer un programme python prenant en entrée nos fichiers d'entrainement et fournissant en sortie le fichier csv chifoumIA.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     line_feuille = []&lt;br /&gt;
     line_pierre = []&lt;br /&gt;
     line_ciseau = []&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Feuille.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_feuille = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Pierre.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_pierre = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Ciseau.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_ciseau = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;chifoumIA.csv&amp;quot;,&amp;quot;w&amp;quot;) as f:&lt;br /&gt;
          for elem in line_feuille:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;feuille,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_pierre:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;pierre,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_ciseau:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;ciseau,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Implémentation et Entrainement de notre IA ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant que nous avons notre fichier d'entrainement, nous implémentons notre IA. &lt;br /&gt;
&lt;br /&gt;
Nous avons commencé par créer un tableau de données et un tableau de classes. &lt;br /&gt;
&lt;br /&gt;
Pour remplir ces tableaux, on va lire ligne par ligne le fichier chifoumIA.csv. Le premier élément de la ligne est stockée dans le tableau de classes et le reste de la ligne est stockée dans le tableau de données. &lt;br /&gt;
 chifoumi_data=[]&lt;br /&gt;
 chifoumi_classe=[]&lt;br /&gt;
 &lt;br /&gt;
 with open('chifoumIA.csv') as csv_file:&lt;br /&gt;
        csv_reader = csv.reader(csv_file,delimiter=',')&lt;br /&gt;
        for row in csv_reader: chifoumi_data.append([int(row[1]),int(row[2]),int(row[3]),int(row[4]),int(row[5]),int(row[6]),int(row[7]),int(row[8]),int(row[9]),int(row[10]),int(row[11]),int(row[12]),int(row[13]),int(row[14]),int(row[15]),int(row[16])])&lt;br /&gt;
                 chifoumi_classe.append(row[0])&lt;br /&gt;
  &lt;br /&gt;
A partir de ces deux tableaux, on construit un ensemble de données d'entraînement et un ensemble de données de tests.&lt;br /&gt;
&lt;br /&gt;
On choisi d'utiliser un réseau de neurone du type MLPClassifer. &lt;br /&gt;
&lt;br /&gt;
ipv6 jcie : 2001:660:4401:6050:216:3eff:fe68:8176&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3973</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3973"/>
		<updated>2024-01-18T15:51:45Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /* Implémentation et Entrainement de notre IA */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Introduction Projet IE Delannoy - Lemaire &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
L’objectif de ce projet est de distribuer le calcul à différents endroits du réseau afin d’être en mesure de proposer des pistes d’optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, vous allez mettre en œuvre un réseau d’objets connectés à des passerelles et à un serveur. Les objets collecteront des données de l’environnement et suivant les scénarios traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Chaque scénario sera évalué en terme de performance de calcul et de sobriété énergétique. Les indicateurs de performances sont à définir (indicateur pour le calcul, pour l’énergie mais aussi un indicateur combiné).&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Présentation du Projet &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le but de notre projet est de réaliser une application permettant de déterminer l'action faite par un joueur de Pierre-Feuille-Ciseau. Notre système devra donc reconnaitre les différents mouvements fait par le joueur.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Mise en oeuvre du réseau &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Création VM XEN ===&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la VM ===&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la borne WIFI Cisco ===&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251 (changement car besoin pour les PEIP) &lt;br /&gt;
&lt;br /&gt;
- dns-server: 193.48.57.33 (changement car problème avec le serveur DNS initial)&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Configuration de la Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadra du projet, nous avons à disposition une Raspberry PI 4 model B que nous allons configurer. Pour ce faire, nous utilisons le logiciel le &amp;quot;Raspberry PI Imager&amp;quot; pour choisir notre OS.&lt;br /&gt;
[[Fichier:JCIE RPI Imager.png|centré|vignette|400x400px]]Maintenant que nous avons une carte SD prête pour la Raspberry, nous la configurons via sa liaison série en passant par minicom :&lt;br /&gt;
 root@zabeth18: / $ minicom -D /dev/ttyACM0 -b 9600&lt;br /&gt;
De plus, nous modifions le fichier /etc/network/interfaces pour pouvoir connecter notre carte au réseau wifi créé plus haut :&lt;br /&gt;
[[Fichier:Screen WiFi.png|centré|vignette|441x441px]]&lt;br /&gt;
Nous verifions ensuite que nous avons une adresse IP :&lt;br /&gt;
[[Fichier:Screenshot from 2023-12-04 17-17-05.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Capteur NUCLEO - 53L5A1 &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Pour ce projet, nous disposons d'une STM32 Nucléo F401RE muni d'un capteur à ultrason X-Nucleo-53L5A1.&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir entrainer notre IA, nous devons faire en sorte d'afficher et de ressortir sur la liaison série les données du capteur. Pour ce faire, nous utilisons le fichier example &amp;quot;'''''53L5A1_ThresholdDetection'''''&amp;quot;. Nous modifions la fonction print_result pour afficher 16 valeurs à la suite :&lt;br /&gt;
[[Fichier:ChifoumIA Print Result.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Après avoir téléversé, nous pouvons vérifier le bon fonctionnement du programme en nous connectant à la carte via minicom :&lt;br /&gt;
&lt;br /&gt;
 root@raspberrypi:/dev$ minicom -D ttyACM0 -b 460800&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Communication VM-Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Envoie de donnée : ===&lt;br /&gt;
&lt;br /&gt;
Dans notre projet, nous avons besoin de remonter les données de notre capteur branché en liaison série à la Raspberry sur le port &amp;quot;ttyACM0&amp;quot;. Nous allons donc passer par des requêtes API entre le serveur sur chassiron et notre Raspberry.&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Raspberry : ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Du côté Raspberry, nous programmons un script en python qui lit sur la liaison série les valeurs du capteurs et les envoie via une requête POST vers le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import requests&lt;br /&gt;
     import json&lt;br /&gt;
     import serial&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;Variable&lt;br /&gt;
     STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
     baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
     Serial_link = serial.Serial(STM32_port,baudrate,timeout=1)&lt;br /&gt;
     print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
     liste_mesures=[]&lt;br /&gt;
     for i in range(101):&lt;br /&gt;
          print(&amp;quot;Mesure&amp;quot;,i)&lt;br /&gt;
          mesure = Serial_link.readline().decode('utf-8')&lt;br /&gt;
          liste_mesures.append(mesure)&lt;br /&gt;
&lt;br /&gt;
     data_to_send = json.dumps(liste_mesures)&lt;br /&gt;
     url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080&amp;quot;&lt;br /&gt;
&lt;br /&gt;
     headers = {&lt;br /&gt;
          'Content-type':'application/json',&lt;br /&gt;
          'Accept':'application/json'&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     r = requests.post(&lt;br /&gt;
          url_request,&lt;br /&gt;
          json=data_to_send,&lt;br /&gt;
          headers=headers&lt;br /&gt;
     )&lt;br /&gt;
     print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Serveur : ====&lt;br /&gt;
La communication entre notre VM et la Raspberry est possible. Nous arrivons à effectuer un ping de l'une sur l'autre en passant par l'addresse IPv6.&lt;br /&gt;
&lt;br /&gt;
IPv6 VM :  2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
IPv6 Raspberry : 2001:660:4401:6050:da3a:ddff:fe59:4cb5&lt;br /&gt;
&lt;br /&gt;
Nous programmons ensuite une API sur notre VM en utilisant la libraire Flask.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import json&lt;br /&gt;
     from flask import Flask&lt;br /&gt;
     from flask import request&lt;br /&gt;
     from waitress import serve&lt;br /&gt;
     from flask import Response&lt;br /&gt;
     from flask_cors import CORS&lt;br /&gt;
     from flask_cors import cross_origin&lt;br /&gt;
&lt;br /&gt;
     app = Flask(__name__)&lt;br /&gt;
     cors = CORS(app, ressourceas={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;:&amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
     def compute_data(data):&lt;br /&gt;
          filename = input(&amp;quot;Nom du fichier :&amp;quot;)&lt;br /&gt;
          to_write = data.split(&amp;quot;\&amp;quot;&amp;quot;)[1:-1]&lt;br /&gt;
          with open(filename, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
               i = 0&lt;br /&gt;
               for elem in to_write:&lt;br /&gt;
                    if i == 0:&lt;br /&gt;
                         print(&amp;quot;We skip&amp;quot;)&lt;br /&gt;
                    else:&lt;br /&gt;
                         if (i%2) == 0:&lt;br /&gt;
                              print(&amp;quot;Data writed :&amp;quot;,elem[:-4])&lt;br /&gt;
                              f.write(elem[:-4])&lt;br /&gt;
                              f.write(&amp;quot;\n&amp;quot;)&lt;br /&gt;
                    i = i + 1&lt;br /&gt;
&lt;br /&gt;
     #Main&lt;br /&gt;
     @app.route('/',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
     @cross_origin()&lt;br /&gt;
     def hello():&lt;br /&gt;
          data = request.json&lt;br /&gt;
          compute_data(data)&lt;br /&gt;
          return data&lt;br /&gt;
&lt;br /&gt;
     if __name__ == '__main__':&lt;br /&gt;
          print(&amp;quot;Listening&amp;quot;)&lt;br /&gt;
          serve(app,host=&amp;quot;::&amp;quot;,port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Implémentation de l'IA : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant qu'on a une communication pour envoyer un fichier à notre serveur depuis la raspberry grâce à notre API, nous la modifions pour que la Raspberry puisse lire la valeur du capteur à ultrason, l'envoyer à notre serveur et recevoir en réponse, la prédiction de l'IA. Nous créons donc une route '''''/predict''''' sur notre API qui récupère les valeurs du capteurs données en paramètre et renvoie la prédiction de l'IA :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 @app.route('/predict',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
 def predict():&lt;br /&gt;
      data = request.json&lt;br /&gt;
      print(data)&lt;br /&gt;
      features = data['Features']&lt;br /&gt;
      print(features)&lt;br /&gt;
      features_splitted = features[0].split(&amp;quot;,&amp;quot;)&lt;br /&gt;
      features_int = [int(elem) for elem in features_splitted]&lt;br /&gt;
      loaded_model = joblib.load('model_entraine.pkl')&lt;br /&gt;
      predictios = loaded_model.predict(np.array(features_int).reshape(1,-1))&lt;br /&gt;
      return jsonify(predictions.tolist())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Entrainement de l'IA &amp;lt;/div&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec NanoEdge AI Studio : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour le projet, nous avons d'abord développé et entrainé notre IA sur la plateforme NanoEdge AI Studio. Pour ce faire, nous devons d'abord définir un projet de classification de n-class (&amp;quot;pierre&amp;quot;,&amp;quot;feuille&amp;quot;,&amp;quot;ciseau&amp;quot;) en utilisant un capteur générique à 16 axes. Pour ce faire, nous modifions le code de la STM32 pour qu'elle renvoie une ligne contenant 16*16 mesure en continue. Une fois le projet créé, nous ajoutons 3 signaux correspondant à nos dataset de &amp;quot;Pierre&amp;quot;, &amp;quot;Feuille&amp;quot; et &amp;quot;Ciseau&amp;quot;. Pour rajouter des valeurs dans notre dataset, nous utilisons la liaison série pour lire les valeurs de notre capteur.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec Scikit : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour la suite de notre projet, nous avons developpé et entrainé une IA avec Scikit.&lt;br /&gt;
&lt;br /&gt;
==== Construction du fichier d'entrainement ====&lt;br /&gt;
Pour commencer, nous avons du construire un fichier csv reprenant nos mesures sur un format de 16 valeurs. Pour chaque mesure, on ajoute en amont de la mesure la catégorie (feuille, ciseau ou pierre). &lt;br /&gt;
[[Fichier:Capture d’écran 2024-01-18 à 16.18.19.png|centré|vignette|500x500px|Fichier chifoumIA.csv]]&lt;br /&gt;
Pour construire ce fichier, nous avons assemblé trois fichiers csv de test que nous avons généré grâce à notre capteur : un fichier d'entrainement Pierre.csv, un fichier d'entrainement Ciseau.csv et un fichier d'entrainement Feuille.csv . &lt;br /&gt;
&lt;br /&gt;
Pour faire cette concaténation nous avons développer un programme python prenant en entrée nos fichiers d'entrainement et fournissant en sortie le fichier csv chifoumIA.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     line_feuille = []&lt;br /&gt;
     line_pierre = []&lt;br /&gt;
     line_ciseau = []&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Feuille.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_feuille = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Pierre.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_pierre = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Ciseau.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_ciseau = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;chifoumIA.csv&amp;quot;,&amp;quot;w&amp;quot;) as f:&lt;br /&gt;
          for elem in line_feuille:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;feuille,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_pierre:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;pierre,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_ciseau:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;ciseau,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Implémentation et Entrainement de notre IA ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant que nous avons notre fichier d'entrainement, nous implémentons notre IA. &lt;br /&gt;
&lt;br /&gt;
Nous avons commencé par créer un tableau de données et un tableau de classes. &lt;br /&gt;
&lt;br /&gt;
Pour remplir ces tableaux, on va lire ligne par ligne le fichier chifoumIA.csv. Le premier élément de la ligne est stockée dans le tableau de classes et le reste de la ligne est stockée dans le tableau de données. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chifoumi_data=[]&lt;br /&gt;
chifoumi_classe=[]&lt;br /&gt;
&lt;br /&gt;
with open('chifoumIA.csv') as csv_file:&lt;br /&gt;
       csv_reader = csv.reader(csv_file,delimiter=',')&lt;br /&gt;
       for row in csv_reader:&lt;br /&gt;
chifoumi_data.append([int(row[1]),int(row[2]),int(row[3]),int(row[4]),int(row[5]),int(row[6]),int(row[7]),int(row[8]),int(row[9]),int(row[10]),int(row[11]),int(row[12]),int(row[13]),int(row[14]),int(row[15]),int(row[16])])&lt;br /&gt;
        chifoumi_classe.append(row[0])&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ipv6 jcie : 2001:660:4401:6050:216:3eff:fe68:8176&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3972</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3972"/>
		<updated>2024-01-18T15:49:29Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /* Entrainement avec Scikit : */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Introduction Projet IE Delannoy - Lemaire &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
L’objectif de ce projet est de distribuer le calcul à différents endroits du réseau afin d’être en mesure de proposer des pistes d’optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, vous allez mettre en œuvre un réseau d’objets connectés à des passerelles et à un serveur. Les objets collecteront des données de l’environnement et suivant les scénarios traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Chaque scénario sera évalué en terme de performance de calcul et de sobriété énergétique. Les indicateurs de performances sont à définir (indicateur pour le calcul, pour l’énergie mais aussi un indicateur combiné).&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Présentation du Projet &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le but de notre projet est de réaliser une application permettant de déterminer l'action faite par un joueur de Pierre-Feuille-Ciseau. Notre système devra donc reconnaitre les différents mouvements fait par le joueur.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Mise en oeuvre du réseau &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Création VM XEN ===&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la VM ===&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la borne WIFI Cisco ===&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251 (changement car besoin pour les PEIP) &lt;br /&gt;
&lt;br /&gt;
- dns-server: 193.48.57.33 (changement car problème avec le serveur DNS initial)&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Configuration de la Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadra du projet, nous avons à disposition une Raspberry PI 4 model B que nous allons configurer. Pour ce faire, nous utilisons le logiciel le &amp;quot;Raspberry PI Imager&amp;quot; pour choisir notre OS.&lt;br /&gt;
[[Fichier:JCIE RPI Imager.png|centré|vignette|400x400px]]Maintenant que nous avons une carte SD prête pour la Raspberry, nous la configurons via sa liaison série en passant par minicom :&lt;br /&gt;
 root@zabeth18: / $ minicom -D /dev/ttyACM0 -b 9600&lt;br /&gt;
De plus, nous modifions le fichier /etc/network/interfaces pour pouvoir connecter notre carte au réseau wifi créé plus haut :&lt;br /&gt;
[[Fichier:Screen WiFi.png|centré|vignette|441x441px]]&lt;br /&gt;
Nous verifions ensuite que nous avons une adresse IP :&lt;br /&gt;
[[Fichier:Screenshot from 2023-12-04 17-17-05.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Capteur NUCLEO - 53L5A1 &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Pour ce projet, nous disposons d'une STM32 Nucléo F401RE muni d'un capteur à ultrason X-Nucleo-53L5A1.&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir entrainer notre IA, nous devons faire en sorte d'afficher et de ressortir sur la liaison série les données du capteur. Pour ce faire, nous utilisons le fichier example &amp;quot;'''''53L5A1_ThresholdDetection'''''&amp;quot;. Nous modifions la fonction print_result pour afficher 16 valeurs à la suite :&lt;br /&gt;
[[Fichier:ChifoumIA Print Result.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Après avoir téléversé, nous pouvons vérifier le bon fonctionnement du programme en nous connectant à la carte via minicom :&lt;br /&gt;
&lt;br /&gt;
 root@raspberrypi:/dev$ minicom -D ttyACM0 -b 460800&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Communication VM-Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Envoie de donnée : ===&lt;br /&gt;
&lt;br /&gt;
Dans notre projet, nous avons besoin de remonter les données de notre capteur branché en liaison série à la Raspberry sur le port &amp;quot;ttyACM0&amp;quot;. Nous allons donc passer par des requêtes API entre le serveur sur chassiron et notre Raspberry.&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Raspberry : ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Du côté Raspberry, nous programmons un script en python qui lit sur la liaison série les valeurs du capteurs et les envoie via une requête POST vers le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import requests&lt;br /&gt;
     import json&lt;br /&gt;
     import serial&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;Variable&lt;br /&gt;
     STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
     baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
     Serial_link = serial.Serial(STM32_port,baudrate,timeout=1)&lt;br /&gt;
     print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
     liste_mesures=[]&lt;br /&gt;
     for i in range(101):&lt;br /&gt;
          print(&amp;quot;Mesure&amp;quot;,i)&lt;br /&gt;
          mesure = Serial_link.readline().decode('utf-8')&lt;br /&gt;
          liste_mesures.append(mesure)&lt;br /&gt;
&lt;br /&gt;
     data_to_send = json.dumps(liste_mesures)&lt;br /&gt;
     url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080&amp;quot;&lt;br /&gt;
&lt;br /&gt;
     headers = {&lt;br /&gt;
          'Content-type':'application/json',&lt;br /&gt;
          'Accept':'application/json'&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     r = requests.post(&lt;br /&gt;
          url_request,&lt;br /&gt;
          json=data_to_send,&lt;br /&gt;
          headers=headers&lt;br /&gt;
     )&lt;br /&gt;
     print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Serveur : ====&lt;br /&gt;
La communication entre notre VM et la Raspberry est possible. Nous arrivons à effectuer un ping de l'une sur l'autre en passant par l'addresse IPv6.&lt;br /&gt;
&lt;br /&gt;
IPv6 VM :  2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
IPv6 Raspberry : 2001:660:4401:6050:da3a:ddff:fe59:4cb5&lt;br /&gt;
&lt;br /&gt;
Nous programmons ensuite une API sur notre VM en utilisant la libraire Flask.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import json&lt;br /&gt;
     from flask import Flask&lt;br /&gt;
     from flask import request&lt;br /&gt;
     from waitress import serve&lt;br /&gt;
     from flask import Response&lt;br /&gt;
     from flask_cors import CORS&lt;br /&gt;
     from flask_cors import cross_origin&lt;br /&gt;
&lt;br /&gt;
     app = Flask(__name__)&lt;br /&gt;
     cors = CORS(app, ressourceas={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;:&amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
     def compute_data(data):&lt;br /&gt;
          filename = input(&amp;quot;Nom du fichier :&amp;quot;)&lt;br /&gt;
          to_write = data.split(&amp;quot;\&amp;quot;&amp;quot;)[1:-1]&lt;br /&gt;
          with open(filename, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
               i = 0&lt;br /&gt;
               for elem in to_write:&lt;br /&gt;
                    if i == 0:&lt;br /&gt;
                         print(&amp;quot;We skip&amp;quot;)&lt;br /&gt;
                    else:&lt;br /&gt;
                         if (i%2) == 0:&lt;br /&gt;
                              print(&amp;quot;Data writed :&amp;quot;,elem[:-4])&lt;br /&gt;
                              f.write(elem[:-4])&lt;br /&gt;
                              f.write(&amp;quot;\n&amp;quot;)&lt;br /&gt;
                    i = i + 1&lt;br /&gt;
&lt;br /&gt;
     #Main&lt;br /&gt;
     @app.route('/',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
     @cross_origin()&lt;br /&gt;
     def hello():&lt;br /&gt;
          data = request.json&lt;br /&gt;
          compute_data(data)&lt;br /&gt;
          return data&lt;br /&gt;
&lt;br /&gt;
     if __name__ == '__main__':&lt;br /&gt;
          print(&amp;quot;Listening&amp;quot;)&lt;br /&gt;
          serve(app,host=&amp;quot;::&amp;quot;,port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Implémentation de l'IA : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant qu'on a une communication pour envoyer un fichier à notre serveur depuis la raspberry grâce à notre API, nous la modifions pour que la Raspberry puisse lire la valeur du capteur à ultrason, l'envoyer à notre serveur et recevoir en réponse, la prédiction de l'IA. Nous créons donc une route '''''/predict''''' sur notre API qui récupère les valeurs du capteurs données en paramètre et renvoie la prédiction de l'IA :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 @app.route('/predict',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
 def predict():&lt;br /&gt;
      data = request.json&lt;br /&gt;
      print(data)&lt;br /&gt;
      features = data['Features']&lt;br /&gt;
      print(features)&lt;br /&gt;
      features_splitted = features[0].split(&amp;quot;,&amp;quot;)&lt;br /&gt;
      features_int = [int(elem) for elem in features_splitted]&lt;br /&gt;
      loaded_model = joblib.load('model_entraine.pkl')&lt;br /&gt;
      predictios = loaded_model.predict(np.array(features_int).reshape(1,-1))&lt;br /&gt;
      return jsonify(predictions.tolist())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Entrainement de l'IA &amp;lt;/div&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec NanoEdge AI Studio : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour le projet, nous avons d'abord développé et entrainé notre IA sur la plateforme NanoEdge AI Studio. Pour ce faire, nous devons d'abord définir un projet de classification de n-class (&amp;quot;pierre&amp;quot;,&amp;quot;feuille&amp;quot;,&amp;quot;ciseau&amp;quot;) en utilisant un capteur générique à 16 axes. Pour ce faire, nous modifions le code de la STM32 pour qu'elle renvoie une ligne contenant 16*16 mesure en continue. Une fois le projet créé, nous ajoutons 3 signaux correspondant à nos dataset de &amp;quot;Pierre&amp;quot;, &amp;quot;Feuille&amp;quot; et &amp;quot;Ciseau&amp;quot;. Pour rajouter des valeurs dans notre dataset, nous utilisons la liaison série pour lire les valeurs de notre capteur.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec Scikit : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour la suite de notre projet, nous avons developpé et entrainé une IA avec Scikit.&lt;br /&gt;
&lt;br /&gt;
==== Construction du fichier d'entrainement ====&lt;br /&gt;
Pour commencer, nous avons du construire un fichier csv reprenant nos mesures sur un format de 16 valeurs. Pour chaque mesure, on ajoute en amont de la mesure la catégorie (feuille, ciseau ou pierre). &lt;br /&gt;
[[Fichier:Capture d’écran 2024-01-18 à 16.18.19.png|centré|vignette|500x500px|Fichier chifoumIA.csv]]&lt;br /&gt;
Pour construire ce fichier, nous avons assemblé trois fichiers csv de test que nous avons généré grâce à notre capteur : un fichier d'entrainement Pierre.csv, un fichier d'entrainement Ciseau.csv et un fichier d'entrainement Feuille.csv . &lt;br /&gt;
&lt;br /&gt;
Pour faire cette concaténation nous avons développer un programme python prenant en entrée nos fichiers d'entrainement et fournissant en sortie le fichier csv chifoumIA.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     line_feuille = []&lt;br /&gt;
     line_pierre = []&lt;br /&gt;
     line_ciseau = []&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Feuille.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_feuille = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Pierre.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_pierre = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;Ciseau.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
          line_ciseau = f.readlines()&lt;br /&gt;
&lt;br /&gt;
     with open(&amp;quot;chifoumIA.csv&amp;quot;,&amp;quot;w&amp;quot;) as f:&lt;br /&gt;
          for elem in line_feuille:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;feuille,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_pierre:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;pierre,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
          for elem in line_ciseau:&lt;br /&gt;
               if(elem != &amp;quot;&amp;quot;):&lt;br /&gt;
                    f.write(&amp;quot;ciseau,&amp;quot;)&lt;br /&gt;
                    f.write(elem)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Implémentation et Entrainement de notre IA ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Maintenant que nous avons notre fichier d'entrainement, nous implémentons notre IA. &lt;br /&gt;
&lt;br /&gt;
Nous avons commencé par créer un tableau de données et un tableau de classes. &lt;br /&gt;
&lt;br /&gt;
Pour remplir ces tableaux, on va lire ligne par ligne le fichier chifoumIA.csv. Le premier élément de la ligne est stockée dans le tableau de classes et le reste de la ligne est stockée dans le tableau de données. &lt;br /&gt;
&lt;br /&gt;
chifoumi_data=[]&lt;br /&gt;
&lt;br /&gt;
chifoumi_classe=[]&lt;br /&gt;
&lt;br /&gt;
with open('chifoumIA.csv') as csv_file:&lt;br /&gt;
&lt;br /&gt;
csv_reader = csv.reader(csv_file,delimiter=',')&lt;br /&gt;
&lt;br /&gt;
for row in csv_reader:&lt;br /&gt;
&lt;br /&gt;
chifoumi_data.append([int(row[1]),int(row[2]),int(row[3]),int(row[4]),int(row[5]),int(row[6]),int(row[7]),int(row[8]),int(row[9]),int(row[10]),int(row[11]),int(row[12]),int(row[13]),int(row[14]),int(row[15]),int(row[16])])&lt;br /&gt;
&lt;br /&gt;
chifoumi_classe.append(row[0])&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ipv6 jcie : 2001:660:4401:6050:216:3eff:fe68:8176&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3968</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3968"/>
		<updated>2024-01-18T15:32:27Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /* Entrainement avec Scikit : */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Introduction Projet IE Delannoy - Lemaire &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
L’objectif de ce projet est de distribuer le calcul à différents endroits du réseau afin d’être en mesure de proposer des pistes d’optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, vous allez mettre en œuvre un réseau d’objets connectés à des passerelles et à un serveur. Les objets collecteront des données de l’environnement et suivant les scénarios traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Chaque scénario sera évalué en terme de performance de calcul et de sobriété énergétique. Les indicateurs de performances sont à définir (indicateur pour le calcul, pour l’énergie mais aussi un indicateur combiné).&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Présentation du Projet &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le but de notre projet est de réaliser une application permettant de déterminer l'action faite par un joueur de Pierre-Feuille-Ciseau. Notre système devra donc reconnaitre les différents mouvements fait par le joueur.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Mise en oeuvre du réseau &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Création VM XEN ===&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la VM ===&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la borne WIFI Cisco ===&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251 (changement car besoin pour les PEIP) &lt;br /&gt;
&lt;br /&gt;
- dns-server: 193.48.57.33 (changement car problème avec le serveur DNS initial)&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Configuration de la Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadra du projet, nous avons à disposition une Raspberry PI 4 model B que nous allons configurer. Pour ce faire, nous utilisons le logiciel le &amp;quot;Raspberry PI Imager&amp;quot; pour choisir notre OS.&lt;br /&gt;
[[Fichier:JCIE RPI Imager.png|centré|vignette|400x400px]]Maintenant que nous avons une carte SD prête pour la Raspberry, nous la configurons via sa liaison série en passant par minicom :&lt;br /&gt;
 root@zabeth18: / $ minicom -D /dev/ttyACM0 -b 9600&lt;br /&gt;
De plus, nous modifions le fichier /etc/network/interfaces pour pouvoir connecter notre carte au réseau wifi créé plus haut :&lt;br /&gt;
[[Fichier:Screen WiFi.png|centré|vignette|441x441px]]&lt;br /&gt;
Nous verifions ensuite que nous avons une adresse IP :&lt;br /&gt;
[[Fichier:Screenshot from 2023-12-04 17-17-05.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Capteur NUCLEO - 53L5A1 &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Pour ce projet, nous disposons d'une STM32 Nucléo F401RE muni d'un capteur à ultrason X-Nucleo-53L5A1.&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir entrainer notre IA, nous devons faire en sorte d'afficher et de ressortir sur la liaison série les données du capteur. Pour ce faire, nous utilisons le fichier example &amp;quot;'''''53L5A1_ThresholdDetection'''''&amp;quot;. Nous modifions la fonction print_result pour afficher 16 valeurs à la suite :&lt;br /&gt;
[[Fichier:ChifoumIA Print Result.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Après avoir téléversé, nous pouvons vérifier le bon fonctionnement du programme en nous connectant à la carte via minicom :&lt;br /&gt;
&lt;br /&gt;
 root@raspberrypi:/dev$ minicom -D ttyACM0 -b 460800&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Communication VM-Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Envoie de donnée : ===&lt;br /&gt;
&lt;br /&gt;
Dans notre projet, nous avons besoin de remonter les données de notre capteur branché en liaison série à la Raspberry sur le port &amp;quot;ttyACM0&amp;quot;. Nous allons donc passer par des requêtes API entre le serveur sur chassiron et notre Raspberry.&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Raspberry : ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Du côté Raspberry, nous programmons un script en python qui lit sur la liaison série les valeurs du capteurs et les envoie via une requête POST vers le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import requests&lt;br /&gt;
     import json&lt;br /&gt;
     import serial&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;Variable&lt;br /&gt;
     STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
     baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
     Serial_link = serial.Serial(STM32_port,baudrate,timeout=1)&lt;br /&gt;
     print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
     liste_mesures=[]&lt;br /&gt;
     for i in range(101):&lt;br /&gt;
          print(&amp;quot;Mesure&amp;quot;,i)&lt;br /&gt;
          mesure = Serial_link.readline().decode('utf-8')&lt;br /&gt;
          liste_mesures.append(mesure)&lt;br /&gt;
&lt;br /&gt;
     data_to_send = json.dumps(liste_mesures)&lt;br /&gt;
     url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080&amp;quot;&lt;br /&gt;
&lt;br /&gt;
     headers = {&lt;br /&gt;
          'Content-type':'application/json',&lt;br /&gt;
          'Accept':'application/json'&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     r = requests.post(&lt;br /&gt;
          url_request,&lt;br /&gt;
          json=data_to_send,&lt;br /&gt;
          headers=headers&lt;br /&gt;
     )&lt;br /&gt;
     print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Serveur : ====&lt;br /&gt;
La communication entre notre VM et la Raspberry est possible. Nous arrivons à effectuer un ping de l'une sur l'autre en passant par l'addresse IPv6.&lt;br /&gt;
&lt;br /&gt;
IPv6 VM :  2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
IPv6 Raspberry : 2001:660:4401:6050:da3a:ddff:fe59:4cb5&lt;br /&gt;
&lt;br /&gt;
Nous programmons ensuite une API sur notre VM en utilisant la libraire Flask.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import json&lt;br /&gt;
     from flask import Flask&lt;br /&gt;
     from flask import request&lt;br /&gt;
     from waitress import serve&lt;br /&gt;
     from flask import Response&lt;br /&gt;
     from flask_cors import CORS&lt;br /&gt;
     from flask_cors import cross_origin&lt;br /&gt;
&lt;br /&gt;
     app = Flask(__name__)&lt;br /&gt;
     cors = CORS(app, ressourceas={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;:&amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
     def compute_data(data):&lt;br /&gt;
          filename = input(&amp;quot;Nom du fichier :&amp;quot;)&lt;br /&gt;
          to_write = data.split(&amp;quot;\&amp;quot;&amp;quot;)[1:-1]&lt;br /&gt;
          with open(filename, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
               i = 0&lt;br /&gt;
               for elem in to_write:&lt;br /&gt;
                    if i == 0:&lt;br /&gt;
                         print(&amp;quot;We skip&amp;quot;)&lt;br /&gt;
                    else:&lt;br /&gt;
                         if (i%2) == 0:&lt;br /&gt;
                              print(&amp;quot;Data writed :&amp;quot;,elem[:-4])&lt;br /&gt;
                              f.write(elem[:-4])&lt;br /&gt;
                              f.write(&amp;quot;\n&amp;quot;)&lt;br /&gt;
                    i = i + 1&lt;br /&gt;
&lt;br /&gt;
     #Main&lt;br /&gt;
     @app.route('/',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
     @cross_origin()&lt;br /&gt;
     def hello():&lt;br /&gt;
          data = request.json&lt;br /&gt;
          compute_data(data)&lt;br /&gt;
          return data&lt;br /&gt;
&lt;br /&gt;
     if __name__ == '__main__':&lt;br /&gt;
          print(&amp;quot;Listening&amp;quot;)&lt;br /&gt;
          serve(app,host=&amp;quot;::&amp;quot;,port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Implémentation de l'IA : ===&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Entrainement de l'IA &amp;lt;/div&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec NanoEdge AI Studio : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour le projet, nous avons d'abord développé et entrainé notre IA sur la plateforme NanoEdge AI Studio. Pour ce faire, nous devons d'abord définir un projet de classification de n-class (&amp;quot;pierre&amp;quot;,&amp;quot;feuille&amp;quot;,&amp;quot;ciseau&amp;quot;) en utilisant un capteur générique à 16 axes. Pour ce faire, nous modifions le code de la STM32 pour qu'elle renvoie une ligne contenant 16*16 mesure en continue. Une fois le projet créé, nous ajoutons 3 signaux correspondant à nos dataset de &amp;quot;Pierre&amp;quot;, &amp;quot;Feuille&amp;quot; et &amp;quot;Ciseau&amp;quot;. Pour rajouter des valeurs dans notre dataset, nous utilisons la liaison série pour lire les valeurs de notre capteur.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec Scikit : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour la suite de notre projet, nous avons developpé et entrainé une IA avec Scikit.&lt;br /&gt;
&lt;br /&gt;
Pour commencer, nous avons du construire un fichier csv reprenant nos mesures sur un format de 16 valeurs. Pour chaque mesure, on ajoute en amont de la mesure la catégorie (feuille, ciseau ou pierre). &lt;br /&gt;
[[Fichier:Capture d’écran 2024-01-18 à 16.18.19.png|centré|vignette|500x500px|Fichier chifoumIA.csv]]&lt;br /&gt;
Pour construire ce fichier, nous avons assemblé trois fichiers csv de test que nous avons généré grâce à notre capteur : un fichier d'entrainement Pierre.csv, un fichier d'entrainement Ciseau.csv et un fichier d'entrainement Feuille.csv . &lt;br /&gt;
&lt;br /&gt;
Pour faire cette concaténation nous avons développer un programme python prenant en entrée nos fichiers d'entrainement et fournissant en sortie le fichier csv chifoumIA.  &lt;br /&gt;
&lt;br /&gt;
 line_feuille = []&lt;br /&gt;
&lt;br /&gt;
 line_pierre = []&lt;br /&gt;
&lt;br /&gt;
 line_ciseau = []&lt;br /&gt;
&lt;br /&gt;
 '''with''' open('''&amp;quot;Feuille.csv&amp;quot;''','''&amp;quot;r&amp;quot;''') '''as''' f:&lt;br /&gt;
&lt;br /&gt;
         line_feuille = f.readlines()&lt;br /&gt;
&lt;br /&gt;
 '''with''' open('''&amp;quot;Pierre.csv&amp;quot;''','''&amp;quot;r&amp;quot;''') '''as''' f:&lt;br /&gt;
&lt;br /&gt;
         line_pierre = f.readlines()&lt;br /&gt;
&lt;br /&gt;
 '''with''' open('''&amp;quot;Ciseau.csv&amp;quot;''','''&amp;quot;r&amp;quot;''') '''as''' f:&lt;br /&gt;
&lt;br /&gt;
         line_ciseau = f.readlines()&lt;br /&gt;
&lt;br /&gt;
 '''with''' open('''&amp;quot;chifoumIA.csv&amp;quot;''','''&amp;quot;w&amp;quot;''') '''as''' f:&lt;br /&gt;
&lt;br /&gt;
         '''for''' elem '''in''' line_feuille:&lt;br /&gt;
&lt;br /&gt;
                 '''if''' (elem != '''&amp;quot;&amp;quot;'''):&lt;br /&gt;
&lt;br /&gt;
                         f.write('''&amp;quot;feuille,&amp;quot;''')&lt;br /&gt;
&lt;br /&gt;
                         f.write(elem)&lt;br /&gt;
&lt;br /&gt;
         '''for''' elem '''in''' line_pierre:&lt;br /&gt;
&lt;br /&gt;
                 '''if''' (elem != '''&amp;quot;&amp;quot;'''):&lt;br /&gt;
&lt;br /&gt;
                         f.write('''&amp;quot;pierre,&amp;quot;''')&lt;br /&gt;
&lt;br /&gt;
                         f.write(elem)&lt;br /&gt;
&lt;br /&gt;
        '''for''' elem '''in''' line_ciseau:&lt;br /&gt;
&lt;br /&gt;
                 '''if''' (elem != '''&amp;quot;&amp;quot;'''):&lt;br /&gt;
&lt;br /&gt;
                         f.write('''&amp;quot;ciseau,&amp;quot;''')&lt;br /&gt;
&lt;br /&gt;
                         f.write(elem)&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
ipv6 jcie : 2001:660:4401:6050:216:3eff:fe68:8176&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3967</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3967"/>
		<updated>2024-01-18T15:31:01Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /* Entrainement avec Scikit : */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Introduction Projet IE Delannoy - Lemaire &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
L’objectif de ce projet est de distribuer le calcul à différents endroits du réseau afin d’être en mesure de proposer des pistes d’optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, vous allez mettre en œuvre un réseau d’objets connectés à des passerelles et à un serveur. Les objets collecteront des données de l’environnement et suivant les scénarios traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Chaque scénario sera évalué en terme de performance de calcul et de sobriété énergétique. Les indicateurs de performances sont à définir (indicateur pour le calcul, pour l’énergie mais aussi un indicateur combiné).&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Présentation du Projet &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le but de notre projet est de réaliser une application permettant de déterminer l'action faite par un joueur de Pierre-Feuille-Ciseau. Notre système devra donc reconnaitre les différents mouvements fait par le joueur.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Mise en oeuvre du réseau &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Création VM XEN ===&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la VM ===&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la borne WIFI Cisco ===&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251 (changement car besoin pour les PEIP) &lt;br /&gt;
&lt;br /&gt;
- dns-server: 193.48.57.33 (changement car problème avec le serveur DNS initial)&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Configuration de la Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadra du projet, nous avons à disposition une Raspberry PI 4 model B que nous allons configurer. Pour ce faire, nous utilisons le logiciel le &amp;quot;Raspberry PI Imager&amp;quot; pour choisir notre OS.&lt;br /&gt;
[[Fichier:JCIE RPI Imager.png|centré|vignette|400x400px]]Maintenant que nous avons une carte SD prête pour la Raspberry, nous la configurons via sa liaison série en passant par minicom :&lt;br /&gt;
 root@zabeth18: / $ minicom -D /dev/ttyACM0 -b 9600&lt;br /&gt;
De plus, nous modifions le fichier /etc/network/interfaces pour pouvoir connecter notre carte au réseau wifi créé plus haut :&lt;br /&gt;
[[Fichier:Screen WiFi.png|centré|vignette|441x441px]]&lt;br /&gt;
Nous verifions ensuite que nous avons une adresse IP :&lt;br /&gt;
[[Fichier:Screenshot from 2023-12-04 17-17-05.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Capteur NUCLEO - 53L5A1 &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Pour ce projet, nous disposons d'une STM32 Nucléo F401RE muni d'un capteur à ultrason X-Nucleo-53L5A1.&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir entrainer notre IA, nous devons faire en sorte d'afficher et de ressortir sur la liaison série les données du capteur. Pour ce faire, nous utilisons le fichier example &amp;quot;'''''53L5A1_ThresholdDetection'''''&amp;quot;. Nous modifions la fonction print_result pour afficher 16 valeurs à la suite :&lt;br /&gt;
[[Fichier:ChifoumIA Print Result.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Après avoir téléversé, nous pouvons vérifier le bon fonctionnement du programme en nous connectant à la carte via minicom :&lt;br /&gt;
&lt;br /&gt;
 root@raspberrypi:/dev$ minicom -D ttyACM0 -b 460800&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Communication VM-Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Envoie de donnée : ===&lt;br /&gt;
&lt;br /&gt;
Dans notre projet, nous avons besoin de remonter les données de notre capteur branché en liaison série à la Raspberry sur le port &amp;quot;ttyACM0&amp;quot;. Nous allons donc passer par des requêtes API entre le serveur sur chassiron et notre Raspberry.&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Raspberry : ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Du côté Raspberry, nous programmons un script en python qui lit sur la liaison série les valeurs du capteurs et les envoie via une requête POST vers le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import requests&lt;br /&gt;
     import json&lt;br /&gt;
     import serial&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;Variable&lt;br /&gt;
     STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
     baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
     Serial_link = serial.Serial(STM32_port,baudrate,timeout=1)&lt;br /&gt;
     print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
     liste_mesures=[]&lt;br /&gt;
     for i in range(101):&lt;br /&gt;
          print(&amp;quot;Mesure&amp;quot;,i)&lt;br /&gt;
          mesure = Serial_link.readline().decode('utf-8')&lt;br /&gt;
          liste_mesures.append(mesure)&lt;br /&gt;
&lt;br /&gt;
     data_to_send = json.dumps(liste_mesures)&lt;br /&gt;
     url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080&amp;quot;&lt;br /&gt;
&lt;br /&gt;
     headers = {&lt;br /&gt;
          'Content-type':'application/json',&lt;br /&gt;
          'Accept':'application/json'&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     r = requests.post(&lt;br /&gt;
          url_request,&lt;br /&gt;
          json=data_to_send,&lt;br /&gt;
          headers=headers&lt;br /&gt;
     )&lt;br /&gt;
     print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Serveur : ====&lt;br /&gt;
La communication entre notre VM et la Raspberry est possible. Nous arrivons à effectuer un ping de l'une sur l'autre en passant par l'addresse IPv6.&lt;br /&gt;
&lt;br /&gt;
IPv6 VM :  2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
IPv6 Raspberry : 2001:660:4401:6050:da3a:ddff:fe59:4cb5&lt;br /&gt;
&lt;br /&gt;
Nous programmons ensuite une API sur notre VM en utilisant la libraire Flask.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #Import Librairies&lt;br /&gt;
     import json&lt;br /&gt;
     from flask import Flask&lt;br /&gt;
     from flask import request&lt;br /&gt;
     from waitress import serve&lt;br /&gt;
     from flask import Response&lt;br /&gt;
     from flask_cors import CORS&lt;br /&gt;
     from flask_cors import cross_origin&lt;br /&gt;
&lt;br /&gt;
     app = Flask(__name__)&lt;br /&gt;
     cors = CORS(app, ressourceas={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;:&amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
     def compute_data(data):&lt;br /&gt;
          filename = input(&amp;quot;Nom du fichier :&amp;quot;)&lt;br /&gt;
          to_write = data.split(&amp;quot;\&amp;quot;&amp;quot;)[1:-1]&lt;br /&gt;
          with open(filename, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
               i = 0&lt;br /&gt;
               for elem in to_write:&lt;br /&gt;
                    if i == 0:&lt;br /&gt;
                         print(&amp;quot;We skip&amp;quot;)&lt;br /&gt;
                    else:&lt;br /&gt;
                         if (i%2) == 0:&lt;br /&gt;
                              print(&amp;quot;Data writed :&amp;quot;,elem[:-4])&lt;br /&gt;
                              f.write(elem[:-4])&lt;br /&gt;
                              f.write(&amp;quot;\n&amp;quot;)&lt;br /&gt;
                    i = i + 1&lt;br /&gt;
&lt;br /&gt;
     #Main&lt;br /&gt;
     @app.route('/',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
     @cross_origin()&lt;br /&gt;
     def hello():&lt;br /&gt;
          data = request.json&lt;br /&gt;
          compute_data(data)&lt;br /&gt;
          return data&lt;br /&gt;
&lt;br /&gt;
     if __name__ == '__main__':&lt;br /&gt;
          print(&amp;quot;Listening&amp;quot;)&lt;br /&gt;
          serve(app,host=&amp;quot;::&amp;quot;,port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Implémentation de l'IA : ===&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Entrainement de l'IA &amp;lt;/div&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec NanoEdge AI Studio : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour le projet, nous avons d'abord développé et entrainé notre IA sur la plateforme NanoEdge AI Studio. Pour ce faire, nous devons d'abord définir un projet de classification de n-class (&amp;quot;pierre&amp;quot;,&amp;quot;feuille&amp;quot;,&amp;quot;ciseau&amp;quot;) en utilisant un capteur générique à 16 axes. Pour ce faire, nous modifions le code de la STM32 pour qu'elle renvoie une ligne contenant 16*16 mesure en continue. Une fois le projet créé, nous ajoutons 3 signaux correspondant à nos dataset de &amp;quot;Pierre&amp;quot;, &amp;quot;Feuille&amp;quot; et &amp;quot;Ciseau&amp;quot;. Pour rajouter des valeurs dans notre dataset, nous utilisons la liaison série pour lire les valeurs de notre capteur.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec Scikit : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour la suite de notre projet, nous avons developpé et entrainé une IA avec Scikit.&lt;br /&gt;
&lt;br /&gt;
Pour commencer, nous avons du construire un fichier csv reprenant nos mesures sur un format de 16 valeurs. Pour chaque mesure, on ajoute en amont de la mesure la catégorie (feuille, ciseau ou pierre). &lt;br /&gt;
[[Fichier:Capture d’écran 2024-01-18 à 16.18.19.png|centré|vignette|500x500px|Fichier chifoumIA.csv]]&lt;br /&gt;
Pour construire ce fichier, nous avons assemblé trois fichiers csv de test que nous avons généré grâce à notre capteur : un fichier d'entrainement Pierre.csv, un fichier d'entrainement Ciseau.csv et un fichier d'entrainement Feuille.csv . &lt;br /&gt;
&lt;br /&gt;
Pour faire cette concaténation nous avons développer un programme python prenant en entrée nos fichiers d'entrainement et fournissant en sortie le fichier csv chifoumIA. &lt;br /&gt;
 line_feuille = []&lt;br /&gt;
&lt;br /&gt;
 line_pierre = []&lt;br /&gt;
&lt;br /&gt;
 line_ciseau = []&lt;br /&gt;
&lt;br /&gt;
 with open(&amp;quot;Feuille.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
&lt;br /&gt;
 	line_feuille = f.readlines()&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
 with open(&amp;quot;Pierre.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
 	line_pierre = f.readlines()&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
 with open(&amp;quot;Ciseau.csv&amp;quot;,&amp;quot;r&amp;quot;) as f:&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
 	line_ciseau = f.readlines()&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
 with open(&amp;quot;chifoumIA.csv&amp;quot;,&amp;quot;w&amp;quot;) as f:&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
 	for elem in line_feuille:&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
 		if (elem != &amp;quot;&amp;quot;):&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
 			f.write(&amp;quot;feuille,&amp;quot;)&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
 			f.write(elem)&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
 	for elem in line_pierre:&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
 		if (elem != &amp;quot;&amp;quot;):&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
 			f.write(&amp;quot;pierre,&amp;quot;)&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
 			f.write(elem)&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
 	for elem in line_ciseau:&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
 		if (elem != &amp;quot;&amp;quot;):&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
 			f.write(&amp;quot;ciseau,&amp;quot;)&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
 			f.write(elem)&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;ipv6 jcie : 2001:660:4401:6050:216:3eff:fe68:8176&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:Capture_d%E2%80%99%C3%A9cran_2024-01-18_%C3%A0_16.18.19.png&amp;diff=3965</id>
		<title>Fichier:Capture d’écran 2024-01-18 à 16.18.19.png</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:Capture_d%E2%80%99%C3%A9cran_2024-01-18_%C3%A0_16.18.19.png&amp;diff=3965"/>
		<updated>2024-01-18T15:24:06Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;fichier csv&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Atelier_SysRes_SE5_2023/2024_E18&amp;diff=3814</id>
		<title>Atelier SysRes SE5 2023/2024 E18</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Atelier_SysRes_SE5_2023/2024_E18&amp;diff=3814"/>
		<updated>2024-01-16T10:02:14Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Zabeth3 : &lt;br /&gt;
&lt;br /&gt;
BSSID              PWR  Beacons    #Data, #/s  CH   MB   ENC CIPHER  AUTH ESSID&lt;br /&gt;
&lt;br /&gt;
74:DA:38:31:B7:6F  -22        3        0    0   8  270   WPA2 CCMP   PSK  RobotinoAPX2.4                                   &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:5D   -3        4        0    0   2   54e. WEP  WEP         cracotte14                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:53    0        5       24    0   2   54e. WEP  WEP         cracotte04                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:51   -3        5       11    0   2   54e. WEP  WEP         cracotte02                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:54   -4        6       13    0   2   54e. WEP  WEP         cracotte05                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:5C   -3        4       22    0   2   54e. WEP  WEP         cracotte13                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:57   -3        7       23    0   2   54e. WEP  WEP         cracotte08                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:5B   -3        5       11    0   2   54e. WEP  WEP         cracotte12                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:59    0        6       25    0   2   54e. WEP  WEP         cracotte10                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:56    0        6       22    0   2   54e. WEP  WEP         cracotte07                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:58   -3        5       27    0   2   54e. WEP  WEP         cracotte09                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:50   -3        4       23    0   2   54e. WEP  WEP         cracotte01                                       &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:01  -126        2        0    0  13   54e. WPA2 CCMP   PSK  kracotte02                                      &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:0B  -126        2        0    0  13   54e. WPA2 CCMP   PSK  kracotte12                                      &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:06  -126        2        0    0  13   54e. WPA2 CCMP   PSK  kracotte07                                      &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:0A  -126        2        0    0  13   54e. WPA2 CCMP   PSK  kracotte11                                      &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:02  -125        2        0    0  13   54e. WPA2 CCMP   PSK  kracotte03                                      &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:09  -126        2        0    0  13   54e. WPA2 CCMP   PSK  kracotte10                                      &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:04   -1        2        0    0  13   54e. WPA2 CCMP   PSK  kracotte05                                       &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:08   -1        2        0    0  13   54e. WPA2 CCMP   PSK  kracotte09                                       &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:00  -126        2        0    0  13   54e. WPA2 CCMP   PSK  kracotte01                                      &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:05   -1        3        0    0  13   54e. WPA2 CCMP   PSK  kracotte06                                       &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:03   -1        3        0    0  13   54e. WPA2 CCMP   PSK  kracotte04                                       &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:0D  -126        3        0    0  13   54e. WPA2 CCMP   PSK  kracotte14                                      &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:07  -126        3        0    0  13   54e. WPA2 CCMP   PSK  kracotte08                                      &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:0C  -126        3        0    0  13   54e. WPA2 CCMP   PSK  kracotte13  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
cracotte 8&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Cle cracotte8.png|centré|vignette|500x500px]]&lt;br /&gt;
   kracotte 8 : WPA handshake: 44:AD:D9:5F:87:07&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CléKcracotte.png|centré|vignette|500x500px]]&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:Cl%C3%A9Kcracotte.png&amp;diff=3813</id>
		<title>Fichier:CléKcracotte.png</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:Cl%C3%A9Kcracotte.png&amp;diff=3813"/>
		<updated>2024-01-16T09:00:56Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;clé Kracotte&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Atelier_SysRes_SE5_2023/2024_E18&amp;diff=3809</id>
		<title>Atelier SysRes SE5 2023/2024 E18</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Atelier_SysRes_SE5_2023/2024_E18&amp;diff=3809"/>
		<updated>2024-01-16T07:51:10Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Zabeth3 : &lt;br /&gt;
&lt;br /&gt;
BSSID              PWR  Beacons    #Data, #/s  CH   MB   ENC CIPHER  AUTH ESSID&lt;br /&gt;
&lt;br /&gt;
74:DA:38:31:B7:6F  -22        3        0    0   8  270   WPA2 CCMP   PSK  RobotinoAPX2.4                                   &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:5D   -3        4        0    0   2   54e. WEP  WEP         cracotte14                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:53    0        5       24    0   2   54e. WEP  WEP         cracotte04                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:51   -3        5       11    0   2   54e. WEP  WEP         cracotte02                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:54   -4        6       13    0   2   54e. WEP  WEP         cracotte05                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:5C   -3        4       22    0   2   54e. WEP  WEP         cracotte13                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:57   -3        7       23    0   2   54e. WEP  WEP         cracotte08                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:5B   -3        5       11    0   2   54e. WEP  WEP         cracotte12                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:59    0        6       25    0   2   54e. WEP  WEP         cracotte10                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:56    0        6       22    0   2   54e. WEP  WEP         cracotte07                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:58   -3        5       27    0   2   54e. WEP  WEP         cracotte09                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:50   -3        4       23    0   2   54e. WEP  WEP         cracotte01                                       &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:01  -126        2        0    0  13   54e. WPA2 CCMP   PSK  kracotte02                                      &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:0B  -126        2        0    0  13   54e. WPA2 CCMP   PSK  kracotte12                                      &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:06  -126        2        0    0  13   54e. WPA2 CCMP   PSK  kracotte07                                      &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:0A  -126        2        0    0  13   54e. WPA2 CCMP   PSK  kracotte11                                      &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:02  -125        2        0    0  13   54e. WPA2 CCMP   PSK  kracotte03                                      &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:09  -126        2        0    0  13   54e. WPA2 CCMP   PSK  kracotte10                                      &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:04   -1        2        0    0  13   54e. WPA2 CCMP   PSK  kracotte05                                       &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:08   -1        2        0    0  13   54e. WPA2 CCMP   PSK  kracotte09                                       &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:00  -126        2        0    0  13   54e. WPA2 CCMP   PSK  kracotte01                                      &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:05   -1        3        0    0  13   54e. WPA2 CCMP   PSK  kracotte06                                       &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:03   -1        3        0    0  13   54e. WPA2 CCMP   PSK  kracotte04                                       &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:0D  -126        3        0    0  13   54e. WPA2 CCMP   PSK  kracotte14                                      &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:07  -126        3        0    0  13   54e. WPA2 CCMP   PSK  kracotte08                                      &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:0C  -126        3        0    0  13   54e. WPA2 CCMP   PSK  kracotte13  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
cracotte 8&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Cle cracotte8.png|centré|vignette|500x500px]]&lt;br /&gt;
   kracotte 8 : WPA handshake: 44:AD:D9:5F:87:07&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Atelier_SysRes_SE5_2023/2024_E18&amp;diff=3808</id>
		<title>Atelier SysRes SE5 2023/2024 E18</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Atelier_SysRes_SE5_2023/2024_E18&amp;diff=3808"/>
		<updated>2024-01-16T07:44:12Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Zabeth3 : &lt;br /&gt;
&lt;br /&gt;
BSSID              PWR  Beacons    #Data, #/s  CH   MB   ENC CIPHER  AUTH ESSID&lt;br /&gt;
&lt;br /&gt;
74:DA:38:31:B7:6F  -22        3        0    0   8  270   WPA2 CCMP   PSK  RobotinoAPX2.4                                   &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:5D   -3        4        0    0   2   54e. WEP  WEP         cracotte14                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:53    0        5       24    0   2   54e. WEP  WEP         cracotte04                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:51   -3        5       11    0   2   54e. WEP  WEP         cracotte02                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:54   -4        6       13    0   2   54e. WEP  WEP         cracotte05                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:5C   -3        4       22    0   2   54e. WEP  WEP         cracotte13                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:57   -3        7       23    0   2   54e. WEP  WEP         cracotte08                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:5B   -3        5       11    0   2   54e. WEP  WEP         cracotte12                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:59    0        6       25    0   2   54e. WEP  WEP         cracotte10                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:56    0        6       22    0   2   54e. WEP  WEP         cracotte07                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:58   -3        5       27    0   2   54e. WEP  WEP         cracotte09                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:50   -3        4       23    0   2   54e. WEP  WEP         cracotte01                                       &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:01  -126        2        0    0  13   54e. WPA2 CCMP   PSK  kracotte02                                      &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:0B  -126        2        0    0  13   54e. WPA2 CCMP   PSK  kracotte12                                      &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:06  -126        2        0    0  13   54e. WPA2 CCMP   PSK  kracotte07                                      &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:0A  -126        2        0    0  13   54e. WPA2 CCMP   PSK  kracotte11                                      &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:02  -125        2        0    0  13   54e. WPA2 CCMP   PSK  kracotte03                                      &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:09  -126        2        0    0  13   54e. WPA2 CCMP   PSK  kracotte10                                      &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:04   -1        2        0    0  13   54e. WPA2 CCMP   PSK  kracotte05                                       &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:08   -1        2        0    0  13   54e. WPA2 CCMP   PSK  kracotte09                                       &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:00  -126        2        0    0  13   54e. WPA2 CCMP   PSK  kracotte01                                      &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:05   -1        3        0    0  13   54e. WPA2 CCMP   PSK  kracotte06                                       &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:03   -1        3        0    0  13   54e. WPA2 CCMP   PSK  kracotte04                                       &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:0D  -126        3        0    0  13   54e. WPA2 CCMP   PSK  kracotte14                                      &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:07  -126        3        0    0  13   54e. WPA2 CCMP   PSK  kracotte08                                      &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:0C  -126        3        0    0  13   54e. WPA2 CCMP   PSK  kracotte13  &lt;br /&gt;
&lt;br /&gt;
[[Fichier:Cle cracotte8.png|centré|vignette|500x500px]]&lt;br /&gt;
   &lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:Cle_cracotte8.png&amp;diff=3807</id>
		<title>Fichier:Cle cracotte8.png</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:Cle_cracotte8.png&amp;diff=3807"/>
		<updated>2024-01-16T07:43:42Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;cracotte8&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Atelier_SysRes_SE5_2023/2024_E18&amp;diff=3806</id>
		<title>Atelier SysRes SE5 2023/2024 E18</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Atelier_SysRes_SE5_2023/2024_E18&amp;diff=3806"/>
		<updated>2024-01-16T07:29:54Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Zabeth3 : &lt;br /&gt;
&lt;br /&gt;
BSSID              PWR  Beacons    #Data, #/s  CH   MB   ENC CIPHER  AUTH ESSID&lt;br /&gt;
&lt;br /&gt;
74:DA:38:31:B7:6F  -22        3        0    0   8  270   WPA2 CCMP   PSK  RobotinoAPX2.4                                   &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:5D   -3        4        0    0   2   54e. WEP  WEP         cracotte14                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:53    0        5       24    0   2   54e. WEP  WEP         cracotte04                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:51   -3        5       11    0   2   54e. WEP  WEP         cracotte02                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:54   -4        6       13    0   2   54e. WEP  WEP         cracotte05                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:5C   -3        4       22    0   2   54e. WEP  WEP         cracotte13                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:57   -3        7       23    0   2   54e. WEP  WEP         cracotte08                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:5B   -3        5       11    0   2   54e. WEP  WEP         cracotte12                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:59    0        6       25    0   2   54e. WEP  WEP         cracotte10                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:56    0        6       22    0   2   54e. WEP  WEP         cracotte07                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:58   -3        5       27    0   2   54e. WEP  WEP         cracotte09                                       &lt;br /&gt;
&lt;br /&gt;
04:DA:D2:9C:50:50   -3        4       23    0   2   54e. WEP  WEP         cracotte01                                       &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:01  -126        2        0    0  13   54e. WPA2 CCMP   PSK  kracotte02                                      &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:0B  -126        2        0    0  13   54e. WPA2 CCMP   PSK  kracotte12                                      &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:06  -126        2        0    0  13   54e. WPA2 CCMP   PSK  kracotte07                                      &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:0A  -126        2        0    0  13   54e. WPA2 CCMP   PSK  kracotte11                                      &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:02  -125        2        0    0  13   54e. WPA2 CCMP   PSK  kracotte03                                      &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:09  -126        2        0    0  13   54e. WPA2 CCMP   PSK  kracotte10                                      &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:04   -1        2        0    0  13   54e. WPA2 CCMP   PSK  kracotte05                                       &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:08   -1        2        0    0  13   54e. WPA2 CCMP   PSK  kracotte09                                       &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:00  -126        2        0    0  13   54e. WPA2 CCMP   PSK  kracotte01                                      &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:05   -1        3        0    0  13   54e. WPA2 CCMP   PSK  kracotte06                                       &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:03   -1        3        0    0  13   54e. WPA2 CCMP   PSK  kracotte04                                       &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:0D  -126        3        0    0  13   54e. WPA2 CCMP   PSK  kracotte14                                      &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:07  -126        3        0    0  13   54e. WPA2 CCMP   PSK  kracotte08                                      &lt;br /&gt;
&lt;br /&gt;
44:AD:D9:5F:87:0C  -126        3        0    0  13   54e. WPA2 CCMP   PSK  kracotte13      &lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3676</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3676"/>
		<updated>2023-12-20T16:58:00Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /* Entrainement avec Scikit : */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Introduction Projet IE Delannoy - Lemaire &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
L’objectif de ce projet est de distribuer le calcul à différents endroits du réseau afin d’être en mesure de proposer des pistes d’optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, vous allez mettre en œuvre un réseau d’objets connectés à des passerelles et à un serveur. Les objets collecteront des données de l’environnement et suivant les scénarios traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Chaque scénario sera évalué en terme de performance de calcul et de sobriété énergétique. Les indicateurs de performances sont à définir (indicateur pour le calcul, pour l’énergie mais aussi un indicateur combiné).&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Présentation du Projet &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le but de notre projet est de réaliser une application permettant de déterminer l'action faite par un joueur de Pierre-Feuille-Ciseau. Notre système devra donc reconnaitre les différents mouvements fait par le joueur.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Mise en oeuvre du réseau &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Création VM XEN ===&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la VM ===&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la borne WIFI Cisco ===&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251 (changement car besoin pour les PEIP) &lt;br /&gt;
&lt;br /&gt;
- dns-server: 193.48.57.33 (changement car problème avec le serveur DNS initial)&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Configuration de la Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadra du projet, nous avons à disposition une Raspberry PI 4 model B que nous allons configurer. Pour ce faire, nous utilisons le logiciel le &amp;quot;Raspberry PI Imager&amp;quot; pour choisir notre OS.&lt;br /&gt;
[[Fichier:JCIE RPI Imager.png|centré|vignette|400x400px]]Maintenant que nous avons une carte SD prête pour la Raspberry, nous la configurons via sa liaison série en passant par minicom :&lt;br /&gt;
 root@zabeth18: / $ minicom -D /dev/ttyACM0 -b 9600&lt;br /&gt;
De plus, nous modifions le fichier /etc/network/interfaces pour pouvoir connecter notre carte au réseau wifi créé plus haut :&lt;br /&gt;
[[Fichier:Screen WiFi.png|centré|vignette|441x441px]]&lt;br /&gt;
Nous verifions ensuite que nous avons une adresse IP :&lt;br /&gt;
[[Fichier:Screenshot from 2023-12-04 17-17-05.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Capteur NUCLEO - 53L5A1 &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Pour ce projet, nous disposons d'une STM32 Nucléo F401RE muni d'un capteur à ultrason X-Nucleo-53L5A1.&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir entrainer notre IA, nous devons faire en sorte d'afficher et de ressortir sur la liaison série les données du capteur. Pour ce faire, nous utilisons le fichier example &amp;quot;'''''53L5A1_ThresholdDetection'''''&amp;quot;. Nous modifions la fonction print_result pour afficher 16 valeurs à la suite :&lt;br /&gt;
[[Fichier:ChifoumIA Print Result.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Après avoir téléversé, nous pouvons vérifier le bon fonctionnement du programme en nous connectant à la carte via minicom :&lt;br /&gt;
&lt;br /&gt;
 root@raspberrypi:/dev$ minicom -D ttyACM0 -b 460800&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Communication VM-Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Envoie de donnée : ===&lt;br /&gt;
&lt;br /&gt;
Dans notre projet, nous avons besoin de remonter les données de notre capteur branché en liaison série à la Raspberry sur le port &amp;quot;ttyACM0&amp;quot;. Nous allons donc passer par des requêtes API entre le serveur sur chassiron et notre Raspberry.&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Raspberry : ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Du côté Raspberry, nous programmons un script en python qui lit sur la liaison série les valeurs du capteurs et les envoie via une requête POST vers le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #&amp;lt;/nowiki&amp;gt;Import Librairies&lt;br /&gt;
     import requests&lt;br /&gt;
     import json&lt;br /&gt;
     import serial&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;Variable&lt;br /&gt;
     STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
     baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
     Serial_link = serial.Serial(STM32_port,baudrate,timeout=1)&lt;br /&gt;
     print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
     liste_mesures=[]&lt;br /&gt;
     for i in range(101):&lt;br /&gt;
          print(&amp;quot;Mesure&amp;quot;,i)&lt;br /&gt;
          mesure = Serial_link.readline().decode('utf-8')&lt;br /&gt;
          liste_mesures.append(mesure)&lt;br /&gt;
&lt;br /&gt;
     data_to_send = json.dumps(liste_mesures)&lt;br /&gt;
     url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080&amp;quot;&lt;br /&gt;
&lt;br /&gt;
     headers = {&lt;br /&gt;
          'Content-type':'application/json',&lt;br /&gt;
          'Accept':'application/json'&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     r = requests.post(&lt;br /&gt;
          url_request,&lt;br /&gt;
          json=data_to_send,&lt;br /&gt;
          headers=headers&lt;br /&gt;
     )&lt;br /&gt;
     print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Serveur : ====&lt;br /&gt;
La communication entre notre VM et la Raspberry est possible. Nous arrivons à effectuer un ping de l'une sur l'autre en passant par l'addresse IPv6.&lt;br /&gt;
&lt;br /&gt;
IPv6 VM :  2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
IPv6 Raspberry : 2001:660:4401:6050:da3a:ddff:fe59:4cb5&lt;br /&gt;
&lt;br /&gt;
Nous programmons ensuite une API sur notre VM en utilisant la libraire Flask.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #&amp;lt;/nowiki&amp;gt;Import Librairies&lt;br /&gt;
     import json&lt;br /&gt;
     from flask import Flask&lt;br /&gt;
     from flask import request&lt;br /&gt;
     from waitress import serve&lt;br /&gt;
     from flask import Response&lt;br /&gt;
     from flask_cors import CORS&lt;br /&gt;
     from flask_cors import cross_origin&lt;br /&gt;
&lt;br /&gt;
     app = Flask(__name__)&lt;br /&gt;
     cors = CORS(app, ressourceas={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;:&amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
     def compute_data(data):&lt;br /&gt;
          filename = input(&amp;quot;Nom du fichier :&amp;quot;)&lt;br /&gt;
          to_write = data.split(&amp;quot;\&amp;quot;&amp;quot;)[1:-1]&lt;br /&gt;
          with open(filename, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
               i = 0&lt;br /&gt;
               for elem in to_write:&lt;br /&gt;
                    if i == 0:&lt;br /&gt;
                         print(&amp;quot;We skip&amp;quot;)&lt;br /&gt;
                    else:&lt;br /&gt;
                         if (i%2) == 0:&lt;br /&gt;
                              print(&amp;quot;Data writed :&amp;quot;,elem[:-4])&lt;br /&gt;
                              f.write(elem[:-4])&lt;br /&gt;
                              f.write(&amp;quot;\n&amp;quot;)&lt;br /&gt;
                    i = i + 1&lt;br /&gt;
&lt;br /&gt;
     #Main&lt;br /&gt;
     @app.route('/',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
     @cross_origin()&lt;br /&gt;
     def hello():&lt;br /&gt;
          data = request.json&lt;br /&gt;
          compute_data(data)&lt;br /&gt;
          return data&lt;br /&gt;
&lt;br /&gt;
     if __name__ == '__main__':&lt;br /&gt;
          print(&amp;quot;Listening&amp;quot;)&lt;br /&gt;
          serve(app,host=&amp;quot;::&amp;quot;,port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Implémentation de l'IA : ===&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Entrainement de l'IA &amp;lt;/div&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec NanoEdge AI Studio : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour le projet, nous avons d'abord développé et entrainé notre IA sur la plateforme NanoEdge AI Studio. Pour ce faire, nous devons d'abord définir un projet de classification de n-class (&amp;quot;pierre&amp;quot;,&amp;quot;feuille&amp;quot;,&amp;quot;ciseau&amp;quot;) en utilisant un capteur générique à 16 axes. Pour ce faire, nous modifions le code de la STM32 pour qu'elle renvoie une ligne contenant 16*16 mesure en continue. Une fois le projet créé, nous ajoutons 3 signaux correspondant à nos dataset de &amp;quot;Pierre&amp;quot;, &amp;quot;Feuille&amp;quot; et &amp;quot;Ciseau&amp;quot;. Pour rajouter des valeurs dans notre dataset, nous utilisons la liaison série pour lire les valeurs de notre capteur.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec Scikit : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour la suite de notre projet, nous avons developpé et entrainé une IA avec Scikit.&lt;br /&gt;
&lt;br /&gt;
Pour commencer, nous avons du construire un fichier csv reprenant&lt;br /&gt;
&lt;br /&gt;
ipv6 jcie : 2001:660:4401:6050:216:3eff:fe68:8176&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3654</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3654"/>
		<updated>2023-12-20T16:28:36Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /* Entrainement avec Scikit : */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Introduction Projet IE Delannoy - Lemaire &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
L’objectif de ce projet est de distribuer le calcul à différents endroits du réseau afin d’être en mesure de proposer des pistes d’optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, vous allez mettre en œuvre un réseau d’objets connectés à des passerelles et à un serveur. Les objets collecteront des données de l’environnement et suivant les scénarios traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Chaque scénario sera évalué en terme de performance de calcul et de sobriété énergétique. Les indicateurs de performances sont à définir (indicateur pour le calcul, pour l’énergie mais aussi un indicateur combiné).&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Présentation du Projet &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le but de notre projet est de réaliser une application permettant de déterminer l'action faite par un joueur de Pierre-Feuille-Ciseau. Notre système devra donc reconnaitre les différents mouvements fait par le joueur.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Mise en oeuvre du réseau &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Création VM XEN ===&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la VM ===&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la borne WIFI Cisco ===&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251 (changement car besoin pour les PEIP) &lt;br /&gt;
&lt;br /&gt;
- dns-server: 193.48.57.33 (changement car problème avec le serveur DNS initial)&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Configuration de la Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadra du projet, nous avons à disposition une Raspberry PI 4 model B que nous allons configurer. Pour ce faire, nous utilisons le logiciel le &amp;quot;Raspberry PI Imager&amp;quot; pour choisir notre OS.&lt;br /&gt;
[[Fichier:JCIE RPI Imager.png|centré|vignette|400x400px]]Maintenant que nous avons une carte SD prête pour la Raspberry, nous la configurons via sa liaison série en passant par minicom :&lt;br /&gt;
 root@zabeth18: / $ minicom -D /dev/ttyACM0 -b 9600&lt;br /&gt;
De plus, nous modifions le fichier /etc/network/interfaces pour pouvoir connecter notre carte au réseau wifi créé plus haut :&lt;br /&gt;
[[Fichier:Screen WiFi.png|centré|vignette|441x441px]]&lt;br /&gt;
Nous verifions ensuite que nous avons une adresse IP :&lt;br /&gt;
[[Fichier:Screenshot from 2023-12-04 17-17-05.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Capteur NUCLEO - 53L5A1 &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Pour ce projet, nous disposons d'une STM32 Nucléo F401RE muni d'un capteur à ultrason X-Nucleo-53L5A1.&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir entrainer notre IA, nous devons faire en sorte d'afficher et de ressortir sur la liaison série les données du capteur. Pour ce faire, nous utilisons le fichier example &amp;quot;'''''53L5A1_ThresholdDetection'''''&amp;quot;. Nous modifions la fonction print_result pour afficher 16 valeurs à la suite :&lt;br /&gt;
[[Fichier:ChifoumIA Print Result.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Après avoir téléversé, nous pouvons vérifier le bon fonctionnement du programme en nous connectant à la carte via minicom :&lt;br /&gt;
&lt;br /&gt;
 root@raspberrypi:/dev$ minicom -D ttyACM0 -b 460800&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Communication VM-Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Envoie de donnée : ===&lt;br /&gt;
&lt;br /&gt;
Dans notre projet, nous avons besoin de remonter les données de notre capteur branché en liaison série à la Raspberry sur le port &amp;quot;ttyACM0&amp;quot;. Nous allons donc passer par des requêtes API entre le serveur sur chassiron et notre Raspberry.&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Raspberry : ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Du côté Raspberry, nous programmons un script en python qui lit sur la liaison série les valeurs du capteurs et les envoie via une requête POST vers le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #&amp;lt;/nowiki&amp;gt;Import Librairies&lt;br /&gt;
     import requests&lt;br /&gt;
     import json&lt;br /&gt;
     import serial&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;Variable&lt;br /&gt;
     STM32_port = &amp;quot;/dev/ttyACM0&amp;quot;&lt;br /&gt;
     baudrate = 460800&lt;br /&gt;
&lt;br /&gt;
     Serial_link = serial.Serial(STM32_port,baudrate,timeout=1)&lt;br /&gt;
     print(&amp;quot;Serial link done&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
     liste_mesures=[]&lt;br /&gt;
     for i in range(101):&lt;br /&gt;
          print(&amp;quot;Mesure&amp;quot;,i)&lt;br /&gt;
          mesure = Serial_link.readline().decode('utf-8')&lt;br /&gt;
          liste_mesures.append(mesure)&lt;br /&gt;
&lt;br /&gt;
     data_to_send = json.dumps(liste_mesures)&lt;br /&gt;
     url_request = &amp;quot;http://[2001:660:4401:6050:216:3eff:fe68:8176]:8080&amp;quot;&lt;br /&gt;
&lt;br /&gt;
     headers = {&lt;br /&gt;
          'Content-type':'application/json',&lt;br /&gt;
          'Accept':'application/json'&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     r = requests.post(&lt;br /&gt;
          url_request,&lt;br /&gt;
          json=data_to_send,&lt;br /&gt;
          headers=headers&lt;br /&gt;
     )&lt;br /&gt;
     print(f&amp;quot;Status code : {r.status_code}&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Programmation côté Serveur : ====&lt;br /&gt;
La communication entre notre VM et la Raspberry est possible. Nous arrivons à effectuer un ping de l'une sur l'autre en passant par l'addresse IPv6.&lt;br /&gt;
&lt;br /&gt;
IPv6 VM :  2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
IPv6 Raspberry : 2001:660:4401:6050:da3a:ddff:fe59:4cb5&lt;br /&gt;
&lt;br /&gt;
Nous programmons ensuite une API sur notre VM en utilisant la libraire Flask.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     #&amp;lt;/nowiki&amp;gt;Import Librairies&lt;br /&gt;
     import json&lt;br /&gt;
     from flask import Flask&lt;br /&gt;
     from flask import request&lt;br /&gt;
     from waitress import serve&lt;br /&gt;
     from flask import Response&lt;br /&gt;
     from flask_cors import CORS&lt;br /&gt;
     from flask_cors import cross_origin&lt;br /&gt;
&lt;br /&gt;
     app = Flask(__name__)&lt;br /&gt;
     cors = CORS(app, ressourceas={r&amp;quot;/api/*&amp;quot;:{&amp;quot;origins&amp;quot;:&amp;quot;*&amp;quot;}})&lt;br /&gt;
&lt;br /&gt;
     def compute_data(data):&lt;br /&gt;
          filename = input(&amp;quot;Nom du fichier :&amp;quot;)&lt;br /&gt;
          to_write = data.split(&amp;quot;\&amp;quot;&amp;quot;)[1:-1]&lt;br /&gt;
          with open(filename, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
               i = 0&lt;br /&gt;
               for elem in to_write:&lt;br /&gt;
                    if i == 0:&lt;br /&gt;
                         print(&amp;quot;We skip&amp;quot;)&lt;br /&gt;
                    else:&lt;br /&gt;
                         if (i%2) == 0:&lt;br /&gt;
                              print(&amp;quot;Data writed :&amp;quot;,elem[:-4])&lt;br /&gt;
                              f.write(elem[:-4])&lt;br /&gt;
                              f.write(&amp;quot;\n&amp;quot;)&lt;br /&gt;
                    i = i + 1&lt;br /&gt;
&lt;br /&gt;
     #Main&lt;br /&gt;
     @app.route('/',methods=[&amp;quot;GET&amp;quot;,&amp;quot;POST&amp;quot;])&lt;br /&gt;
     @cross_origin()&lt;br /&gt;
     def hello():&lt;br /&gt;
          data = request.json&lt;br /&gt;
          compute_data(data)&lt;br /&gt;
          return data&lt;br /&gt;
&lt;br /&gt;
     if __name__ == '__main__':&lt;br /&gt;
          print(&amp;quot;Listening&amp;quot;)&lt;br /&gt;
          serve(app,host=&amp;quot;::&amp;quot;,port=&amp;quot;8080&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Implémentation de l'IA : ===&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Entrainement de l'IA &amp;lt;/div&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec NanoEdge AI Studio : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour le projet, nous avons d'abord développé et entrainé notre IA sur la plateforme NanoEdge AI Studio. Pour ce faire, nous devons d'abord définir un projet de classification de n-class (&amp;quot;pierre&amp;quot;,&amp;quot;feuille&amp;quot;,&amp;quot;ciseau&amp;quot;) en utilisant un capteur générique à 16 axes. Pour ce faire, nous modifions le code de la STM32 pour qu'elle renvoie une ligne contenant 16*16 mesure en continue. Une fois le projet créé&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Entrainement avec Scikit : ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour la suite de notre projet, nous avons developpé et entrainé une IA avec Scikit.&lt;br /&gt;
&lt;br /&gt;
Pour commencer, nous avons du construire un fichier csv reprenant&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3519</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3519"/>
		<updated>2023-12-19T13:00:05Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /* Configuration de la borne WIFI Cisco */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Introduction Projet IE Delannoy - Lemaire &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
L’objectif de ce projet est de distribuer le calcul à différents endroits du réseau afin d’être en mesure de proposer des pistes d’optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, vous allez mettre en œuvre un réseau d’objets connectés à des passerelles et à un serveur. Les objets collecteront des données de l’environnement et suivant les scénarios traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Chaque scénario sera évalué en terme de performance de calcul et de sobriété énergétique. Les indicateurs de performances sont à définir (indicateur pour le calcul, pour l’énergie mais aussi un indicateur combiné).&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Présentation du Projet &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le but de notre projet est de réaliser une application permettant de déterminer l'action faite par un joueur de Pierre-Feuille-Ciseau. Notre système devra donc reconnaitre les différents mouvements fait par le joueur.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Mise en oeuvre du réseau &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Création VM XEN ===&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la VM ===&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la borne WIFI Cisco ===&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251 (changement car besoin pour les PEIP) &lt;br /&gt;
&lt;br /&gt;
- dns-server: 193.48.57.33 (changement car problème avec le serveur DNS initial)&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Configuration de la Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadra du projet, nous avons à disposition une Raspberry PI 4 model B que nous allons configurer. Pour ce faire, nous utilisons le logiciel le &amp;quot;Raspberry PI Imager&amp;quot; pour choisir notre OS.&lt;br /&gt;
[[Fichier:JCIE RPI Imager.png|centré|vignette|400x400px]]Maintenant que nous avons une carte SD prête pour la Raspberry, nous la configurons via sa liaison série en passant par minicom :&lt;br /&gt;
 root@zabeth18: / $ minicom -D /dev/ttyACM0 -b 9600&lt;br /&gt;
De plus, nous modifions le fichier /etc/network/interfaces pour pouvoir connecter notre carte au réseau wifi créé plus haut :&lt;br /&gt;
[[Fichier:Screen WiFi.png|centré|vignette|441x441px]]&lt;br /&gt;
Nous verifions ensuite que nous avons une adresse IP :&lt;br /&gt;
[[Fichier:Screenshot from 2023-12-04 17-17-05.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Communication VM-Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La communication entre notre VM et la Raspberry est possible. Nous arrivons à effectuer un ping de l'une sur l'autre en passant par l'addresse IPv6.&lt;br /&gt;
&lt;br /&gt;
IPv6 VM :  2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
IPv6 Raspberry : 2001:660:4401:6050:da3a:ddff:fe59:4cb5&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Capteur NUCLEO - 53L5A1 &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ouverture de Minicom dans un terminal avec un baudrate de 460800&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3429</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3429"/>
		<updated>2023-12-18T10:47:59Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /* Capteur Nucleo - 53L5A1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Introduction Projet IE Delannoy - Lemaire &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
L’objectif de ce projet est de distribuer le calcul à différents endroits du réseau afin d’être en mesure de proposer des pistes d’optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, vous allez mettre en œuvre un réseau d’objets connectés à des passerelles et à un serveur. Les objets collecteront des données de l’environnement et suivant les scénarios traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Chaque scénario sera évalué en terme de performance de calcul et de sobriété énergétique. Les indicateurs de performances sont à définir (indicateur pour le calcul, pour l’énergie mais aussi un indicateur combiné).&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Présentation du Projet &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le but de notre projet est de réaliser une application permettant de déterminer l'action faite par un joueur de Pierre-Feuille-Ciseau. Notre système devra donc reconnaitre les différents mouvements fait par le joueur.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Mise en oeuvre du réseau &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Création VM XEN ===&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la VM ===&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la borne WIFI Cisco ===&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251&lt;br /&gt;
&lt;br /&gt;
- dns-server: 193.48.57.33 (changement car problème avec le serveur DNS initial)&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Configuration de la Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadra du projet, nous avons à disposition une Raspberry PI 4 model B que nous allons configurer. Pour ce faire, nous utilisons le logiciel le &amp;quot;Raspberry PI Imager&amp;quot; pour choisir notre OS.&lt;br /&gt;
[[Fichier:JCIE RPI Imager.png|centré|vignette|400x400px]]&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Communication VM-Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La communication entre notre VM et la Raspberry est possible. Nous arrivons à effectuer un ping de l'une sur l'autre en passant par l'addresse IPv6.&lt;br /&gt;
&lt;br /&gt;
IPv6 VM :  2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
IPv6 Raspberry : 2001:660:4401:6050:da3a:ddff:fe59:4cb5&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Capteur NUCLEO - 53L5A1 &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ouverture de Minicom dans un terminal avec un baudrate de 460800&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3428</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3428"/>
		<updated>2023-12-18T10:47:06Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Introduction Projet IE Delannoy - Lemaire &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
L’objectif de ce projet est de distribuer le calcul à différents endroits du réseau afin d’être en mesure de proposer des pistes d’optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, vous allez mettre en œuvre un réseau d’objets connectés à des passerelles et à un serveur. Les objets collecteront des données de l’environnement et suivant les scénarios traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Chaque scénario sera évalué en terme de performance de calcul et de sobriété énergétique. Les indicateurs de performances sont à définir (indicateur pour le calcul, pour l’énergie mais aussi un indicateur combiné).&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Présentation du Projet &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le but de notre projet est de réaliser une application permettant de déterminer l'action faite par un joueur de Pierre-Feuille-Ciseau. Notre système devra donc reconnaitre les différents mouvements fait par le joueur.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Mise en oeuvre du réseau &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Création VM XEN ===&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la VM ===&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la borne WIFI Cisco ===&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251&lt;br /&gt;
&lt;br /&gt;
- dns-server: 193.48.57.33 (changement car problème avec le serveur DNS initial)&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Configuration de la Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadra du projet, nous avons à disposition une Raspberry PI 4 model B que nous allons configurer. Pour ce faire, nous utilisons le logiciel le &amp;quot;Raspberry PI Imager&amp;quot; pour choisir notre OS.&lt;br /&gt;
[[Fichier:JCIE RPI Imager.png|centré|vignette|400x400px]]&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Communication VM-Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La communication entre notre VM et la Raspberry est possible. Nous arrivons à effectuer un ping de l'une sur l'autre en passant par l'addresse IPv6.&lt;br /&gt;
&lt;br /&gt;
IPv6 VM :  2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
IPv6 Raspberry : 2001:660:4401:6050:da3a:ddff:fe59:4cb5&lt;br /&gt;
&lt;br /&gt;
== Capteur Nucleo - 53L5A1 ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ouverture de Minicom dans un terminal avec un baudrate de 460800&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3427</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3427"/>
		<updated>2023-12-18T10:42:32Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /*  Communication VM-Raspberry  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Introduction Projet IE Delannoy - Lemaire &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
L’objectif de ce projet est de distribuer le calcul à différents endroits du réseau afin d’être en mesure de proposer des pistes d’optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, vous allez mettre en œuvre un réseau d’objets connectés à des passerelles et à un serveur. Les objets collecteront des données de l’environnement et suivant les scénarios traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Chaque scénario sera évalué en terme de performance de calcul et de sobriété énergétique. Les indicateurs de performances sont à définir (indicateur pour le calcul, pour l’énergie mais aussi un indicateur combiné).&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Présentation du Projet &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le but de notre projet est de réaliser une application permettant de déterminer l'action faite par un joueur de Pierre-Feuille-Ciseau. Notre système devra donc reconnaitre les différents mouvements fait par le joueur.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Mise en oeuvre du réseau &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Création VM XEN ===&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la VM ===&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la borne WIFI Cisco ===&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251&lt;br /&gt;
&lt;br /&gt;
- dns-server: 193.48.57.33 (changement car problème avec le serveur DNS initial)&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Configuration de la Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadra du projet, nous avons à disposition une Raspberry PI 4 model B que nous allons configurer. Pour ce faire, nous utilisons le logiciel le &amp;quot;Raspberry PI Imager&amp;quot; pour choisir notre OS.&lt;br /&gt;
[[Fichier:JCIE RPI Imager.png|centré|vignette|400x400px]]&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Communication VM-Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La communication entre notre VM et la Raspberry est possible. Nous arrivons à effectuer un ping de l'une sur l'autre en passant par l'addresse IPv6.&lt;br /&gt;
&lt;br /&gt;
IPv6 VM :  2001:660:4401:6050:216:3eff:fe68:8176&lt;br /&gt;
&lt;br /&gt;
IPv6 Raspberry : 2001:660:4401:6050:da3a:ddff:fe59:4cb5&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3426</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3426"/>
		<updated>2023-12-18T10:41:32Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /* Configuration de la borne WIFI Cisco */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Introduction Projet IE Delannoy - Lemaire &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
L’objectif de ce projet est de distribuer le calcul à différents endroits du réseau afin d’être en mesure de proposer des pistes d’optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, vous allez mettre en œuvre un réseau d’objets connectés à des passerelles et à un serveur. Les objets collecteront des données de l’environnement et suivant les scénarios traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Chaque scénario sera évalué en terme de performance de calcul et de sobriété énergétique. Les indicateurs de performances sont à définir (indicateur pour le calcul, pour l’énergie mais aussi un indicateur combiné).&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Présentation du Projet &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le but de notre projet est de réaliser une application permettant de déterminer l'action faite par un joueur de Pierre-Feuille-Ciseau. Notre système devra donc reconnaitre les différents mouvements fait par le joueur.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Mise en oeuvre du réseau &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Création VM XEN ===&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la VM ===&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la borne WIFI Cisco ===&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251&lt;br /&gt;
&lt;br /&gt;
- dns-server: 193.48.57.33 (changement car problème avec le serveur DNS initial)&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Configuration de la Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadra du projet, nous avons à disposition une Raspberry PI 4 model B que nous allons configurer. Pour ce faire, nous utilisons le logiciel le &amp;quot;Raspberry PI Imager&amp;quot; pour choisir notre OS.&lt;br /&gt;
[[Fichier:JCIE RPI Imager.png|centré|vignette|400x400px]]&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Communication VM-Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La communication entre notre VM et la Raspberry est possible. Nous arrivons à effectuer un ping de l'une sur l'autre en passant par l'addresse IPv6.&lt;br /&gt;
&lt;br /&gt;
IPv6 VM :  2001:660:4401:6050:216:3eff:fe68:8176&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3423</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3423"/>
		<updated>2023-12-18T10:39:30Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /* Configuration de la borne WIFI Cisco */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Introduction Projet IE Delannoy - Lemaire &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
L’objectif de ce projet est de distribuer le calcul à différents endroits du réseau afin d’être en mesure de proposer des pistes d’optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, vous allez mettre en œuvre un réseau d’objets connectés à des passerelles et à un serveur. Les objets collecteront des données de l’environnement et suivant les scénarios traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Chaque scénario sera évalué en terme de performance de calcul et de sobriété énergétique. Les indicateurs de performances sont à définir (indicateur pour le calcul, pour l’énergie mais aussi un indicateur combiné).&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Présentation du Projet &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le but de notre projet est de réaliser une application permettant de déterminer l'action faite par un joueur de Pierre-Feuille-Ciseau. Notre système devra donc reconnaitre les différents mouvements fait par le joueur.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Mise en oeuvre du réseau &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Création VM XEN ===&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la VM ===&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la borne WIFI Cisco ===&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251&lt;br /&gt;
&lt;br /&gt;
- dns-server: 193.48.57.33 ( changement car problème avec le serveur dns initial)&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Configuration de la Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadra du projet, nous avons à disposition une Raspberry PI 4 model B que nous allons configurer. Pour ce faire, nous utilisons le logiciel le &amp;quot;Raspberry PI Imager&amp;quot; pour choisir notre OS.&lt;br /&gt;
[[Fichier:JCIE RPI Imager.png|centré|vignette|400x400px]]&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Communication VM-Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La communication entre notre VM et la Raspberry est possible. Nous arrivons à effectuer un ping de l'une sur l'autre en passant par l'addresse IPv6.&lt;br /&gt;
&lt;br /&gt;
IPv6 VM :  2001:660:4401:6050:216:3eff:fe68:8176&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3421</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3421"/>
		<updated>2023-12-18T10:37:08Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /*  Configuration de la Raspberry  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Introduction Projet IE Delannoy - Lemaire &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
L’objectif de ce projet est de distribuer le calcul à différents endroits du réseau afin d’être en mesure de proposer des pistes d’optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, vous allez mettre en œuvre un réseau d’objets connectés à des passerelles et à un serveur. Les objets collecteront des données de l’environnement et suivant les scénarios traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Chaque scénario sera évalué en terme de performance de calcul et de sobriété énergétique. Les indicateurs de performances sont à définir (indicateur pour le calcul, pour l’énergie mais aussi un indicateur combiné).&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Présentation du Projet &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le but de notre projet est de réaliser une application permettant de déterminer l'action faite par un joueur de Pierre-Feuille-Ciseau. Notre système devra donc reconnaitre les différents mouvements fait par le joueur.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Mise en oeuvre du réseau &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
=== Création VM XEN ===&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la VM ===&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
=== Configuration de la borne WIFI Cisco ===&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251&lt;br /&gt;
&lt;br /&gt;
- dns-server: 193.48.57.33 ( changement car problème avec le serveur dns initial)&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Configuration de la Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Dans le cadra du projet, nous avons à disposition une Raspberry PI 4 model B que nous allons configurer. Pour ce faire, nous utilisons le logiciel le &amp;quot;Raspberry PI Imager&amp;quot; pour choisir notre OS.&lt;br /&gt;
[[Fichier:JCIE RPI Imager.png|centré|vignette|500x500px]]&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;div class=&amp;quot;mcwiki-header&amp;quot; style=&amp;quot;border-radius: 15px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #42acc9; vertical-align: top; width: 96%;&amp;quot;&amp;gt; Communication VM-Raspberry &amp;lt;/div&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La communication entre notre VM et la Raspberry est possible. Nous arrivons à effectuer un ping de l'une sur l'autre en passant par l'addresse IPv6.&lt;br /&gt;
&lt;br /&gt;
IPv6 VM :  2001:660:4401:6050:216:3eff:fe68:8176&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3406</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3406"/>
		<updated>2023-12-18T10:04:48Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /* Communication VM - Raspberry */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction Projet IE Delannoy - Lemaire ==&lt;br /&gt;
L’objectif de ce projet est de distribuer le calcul à différents endroits du réseau afin d’être en mesure de proposer des pistes d’optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, vous allez mettre en œuvre un réseau d’objets connectés à des passerelles et à un serveur. Les objets collecteront des données de l’environnement et suivant les scénarios traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Chaque scénario sera évalué en terme de performance de calcul et de sobriété énergétique. Les indicateurs de performances sont à définir (indicateur pour le calcul, pour l’énergie mais aussi un indicateur combiné).&lt;br /&gt;
&lt;br /&gt;
== Projet ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Notre projet est de &lt;br /&gt;
&lt;br /&gt;
== Mise en oeuvre du réseau ==&lt;br /&gt;
&lt;br /&gt;
== Création VM XEN ==&lt;br /&gt;
&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]&lt;br /&gt;
&lt;br /&gt;
== Configuration de la VM ==&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
== Configuration de la borne WIFI Cisco ==&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251&lt;br /&gt;
&lt;br /&gt;
- dns-server : 193.48.57.33&lt;br /&gt;
&lt;br /&gt;
== Configuration de la Raspberrypi ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Communication VM - Raspberry ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La communication entre notre VM et la Raspberry est possible. Nous arrivons à effectuer un ping de l'une sur l'autre en passant par l'addresse IPv6.&lt;br /&gt;
&lt;br /&gt;
IPv6 VM :  2001:660:4401:6050:216:3eff:fe68:8176&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3399</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3399"/>
		<updated>2023-12-18T09:53:56Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /* Configuration de la Raspberrypi */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction Projet IE Delannoy - Lemaire ==&lt;br /&gt;
L’objectif de ce projet est de distribuer le calcul à différents endroits du réseau afin d’être en mesure de proposer des pistes d’optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, vous allez mettre en œuvre un réseau d’objets connectés à des passerelles et à un serveur. Les objets collecteront des données de l’environnement et suivant les scénarios traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Chaque scénario sera évalué en terme de performance de calcul et de sobriété énergétique. Les indicateurs de performances sont à définir (indicateur pour le calcul, pour l’énergie mais aussi un indicateur combiné).&lt;br /&gt;
&lt;br /&gt;
== Projet ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Notre projet est de &lt;br /&gt;
&lt;br /&gt;
== Mise en oeuvre du réseau ==&lt;br /&gt;
&lt;br /&gt;
== Création VM XEN ==&lt;br /&gt;
&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]&lt;br /&gt;
&lt;br /&gt;
== Configuration de la VM ==&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
== Configuration de la borne WIFI Cisco ==&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251&lt;br /&gt;
&lt;br /&gt;
- dns-server : 193.48.57.33&lt;br /&gt;
&lt;br /&gt;
== Configuration de la Raspberrypi ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Communication VM - Raspberry ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La communication entre notre VM et la Raspberry est possible. Nous arrivons à effectuer un ping de l'une sur l'autre en passant par l'addresse IPv6.&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3389</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3389"/>
		<updated>2023-12-18T08:11:36Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /* Configuration de la borne WIFI Cisco */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction Projet IE Delannoy - Lemaire ==&lt;br /&gt;
L’objectif de ce projet est de distribuer le calcul à différents endroits du réseau afin d’être en mesure de proposer des pistes d’optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, vous allez mettre en œuvre un réseau d’objets connectés à des passerelles et à un serveur. Les objets collecteront des données de l’environnement et suivant les scénarios traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Chaque scénario sera évalué en terme de performance de calcul et de sobriété énergétique. Les indicateurs de performances sont à définir (indicateur pour le calcul, pour l’énergie mais aussi un indicateur combiné).&lt;br /&gt;
&lt;br /&gt;
== Projet ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Notre projet est de &lt;br /&gt;
&lt;br /&gt;
== Mise en oeuvre du réseau ==&lt;br /&gt;
&lt;br /&gt;
== Création VM XEN ==&lt;br /&gt;
&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]&lt;br /&gt;
&lt;br /&gt;
== Configuration de la VM ==&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
== Configuration de la borne WIFI Cisco ==&lt;br /&gt;
La connexion avec la borne Wifi CISCO se fait via minicom sur le port ttyS0 avec un baudrate de 9600. &lt;br /&gt;
&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]Le point d'accès a été modifié par Monsieur Redon pour les projets PEIP. On a maintenant : &lt;br /&gt;
&lt;br /&gt;
Dans le protocole DHCP:&lt;br /&gt;
&lt;br /&gt;
- default-router 172.26.145.251&lt;br /&gt;
&lt;br /&gt;
- dns-server : 193.48.57.33&lt;br /&gt;
&lt;br /&gt;
== Configuration de la Raspberrypi ==&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3360</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3360"/>
		<updated>2023-12-07T20:54:48Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /* Introduction Projet IE Delannoy - Lemaire */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction Projet IE Delannoy - Lemaire ==&lt;br /&gt;
L’objectif de ce projet est de distribuer le calcul à différents endroits du réseau afin d’être en mesure de proposer des pistes d’optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, vous allez mettre en œuvre un réseau d’objets connectés à des passerelles et à un serveur. Les objets collecteront des données de l’environnement et suivant les scénarios traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Chaque scénario sera évalué en terme de performance de calcul et de sobriété énergétique. Les indicateurs de performances sont à définir (indicateur pour le calcul, pour l’énergie mais aussi un indicateur combiné).&lt;br /&gt;
&lt;br /&gt;
L’objectif de ce projet est de distribuer le calcul à différents endroits du réseau afin d’être en mesure de proposer des pistes d’optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, vous allez mettre en œuvre un réseau d’objets connectés à des passerelles et à un serveur. Les objets collecteront des données de l’environnement et suivant les scénarios traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Chaque scénario sera évalué en terme de performance de calcul et de sobriété énergétique. Les indicateurs de performances sont à définir (indicateur pour le calcul, pour l’énergie mais aussi un indicateur combiné).&lt;br /&gt;
== Mise en oeuvre du réseau ==&lt;br /&gt;
&lt;br /&gt;
== Création VM XEN ==&lt;br /&gt;
&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]&lt;br /&gt;
&lt;br /&gt;
== Configuration de la VM ==&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
== Configuration de la borne WIFI Cisco ==&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3359</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3359"/>
		<updated>2023-12-07T20:54:14Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /* Configuration de la borne WIFI Cisco */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction Projet IE Delannoy - Lemaire ==&lt;br /&gt;
L’objectif de ce projet est de distribuer le calcul à différents endroits du réseau afin d’être en mesure de proposer des pistes d’optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, vous allez mettre en œuvre un réseau d’objets connectés à des passerelles et à un serveur. Les objets collecteront des données de l’environnement et suivant les scénarios traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Chaque scénario sera évalué en terme de performance de calcul et de sobriété énergétique. Les indicateurs de performances sont à définir (indicateur pour le calcul, pour l’énergie mais aussi un indicateur combiné).&lt;br /&gt;
== Mise en oeuvre du réseau ==&lt;br /&gt;
&lt;br /&gt;
== Création VM XEN ==&lt;br /&gt;
&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]&lt;br /&gt;
&lt;br /&gt;
== Configuration de la VM ==&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
== Configuration de la borne WIFI Cisco ==&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|500x500px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi: WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3358</id>
		<title>SE5 ECEAI/eceai 2023/2024/jcie</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/jcie&amp;diff=3358"/>
		<updated>2023-12-07T20:51:15Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : /* Introduction Projet IE Delannoy - Lemaire */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction Projet IE Delannoy - Lemaire ==&lt;br /&gt;
L’objectif de ce projet est de distribuer le calcul à différents endroits du réseau afin d’être en mesure de proposer des pistes d’optimisation que ce soit en terme de performance ou en terme de sobriété énergétique. Pour cela, vous allez mettre en œuvre un réseau d’objets connectés à des passerelles et à un serveur. Les objets collecteront des données de l’environnement et suivant les scénarios traiteront les données ou les enverront de façon brute à la passerelle ou au serveur. Chaque scénario sera évalué en terme de performance de calcul et de sobriété énergétique. Les indicateurs de performances sont à définir (indicateur pour le calcul, pour l’énergie mais aussi un indicateur combiné).&lt;br /&gt;
== Mise en oeuvre du réseau ==&lt;br /&gt;
&lt;br /&gt;
== Création VM XEN ==&lt;br /&gt;
&lt;br /&gt;
Nous avons commencé par créer une machine virtuelle sur Chassiron avec la commande : &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
xen-create-image --hostname jcie --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:Creation VM.png|centré|vignette|600x600px]]&lt;br /&gt;
&lt;br /&gt;
== Configuration de la VM ==&lt;br /&gt;
&lt;br /&gt;
===== Configuration de l'interface enX0 en ipv6: =====&lt;br /&gt;
 auto enX0&lt;br /&gt;
 iface enX0 inet6 auto &lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier resolv.conf: =====&lt;br /&gt;
Ce fichier permet de stocker les adresses des serveurs DNS du système. Dans notre cas, nous allons interroger le serveur DNS de l'école: plil.info.&lt;br /&gt;
 domain plil.info&lt;br /&gt;
 search plil.info&lt;br /&gt;
 nameserver 2a01:c916:2047:c800:216:3eff:fe82:8a5c&lt;br /&gt;
&lt;br /&gt;
===== Modification du fichier sources.list: =====&lt;br /&gt;
Ce fichier se situe dans le répertoire &amp;quot;/etc/apt/&amp;quot;. Il référence l'ensemble des sources utilisées par l'utilitaire APT pour télécharger les paquets.&lt;br /&gt;
&lt;br /&gt;
Nous avons ajouté deux nouvelles sources :&lt;br /&gt;
&lt;br /&gt;
deb http://deb.debian.org/debian    bookworm main contrib non-free non-free-firmware &lt;br /&gt;
&lt;br /&gt;
deb-src http://deb.debian.org/debian   bookworm main contrib non-free non-free-firmware&lt;br /&gt;
&lt;br /&gt;
== Configuration de la borne WIFI Cisco ==&lt;br /&gt;
Pour réaliser notre point d'accès, nous avons configurer l'interface dot11Radio1&lt;br /&gt;
[[Fichier:Intdot11.png|centré|vignette|600x600px]]&lt;br /&gt;
Nous avons nommé notre point d'accès Wifi : WiFi_IE_1&lt;br /&gt;
&lt;br /&gt;
Pour la connexion à celui-ci nous devons utiliser le mot de passe glopglop.&lt;br /&gt;
[[Fichier:Dot11config.png|centré|vignette|500x500px]]&lt;br /&gt;
Pour l'attribution de l'adresse, on utilise le protocole DHCP. Dans la définition de notre protocole, on exclut les intervalles d'adresses suivantes : 172.26.145.1 - 172.26.145.100 et 172.26.145.139 - 172.26.145.254&lt;br /&gt;
[[Fichier:Dhcp.png|centré|vignette|500x500px]]&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:Intdot11.png&amp;diff=3357</id>
		<title>Fichier:Intdot11.png</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:Intdot11.png&amp;diff=3357"/>
		<updated>2023-12-07T20:50:38Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Intdot11&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:Dhcp.png&amp;diff=3356</id>
		<title>Fichier:Dhcp.png</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:Dhcp.png&amp;diff=3356"/>
		<updated>2023-12-07T20:48:21Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;DHCP&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:Dot11config.png&amp;diff=3355</id>
		<title>Fichier:Dot11config.png</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:Dot11config.png&amp;diff=3355"/>
		<updated>2023-12-07T20:46:59Z</updated>

		<summary type="html">&lt;p&gt;Clemair1 : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;dot11config&lt;/div&gt;</summary>
		<author><name>Clemair1</name></author>
	</entry>
</feed>