<?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=Fvallee</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=Fvallee"/>
	<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php/Sp%C3%A9cial:Contributions/Fvallee"/>
	<updated>2026-05-14T10:24:26Z</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/ValleeSellali&amp;diff=4749</id>
		<title>SE5 ECEAI/eceai 2023/2024/ValleeSellali</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/ValleeSellali&amp;diff=4749"/>
		<updated>2024-01-28T13:18:31Z</updated>

		<summary type="html">&lt;p&gt;Fvallee : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Groupe Vallée-Sellali&lt;br /&gt;
&lt;br /&gt;
== Séance n°1 ==&lt;br /&gt;
Machine virtuelle créée sur chassiron :&lt;br /&gt;
&lt;br /&gt;
Hostname       :  ValSel&lt;br /&gt;
&lt;br /&gt;
Distribution    :  bookworm&lt;br /&gt;
&lt;br /&gt;
Stockage  : 10G&lt;br /&gt;
&lt;br /&gt;
Mémoire vive : 1G&lt;br /&gt;
&lt;br /&gt;
Mot de passe habituel&lt;br /&gt;
&lt;br /&gt;
Les fichiers /etc/network/interfaces, /etc/resolv.conf et /etc/apt/sources.list ont été modifiés comme demandés.&lt;br /&gt;
&lt;br /&gt;
Raspberry 4 :&lt;br /&gt;
&lt;br /&gt;
Communication via le port série possible&lt;br /&gt;
&lt;br /&gt;
Login : valsel Pwd : pasglop&lt;br /&gt;
&lt;br /&gt;
STM32F401RE : Nanoedge et IDE installés, conception d'un code pour tester le capteur en cours&lt;br /&gt;
&lt;br /&gt;
== Séance n°2 (18/12/2023) ==&lt;br /&gt;
Raspberry connectée au WiFi SE5&lt;br /&gt;
&lt;br /&gt;
Connexion ipv6 possible entre la VM et la raspberry&lt;br /&gt;
&lt;br /&gt;
Données du capteur lues et envoyées au port série&lt;br /&gt;
&lt;br /&gt;
Création d'un programme python client à destination de la raspberry qui : lit le port série, stocke les données reçues, envoie les données reçues en http vers le &amp;quot;serveur&amp;quot; présent sur la VM&lt;br /&gt;
&lt;br /&gt;
Création d'un programme python serveur à destination de la VM qui reçoit et stocke les données&lt;br /&gt;
&lt;br /&gt;
== Séance 3 (19/12/2023) ==&lt;br /&gt;
Création des datasets : main fermée et main ouverte (Une ligne = 16 * 16 données, environ 30 lignes par fichier)&lt;br /&gt;
&lt;br /&gt;
Choix de garder les capteurs en 4x4 pour un compromis vitesse de création des datasets/temps d'entrainement du modèle/efficacité du capteur de mouvement.&lt;br /&gt;
&lt;br /&gt;
Entrainement du modèle avec les datasets sur NanoEdge&lt;br /&gt;
&lt;br /&gt;
==  Séance 4 (20/12/2023) ==&lt;br /&gt;
Création de nouveaux datasets et de fichiers de tests : (100 lignes de 16 * 16 données)&lt;br /&gt;
&lt;br /&gt;
Création d'un script Python utilisant la bibliothèque sklearn pour implémenter un algorithme de classification SVM, à destination de la Raspberry et de la VM&lt;br /&gt;
&lt;br /&gt;
Le choix de main ouverte/main fermée se questionne, on utilise pas l'aspect mouvement que permet les algorithmes.&lt;br /&gt;
&lt;br /&gt;
Les algorithmes donnent un bon résultat avec une précision proche de 70%. La communication entre la VM et la zabeth sur laquelle on teste les fichiers pythons fonctionne.&lt;br /&gt;
&lt;br /&gt;
Du microcontrôleur, on reçoit les données brutes et l'estimation de l'état de la main. Le fichier python sur la zabeth, à destination future de la raspberry, reçoit ces données via le port série, les stocke dans un fichier txt, fait une estimation de l'état de la main, et envoie les données brutes à la VM en utilisant TCP/IP avec l'adresse IPV6 de la VM.&lt;br /&gt;
&lt;br /&gt;
La VM reçoit les données mais ne les traite pas encore.&lt;br /&gt;
&lt;br /&gt;
== Travail hors des séances et rendu final ==&lt;br /&gt;
&lt;br /&gt;
=== Ajouts ===&lt;br /&gt;
Extension du programme sur la STM aux 64 capteurs.&lt;br /&gt;
&lt;br /&gt;
Nouveau choix de test qui prend en compte les mouvements.&lt;br /&gt;
&lt;br /&gt;
Création de nouveaux datasets adaptés : lignes de 64 * 16 données, une ligne correspond à une itération du mouvement, environ 170 lignes par datasets pour une prise en compte de plusieurs cas&lt;br /&gt;
&lt;br /&gt;
(passage rapide, passage lent, hauteurs différentes). (Utilisation du code annexe GestionData sans la communication TCP pour la création des fichiers)&lt;br /&gt;
&lt;br /&gt;
Les mouvements sont : &lt;br /&gt;
&lt;br /&gt;
- Mouvement de gauche à droite&lt;br /&gt;
&lt;br /&gt;
- Mouvement de droite à gauche&lt;br /&gt;
&lt;br /&gt;
- Aucune présence&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir tester les modèles résultant de ces datasets, 3 fichiers de tests sont créés contenant chacun une trentaine d'itérations du mouvement.&lt;br /&gt;
&lt;br /&gt;
Avec Nanoedge, entraînement d'un nouveau modèle à destination de la STM. Le modèle le plus efficace avec nos fichiers de tests sont, contrairement aux premières séances, un modèle MLP (multilayer&lt;br /&gt;
&lt;br /&gt;
perceptron). Résultats avec nos fichiers de tests : précision de 90%. &lt;br /&gt;
&lt;br /&gt;
Intégration de la bibliothèque libneai.a créée par Nanoedge dans le projet STM et adaptation du code de la STM pour y intégrer l'estimation à partir des données des capteurs. (Annexe app_tof.c)&lt;br /&gt;
&lt;br /&gt;
En effet, les modèles SVM ne semblent pas adaptés à nos datasets =&amp;gt; Adaptation du code python de la raspberry pour utiliser lui aussi un modèle MLP, ce qui est plus efficace. (entraînement du modèle avec le programme mlpAlgo.py présent en annexe)&lt;br /&gt;
&lt;br /&gt;
Modèle résultant avec comme input les fichiers de tests : 70% de précision sur Droite à gauche, 68% de gauche à droite, 100% si aucune présence.&lt;br /&gt;
&lt;br /&gt;
Intégration du code GestionData.py dans la raspberry ainsi que du modèle créé par mlpAlgo.py (uniquement l'output)&lt;br /&gt;
&lt;br /&gt;
=== Transmission et stockage des données ===&lt;br /&gt;
- La STM32 envoie les données brutes + l'estimation du mouvement issue de son modèle intégré, par le port série (ap_tof.c disponible en annexe)&lt;br /&gt;
&lt;br /&gt;
- La Raspberry Pi reçoit ces données brutes, les stocke dans un fichier texte, estime le mouvement effectué, et affiche l'estimation en plus de celle de la STM. Ensuite, les données brutes sont transmises à la VM par TCP/IP en IPV6, à la condition que 1024 données soient présentes à chaque lecture. Si ce n'est pas le cas, les données &amp;quot;corrompues&amp;quot; ne sont pas transmises puisqu'inexploitables. (Voir GestionData.py en annexe)&lt;br /&gt;
&lt;br /&gt;
- La VM reçoit les données par paquet de 1024 entiers, stocke les données dans un fichier txt, et fait une estimation du mouvement en utilisant le même modèle que celui présent dans la raspberry pi.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Lors des tests, nous avons constaté que la communication TCP ne semblait pas permise depuis un ordinateur externe au réseau des zabeths vers la VM : le ping est possible, mais la communication ne semble pas. Nous avons donc fait le choix d'utiliser un ordinateur personnel pour montrer l'efficacité du projet : le fonctionnement est similaire, les données sont envoyées sur la machine personnelle en IPV6.&lt;br /&gt;
[[Fichier:TerminauxECEAI Vallee.png|vignette|570x570px]]&lt;br /&gt;
&lt;br /&gt;
=== Vidéo ===&lt;br /&gt;
Image de l'écran capturé dans la vidéo : [[:Fichier:DemoVideo.mp4|DemoVideo.mp4]]&lt;br /&gt;
&lt;br /&gt;
[[:Fichier:TerminauxECEAI Vallee.png|TerminauxECEAI Vallee.png]][[Fichier:DemoVideo.mp4|vignette]]On constate : Si les données reçues ne contiennent pas 1024 données avant le \n, alors ces données ne sont pas transmises car non exploitables par les modèles de la RPi/VM. On obtient tout de même l'estimation de la STM32.&lt;br /&gt;
&lt;br /&gt;
Comme montré sur la vidéo, on constate que lorsqu'il n'y a aucun mouvement, les estimations sont bonnes.&lt;br /&gt;
&lt;br /&gt;
Pour les trois tests de gauche à droite, les estimations sont bonnes.&lt;br /&gt;
&lt;br /&gt;
Pour les trois tests de droite à gauche, les estimations sont bonnes, à l'exception de la dernière estimation donnée par la RPi et par la VM (vu que les modèles sont les mêmes et qu'ils utilisent les mêmes données à ce moment) : cela est du aux 70% de précision observés lors des tests.&lt;br /&gt;
&lt;br /&gt;
==  Annexe ==&lt;br /&gt;
Tous les codes rendus en annexe sont dans leur version finale et ont été utilisés au cours du projet.&lt;br /&gt;
&lt;br /&gt;
=== Codes externes ayant servis à l'entraînement ===&lt;br /&gt;
Les fichiers de type data ou test ont été réalisés en lisant le port série et en insérant directement les données dans le fichier texte à condition que les données ne soient pas corrompues. &lt;br /&gt;
&lt;br /&gt;
mlpAlgo.py : programme permettant de générer un modèle utilisant l'algorithme MLP &amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
#Import mlp model&lt;br /&gt;
from sklearn import neural_network&lt;br /&gt;
from sklearn import metrics&lt;br /&gt;
import joblib&lt;br /&gt;
&lt;br /&gt;
GtoD_path = 'data_GtoD.txt'&lt;br /&gt;
DtoG_path = 'data_DtoG.txt'&lt;br /&gt;
GtoD_test_path = 'test_GtoD.txt'&lt;br /&gt;
DtoG_test_path = 'test_DtoG.txt'&lt;br /&gt;
rien_path = 'data_rien.txt'&lt;br /&gt;
rien_test_path = 'test_rien.txt'&lt;br /&gt;
&lt;br /&gt;
GtoD_train = []&lt;br /&gt;
DtoG_train = []&lt;br /&gt;
GtoD_target = []&lt;br /&gt;
DtoG_target = []&lt;br /&gt;
rien_train = []&lt;br /&gt;
rien_target = []&lt;br /&gt;
test = []&lt;br /&gt;
data = []&lt;br /&gt;
targets = []&lt;br /&gt;
target_test = []&lt;br /&gt;
&lt;br /&gt;
def ReadAndFill(nom_fichier, target_tab, target_int, taille_sous_liste=1024):&lt;br /&gt;
    try:&lt;br /&gt;
        # Ouverture du fichier en mode lecture&lt;br /&gt;
        with open(nom_fichier, 'r') as fichier:&lt;br /&gt;
            # Lecture du contenu du fichier ligne par ligne&lt;br /&gt;
            lignes = fichier.readlines()&lt;br /&gt;
&lt;br /&gt;
            # Pour chaque ligne, conversion en liste d'entiers&lt;br /&gt;
            tableau = [[int(nombre) for nombre in ligne.split()] for ligne in lignes]&lt;br /&gt;
            tableau_filtre = [sous_liste for sous_liste in tableau if len(sous_liste) == taille_sous_liste]&lt;br /&gt;
            target_tab = len(tableau_filtre) * [target_int]&lt;br /&gt;
&lt;br /&gt;
        return tableau_filtre, target_tab&lt;br /&gt;
    &lt;br /&gt;
    except FileNotFoundError:&lt;br /&gt;
        print(f&amp;quot;Le fichier {nom_fichier} n'a pas été trouvé.&amp;quot;)&lt;br /&gt;
        return []&lt;br /&gt;
    except Exception as e:&lt;br /&gt;
        print(f&amp;quot;Une erreur s'est produite : {e}&amp;quot;)&lt;br /&gt;
        return []&lt;br /&gt;
&lt;br /&gt;
# Exemple d'utilisation&lt;br /&gt;
GtoD_train, GtoD_target = ReadAndFill(GtoD_path, GtoD_target, 2)&lt;br /&gt;
DtoG_train, DtoG_target = ReadAndFill(DtoG_path, DtoG_target, 1)&lt;br /&gt;
rien_train, rien_target = ReadAndFill(rien_path, rien_target, 0)&lt;br /&gt;
data = GtoD_train + DtoG_train + rien_train&lt;br /&gt;
targets = GtoD_target + DtoG_target + rien_target&lt;br /&gt;
&lt;br /&gt;
#Create a svm Classifier&lt;br /&gt;
clf = neural_network.MLPClassifier(max_iter=5000000)&lt;br /&gt;
&lt;br /&gt;
#Train the model using the training sets&lt;br /&gt;
clf.fit(data, targets)&lt;br /&gt;
joblib.dump(clf, 'modele_mlp2.pkl')&lt;br /&gt;
&lt;br /&gt;
test, target_test = ReadAndFill(GtoD_test_path, target_test, 2)&lt;br /&gt;
&lt;br /&gt;
#Predict the response for test dataset&lt;br /&gt;
pred = clf.predict(test)&lt;br /&gt;
print(pred)&lt;br /&gt;
# Model Accuracy: how often is the classifier correct?&lt;br /&gt;
print(&amp;quot;Fichier de test actuel :&amp;quot;,GtoD_test_path)&lt;br /&gt;
print(&amp;quot;Accuracy:&amp;quot;,metrics.accuracy_score(target_test, pred))&lt;br /&gt;
&lt;br /&gt;
test, target_test = ReadAndFill(DtoG_test_path, target_test, 1)&lt;br /&gt;
&lt;br /&gt;
#Predict the response for test dataset&lt;br /&gt;
pred = clf.predict(test)&lt;br /&gt;
print(pred)&lt;br /&gt;
# Model Accuracy: how often is the classifier correct?&lt;br /&gt;
print(&amp;quot;Fichier de test actuel :&amp;quot;,DtoG_test_path)&lt;br /&gt;
print(&amp;quot;Accuracy:&amp;quot;,metrics.accuracy_score(target_test, pred))&lt;br /&gt;
&lt;br /&gt;
test, target_test = ReadAndFill(rien_test_path, target_test, 0)&lt;br /&gt;
&lt;br /&gt;
#Predict the response for test dataset&lt;br /&gt;
pred = clf.predict(test)&lt;br /&gt;
print(pred)&lt;br /&gt;
# Model Accuracy: how often is the classifier correct?&lt;br /&gt;
print(&amp;quot;Fichier de test actuel :&amp;quot;,rien_path)&lt;br /&gt;
print(&amp;quot;Accuracy:&amp;quot;,metrics.accuracy_score(target_test, pred))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;mlpPredic.py : Code similaire servant à tester de charger un modèle créé et sauvegardé auparavant &amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
#Import mlp model&lt;br /&gt;
from sklearn import neural_network&lt;br /&gt;
from sklearn import metrics&lt;br /&gt;
import joblib&lt;br /&gt;
&lt;br /&gt;
GtoD_test_path = 'test_GtoD.txt'&lt;br /&gt;
DtoG_test_path = 'test_DtoG.txt'&lt;br /&gt;
rien_test_path = 'test_rien.txt'&lt;br /&gt;
&lt;br /&gt;
test = []&lt;br /&gt;
data = []&lt;br /&gt;
targets = []&lt;br /&gt;
target_test = []&lt;br /&gt;
&lt;br /&gt;
def ReadAndFill(nom_fichier, target_tab, target_int, taille_sous_liste=1024):&lt;br /&gt;
    try:&lt;br /&gt;
        # Ouverture du fichier en mode lecture&lt;br /&gt;
        with open(nom_fichier, 'r') as fichier:&lt;br /&gt;
            # Lecture du contenu du fichier ligne par ligne&lt;br /&gt;
            lignes = fichier.readlines()&lt;br /&gt;
&lt;br /&gt;
            # Pour chaque ligne, conversion en liste d'entiers&lt;br /&gt;
            tableau = [[int(nombre) for nombre in ligne.split()] for ligne in lignes]&lt;br /&gt;
            tableau_filtre = [sous_liste for sous_liste in tableau if len(sous_liste) == taille_sous_liste]&lt;br /&gt;
            target_tab = len(tableau_filtre) * [target_int]&lt;br /&gt;
&lt;br /&gt;
        return tableau_filtre, target_tab&lt;br /&gt;
    &lt;br /&gt;
    except FileNotFoundError:&lt;br /&gt;
        print(f&amp;quot;Le fichier {nom_fichier} n'a pas été trouvé.&amp;quot;)&lt;br /&gt;
        return []&lt;br /&gt;
    except Exception as e:&lt;br /&gt;
        print(f&amp;quot;Une erreur s'est produite : {e}&amp;quot;)&lt;br /&gt;
        return []&lt;br /&gt;
&lt;br /&gt;
#Create a svm Classifier&lt;br /&gt;
clf = joblib.load('modele_mlp.pkl')&lt;br /&gt;
&lt;br /&gt;
test, target_test = ReadAndFill(GtoD_test_path, target_test, 2)&lt;br /&gt;
&lt;br /&gt;
#Predict the response for test dataset&lt;br /&gt;
pred = clf.predict(test)&lt;br /&gt;
print(pred)&lt;br /&gt;
# Model Accuracy: how often is the classifier correct?&lt;br /&gt;
print(&amp;quot;Fichier de test actuel :&amp;quot;,GtoD_test_path)&lt;br /&gt;
print(&amp;quot;Accuracy:&amp;quot;,metrics.accuracy_score(target_test, pred))&lt;br /&gt;
&lt;br /&gt;
test, target_test = ReadAndFill(DtoG_test_path, target_test, 1)&lt;br /&gt;
&lt;br /&gt;
#Predict the response for test dataset&lt;br /&gt;
pred = clf.predict(test)&lt;br /&gt;
print(pred)&lt;br /&gt;
# Model Accuracy: how often is the classifier correct?&lt;br /&gt;
print(&amp;quot;Fichier de test actuel :&amp;quot;,DtoG_test_path)&lt;br /&gt;
print(&amp;quot;Accuracy:&amp;quot;,metrics.accuracy_score(target_test, pred))&lt;br /&gt;
&lt;br /&gt;
test, target_test = ReadAndFill(rien_test_path, target_test, 0)&lt;br /&gt;
&lt;br /&gt;
#Predict the response for test dataset&lt;br /&gt;
pred = clf.predict(test)&lt;br /&gt;
print(pred)&lt;br /&gt;
# Model Accuracy: how often is the classifier correct?&lt;br /&gt;
print(&amp;quot;Fichier de test actuel :&amp;quot;,rien_test_path)&lt;br /&gt;
print(&amp;quot;Accuracy:&amp;quot;,metrics.accuracy_score(target_test, pred))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Codes internes à la STM ===&lt;br /&gt;
app_tof.c : Code du process. Acquisition des données des 64 capteurs, 16 fois, envoi en temps réel des données et stockage temporaire des données pour faire une estimation avec le modèle interne à la stm32. Une fois les 1024 données récupérées, print d'un \n pour que &amp;quot;serial.readline()&amp;quot; des commandes python se termine.&lt;br /&gt;
&lt;br /&gt;
Envoi de l'estimation après 1024 données.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
static void MX_53L5A1_SimpleRanging_Process(void)&lt;br /&gt;
{&lt;br /&gt;
  uint32_t Id;&lt;br /&gt;
  int8_t compteur = 0;&lt;br /&gt;
  uint8_t zones_per_line;&lt;br /&gt;
&lt;br /&gt;
  VL53L5A1_RANGING_SENSOR_ReadID(VL53L5A1_DEV_CENTER, &amp;amp;Id);&lt;br /&gt;
  VL53L5A1_RANGING_SENSOR_GetCapabilities(VL53L5A1_DEV_CENTER, &amp;amp;Cap);&lt;br /&gt;
&lt;br /&gt;
  Profile.RangingProfile = RS_PROFILE_8x8_CONTINUOUS;&lt;br /&gt;
  Profile.TimingBudget = TIMING_BUDGET; /* 5 ms &amp;lt; TimingBudget &amp;lt; 100 ms */&lt;br /&gt;
  Profile.Frequency = RANGING_FREQUENCY; /* Ranging frequency Hz (shall be consistent with TimingBudget value) */&lt;br /&gt;
  Profile.EnableAmbient = 0; /* Enable: 1, Disable: 0 */&lt;br /&gt;
  Profile.EnableSignal = 0; /* Enable: 1, Disable: 0 */&lt;br /&gt;
&lt;br /&gt;
  uint16_t id_class = 0;&lt;br /&gt;
  float input_user_buffer[DATA_INPUT_USER * AXIS_NUMBER]; // Buffer of input values&lt;br /&gt;
  float output_class_buffer[CLASS_NUMBER];&lt;br /&gt;
  zones_per_line = ((Profile.RangingProfile == RS_PROFILE_8x8_AUTONOMOUS) ||&lt;br /&gt;
         (Profile.RangingProfile == RS_PROFILE_8x8_CONTINUOUS)) ? 8 : 4;&lt;br /&gt;
  enum neai_state error_code = neai_classification_init(knowledge);&lt;br /&gt;
  if (error_code != NEAI_OK)&lt;br /&gt;
  {&lt;br /&gt;
		printf(&amp;quot;Erreur lib \n&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  /* set the profile if different from default one */&lt;br /&gt;
  VL53L5A1_RANGING_SENSOR_ConfigProfile(VL53L5A1_DEV_CENTER, &amp;amp;Profile);&lt;br /&gt;
&lt;br /&gt;
  status = VL53L5A1_RANGING_SENSOR_Start(VL53L5A1_DEV_CENTER, RS_MODE_BLOCKING_CONTINUOUS);&lt;br /&gt;
&lt;br /&gt;
  if (status != BSP_ERROR_NONE)&lt;br /&gt;
  {&lt;br /&gt;
    printf(&amp;quot;VL53L5A1_RANGING_SENSOR_Start failed\n&amp;quot;);&lt;br /&gt;
    while (1);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  while (1)&lt;br /&gt;
  {&lt;br /&gt;
    /* polling mode */&lt;br /&gt;
    status = VL53L5A1_RANGING_SENSOR_GetDistance(VL53L5A1_DEV_CENTER, &amp;amp;Result);&lt;br /&gt;
    int sous_buffer[DATA_INPUT_USER];&lt;br /&gt;
&lt;br /&gt;
    if (status == BSP_ERROR_NONE)&lt;br /&gt;
    {&lt;br /&gt;
      print_result(&amp;amp;Result, sous_buffer);&lt;br /&gt;
      //afficher_tableau(sous_buffer, DATA_INPUT_USER);&lt;br /&gt;
      fill_buffer(input_user_buffer, sous_buffer, compteur);&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    if (compteur == 15)&lt;br /&gt;
    {&lt;br /&gt;
    	//printf(&amp;quot;Class number :%d Data user input : %d axis : %d multiply : %d&amp;quot;,CLASS_NUMBER, DATA_INPUT_USER, AXIS_NUMBER, AXIS_NUMBER*DATA_INPUT_USER);&lt;br /&gt;
        neai_classification(input_user_buffer, output_class_buffer, &amp;amp;id_class);&lt;br /&gt;
    	//afficher_tableau(input_user_buffer, DATA_INPUT_USER*AXIS_NUMBER);&lt;br /&gt;
    	printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
    	printf(&amp;quot;%s\n&amp;quot;,id2class[id_class]);&lt;br /&gt;
    	compteur = 0;&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
    	compteur++;//printf(&amp;quot;Compteur = %d&amp;quot;,compteur);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (com_has_data())&lt;br /&gt;
    {&lt;br /&gt;
      handle_cmd(get_key());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    HAL_Delay(POLLING_PERIOD);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static void print_result(RANGING_SENSOR_Result_t *Result, int sous_buffer[DATA_INPUT_USER])&lt;br /&gt;
{&lt;br /&gt;
  int8_t j;&lt;br /&gt;
  int8_t k;&lt;br /&gt;
  int8_t l;&lt;br /&gt;
  int8_t buffer_position = 0;&lt;br /&gt;
  int8_t total_values = 0;&lt;br /&gt;
  uint8_t zones_per_line;&lt;br /&gt;
  zones_per_line = ((Profile.RangingProfile == RS_PROFILE_8x8_AUTONOMOUS) ||&lt;br /&gt;
         (Profile.RangingProfile == RS_PROFILE_8x8_CONTINUOUS)) ? 8 : 4;&lt;br /&gt;
&lt;br /&gt;
  for (j = 0; j &amp;lt; Result-&amp;gt;NumberOfZones; j += zones_per_line)&lt;br /&gt;
  {&lt;br /&gt;
    for (l = 0; l &amp;lt; RANGING_SENSOR_NB_TARGET_PER_ZONE; l++)&lt;br /&gt;
    {&lt;br /&gt;
      /* Print distance and status */&lt;br /&gt;
      for (k = (zones_per_line - 1); k &amp;gt;= 0; k--)&lt;br /&gt;
      {&lt;br /&gt;
        if (Result-&amp;gt;ZoneResult[j+k].NumberOfTargets &amp;gt; 0)&lt;br /&gt;
        {&lt;br /&gt;
          printf(&amp;quot;%d &amp;quot;,(int)Result-&amp;gt;ZoneResult[j+k].Distance[l]);&lt;br /&gt;
          sous_buffer[buffer_position] = (int)Result-&amp;gt;ZoneResult[j+k].Distance[l];&lt;br /&gt;
          buffer_position++;&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
          printf(&amp;quot;%d &amp;quot;, '10');&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  //printf(&amp;quot;total : %d &amp;quot;,total_values);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Codes internes à la Raspberry pi ===&lt;br /&gt;
GestionData.py : Lis le port série, stocke les données, effectue une estimation du mouvement, affiche l'estimation provenant de la STM32 et envoie les données brutes à la VM via TCP&lt;br /&gt;
&lt;br /&gt;
COM3 pour les test depuis la machine windows,  ACM0 pour l'application finale sur la raspberry&lt;br /&gt;
&lt;br /&gt;
IPV6 de la VM laissée en commentaire&amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
import serial&lt;br /&gt;
import datetime&lt;br /&gt;
import csv&lt;br /&gt;
import socket&lt;br /&gt;
import joblib&lt;br /&gt;
import requests&lt;br /&gt;
import struct&lt;br /&gt;
&lt;br /&gt;
port = 'COM3'#'/dev/ttyACM0'&lt;br /&gt;
baudrate = 460800&lt;br /&gt;
ser = serial.Serial(port, baudrate)&lt;br /&gt;
&lt;br /&gt;
csv_filename = 'donnees_raspberry.txt'&lt;br /&gt;
max_lines = 200&lt;br /&gt;
clf = joblib.load('modele_mlp.pkl')&lt;br /&gt;
server_address = '2001:861:3541:4260:c69f:9d4:ccf5:7673'#'2001:660:4401:6050:216:3eff:febc:550c'&lt;br /&gt;
server_port = 12345&lt;br /&gt;
classes = [&amp;quot;Aucune presence&amp;quot;, &amp;quot;Mouvement de droite a gauche&amp;quot;,&amp;quot;Mouvement de gauche a droite&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
def DataToTab(ligne, taille_sous_liste=1024):&lt;br /&gt;
     tableau = [int(nombre) for nombre in ligne.split()]&lt;br /&gt;
     if (len(tableau)!=taille_sous_liste):&lt;br /&gt;
         return tableau, 1&lt;br /&gt;
     return tableau, 0&lt;br /&gt;
&lt;br /&gt;
with open(csv_filename, 'w', newline='') as csv_file:&lt;br /&gt;
    csv_writer = csv.writer(csv_file)&lt;br /&gt;
    line_count = 0&lt;br /&gt;
    client_socket = socket.socket(socket.AF_INET6,socket.SOCK_STREAM)&lt;br /&gt;
    client_socket.connect((server_address, server_port))&lt;br /&gt;
    try:&lt;br /&gt;
        while line_count &amp;lt; max_lines:&lt;br /&gt;
            data = ser.readline().decode('utf-8').strip()&lt;br /&gt;
            #print(&amp;quot;Ligne : &amp;quot;, line_count,&amp;quot;\n&amp;quot;)&lt;br /&gt;
            timestamp = datetime.datetime.now().strftime('%H:%M:%S')&lt;br /&gt;
            #print(f&amp;quot;{timestamp} - Données lues: {data}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
            headers = {'Content-type': 'text/plain'}&lt;br /&gt;
            body = f&amp;quot;{timestamp} - Données lues: {data}&amp;quot;&lt;br /&gt;
            tableau, error = DataToTab(data)&lt;br /&gt;
            if error == 1:&lt;br /&gt;
                print(&amp;quot;Taille de tableau non conforme&amp;quot;)&lt;br /&gt;
            else:&lt;br /&gt;
                pred = clf.predict([tableau])&lt;br /&gt;
                print(&amp;quot;Classe identifiee sur la Raspberry:&amp;quot;, classes[pred[0]])&lt;br /&gt;
                try:&lt;br /&gt;
                    donnees_brutes = struct.pack('!{}i'.format(len(tableau)), *tableau)&lt;br /&gt;
                    client_socket.sendall(donnees_brutes)&lt;br /&gt;
                except Exception as e:&lt;br /&gt;
                    print(f&amp;quot;Erreur : {e}&amp;quot;)&lt;br /&gt;
            csv_writer.writerow([data])&lt;br /&gt;
            &lt;br /&gt;
            classe = ser.readline().decode('utf-8').strip()&lt;br /&gt;
            print(&amp;quot;Classe identifiee par la STM:&amp;quot;, classe);&lt;br /&gt;
            line_count += 1&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    except KeyboardInterrupt:&lt;br /&gt;
        pass&lt;br /&gt;
    &lt;br /&gt;
    finally:&lt;br /&gt;
        client_socket.close()&lt;br /&gt;
        ser.close()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Codes internes à la VM (présents en réalité sur la machine personnelle) ===&lt;br /&gt;
server_tcp.py : Ecoute sur le port donné, reçois les données brutes, les stocke, et estime le mouvement effectué&amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
import socket&lt;br /&gt;
import struct&lt;br /&gt;
import csv&lt;br /&gt;
import joblib&lt;br /&gt;
import datetime&lt;br /&gt;
packet_size = 1024&lt;br /&gt;
&lt;br /&gt;
classes = [&amp;quot;Aucune presence&amp;quot;, &amp;quot;Mouvement de droite a gauche&amp;quot;,&amp;quot;Mouvement de gauche a droite&amp;quot;]&lt;br /&gt;
csv_filename = 'donnees_recues.txt'&lt;br /&gt;
max_lines = 200&lt;br /&gt;
clf = joblib.load('modele_mlp.pkl')&lt;br /&gt;
&lt;br /&gt;
def start_tcp_server(ip, port):&lt;br /&gt;
    with open(csv_filename, 'w', newline='') as csv_file:&lt;br /&gt;
        csv_writer = csv.writer(csv_file)&lt;br /&gt;
        server_socket = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)&lt;br /&gt;
        server_socket.bind((ip, port))&lt;br /&gt;
        server_socket.listen(1)&lt;br /&gt;
        print(f&amp;quot;Serveur tcp en ecoute sur {ip}:{port}&amp;quot;)&lt;br /&gt;
        client_socket, client_address = server_socket.accept()&lt;br /&gt;
        line_count = 0&lt;br /&gt;
        try:&lt;br /&gt;
            while line_count &amp;lt; max_lines:&lt;br /&gt;
                donnees_brutes = client_socket.recv(packet_size * 4)&lt;br /&gt;
                liste_entiers = list(struct.unpack('!{}i'.format(packet_size), donnees_brutes))&lt;br /&gt;
                #print(&amp;quot;Recu :&amp;quot;, liste_entiers)&lt;br /&gt;
                csv_writer.writerow(liste_entiers)&lt;br /&gt;
                pred = clf.predict([liste_entiers])&lt;br /&gt;
                timestamp = datetime.datetime.now().strftime('%H:%M:%S')&lt;br /&gt;
                print(f&amp;quot;{timestamp}&amp;quot;)&lt;br /&gt;
                print(&amp;quot;Classe identifiee sur la VM:&amp;quot;, classes[pred[0]])&lt;br /&gt;
                line_count+=1&lt;br /&gt;
        except KeyboardInterrupt:&lt;br /&gt;
            pass&lt;br /&gt;
        finally:&lt;br /&gt;
            client_socket.close&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    server_ip = '2001:861:5642:4610:46fb:e35c:a75d:2b74'&lt;br /&gt;
    server_port = 12345&lt;br /&gt;
    start_tcp_server(server_ip, server_port)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Fvallee</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/ValleeSellali&amp;diff=4748</id>
		<title>SE5 ECEAI/eceai 2023/2024/ValleeSellali</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/ValleeSellali&amp;diff=4748"/>
		<updated>2024-01-28T13:17:52Z</updated>

		<summary type="html">&lt;p&gt;Fvallee : Mise en page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Groupe Vallée-Sellali&lt;br /&gt;
&lt;br /&gt;
== Séance n°1 ==&lt;br /&gt;
Machine virtuelle créée sur chassiron :&lt;br /&gt;
&lt;br /&gt;
Hostname       :  ValSel&lt;br /&gt;
&lt;br /&gt;
Distribution    :  bookworm&lt;br /&gt;
&lt;br /&gt;
Stockage  : 10G&lt;br /&gt;
&lt;br /&gt;
Mémoire vive : 1G&lt;br /&gt;
&lt;br /&gt;
Mot de passe habituel&lt;br /&gt;
&lt;br /&gt;
Les fichiers /etc/network/interfaces, /etc/resolv.conf et /etc/apt/sources.list ont été modifiés comme demandés.&lt;br /&gt;
&lt;br /&gt;
Raspberry 4 :&lt;br /&gt;
&lt;br /&gt;
Communication via le port série possible&lt;br /&gt;
&lt;br /&gt;
Login : valsel Pwd : pasglop&lt;br /&gt;
&lt;br /&gt;
STM32F401RE : Nanoedge et IDE installés, conception d'un code pour tester le capteur en cours&lt;br /&gt;
&lt;br /&gt;
== Séance n°2 (18/12/2023) ==&lt;br /&gt;
Raspberry connectée au WiFi SE5&lt;br /&gt;
&lt;br /&gt;
Connexion ipv6 possible entre la VM et la raspberry&lt;br /&gt;
&lt;br /&gt;
Données du capteur lues et envoyées au port série&lt;br /&gt;
&lt;br /&gt;
Création d'un programme python client à destination de la raspberry qui : lit le port série, stocke les données reçues, envoie les données reçues en http vers le &amp;quot;serveur&amp;quot; présent sur la VM&lt;br /&gt;
&lt;br /&gt;
Création d'un programme python serveur à destination de la VM qui reçoit et stocke les données&lt;br /&gt;
&lt;br /&gt;
== Séance 3 (19/12/2023) ==&lt;br /&gt;
Création des datasets : main fermée et main ouverte (Une ligne = 16 * 16 données, environ 30 lignes par fichier)&lt;br /&gt;
&lt;br /&gt;
Choix de garder les capteurs en 4x4 pour un compromis vitesse de création des datasets/temps d'entrainement du modèle/efficacité du capteur de mouvement.&lt;br /&gt;
&lt;br /&gt;
Entrainement du modèle avec les datasets sur NanoEdge&lt;br /&gt;
&lt;br /&gt;
==  Séance 4 (20/12/2023) ==&lt;br /&gt;
Création de nouveaux datasets et de fichiers de tests : (100 lignes de 16 * 16 données)&lt;br /&gt;
&lt;br /&gt;
Création d'un script Python utilisant la bibliothèque sklearn pour implémenter un algorithme de classification SVM, à destination de la Raspberry et de la VM&lt;br /&gt;
&lt;br /&gt;
Le choix de main ouverte/main fermée se questionne, on utilise pas l'aspect mouvement que permet les algorithmes.&lt;br /&gt;
&lt;br /&gt;
Les algorithmes donnent un bon résultat avec une précision proche de 70%. La communication entre la VM et la zabeth sur laquelle on teste les fichiers pythons fonctionne.&lt;br /&gt;
&lt;br /&gt;
Du microcontrôleur, on reçoit les données brutes et l'estimation de l'état de la main. Le fichier python sur la zabeth, à destination future de la raspberry, reçoit ces données via le port série, les stocke dans un fichier txt, fait une estimation de l'état de la main, et envoie les données brutes à la VM en utilisant TCP/IP avec l'adresse IPV6 de la VM.&lt;br /&gt;
&lt;br /&gt;
La VM reçoit les données mais ne les traite pas encore.&lt;br /&gt;
&lt;br /&gt;
== Travail hors des séances et rendu final ==&lt;br /&gt;
&lt;br /&gt;
=== Ajouts ===&lt;br /&gt;
Extension du programme sur la STM aux 64 capteurs.&lt;br /&gt;
&lt;br /&gt;
Nouveau choix de test qui prend en compte les mouvements.&lt;br /&gt;
&lt;br /&gt;
Création de nouveaux datasets adaptés : lignes de 64 * 16 données, une ligne correspond à une itération du mouvement, environ 170 lignes par datasets pour une prise en compte de plusieurs cas&lt;br /&gt;
&lt;br /&gt;
(passage rapide, passage lent, hauteurs différentes). (Utilisation du code annexe GestionData sans la communication TCP pour la création des fichiers)&lt;br /&gt;
&lt;br /&gt;
Les mouvements sont : &lt;br /&gt;
&lt;br /&gt;
- Mouvement de gauche à droite&lt;br /&gt;
&lt;br /&gt;
- Mouvement de droite à gauche&lt;br /&gt;
&lt;br /&gt;
- Aucune présence&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir tester les modèles résultant de ces datasets, 3 fichiers de tests sont créés contenant chacun une trentaine d'itérations du mouvement.&lt;br /&gt;
&lt;br /&gt;
Avec Nanoedge, entraînement d'un nouveau modèle à destination de la STM. Le modèle le plus efficace avec nos fichiers de tests sont, contrairement aux premières séances, un modèle MLP (multilayer&lt;br /&gt;
&lt;br /&gt;
perceptron). Résultats avec nos fichiers de tests : précision de 90%. &lt;br /&gt;
&lt;br /&gt;
Intégration de la bibliothèque libneai.a créée par Nanoedge dans le projet STM et adaptation du code de la STM pour y intégrer l'estimation à partir des données des capteurs. (Annexe app_tof.c)&lt;br /&gt;
&lt;br /&gt;
En effet, les modèles SVM ne semblent pas adaptés à nos datasets =&amp;gt; Adaptation du code python de la raspberry pour utiliser lui aussi un modèle MLP, ce qui est plus efficace. (entraînement du modèle avec le programme mlpAlgo.py présent en annexe)&lt;br /&gt;
&lt;br /&gt;
Modèle résultant avec comme input les fichiers de tests : 70% de précision sur Droite à gauche, 68% de gauche à droite, 100% si aucune présence.&lt;br /&gt;
&lt;br /&gt;
Intégration du code GestionData.py dans la raspberry ainsi que du modèle créé par mlpAlgo.py (uniquement l'output)&lt;br /&gt;
&lt;br /&gt;
=== Réseau ===&lt;br /&gt;
- La STM32 envoie les données brutes + l'estimation du mouvement issue de son modèle intégré, par le port série (ap_tof.c disponible en annexe)&lt;br /&gt;
&lt;br /&gt;
- La Raspberry Pi reçoit ces données brutes, les stocke dans un fichier texte, estime le mouvement effectué, et affiche l'estimation en plus de celle de la STM. Ensuite, les données brutes sont transmises à la VM par TCP/IP en IPV6, à la condition que 1024 données soient présentes à chaque lecture. Si ce n'est pas le cas, les données &amp;quot;corrompues&amp;quot; ne sont pas transmises puisqu'inexploitables. (Voir GestionData.py en annexe)&lt;br /&gt;
&lt;br /&gt;
- La VM reçoit les données par paquet de 1024 entiers, stocke les données dans un fichier txt, et fait une estimation du mouvement en utilisant le même modèle que celui présent dans la raspberry pi.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Lors des tests, nous avons constaté que la communication TCP ne semblait pas permise depuis un ordinateur externe au réseau des zabeths vers la VM : le ping est possible, mais la communication ne semble pas. Nous avons donc fait le choix d'utiliser un ordinateur personnel pour montrer l'efficacité du projet : le fonctionnement est similaire, les données sont envoyées sur la machine personnelle en IPV6.&lt;br /&gt;
[[Fichier:TerminauxECEAI Vallee.png|vignette|570x570px]]&lt;br /&gt;
&lt;br /&gt;
=== Vidéo ===&lt;br /&gt;
Image de l'écran capturé dans la vidéo : [[:Fichier:DemoVideo.mp4|DemoVideo.mp4]]&lt;br /&gt;
&lt;br /&gt;
[[:Fichier:TerminauxECEAI Vallee.png|TerminauxECEAI Vallee.png]][[Fichier:DemoVideo.mp4|vignette]]On constate : Si les données reçues ne contiennent pas 1024 données avant le \n, alors ces données ne sont pas transmises car non exploitables par les modèles de la RPi/VM. On obtient tout de même l'estimation de la STM32.&lt;br /&gt;
&lt;br /&gt;
Comme montré sur la vidéo, on constate que lorsqu'il n'y a aucun mouvement, les estimations sont bonnes.&lt;br /&gt;
&lt;br /&gt;
Pour les trois tests de gauche à droite, les estimations sont bonnes.&lt;br /&gt;
&lt;br /&gt;
Pour les trois tests de droite à gauche, les estimations sont bonnes, à l'exception de la dernière estimation donnée par la RPi et par la VM (vu que les modèles sont les mêmes et qu'ils utilisent les mêmes données à ce moment) : cela est du aux 70% de précision observés lors des tests.&lt;br /&gt;
&lt;br /&gt;
==  Annexe ==&lt;br /&gt;
Tous les codes rendus en annexe sont dans leur version finale et ont été utilisés au cours du projet.&lt;br /&gt;
&lt;br /&gt;
=== Codes externes ayant servis à l'entraînement ===&lt;br /&gt;
Les fichiers de type data ou test ont été réalisés en lisant le port série et en insérant directement les données dans le fichier texte à condition que les données ne soient pas corrompues. &lt;br /&gt;
&lt;br /&gt;
mlpAlgo.py : programme permettant de générer un modèle utilisant l'algorithme MLP &amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
#Import mlp model&lt;br /&gt;
from sklearn import neural_network&lt;br /&gt;
from sklearn import metrics&lt;br /&gt;
import joblib&lt;br /&gt;
&lt;br /&gt;
GtoD_path = 'data_GtoD.txt'&lt;br /&gt;
DtoG_path = 'data_DtoG.txt'&lt;br /&gt;
GtoD_test_path = 'test_GtoD.txt'&lt;br /&gt;
DtoG_test_path = 'test_DtoG.txt'&lt;br /&gt;
rien_path = 'data_rien.txt'&lt;br /&gt;
rien_test_path = 'test_rien.txt'&lt;br /&gt;
&lt;br /&gt;
GtoD_train = []&lt;br /&gt;
DtoG_train = []&lt;br /&gt;
GtoD_target = []&lt;br /&gt;
DtoG_target = []&lt;br /&gt;
rien_train = []&lt;br /&gt;
rien_target = []&lt;br /&gt;
test = []&lt;br /&gt;
data = []&lt;br /&gt;
targets = []&lt;br /&gt;
target_test = []&lt;br /&gt;
&lt;br /&gt;
def ReadAndFill(nom_fichier, target_tab, target_int, taille_sous_liste=1024):&lt;br /&gt;
    try:&lt;br /&gt;
        # Ouverture du fichier en mode lecture&lt;br /&gt;
        with open(nom_fichier, 'r') as fichier:&lt;br /&gt;
            # Lecture du contenu du fichier ligne par ligne&lt;br /&gt;
            lignes = fichier.readlines()&lt;br /&gt;
&lt;br /&gt;
            # Pour chaque ligne, conversion en liste d'entiers&lt;br /&gt;
            tableau = [[int(nombre) for nombre in ligne.split()] for ligne in lignes]&lt;br /&gt;
            tableau_filtre = [sous_liste for sous_liste in tableau if len(sous_liste) == taille_sous_liste]&lt;br /&gt;
            target_tab = len(tableau_filtre) * [target_int]&lt;br /&gt;
&lt;br /&gt;
        return tableau_filtre, target_tab&lt;br /&gt;
    &lt;br /&gt;
    except FileNotFoundError:&lt;br /&gt;
        print(f&amp;quot;Le fichier {nom_fichier} n'a pas été trouvé.&amp;quot;)&lt;br /&gt;
        return []&lt;br /&gt;
    except Exception as e:&lt;br /&gt;
        print(f&amp;quot;Une erreur s'est produite : {e}&amp;quot;)&lt;br /&gt;
        return []&lt;br /&gt;
&lt;br /&gt;
# Exemple d'utilisation&lt;br /&gt;
GtoD_train, GtoD_target = ReadAndFill(GtoD_path, GtoD_target, 2)&lt;br /&gt;
DtoG_train, DtoG_target = ReadAndFill(DtoG_path, DtoG_target, 1)&lt;br /&gt;
rien_train, rien_target = ReadAndFill(rien_path, rien_target, 0)&lt;br /&gt;
data = GtoD_train + DtoG_train + rien_train&lt;br /&gt;
targets = GtoD_target + DtoG_target + rien_target&lt;br /&gt;
&lt;br /&gt;
#Create a svm Classifier&lt;br /&gt;
clf = neural_network.MLPClassifier(max_iter=5000000)&lt;br /&gt;
&lt;br /&gt;
#Train the model using the training sets&lt;br /&gt;
clf.fit(data, targets)&lt;br /&gt;
joblib.dump(clf, 'modele_mlp2.pkl')&lt;br /&gt;
&lt;br /&gt;
test, target_test = ReadAndFill(GtoD_test_path, target_test, 2)&lt;br /&gt;
&lt;br /&gt;
#Predict the response for test dataset&lt;br /&gt;
pred = clf.predict(test)&lt;br /&gt;
print(pred)&lt;br /&gt;
# Model Accuracy: how often is the classifier correct?&lt;br /&gt;
print(&amp;quot;Fichier de test actuel :&amp;quot;,GtoD_test_path)&lt;br /&gt;
print(&amp;quot;Accuracy:&amp;quot;,metrics.accuracy_score(target_test, pred))&lt;br /&gt;
&lt;br /&gt;
test, target_test = ReadAndFill(DtoG_test_path, target_test, 1)&lt;br /&gt;
&lt;br /&gt;
#Predict the response for test dataset&lt;br /&gt;
pred = clf.predict(test)&lt;br /&gt;
print(pred)&lt;br /&gt;
# Model Accuracy: how often is the classifier correct?&lt;br /&gt;
print(&amp;quot;Fichier de test actuel :&amp;quot;,DtoG_test_path)&lt;br /&gt;
print(&amp;quot;Accuracy:&amp;quot;,metrics.accuracy_score(target_test, pred))&lt;br /&gt;
&lt;br /&gt;
test, target_test = ReadAndFill(rien_test_path, target_test, 0)&lt;br /&gt;
&lt;br /&gt;
#Predict the response for test dataset&lt;br /&gt;
pred = clf.predict(test)&lt;br /&gt;
print(pred)&lt;br /&gt;
# Model Accuracy: how often is the classifier correct?&lt;br /&gt;
print(&amp;quot;Fichier de test actuel :&amp;quot;,rien_path)&lt;br /&gt;
print(&amp;quot;Accuracy:&amp;quot;,metrics.accuracy_score(target_test, pred))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;mlpPredic.py : Code similaire servant à tester de charger un modèle créé et sauvegardé auparavant &amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
#Import mlp model&lt;br /&gt;
from sklearn import neural_network&lt;br /&gt;
from sklearn import metrics&lt;br /&gt;
import joblib&lt;br /&gt;
&lt;br /&gt;
GtoD_test_path = 'test_GtoD.txt'&lt;br /&gt;
DtoG_test_path = 'test_DtoG.txt'&lt;br /&gt;
rien_test_path = 'test_rien.txt'&lt;br /&gt;
&lt;br /&gt;
test = []&lt;br /&gt;
data = []&lt;br /&gt;
targets = []&lt;br /&gt;
target_test = []&lt;br /&gt;
&lt;br /&gt;
def ReadAndFill(nom_fichier, target_tab, target_int, taille_sous_liste=1024):&lt;br /&gt;
    try:&lt;br /&gt;
        # Ouverture du fichier en mode lecture&lt;br /&gt;
        with open(nom_fichier, 'r') as fichier:&lt;br /&gt;
            # Lecture du contenu du fichier ligne par ligne&lt;br /&gt;
            lignes = fichier.readlines()&lt;br /&gt;
&lt;br /&gt;
            # Pour chaque ligne, conversion en liste d'entiers&lt;br /&gt;
            tableau = [[int(nombre) for nombre in ligne.split()] for ligne in lignes]&lt;br /&gt;
            tableau_filtre = [sous_liste for sous_liste in tableau if len(sous_liste) == taille_sous_liste]&lt;br /&gt;
            target_tab = len(tableau_filtre) * [target_int]&lt;br /&gt;
&lt;br /&gt;
        return tableau_filtre, target_tab&lt;br /&gt;
    &lt;br /&gt;
    except FileNotFoundError:&lt;br /&gt;
        print(f&amp;quot;Le fichier {nom_fichier} n'a pas été trouvé.&amp;quot;)&lt;br /&gt;
        return []&lt;br /&gt;
    except Exception as e:&lt;br /&gt;
        print(f&amp;quot;Une erreur s'est produite : {e}&amp;quot;)&lt;br /&gt;
        return []&lt;br /&gt;
&lt;br /&gt;
#Create a svm Classifier&lt;br /&gt;
clf = joblib.load('modele_mlp.pkl')&lt;br /&gt;
&lt;br /&gt;
test, target_test = ReadAndFill(GtoD_test_path, target_test, 2)&lt;br /&gt;
&lt;br /&gt;
#Predict the response for test dataset&lt;br /&gt;
pred = clf.predict(test)&lt;br /&gt;
print(pred)&lt;br /&gt;
# Model Accuracy: how often is the classifier correct?&lt;br /&gt;
print(&amp;quot;Fichier de test actuel :&amp;quot;,GtoD_test_path)&lt;br /&gt;
print(&amp;quot;Accuracy:&amp;quot;,metrics.accuracy_score(target_test, pred))&lt;br /&gt;
&lt;br /&gt;
test, target_test = ReadAndFill(DtoG_test_path, target_test, 1)&lt;br /&gt;
&lt;br /&gt;
#Predict the response for test dataset&lt;br /&gt;
pred = clf.predict(test)&lt;br /&gt;
print(pred)&lt;br /&gt;
# Model Accuracy: how often is the classifier correct?&lt;br /&gt;
print(&amp;quot;Fichier de test actuel :&amp;quot;,DtoG_test_path)&lt;br /&gt;
print(&amp;quot;Accuracy:&amp;quot;,metrics.accuracy_score(target_test, pred))&lt;br /&gt;
&lt;br /&gt;
test, target_test = ReadAndFill(rien_test_path, target_test, 0)&lt;br /&gt;
&lt;br /&gt;
#Predict the response for test dataset&lt;br /&gt;
pred = clf.predict(test)&lt;br /&gt;
print(pred)&lt;br /&gt;
# Model Accuracy: how often is the classifier correct?&lt;br /&gt;
print(&amp;quot;Fichier de test actuel :&amp;quot;,rien_test_path)&lt;br /&gt;
print(&amp;quot;Accuracy:&amp;quot;,metrics.accuracy_score(target_test, pred))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Codes internes à la STM ===&lt;br /&gt;
app_tof.c : Code du process. Acquisition des données des 64 capteurs, 16 fois, envoi en temps réel des données et stockage temporaire des données pour faire une estimation avec le modèle interne à la stm32. Une fois les 1024 données récupérées, print d'un \n pour que &amp;quot;serial.readline()&amp;quot; des commandes python se termine.&lt;br /&gt;
&lt;br /&gt;
Envoi de l'estimation après 1024 données.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
static void MX_53L5A1_SimpleRanging_Process(void)&lt;br /&gt;
{&lt;br /&gt;
  uint32_t Id;&lt;br /&gt;
  int8_t compteur = 0;&lt;br /&gt;
  uint8_t zones_per_line;&lt;br /&gt;
&lt;br /&gt;
  VL53L5A1_RANGING_SENSOR_ReadID(VL53L5A1_DEV_CENTER, &amp;amp;Id);&lt;br /&gt;
  VL53L5A1_RANGING_SENSOR_GetCapabilities(VL53L5A1_DEV_CENTER, &amp;amp;Cap);&lt;br /&gt;
&lt;br /&gt;
  Profile.RangingProfile = RS_PROFILE_8x8_CONTINUOUS;&lt;br /&gt;
  Profile.TimingBudget = TIMING_BUDGET; /* 5 ms &amp;lt; TimingBudget &amp;lt; 100 ms */&lt;br /&gt;
  Profile.Frequency = RANGING_FREQUENCY; /* Ranging frequency Hz (shall be consistent with TimingBudget value) */&lt;br /&gt;
  Profile.EnableAmbient = 0; /* Enable: 1, Disable: 0 */&lt;br /&gt;
  Profile.EnableSignal = 0; /* Enable: 1, Disable: 0 */&lt;br /&gt;
&lt;br /&gt;
  uint16_t id_class = 0;&lt;br /&gt;
  float input_user_buffer[DATA_INPUT_USER * AXIS_NUMBER]; // Buffer of input values&lt;br /&gt;
  float output_class_buffer[CLASS_NUMBER];&lt;br /&gt;
  zones_per_line = ((Profile.RangingProfile == RS_PROFILE_8x8_AUTONOMOUS) ||&lt;br /&gt;
         (Profile.RangingProfile == RS_PROFILE_8x8_CONTINUOUS)) ? 8 : 4;&lt;br /&gt;
  enum neai_state error_code = neai_classification_init(knowledge);&lt;br /&gt;
  if (error_code != NEAI_OK)&lt;br /&gt;
  {&lt;br /&gt;
		printf(&amp;quot;Erreur lib \n&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  /* set the profile if different from default one */&lt;br /&gt;
  VL53L5A1_RANGING_SENSOR_ConfigProfile(VL53L5A1_DEV_CENTER, &amp;amp;Profile);&lt;br /&gt;
&lt;br /&gt;
  status = VL53L5A1_RANGING_SENSOR_Start(VL53L5A1_DEV_CENTER, RS_MODE_BLOCKING_CONTINUOUS);&lt;br /&gt;
&lt;br /&gt;
  if (status != BSP_ERROR_NONE)&lt;br /&gt;
  {&lt;br /&gt;
    printf(&amp;quot;VL53L5A1_RANGING_SENSOR_Start failed\n&amp;quot;);&lt;br /&gt;
    while (1);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  while (1)&lt;br /&gt;
  {&lt;br /&gt;
    /* polling mode */&lt;br /&gt;
    status = VL53L5A1_RANGING_SENSOR_GetDistance(VL53L5A1_DEV_CENTER, &amp;amp;Result);&lt;br /&gt;
    int sous_buffer[DATA_INPUT_USER];&lt;br /&gt;
&lt;br /&gt;
    if (status == BSP_ERROR_NONE)&lt;br /&gt;
    {&lt;br /&gt;
      print_result(&amp;amp;Result, sous_buffer);&lt;br /&gt;
      //afficher_tableau(sous_buffer, DATA_INPUT_USER);&lt;br /&gt;
      fill_buffer(input_user_buffer, sous_buffer, compteur);&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    if (compteur == 15)&lt;br /&gt;
    {&lt;br /&gt;
    	//printf(&amp;quot;Class number :%d Data user input : %d axis : %d multiply : %d&amp;quot;,CLASS_NUMBER, DATA_INPUT_USER, AXIS_NUMBER, AXIS_NUMBER*DATA_INPUT_USER);&lt;br /&gt;
        neai_classification(input_user_buffer, output_class_buffer, &amp;amp;id_class);&lt;br /&gt;
    	//afficher_tableau(input_user_buffer, DATA_INPUT_USER*AXIS_NUMBER);&lt;br /&gt;
    	printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
    	printf(&amp;quot;%s\n&amp;quot;,id2class[id_class]);&lt;br /&gt;
    	compteur = 0;&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
    	compteur++;//printf(&amp;quot;Compteur = %d&amp;quot;,compteur);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (com_has_data())&lt;br /&gt;
    {&lt;br /&gt;
      handle_cmd(get_key());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    HAL_Delay(POLLING_PERIOD);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static void print_result(RANGING_SENSOR_Result_t *Result, int sous_buffer[DATA_INPUT_USER])&lt;br /&gt;
{&lt;br /&gt;
  int8_t j;&lt;br /&gt;
  int8_t k;&lt;br /&gt;
  int8_t l;&lt;br /&gt;
  int8_t buffer_position = 0;&lt;br /&gt;
  int8_t total_values = 0;&lt;br /&gt;
  uint8_t zones_per_line;&lt;br /&gt;
  zones_per_line = ((Profile.RangingProfile == RS_PROFILE_8x8_AUTONOMOUS) ||&lt;br /&gt;
         (Profile.RangingProfile == RS_PROFILE_8x8_CONTINUOUS)) ? 8 : 4;&lt;br /&gt;
&lt;br /&gt;
  for (j = 0; j &amp;lt; Result-&amp;gt;NumberOfZones; j += zones_per_line)&lt;br /&gt;
  {&lt;br /&gt;
    for (l = 0; l &amp;lt; RANGING_SENSOR_NB_TARGET_PER_ZONE; l++)&lt;br /&gt;
    {&lt;br /&gt;
      /* Print distance and status */&lt;br /&gt;
      for (k = (zones_per_line - 1); k &amp;gt;= 0; k--)&lt;br /&gt;
      {&lt;br /&gt;
        if (Result-&amp;gt;ZoneResult[j+k].NumberOfTargets &amp;gt; 0)&lt;br /&gt;
        {&lt;br /&gt;
          printf(&amp;quot;%d &amp;quot;,(int)Result-&amp;gt;ZoneResult[j+k].Distance[l]);&lt;br /&gt;
          sous_buffer[buffer_position] = (int)Result-&amp;gt;ZoneResult[j+k].Distance[l];&lt;br /&gt;
          buffer_position++;&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
          printf(&amp;quot;%d &amp;quot;, '10');&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  //printf(&amp;quot;total : %d &amp;quot;,total_values);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Codes internes à la Raspberry pi ===&lt;br /&gt;
GestionData.py : Lis le port série, stocke les données, effectue une estimation du mouvement, affiche l'estimation provenant de la STM32 et envoie les données brutes à la VM via TCP&lt;br /&gt;
&lt;br /&gt;
COM3 pour les test depuis la machine windows,  ACM0 pour l'application finale sur la raspberry&lt;br /&gt;
&lt;br /&gt;
IPV6 de la VM laissée en commentaire&amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
import serial&lt;br /&gt;
import datetime&lt;br /&gt;
import csv&lt;br /&gt;
import socket&lt;br /&gt;
import joblib&lt;br /&gt;
import requests&lt;br /&gt;
import struct&lt;br /&gt;
&lt;br /&gt;
port = 'COM3'#'/dev/ttyACM0'&lt;br /&gt;
baudrate = 460800&lt;br /&gt;
ser = serial.Serial(port, baudrate)&lt;br /&gt;
&lt;br /&gt;
csv_filename = 'donnees_raspberry.txt'&lt;br /&gt;
max_lines = 200&lt;br /&gt;
clf = joblib.load('modele_mlp.pkl')&lt;br /&gt;
server_address = '2001:861:3541:4260:c69f:9d4:ccf5:7673'#'2001:660:4401:6050:216:3eff:febc:550c'&lt;br /&gt;
server_port = 12345&lt;br /&gt;
classes = [&amp;quot;Aucune presence&amp;quot;, &amp;quot;Mouvement de droite a gauche&amp;quot;,&amp;quot;Mouvement de gauche a droite&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
def DataToTab(ligne, taille_sous_liste=1024):&lt;br /&gt;
     tableau = [int(nombre) for nombre in ligne.split()]&lt;br /&gt;
     if (len(tableau)!=taille_sous_liste):&lt;br /&gt;
         return tableau, 1&lt;br /&gt;
     return tableau, 0&lt;br /&gt;
&lt;br /&gt;
with open(csv_filename, 'w', newline='') as csv_file:&lt;br /&gt;
    csv_writer = csv.writer(csv_file)&lt;br /&gt;
    line_count = 0&lt;br /&gt;
    client_socket = socket.socket(socket.AF_INET6,socket.SOCK_STREAM)&lt;br /&gt;
    client_socket.connect((server_address, server_port))&lt;br /&gt;
    try:&lt;br /&gt;
        while line_count &amp;lt; max_lines:&lt;br /&gt;
            data = ser.readline().decode('utf-8').strip()&lt;br /&gt;
            #print(&amp;quot;Ligne : &amp;quot;, line_count,&amp;quot;\n&amp;quot;)&lt;br /&gt;
            timestamp = datetime.datetime.now().strftime('%H:%M:%S')&lt;br /&gt;
            #print(f&amp;quot;{timestamp} - Données lues: {data}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
            headers = {'Content-type': 'text/plain'}&lt;br /&gt;
            body = f&amp;quot;{timestamp} - Données lues: {data}&amp;quot;&lt;br /&gt;
            tableau, error = DataToTab(data)&lt;br /&gt;
            if error == 1:&lt;br /&gt;
                print(&amp;quot;Taille de tableau non conforme&amp;quot;)&lt;br /&gt;
            else:&lt;br /&gt;
                pred = clf.predict([tableau])&lt;br /&gt;
                print(&amp;quot;Classe identifiee sur la Raspberry:&amp;quot;, classes[pred[0]])&lt;br /&gt;
                try:&lt;br /&gt;
                    donnees_brutes = struct.pack('!{}i'.format(len(tableau)), *tableau)&lt;br /&gt;
                    client_socket.sendall(donnees_brutes)&lt;br /&gt;
                except Exception as e:&lt;br /&gt;
                    print(f&amp;quot;Erreur : {e}&amp;quot;)&lt;br /&gt;
            csv_writer.writerow([data])&lt;br /&gt;
            &lt;br /&gt;
            classe = ser.readline().decode('utf-8').strip()&lt;br /&gt;
            print(&amp;quot;Classe identifiee par la STM:&amp;quot;, classe);&lt;br /&gt;
            line_count += 1&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    except KeyboardInterrupt:&lt;br /&gt;
        pass&lt;br /&gt;
    &lt;br /&gt;
    finally:&lt;br /&gt;
        client_socket.close()&lt;br /&gt;
        ser.close()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Codes internes à la VM (présents en réalité sur la machine personnelle) ===&lt;br /&gt;
server_tcp.py : Ecoute sur le port donné, reçois les données brutes, les stocke, et estime le mouvement effectué&amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
import socket&lt;br /&gt;
import struct&lt;br /&gt;
import csv&lt;br /&gt;
import joblib&lt;br /&gt;
import datetime&lt;br /&gt;
packet_size = 1024&lt;br /&gt;
&lt;br /&gt;
classes = [&amp;quot;Aucune presence&amp;quot;, &amp;quot;Mouvement de droite a gauche&amp;quot;,&amp;quot;Mouvement de gauche a droite&amp;quot;]&lt;br /&gt;
csv_filename = 'donnees_recues.txt'&lt;br /&gt;
max_lines = 200&lt;br /&gt;
clf = joblib.load('modele_mlp.pkl')&lt;br /&gt;
&lt;br /&gt;
def start_tcp_server(ip, port):&lt;br /&gt;
    with open(csv_filename, 'w', newline='') as csv_file:&lt;br /&gt;
        csv_writer = csv.writer(csv_file)&lt;br /&gt;
        server_socket = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)&lt;br /&gt;
        server_socket.bind((ip, port))&lt;br /&gt;
        server_socket.listen(1)&lt;br /&gt;
        print(f&amp;quot;Serveur tcp en ecoute sur {ip}:{port}&amp;quot;)&lt;br /&gt;
        client_socket, client_address = server_socket.accept()&lt;br /&gt;
        line_count = 0&lt;br /&gt;
        try:&lt;br /&gt;
            while line_count &amp;lt; max_lines:&lt;br /&gt;
                donnees_brutes = client_socket.recv(packet_size * 4)&lt;br /&gt;
                liste_entiers = list(struct.unpack('!{}i'.format(packet_size), donnees_brutes))&lt;br /&gt;
                #print(&amp;quot;Recu :&amp;quot;, liste_entiers)&lt;br /&gt;
                csv_writer.writerow(liste_entiers)&lt;br /&gt;
                pred = clf.predict([liste_entiers])&lt;br /&gt;
                timestamp = datetime.datetime.now().strftime('%H:%M:%S')&lt;br /&gt;
                print(f&amp;quot;{timestamp}&amp;quot;)&lt;br /&gt;
                print(&amp;quot;Classe identifiee sur la VM:&amp;quot;, classes[pred[0]])&lt;br /&gt;
                line_count+=1&lt;br /&gt;
        except KeyboardInterrupt:&lt;br /&gt;
            pass&lt;br /&gt;
        finally:&lt;br /&gt;
            client_socket.close&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    server_ip = '2001:861:5642:4610:46fb:e35c:a75d:2b74'&lt;br /&gt;
    server_port = 12345&lt;br /&gt;
    start_tcp_server(server_ip, server_port)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Fvallee</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/ValleeSellali&amp;diff=4747</id>
		<title>SE5 ECEAI/eceai 2023/2024/ValleeSellali</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/ValleeSellali&amp;diff=4747"/>
		<updated>2024-01-28T13:17:16Z</updated>

		<summary type="html">&lt;p&gt;Fvallee : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Groupe Vallée-Sellali&lt;br /&gt;
&lt;br /&gt;
== Séance n°1 ==&lt;br /&gt;
Machine virtuelle créée sur chassiron :&lt;br /&gt;
&lt;br /&gt;
Hostname       :  ValSel&lt;br /&gt;
&lt;br /&gt;
Distribution    :  bookworm&lt;br /&gt;
&lt;br /&gt;
Stockage  : 10G&lt;br /&gt;
&lt;br /&gt;
Mémoire vive : 1G&lt;br /&gt;
&lt;br /&gt;
Mot de passe habituel&lt;br /&gt;
&lt;br /&gt;
Les fichiers /etc/network/interfaces, /etc/resolv.conf et /etc/apt/sources.list ont été modifiés comme demandés.&lt;br /&gt;
&lt;br /&gt;
Raspberry 4 :&lt;br /&gt;
&lt;br /&gt;
Communication via le port série possible&lt;br /&gt;
&lt;br /&gt;
Login : valsel Pwd : pasglop&lt;br /&gt;
&lt;br /&gt;
STM32F401RE : Nanoedge et IDE installés, conception d'un code pour tester le capteur en cours&lt;br /&gt;
&lt;br /&gt;
== Séance n°2 (18/12/2023) ==&lt;br /&gt;
Raspberry connectée au WiFi SE5&lt;br /&gt;
&lt;br /&gt;
Connexion ipv6 possible entre la VM et la raspberry&lt;br /&gt;
&lt;br /&gt;
Données du capteur lues et envoyées au port série&lt;br /&gt;
&lt;br /&gt;
Création d'un programme python client à destination de la raspberry qui : lit le port série, stocke les données reçues, envoie les données reçues en http vers le &amp;quot;serveur&amp;quot; présent sur la VM&lt;br /&gt;
&lt;br /&gt;
Création d'un programme python serveur à destination de la VM qui reçoit et stocke les données&lt;br /&gt;
&lt;br /&gt;
== Séance 3 (19/12/2023) ==&lt;br /&gt;
Création des datasets : main fermée et main ouverte (Une ligne = 16 * 16 données, environ 30 lignes par fichier)&lt;br /&gt;
&lt;br /&gt;
Choix de garder les capteurs en 4x4 pour un compromis vitesse de création des datasets/temps d'entrainement du modèle/efficacité du capteur de mouvement.&lt;br /&gt;
&lt;br /&gt;
Entrainement du modèle avec les datasets sur NanoEdge&lt;br /&gt;
&lt;br /&gt;
==  Séance 4 (20/12/2023) ==&lt;br /&gt;
Création de nouveaux datasets et de fichiers de tests : (100 lignes de 16 * 16 données)&lt;br /&gt;
&lt;br /&gt;
Création d'un script Python utilisant la bibliothèque sklearn pour implémenter un algorithme de classification SVM, à destination de la Raspberry et de la VM&lt;br /&gt;
&lt;br /&gt;
Le choix de main ouverte/main fermée se questionne, on utilise pas l'aspect mouvement que permet les algorithmes.&lt;br /&gt;
&lt;br /&gt;
Les algorithmes donnent un bon résultat avec une précision proche de 70%. La communication entre la VM et la zabeth sur laquelle on teste les fichiers pythons fonctionne.&lt;br /&gt;
&lt;br /&gt;
Du microcontrôleur, on reçoit les données brutes et l'estimation de l'état de la main. Le fichier python sur la zabeth, à destination future de la raspberry, reçoit ces données via le port série, les stocke dans un fichier txt, fait une estimation de l'état de la main, et envoie les données brutes à la VM en utilisant TCP/IP avec l'adresse IPV6 de la VM.&lt;br /&gt;
&lt;br /&gt;
La VM reçoit les données mais ne les traite pas encore.&lt;br /&gt;
&lt;br /&gt;
== Travail hors des séances et rendu final ==&lt;br /&gt;
&lt;br /&gt;
=== Ajouts ===&lt;br /&gt;
Extension du programme sur la STM aux 64 capteurs.&lt;br /&gt;
&lt;br /&gt;
Nouveau choix de test qui prend en compte les mouvements.&lt;br /&gt;
&lt;br /&gt;
Création de nouveaux datasets adaptés : lignes de 64 * 16 données, une ligne correspond à une itération du mouvement, environ 170 lignes par datasets pour une prise en compte de plusieurs cas&lt;br /&gt;
&lt;br /&gt;
(passage rapide, passage lent, hauteurs différentes). (Utilisation du code annexe GestionData sans la communication TCP pour la création des fichiers)&lt;br /&gt;
&lt;br /&gt;
Les mouvements sont : &lt;br /&gt;
&lt;br /&gt;
- Mouvement de gauche à droite&lt;br /&gt;
&lt;br /&gt;
- Mouvement de droite à gauche&lt;br /&gt;
&lt;br /&gt;
- Aucune présence&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir tester les modèles résultant de ces datasets, 3 fichiers de tests sont créés contenant chacun une trentaine d'itérations du mouvement.&lt;br /&gt;
&lt;br /&gt;
Avec Nanoedge, entraînement d'un nouveau modèle à destination de la STM. Le modèle le plus efficace avec nos fichiers de tests sont, contrairement aux premières séances, un modèle MLP (multilayer&lt;br /&gt;
&lt;br /&gt;
perceptron). Résultats avec nos fichiers de tests : précision de 90%. &lt;br /&gt;
&lt;br /&gt;
Intégration de la bibliothèque libneai.a créée par Nanoedge dans le projet STM et adaptation du code de la STM pour y intégrer l'estimation à partir des données des capteurs. (Annexe app_tof.c)&lt;br /&gt;
&lt;br /&gt;
En effet, les modèles SVM ne semblent pas adaptés à nos datasets =&amp;gt; Adaptation du code python de la raspberry pour utiliser lui aussi un modèle MLP, ce qui est plus efficace. (entraînement du modèle avec le programme mlpAlgo.py présent en annexe)&lt;br /&gt;
&lt;br /&gt;
Modèle résultant avec comme input les fichiers de tests : 70% de précision sur Droite à gauche, 68% de gauche à droite, 100% si aucune présence.&lt;br /&gt;
&lt;br /&gt;
Intégration du code GestionData.py dans la raspberry ainsi que du modèle créé par mlpAlgo.py (uniquement l'output)&lt;br /&gt;
&lt;br /&gt;
==== Réseau ====&lt;br /&gt;
- La STM32 envoie les données brutes + l'estimation du mouvement issue de son modèle intégré, par le port série (ap_tof.c disponible en annexe)&lt;br /&gt;
&lt;br /&gt;
- La Raspberry Pi reçoit ces données brutes, les stocke dans un fichier texte, estime le mouvement effectué, et affiche l'estimation en plus de celle de la STM. Ensuite, les données brutes sont transmises à la VM par TCP/IP en IPV6, à la condition que 1024 données soient présentes à chaque lecture. Si ce n'est pas le cas, les données &amp;quot;corrompues&amp;quot; ne sont pas transmises puisqu'inexploitables. (Voir GestionData.py en annexe)&lt;br /&gt;
&lt;br /&gt;
- La VM reçoit les données par paquet de 1024 entiers, stocke les données dans un fichier txt, et fait une estimation du mouvement en utilisant le même modèle que celui présent dans la raspberry pi.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Lors des tests, nous avons constaté que la communication TCP ne semblait pas permise depuis un ordinateur externe au réseau des zabeths vers la VM : le ping est possible, mais la communication ne semble pas. Nous avons donc fait le choix d'utiliser un ordinateur personnel pour montrer l'efficacité du projet : le fonctionnement est similaire, les données sont envoyées sur la machine personnelle en IPV6.&lt;br /&gt;
[[Fichier:TerminauxECEAI Vallee.png|vignette|570x570px]]&lt;br /&gt;
&lt;br /&gt;
===  Vidéo : ===&lt;br /&gt;
Image de l'écran capturé dans la vidéo : [[:Fichier:DemoVideo.mp4|DemoVideo.mp4]]&lt;br /&gt;
&lt;br /&gt;
[[:Fichier:TerminauxECEAI Vallee.png|TerminauxECEAI Vallee.png]][[Fichier:DemoVideo.mp4|vignette]]On constate : Si les données reçues ne contiennent pas 1024 données avant le \n, alors ces données ne sont pas transmises car non exploitables par les modèles de la RPi/VM. On obtient tout de même l'estimation de la STM32.&lt;br /&gt;
&lt;br /&gt;
Comme montré sur la vidéo, on constate que lorsqu'il n'y a aucun mouvement, les estimations sont bonnes.&lt;br /&gt;
&lt;br /&gt;
Pour les trois tests de gauche à droite, les estimations sont bonnes.&lt;br /&gt;
&lt;br /&gt;
Pour les trois tests de droite à gauche, les estimations sont bonnes, à l'exception de la dernière estimation donnée par la RPi et par la VM (vu que les modèles sont les mêmes et qu'ils utilisent les mêmes données à ce moment) : cela est du aux 70% de précision observés lors des tests.&lt;br /&gt;
&lt;br /&gt;
==  Annexe ==&lt;br /&gt;
Tous les codes rendus en annexe sont dans leur version finale et ont été utilisés au cours du projet.&lt;br /&gt;
&lt;br /&gt;
=== Codes externes ayant servis à l'entraînement ===&lt;br /&gt;
Les fichiers de type data ou test ont été réalisés en lisant le port série et en insérant directement les données dans le fichier texte à condition que les données ne soient pas corrompues. &lt;br /&gt;
&lt;br /&gt;
mlpAlgo.py : programme permettant de générer un modèle utilisant l'algorithme MLP &amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
#Import mlp model&lt;br /&gt;
from sklearn import neural_network&lt;br /&gt;
from sklearn import metrics&lt;br /&gt;
import joblib&lt;br /&gt;
&lt;br /&gt;
GtoD_path = 'data_GtoD.txt'&lt;br /&gt;
DtoG_path = 'data_DtoG.txt'&lt;br /&gt;
GtoD_test_path = 'test_GtoD.txt'&lt;br /&gt;
DtoG_test_path = 'test_DtoG.txt'&lt;br /&gt;
rien_path = 'data_rien.txt'&lt;br /&gt;
rien_test_path = 'test_rien.txt'&lt;br /&gt;
&lt;br /&gt;
GtoD_train = []&lt;br /&gt;
DtoG_train = []&lt;br /&gt;
GtoD_target = []&lt;br /&gt;
DtoG_target = []&lt;br /&gt;
rien_train = []&lt;br /&gt;
rien_target = []&lt;br /&gt;
test = []&lt;br /&gt;
data = []&lt;br /&gt;
targets = []&lt;br /&gt;
target_test = []&lt;br /&gt;
&lt;br /&gt;
def ReadAndFill(nom_fichier, target_tab, target_int, taille_sous_liste=1024):&lt;br /&gt;
    try:&lt;br /&gt;
        # Ouverture du fichier en mode lecture&lt;br /&gt;
        with open(nom_fichier, 'r') as fichier:&lt;br /&gt;
            # Lecture du contenu du fichier ligne par ligne&lt;br /&gt;
            lignes = fichier.readlines()&lt;br /&gt;
&lt;br /&gt;
            # Pour chaque ligne, conversion en liste d'entiers&lt;br /&gt;
            tableau = [[int(nombre) for nombre in ligne.split()] for ligne in lignes]&lt;br /&gt;
            tableau_filtre = [sous_liste for sous_liste in tableau if len(sous_liste) == taille_sous_liste]&lt;br /&gt;
            target_tab = len(tableau_filtre) * [target_int]&lt;br /&gt;
&lt;br /&gt;
        return tableau_filtre, target_tab&lt;br /&gt;
    &lt;br /&gt;
    except FileNotFoundError:&lt;br /&gt;
        print(f&amp;quot;Le fichier {nom_fichier} n'a pas été trouvé.&amp;quot;)&lt;br /&gt;
        return []&lt;br /&gt;
    except Exception as e:&lt;br /&gt;
        print(f&amp;quot;Une erreur s'est produite : {e}&amp;quot;)&lt;br /&gt;
        return []&lt;br /&gt;
&lt;br /&gt;
# Exemple d'utilisation&lt;br /&gt;
GtoD_train, GtoD_target = ReadAndFill(GtoD_path, GtoD_target, 2)&lt;br /&gt;
DtoG_train, DtoG_target = ReadAndFill(DtoG_path, DtoG_target, 1)&lt;br /&gt;
rien_train, rien_target = ReadAndFill(rien_path, rien_target, 0)&lt;br /&gt;
data = GtoD_train + DtoG_train + rien_train&lt;br /&gt;
targets = GtoD_target + DtoG_target + rien_target&lt;br /&gt;
&lt;br /&gt;
#Create a svm Classifier&lt;br /&gt;
clf = neural_network.MLPClassifier(max_iter=5000000)&lt;br /&gt;
&lt;br /&gt;
#Train the model using the training sets&lt;br /&gt;
clf.fit(data, targets)&lt;br /&gt;
joblib.dump(clf, 'modele_mlp2.pkl')&lt;br /&gt;
&lt;br /&gt;
test, target_test = ReadAndFill(GtoD_test_path, target_test, 2)&lt;br /&gt;
&lt;br /&gt;
#Predict the response for test dataset&lt;br /&gt;
pred = clf.predict(test)&lt;br /&gt;
print(pred)&lt;br /&gt;
# Model Accuracy: how often is the classifier correct?&lt;br /&gt;
print(&amp;quot;Fichier de test actuel :&amp;quot;,GtoD_test_path)&lt;br /&gt;
print(&amp;quot;Accuracy:&amp;quot;,metrics.accuracy_score(target_test, pred))&lt;br /&gt;
&lt;br /&gt;
test, target_test = ReadAndFill(DtoG_test_path, target_test, 1)&lt;br /&gt;
&lt;br /&gt;
#Predict the response for test dataset&lt;br /&gt;
pred = clf.predict(test)&lt;br /&gt;
print(pred)&lt;br /&gt;
# Model Accuracy: how often is the classifier correct?&lt;br /&gt;
print(&amp;quot;Fichier de test actuel :&amp;quot;,DtoG_test_path)&lt;br /&gt;
print(&amp;quot;Accuracy:&amp;quot;,metrics.accuracy_score(target_test, pred))&lt;br /&gt;
&lt;br /&gt;
test, target_test = ReadAndFill(rien_test_path, target_test, 0)&lt;br /&gt;
&lt;br /&gt;
#Predict the response for test dataset&lt;br /&gt;
pred = clf.predict(test)&lt;br /&gt;
print(pred)&lt;br /&gt;
# Model Accuracy: how often is the classifier correct?&lt;br /&gt;
print(&amp;quot;Fichier de test actuel :&amp;quot;,rien_path)&lt;br /&gt;
print(&amp;quot;Accuracy:&amp;quot;,metrics.accuracy_score(target_test, pred))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;mlpPredic.py : Code similaire servant à tester de charger un modèle créé et sauvegardé auparavant &amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
#Import mlp model&lt;br /&gt;
from sklearn import neural_network&lt;br /&gt;
from sklearn import metrics&lt;br /&gt;
import joblib&lt;br /&gt;
&lt;br /&gt;
GtoD_test_path = 'test_GtoD.txt'&lt;br /&gt;
DtoG_test_path = 'test_DtoG.txt'&lt;br /&gt;
rien_test_path = 'test_rien.txt'&lt;br /&gt;
&lt;br /&gt;
test = []&lt;br /&gt;
data = []&lt;br /&gt;
targets = []&lt;br /&gt;
target_test = []&lt;br /&gt;
&lt;br /&gt;
def ReadAndFill(nom_fichier, target_tab, target_int, taille_sous_liste=1024):&lt;br /&gt;
    try:&lt;br /&gt;
        # Ouverture du fichier en mode lecture&lt;br /&gt;
        with open(nom_fichier, 'r') as fichier:&lt;br /&gt;
            # Lecture du contenu du fichier ligne par ligne&lt;br /&gt;
            lignes = fichier.readlines()&lt;br /&gt;
&lt;br /&gt;
            # Pour chaque ligne, conversion en liste d'entiers&lt;br /&gt;
            tableau = [[int(nombre) for nombre in ligne.split()] for ligne in lignes]&lt;br /&gt;
            tableau_filtre = [sous_liste for sous_liste in tableau if len(sous_liste) == taille_sous_liste]&lt;br /&gt;
            target_tab = len(tableau_filtre) * [target_int]&lt;br /&gt;
&lt;br /&gt;
        return tableau_filtre, target_tab&lt;br /&gt;
    &lt;br /&gt;
    except FileNotFoundError:&lt;br /&gt;
        print(f&amp;quot;Le fichier {nom_fichier} n'a pas été trouvé.&amp;quot;)&lt;br /&gt;
        return []&lt;br /&gt;
    except Exception as e:&lt;br /&gt;
        print(f&amp;quot;Une erreur s'est produite : {e}&amp;quot;)&lt;br /&gt;
        return []&lt;br /&gt;
&lt;br /&gt;
#Create a svm Classifier&lt;br /&gt;
clf = joblib.load('modele_mlp.pkl')&lt;br /&gt;
&lt;br /&gt;
test, target_test = ReadAndFill(GtoD_test_path, target_test, 2)&lt;br /&gt;
&lt;br /&gt;
#Predict the response for test dataset&lt;br /&gt;
pred = clf.predict(test)&lt;br /&gt;
print(pred)&lt;br /&gt;
# Model Accuracy: how often is the classifier correct?&lt;br /&gt;
print(&amp;quot;Fichier de test actuel :&amp;quot;,GtoD_test_path)&lt;br /&gt;
print(&amp;quot;Accuracy:&amp;quot;,metrics.accuracy_score(target_test, pred))&lt;br /&gt;
&lt;br /&gt;
test, target_test = ReadAndFill(DtoG_test_path, target_test, 1)&lt;br /&gt;
&lt;br /&gt;
#Predict the response for test dataset&lt;br /&gt;
pred = clf.predict(test)&lt;br /&gt;
print(pred)&lt;br /&gt;
# Model Accuracy: how often is the classifier correct?&lt;br /&gt;
print(&amp;quot;Fichier de test actuel :&amp;quot;,DtoG_test_path)&lt;br /&gt;
print(&amp;quot;Accuracy:&amp;quot;,metrics.accuracy_score(target_test, pred))&lt;br /&gt;
&lt;br /&gt;
test, target_test = ReadAndFill(rien_test_path, target_test, 0)&lt;br /&gt;
&lt;br /&gt;
#Predict the response for test dataset&lt;br /&gt;
pred = clf.predict(test)&lt;br /&gt;
print(pred)&lt;br /&gt;
# Model Accuracy: how often is the classifier correct?&lt;br /&gt;
print(&amp;quot;Fichier de test actuel :&amp;quot;,rien_test_path)&lt;br /&gt;
print(&amp;quot;Accuracy:&amp;quot;,metrics.accuracy_score(target_test, pred))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Codes internes à la STM ===&lt;br /&gt;
app_tof.c : Code du process. Acquisition des données des 64 capteurs, 16 fois, envoi en temps réel des données et stockage temporaire des données pour faire une estimation avec le modèle interne à la stm32. Une fois les 1024 données récupérées, print d'un \n pour que &amp;quot;serial.readline()&amp;quot; des commandes python se termine.&lt;br /&gt;
&lt;br /&gt;
Envoi de l'estimation après 1024 données.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
static void MX_53L5A1_SimpleRanging_Process(void)&lt;br /&gt;
{&lt;br /&gt;
  uint32_t Id;&lt;br /&gt;
  int8_t compteur = 0;&lt;br /&gt;
  uint8_t zones_per_line;&lt;br /&gt;
&lt;br /&gt;
  VL53L5A1_RANGING_SENSOR_ReadID(VL53L5A1_DEV_CENTER, &amp;amp;Id);&lt;br /&gt;
  VL53L5A1_RANGING_SENSOR_GetCapabilities(VL53L5A1_DEV_CENTER, &amp;amp;Cap);&lt;br /&gt;
&lt;br /&gt;
  Profile.RangingProfile = RS_PROFILE_8x8_CONTINUOUS;&lt;br /&gt;
  Profile.TimingBudget = TIMING_BUDGET; /* 5 ms &amp;lt; TimingBudget &amp;lt; 100 ms */&lt;br /&gt;
  Profile.Frequency = RANGING_FREQUENCY; /* Ranging frequency Hz (shall be consistent with TimingBudget value) */&lt;br /&gt;
  Profile.EnableAmbient = 0; /* Enable: 1, Disable: 0 */&lt;br /&gt;
  Profile.EnableSignal = 0; /* Enable: 1, Disable: 0 */&lt;br /&gt;
&lt;br /&gt;
  uint16_t id_class = 0;&lt;br /&gt;
  float input_user_buffer[DATA_INPUT_USER * AXIS_NUMBER]; // Buffer of input values&lt;br /&gt;
  float output_class_buffer[CLASS_NUMBER];&lt;br /&gt;
  zones_per_line = ((Profile.RangingProfile == RS_PROFILE_8x8_AUTONOMOUS) ||&lt;br /&gt;
         (Profile.RangingProfile == RS_PROFILE_8x8_CONTINUOUS)) ? 8 : 4;&lt;br /&gt;
  enum neai_state error_code = neai_classification_init(knowledge);&lt;br /&gt;
  if (error_code != NEAI_OK)&lt;br /&gt;
  {&lt;br /&gt;
		printf(&amp;quot;Erreur lib \n&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  /* set the profile if different from default one */&lt;br /&gt;
  VL53L5A1_RANGING_SENSOR_ConfigProfile(VL53L5A1_DEV_CENTER, &amp;amp;Profile);&lt;br /&gt;
&lt;br /&gt;
  status = VL53L5A1_RANGING_SENSOR_Start(VL53L5A1_DEV_CENTER, RS_MODE_BLOCKING_CONTINUOUS);&lt;br /&gt;
&lt;br /&gt;
  if (status != BSP_ERROR_NONE)&lt;br /&gt;
  {&lt;br /&gt;
    printf(&amp;quot;VL53L5A1_RANGING_SENSOR_Start failed\n&amp;quot;);&lt;br /&gt;
    while (1);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  while (1)&lt;br /&gt;
  {&lt;br /&gt;
    /* polling mode */&lt;br /&gt;
    status = VL53L5A1_RANGING_SENSOR_GetDistance(VL53L5A1_DEV_CENTER, &amp;amp;Result);&lt;br /&gt;
    int sous_buffer[DATA_INPUT_USER];&lt;br /&gt;
&lt;br /&gt;
    if (status == BSP_ERROR_NONE)&lt;br /&gt;
    {&lt;br /&gt;
      print_result(&amp;amp;Result, sous_buffer);&lt;br /&gt;
      //afficher_tableau(sous_buffer, DATA_INPUT_USER);&lt;br /&gt;
      fill_buffer(input_user_buffer, sous_buffer, compteur);&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    if (compteur == 15)&lt;br /&gt;
    {&lt;br /&gt;
    	//printf(&amp;quot;Class number :%d Data user input : %d axis : %d multiply : %d&amp;quot;,CLASS_NUMBER, DATA_INPUT_USER, AXIS_NUMBER, AXIS_NUMBER*DATA_INPUT_USER);&lt;br /&gt;
        neai_classification(input_user_buffer, output_class_buffer, &amp;amp;id_class);&lt;br /&gt;
    	//afficher_tableau(input_user_buffer, DATA_INPUT_USER*AXIS_NUMBER);&lt;br /&gt;
    	printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
    	printf(&amp;quot;%s\n&amp;quot;,id2class[id_class]);&lt;br /&gt;
    	compteur = 0;&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
    	compteur++;//printf(&amp;quot;Compteur = %d&amp;quot;,compteur);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (com_has_data())&lt;br /&gt;
    {&lt;br /&gt;
      handle_cmd(get_key());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    HAL_Delay(POLLING_PERIOD);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static void print_result(RANGING_SENSOR_Result_t *Result, int sous_buffer[DATA_INPUT_USER])&lt;br /&gt;
{&lt;br /&gt;
  int8_t j;&lt;br /&gt;
  int8_t k;&lt;br /&gt;
  int8_t l;&lt;br /&gt;
  int8_t buffer_position = 0;&lt;br /&gt;
  int8_t total_values = 0;&lt;br /&gt;
  uint8_t zones_per_line;&lt;br /&gt;
  zones_per_line = ((Profile.RangingProfile == RS_PROFILE_8x8_AUTONOMOUS) ||&lt;br /&gt;
         (Profile.RangingProfile == RS_PROFILE_8x8_CONTINUOUS)) ? 8 : 4;&lt;br /&gt;
&lt;br /&gt;
  for (j = 0; j &amp;lt; Result-&amp;gt;NumberOfZones; j += zones_per_line)&lt;br /&gt;
  {&lt;br /&gt;
    for (l = 0; l &amp;lt; RANGING_SENSOR_NB_TARGET_PER_ZONE; l++)&lt;br /&gt;
    {&lt;br /&gt;
      /* Print distance and status */&lt;br /&gt;
      for (k = (zones_per_line - 1); k &amp;gt;= 0; k--)&lt;br /&gt;
      {&lt;br /&gt;
        if (Result-&amp;gt;ZoneResult[j+k].NumberOfTargets &amp;gt; 0)&lt;br /&gt;
        {&lt;br /&gt;
          printf(&amp;quot;%d &amp;quot;,(int)Result-&amp;gt;ZoneResult[j+k].Distance[l]);&lt;br /&gt;
          sous_buffer[buffer_position] = (int)Result-&amp;gt;ZoneResult[j+k].Distance[l];&lt;br /&gt;
          buffer_position++;&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
          printf(&amp;quot;%d &amp;quot;, '10');&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  //printf(&amp;quot;total : %d &amp;quot;,total_values);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Codes internes à la Raspberry pi ===&lt;br /&gt;
GestionData.py : Lis le port série, stocke les données, effectue une estimation du mouvement, affiche l'estimation provenant de la STM32 et envoie les données brutes à la VM via TCP&lt;br /&gt;
&lt;br /&gt;
COM3 pour les test depuis la machine windows,  ACM0 pour l'application finale sur la raspberry&lt;br /&gt;
&lt;br /&gt;
IPV6 de la VM laissée en commentaire&amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
import serial&lt;br /&gt;
import datetime&lt;br /&gt;
import csv&lt;br /&gt;
import socket&lt;br /&gt;
import joblib&lt;br /&gt;
import requests&lt;br /&gt;
import struct&lt;br /&gt;
&lt;br /&gt;
port = 'COM3'#'/dev/ttyACM0'&lt;br /&gt;
baudrate = 460800&lt;br /&gt;
ser = serial.Serial(port, baudrate)&lt;br /&gt;
&lt;br /&gt;
csv_filename = 'donnees_raspberry.txt'&lt;br /&gt;
max_lines = 200&lt;br /&gt;
clf = joblib.load('modele_mlp.pkl')&lt;br /&gt;
server_address = '2001:861:3541:4260:c69f:9d4:ccf5:7673'#'2001:660:4401:6050:216:3eff:febc:550c'&lt;br /&gt;
server_port = 12345&lt;br /&gt;
classes = [&amp;quot;Aucune presence&amp;quot;, &amp;quot;Mouvement de droite a gauche&amp;quot;,&amp;quot;Mouvement de gauche a droite&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
def DataToTab(ligne, taille_sous_liste=1024):&lt;br /&gt;
     tableau = [int(nombre) for nombre in ligne.split()]&lt;br /&gt;
     if (len(tableau)!=taille_sous_liste):&lt;br /&gt;
         return tableau, 1&lt;br /&gt;
     return tableau, 0&lt;br /&gt;
&lt;br /&gt;
with open(csv_filename, 'w', newline='') as csv_file:&lt;br /&gt;
    csv_writer = csv.writer(csv_file)&lt;br /&gt;
    line_count = 0&lt;br /&gt;
    client_socket = socket.socket(socket.AF_INET6,socket.SOCK_STREAM)&lt;br /&gt;
    client_socket.connect((server_address, server_port))&lt;br /&gt;
    try:&lt;br /&gt;
        while line_count &amp;lt; max_lines:&lt;br /&gt;
            data = ser.readline().decode('utf-8').strip()&lt;br /&gt;
            #print(&amp;quot;Ligne : &amp;quot;, line_count,&amp;quot;\n&amp;quot;)&lt;br /&gt;
            timestamp = datetime.datetime.now().strftime('%H:%M:%S')&lt;br /&gt;
            #print(f&amp;quot;{timestamp} - Données lues: {data}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
            headers = {'Content-type': 'text/plain'}&lt;br /&gt;
            body = f&amp;quot;{timestamp} - Données lues: {data}&amp;quot;&lt;br /&gt;
            tableau, error = DataToTab(data)&lt;br /&gt;
            if error == 1:&lt;br /&gt;
                print(&amp;quot;Taille de tableau non conforme&amp;quot;)&lt;br /&gt;
            else:&lt;br /&gt;
                pred = clf.predict([tableau])&lt;br /&gt;
                print(&amp;quot;Classe identifiee sur la Raspberry:&amp;quot;, classes[pred[0]])&lt;br /&gt;
                try:&lt;br /&gt;
                    donnees_brutes = struct.pack('!{}i'.format(len(tableau)), *tableau)&lt;br /&gt;
                    client_socket.sendall(donnees_brutes)&lt;br /&gt;
                except Exception as e:&lt;br /&gt;
                    print(f&amp;quot;Erreur : {e}&amp;quot;)&lt;br /&gt;
            csv_writer.writerow([data])&lt;br /&gt;
            &lt;br /&gt;
            classe = ser.readline().decode('utf-8').strip()&lt;br /&gt;
            print(&amp;quot;Classe identifiee par la STM:&amp;quot;, classe);&lt;br /&gt;
            line_count += 1&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    except KeyboardInterrupt:&lt;br /&gt;
        pass&lt;br /&gt;
    &lt;br /&gt;
    finally:&lt;br /&gt;
        client_socket.close()&lt;br /&gt;
        ser.close()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Codes internes à la VM (présents en réalité sur la machine personnelle) ===&lt;br /&gt;
server_tcp.py : Ecoute sur le port donné, reçois les données brutes, les stocke, et estime le mouvement effectué&amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
import socket&lt;br /&gt;
import struct&lt;br /&gt;
import csv&lt;br /&gt;
import joblib&lt;br /&gt;
import datetime&lt;br /&gt;
packet_size = 1024&lt;br /&gt;
&lt;br /&gt;
classes = [&amp;quot;Aucune presence&amp;quot;, &amp;quot;Mouvement de droite a gauche&amp;quot;,&amp;quot;Mouvement de gauche a droite&amp;quot;]&lt;br /&gt;
csv_filename = 'donnees_recues.txt'&lt;br /&gt;
max_lines = 200&lt;br /&gt;
clf = joblib.load('modele_mlp.pkl')&lt;br /&gt;
&lt;br /&gt;
def start_tcp_server(ip, port):&lt;br /&gt;
    with open(csv_filename, 'w', newline='') as csv_file:&lt;br /&gt;
        csv_writer = csv.writer(csv_file)&lt;br /&gt;
        server_socket = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)&lt;br /&gt;
        server_socket.bind((ip, port))&lt;br /&gt;
        server_socket.listen(1)&lt;br /&gt;
        print(f&amp;quot;Serveur tcp en ecoute sur {ip}:{port}&amp;quot;)&lt;br /&gt;
        client_socket, client_address = server_socket.accept()&lt;br /&gt;
        line_count = 0&lt;br /&gt;
        try:&lt;br /&gt;
            while line_count &amp;lt; max_lines:&lt;br /&gt;
                donnees_brutes = client_socket.recv(packet_size * 4)&lt;br /&gt;
                liste_entiers = list(struct.unpack('!{}i'.format(packet_size), donnees_brutes))&lt;br /&gt;
                #print(&amp;quot;Recu :&amp;quot;, liste_entiers)&lt;br /&gt;
                csv_writer.writerow(liste_entiers)&lt;br /&gt;
                pred = clf.predict([liste_entiers])&lt;br /&gt;
                timestamp = datetime.datetime.now().strftime('%H:%M:%S')&lt;br /&gt;
                print(f&amp;quot;{timestamp}&amp;quot;)&lt;br /&gt;
                print(&amp;quot;Classe identifiee sur la VM:&amp;quot;, classes[pred[0]])&lt;br /&gt;
                line_count+=1&lt;br /&gt;
        except KeyboardInterrupt:&lt;br /&gt;
            pass&lt;br /&gt;
        finally:&lt;br /&gt;
            client_socket.close&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    server_ip = '2001:861:5642:4610:46fb:e35c:a75d:2b74'&lt;br /&gt;
    server_port = 12345&lt;br /&gt;
    start_tcp_server(server_ip, server_port)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Fvallee</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/ValleeSellali&amp;diff=4746</id>
		<title>SE5 ECEAI/eceai 2023/2024/ValleeSellali</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/ValleeSellali&amp;diff=4746"/>
		<updated>2024-01-28T13:15:16Z</updated>

		<summary type="html">&lt;p&gt;Fvallee : Explications Video&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Groupe Vallée-Sellali&lt;br /&gt;
&lt;br /&gt;
== Séance n°1: ==&lt;br /&gt;
Machine virtuelle créée sur chassiron :&lt;br /&gt;
&lt;br /&gt;
Hostname       :  ValSel&lt;br /&gt;
&lt;br /&gt;
Distribution    :  bookworm&lt;br /&gt;
&lt;br /&gt;
Stockage  : 10G&lt;br /&gt;
&lt;br /&gt;
Mémoire vive : 1G&lt;br /&gt;
&lt;br /&gt;
Mot de passe habituel&lt;br /&gt;
&lt;br /&gt;
Les fichiers /etc/network/interfaces, /etc/resolv.conf et /etc/apt/sources.list ont été modifiés comme demandés.&lt;br /&gt;
&lt;br /&gt;
Raspberry 4 :&lt;br /&gt;
&lt;br /&gt;
Communication via le port série possible&lt;br /&gt;
&lt;br /&gt;
Login : valsel Pwd : pasglop&lt;br /&gt;
&lt;br /&gt;
STM32F401RE : Nanoedge et IDE installés, conception d'un code pour tester le capteur en cours&lt;br /&gt;
&lt;br /&gt;
==  Séance n°2 (18/12/2023) : ==&lt;br /&gt;
Raspberry connectée au WiFi SE5&lt;br /&gt;
&lt;br /&gt;
Connexion ipv6 possible entre la VM et la raspberry&lt;br /&gt;
&lt;br /&gt;
Données du capteur lues et envoyées au port série&lt;br /&gt;
&lt;br /&gt;
Création d'un programme python client à destination de la raspberry qui : lit le port série, stocke les données reçues, envoie les données reçues en http vers le &amp;quot;serveur&amp;quot; présent sur la VM&lt;br /&gt;
&lt;br /&gt;
Création d'un programme python serveur à destination de la VM qui reçoit et stocke les données&lt;br /&gt;
&lt;br /&gt;
==  Séance 3 (19/12/2023) : ==&lt;br /&gt;
Création des datasets : main fermée et main ouverte (Une ligne = 16 * 16 données, environ 30 lignes par fichier)&lt;br /&gt;
&lt;br /&gt;
Choix de garder les capteurs en 4x4 pour un compromis vitesse de création des datasets/temps d'entrainement du modèle/efficacité du capteur de mouvement.&lt;br /&gt;
&lt;br /&gt;
Entrainement du modèle avec les datasets sur NanoEdge&lt;br /&gt;
&lt;br /&gt;
==  Séance 4 (20/12/2023) ==&lt;br /&gt;
Création de nouveaux datasets et de fichiers de tests : (100 lignes de 16 * 16 données)&lt;br /&gt;
&lt;br /&gt;
Création d'un script Python utilisant la bibliothèque sklearn pour implémenter un algorithme de classification SVM, à destination de la Raspberry et de la VM&lt;br /&gt;
&lt;br /&gt;
Le choix de main ouverte/main fermée se questionne, on utilise pas l'aspect mouvement que permet les algorithmes.&lt;br /&gt;
&lt;br /&gt;
Les algorithmes donnent un bon résultat avec une précision proche de 70%. La communication entre la VM et la zabeth sur laquelle on teste les fichiers pythons fonctionne.&lt;br /&gt;
&lt;br /&gt;
Du microcontrôleur, on reçoit les données brutes et l'estimation de l'état de la main. Le fichier python sur la zabeth, à destination future de la raspberry, reçoit ces données via le port série, les stocke dans un fichier txt, fait une estimation de l'état de la main, et envoie les données brutes à la VM en utilisant TCP/IP avec l'adresse IPV6 de la VM.&lt;br /&gt;
&lt;br /&gt;
La VM reçoit les données mais ne les traite pas encore.&lt;br /&gt;
&lt;br /&gt;
==  Travail hors des séances et rendu final : ==&lt;br /&gt;
Extension du programme sur la STM aux 64 capteurs.&lt;br /&gt;
&lt;br /&gt;
Nouveau choix de test qui prend en compte les mouvements.&lt;br /&gt;
&lt;br /&gt;
Création de nouveaux datasets adaptés : lignes de 64 * 16 données, une ligne correspond à une itération du mouvement, environ 170 lignes par datasets pour une prise en compte de plusieurs cas&lt;br /&gt;
&lt;br /&gt;
(passage rapide, passage lent, hauteurs différentes). (Utilisation du code annexe GestionData sans la communication TCP pour la création des fichiers)&lt;br /&gt;
&lt;br /&gt;
Les mouvements sont : &lt;br /&gt;
&lt;br /&gt;
- Mouvement de gauche à droite&lt;br /&gt;
&lt;br /&gt;
- Mouvement de droite à gauche&lt;br /&gt;
&lt;br /&gt;
- Aucune présence&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir tester les modèles résultant de ces datasets, 3 fichiers de tests sont créés contenant chacun une trentaine d'itérations du mouvement.&lt;br /&gt;
&lt;br /&gt;
Avec Nanoedge, entraînement d'un nouveau modèle à destination de la STM. Le modèle le plus efficace avec nos fichiers de tests sont, contrairement aux premières séances, un modèle MLP (multilayer&lt;br /&gt;
&lt;br /&gt;
perceptron). Résultats avec nos fichiers de tests : précision de 90%. &lt;br /&gt;
&lt;br /&gt;
Intégration de la bibliothèque libneai.a créée par Nanoedge dans le projet STM et adaptation du code de la STM pour y intégrer l'estimation à partir des données des capteurs. (Annexe app_tof.c)&lt;br /&gt;
&lt;br /&gt;
En effet, les modèles SVM ne semblent pas adaptés à nos datasets =&amp;gt; Adaptation du code python de la raspberry pour utiliser lui aussi un modèle MLP, ce qui est plus efficace. (entraînement du modèle avec le programme mlpAlgo.py présent en annexe)&lt;br /&gt;
&lt;br /&gt;
Modèle résultant avec comme input les fichiers de tests : 70% de précision sur Droite à gauche, 68% de gauche à droite, 100% si aucune présence.&lt;br /&gt;
&lt;br /&gt;
Intégration du code GestionData.py dans la raspberry ainsi que du modèle créé par mlpAlgo.py (uniquement l'output)&lt;br /&gt;
&lt;br /&gt;
==== Réseau : ====&lt;br /&gt;
- La STM32 envoie les données brutes + l'estimation du mouvement issue de son modèle intégré, par le port série (ap_tof.c disponible en annexe)&lt;br /&gt;
&lt;br /&gt;
- La Raspberry Pi reçoit ces données brutes, les stocke dans un fichier texte, estime le mouvement effectué, et affiche l'estimation en plus de celle de la STM. Ensuite, les données brutes sont transmises à la VM par TCP/IP en IPV6, à la condition que 1024 données soient présentes à chaque lecture. Si ce n'est pas le cas, les données &amp;quot;corrompues&amp;quot; ne sont pas transmises puisqu'inexploitables. (Voir GestionData.py en annexe)&lt;br /&gt;
&lt;br /&gt;
- La VM reçoit les données par paquet de 1024 entiers, stocke les données dans un fichier txt, et fait une estimation du mouvement en utilisant le même modèle que celui présent dans la raspberry pi.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Lors des tests, nous avons constaté que la communication TCP ne semblait pas permise depuis un ordinateur externe au réseau des zabeths vers la VM : le ping est possible, mais la communication ne semble pas. Nous avons donc fait le choix d'utiliser un ordinateur personnel pour montrer l'efficacité du projet : le fonctionnement est similaire, les données sont envoyées sur la machine personnelle en IPV6.&lt;br /&gt;
[[Fichier:TerminauxECEAI Vallee.png|vignette|570x570px]]&lt;br /&gt;
&lt;br /&gt;
===  Vidéo : ===&lt;br /&gt;
Image de l'écran capturé dans la vidéo : [[:Fichier:DemoVideo.mp4|DemoVideo.mp4]]&lt;br /&gt;
&lt;br /&gt;
[[:Fichier:TerminauxECEAI Vallee.png|TerminauxECEAI Vallee.png]][[Fichier:DemoVideo.mp4|vignette]]On constate : Si les données reçues ne contiennent pas 1024 données avant le \n, alors ces données ne sont pas transmises car non exploitables par les modèles de la RPi/VM. On obtient tout de même l'estimation de la STM32.&lt;br /&gt;
&lt;br /&gt;
Comme montré sur la vidéo, on constate que lorsqu'il n'y a aucun mouvement, les estimations sont bonnes.&lt;br /&gt;
&lt;br /&gt;
Pour les trois tests de gauche à droite, les estimations sont bonnes.&lt;br /&gt;
&lt;br /&gt;
Pour les trois tests de droite à gauche, les estimations sont bonnes, à l'exception de la dernière estimation donnée par la RPi et par la VM (vu que les modèles sont les mêmes et qu'ils utilisent les mêmes données à ce moment) : cela est du aux 70% de précision observés lors des tests.&lt;br /&gt;
&lt;br /&gt;
==  Annexe ==&lt;br /&gt;
Tous les codes rendus en annexe sont dans leur version finale et ont été utilisés au cours du projet.&lt;br /&gt;
&lt;br /&gt;
=== Codes externes ayant servis à l'entraînement : ===&lt;br /&gt;
Les fichiers de type data ou test ont été réalisés en lisant le port série et en insérant directement les données dans le fichier texte à condition que les données ne soient pas corrompues. &lt;br /&gt;
&lt;br /&gt;
mlpAlgo.py : programme permettant de générer un modèle utilisant l'algorithme MLP &amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
#Import mlp model&lt;br /&gt;
from sklearn import neural_network&lt;br /&gt;
from sklearn import metrics&lt;br /&gt;
import joblib&lt;br /&gt;
&lt;br /&gt;
GtoD_path = 'data_GtoD.txt'&lt;br /&gt;
DtoG_path = 'data_DtoG.txt'&lt;br /&gt;
GtoD_test_path = 'test_GtoD.txt'&lt;br /&gt;
DtoG_test_path = 'test_DtoG.txt'&lt;br /&gt;
rien_path = 'data_rien.txt'&lt;br /&gt;
rien_test_path = 'test_rien.txt'&lt;br /&gt;
&lt;br /&gt;
GtoD_train = []&lt;br /&gt;
DtoG_train = []&lt;br /&gt;
GtoD_target = []&lt;br /&gt;
DtoG_target = []&lt;br /&gt;
rien_train = []&lt;br /&gt;
rien_target = []&lt;br /&gt;
test = []&lt;br /&gt;
data = []&lt;br /&gt;
targets = []&lt;br /&gt;
target_test = []&lt;br /&gt;
&lt;br /&gt;
def ReadAndFill(nom_fichier, target_tab, target_int, taille_sous_liste=1024):&lt;br /&gt;
    try:&lt;br /&gt;
        # Ouverture du fichier en mode lecture&lt;br /&gt;
        with open(nom_fichier, 'r') as fichier:&lt;br /&gt;
            # Lecture du contenu du fichier ligne par ligne&lt;br /&gt;
            lignes = fichier.readlines()&lt;br /&gt;
&lt;br /&gt;
            # Pour chaque ligne, conversion en liste d'entiers&lt;br /&gt;
            tableau = [[int(nombre) for nombre in ligne.split()] for ligne in lignes]&lt;br /&gt;
            tableau_filtre = [sous_liste for sous_liste in tableau if len(sous_liste) == taille_sous_liste]&lt;br /&gt;
            target_tab = len(tableau_filtre) * [target_int]&lt;br /&gt;
&lt;br /&gt;
        return tableau_filtre, target_tab&lt;br /&gt;
    &lt;br /&gt;
    except FileNotFoundError:&lt;br /&gt;
        print(f&amp;quot;Le fichier {nom_fichier} n'a pas été trouvé.&amp;quot;)&lt;br /&gt;
        return []&lt;br /&gt;
    except Exception as e:&lt;br /&gt;
        print(f&amp;quot;Une erreur s'est produite : {e}&amp;quot;)&lt;br /&gt;
        return []&lt;br /&gt;
&lt;br /&gt;
# Exemple d'utilisation&lt;br /&gt;
GtoD_train, GtoD_target = ReadAndFill(GtoD_path, GtoD_target, 2)&lt;br /&gt;
DtoG_train, DtoG_target = ReadAndFill(DtoG_path, DtoG_target, 1)&lt;br /&gt;
rien_train, rien_target = ReadAndFill(rien_path, rien_target, 0)&lt;br /&gt;
data = GtoD_train + DtoG_train + rien_train&lt;br /&gt;
targets = GtoD_target + DtoG_target + rien_target&lt;br /&gt;
&lt;br /&gt;
#Create a svm Classifier&lt;br /&gt;
clf = neural_network.MLPClassifier(max_iter=5000000)&lt;br /&gt;
&lt;br /&gt;
#Train the model using the training sets&lt;br /&gt;
clf.fit(data, targets)&lt;br /&gt;
joblib.dump(clf, 'modele_mlp2.pkl')&lt;br /&gt;
&lt;br /&gt;
test, target_test = ReadAndFill(GtoD_test_path, target_test, 2)&lt;br /&gt;
&lt;br /&gt;
#Predict the response for test dataset&lt;br /&gt;
pred = clf.predict(test)&lt;br /&gt;
print(pred)&lt;br /&gt;
# Model Accuracy: how often is the classifier correct?&lt;br /&gt;
print(&amp;quot;Fichier de test actuel :&amp;quot;,GtoD_test_path)&lt;br /&gt;
print(&amp;quot;Accuracy:&amp;quot;,metrics.accuracy_score(target_test, pred))&lt;br /&gt;
&lt;br /&gt;
test, target_test = ReadAndFill(DtoG_test_path, target_test, 1)&lt;br /&gt;
&lt;br /&gt;
#Predict the response for test dataset&lt;br /&gt;
pred = clf.predict(test)&lt;br /&gt;
print(pred)&lt;br /&gt;
# Model Accuracy: how often is the classifier correct?&lt;br /&gt;
print(&amp;quot;Fichier de test actuel :&amp;quot;,DtoG_test_path)&lt;br /&gt;
print(&amp;quot;Accuracy:&amp;quot;,metrics.accuracy_score(target_test, pred))&lt;br /&gt;
&lt;br /&gt;
test, target_test = ReadAndFill(rien_test_path, target_test, 0)&lt;br /&gt;
&lt;br /&gt;
#Predict the response for test dataset&lt;br /&gt;
pred = clf.predict(test)&lt;br /&gt;
print(pred)&lt;br /&gt;
# Model Accuracy: how often is the classifier correct?&lt;br /&gt;
print(&amp;quot;Fichier de test actuel :&amp;quot;,rien_path)&lt;br /&gt;
print(&amp;quot;Accuracy:&amp;quot;,metrics.accuracy_score(target_test, pred))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;mlpPredic.py : Code similaire servant à tester de charger un modèle créé et sauvegardé auparavant &amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
#Import mlp model&lt;br /&gt;
from sklearn import neural_network&lt;br /&gt;
from sklearn import metrics&lt;br /&gt;
import joblib&lt;br /&gt;
&lt;br /&gt;
GtoD_test_path = 'test_GtoD.txt'&lt;br /&gt;
DtoG_test_path = 'test_DtoG.txt'&lt;br /&gt;
rien_test_path = 'test_rien.txt'&lt;br /&gt;
&lt;br /&gt;
test = []&lt;br /&gt;
data = []&lt;br /&gt;
targets = []&lt;br /&gt;
target_test = []&lt;br /&gt;
&lt;br /&gt;
def ReadAndFill(nom_fichier, target_tab, target_int, taille_sous_liste=1024):&lt;br /&gt;
    try:&lt;br /&gt;
        # Ouverture du fichier en mode lecture&lt;br /&gt;
        with open(nom_fichier, 'r') as fichier:&lt;br /&gt;
            # Lecture du contenu du fichier ligne par ligne&lt;br /&gt;
            lignes = fichier.readlines()&lt;br /&gt;
&lt;br /&gt;
            # Pour chaque ligne, conversion en liste d'entiers&lt;br /&gt;
            tableau = [[int(nombre) for nombre in ligne.split()] for ligne in lignes]&lt;br /&gt;
            tableau_filtre = [sous_liste for sous_liste in tableau if len(sous_liste) == taille_sous_liste]&lt;br /&gt;
            target_tab = len(tableau_filtre) * [target_int]&lt;br /&gt;
&lt;br /&gt;
        return tableau_filtre, target_tab&lt;br /&gt;
    &lt;br /&gt;
    except FileNotFoundError:&lt;br /&gt;
        print(f&amp;quot;Le fichier {nom_fichier} n'a pas été trouvé.&amp;quot;)&lt;br /&gt;
        return []&lt;br /&gt;
    except Exception as e:&lt;br /&gt;
        print(f&amp;quot;Une erreur s'est produite : {e}&amp;quot;)&lt;br /&gt;
        return []&lt;br /&gt;
&lt;br /&gt;
#Create a svm Classifier&lt;br /&gt;
clf = joblib.load('modele_mlp.pkl')&lt;br /&gt;
&lt;br /&gt;
test, target_test = ReadAndFill(GtoD_test_path, target_test, 2)&lt;br /&gt;
&lt;br /&gt;
#Predict the response for test dataset&lt;br /&gt;
pred = clf.predict(test)&lt;br /&gt;
print(pred)&lt;br /&gt;
# Model Accuracy: how often is the classifier correct?&lt;br /&gt;
print(&amp;quot;Fichier de test actuel :&amp;quot;,GtoD_test_path)&lt;br /&gt;
print(&amp;quot;Accuracy:&amp;quot;,metrics.accuracy_score(target_test, pred))&lt;br /&gt;
&lt;br /&gt;
test, target_test = ReadAndFill(DtoG_test_path, target_test, 1)&lt;br /&gt;
&lt;br /&gt;
#Predict the response for test dataset&lt;br /&gt;
pred = clf.predict(test)&lt;br /&gt;
print(pred)&lt;br /&gt;
# Model Accuracy: how often is the classifier correct?&lt;br /&gt;
print(&amp;quot;Fichier de test actuel :&amp;quot;,DtoG_test_path)&lt;br /&gt;
print(&amp;quot;Accuracy:&amp;quot;,metrics.accuracy_score(target_test, pred))&lt;br /&gt;
&lt;br /&gt;
test, target_test = ReadAndFill(rien_test_path, target_test, 0)&lt;br /&gt;
&lt;br /&gt;
#Predict the response for test dataset&lt;br /&gt;
pred = clf.predict(test)&lt;br /&gt;
print(pred)&lt;br /&gt;
# Model Accuracy: how often is the classifier correct?&lt;br /&gt;
print(&amp;quot;Fichier de test actuel :&amp;quot;,rien_test_path)&lt;br /&gt;
print(&amp;quot;Accuracy:&amp;quot;,metrics.accuracy_score(target_test, pred))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Codes internes à la STM : ===&lt;br /&gt;
app_tof.c : Code du process. Acquisition des données des 64 capteurs, 16 fois, envoi en temps réel des données et stockage temporaire des données pour faire une estimation avec le modèle interne à la stm32. Une fois les 1024 données récupérées, print d'un \n pour que &amp;quot;serial.readline()&amp;quot; des commandes python se termine.&lt;br /&gt;
&lt;br /&gt;
Envoi de l'estimation après 1024 données.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
static void MX_53L5A1_SimpleRanging_Process(void)&lt;br /&gt;
{&lt;br /&gt;
  uint32_t Id;&lt;br /&gt;
  int8_t compteur = 0;&lt;br /&gt;
  uint8_t zones_per_line;&lt;br /&gt;
&lt;br /&gt;
  VL53L5A1_RANGING_SENSOR_ReadID(VL53L5A1_DEV_CENTER, &amp;amp;Id);&lt;br /&gt;
  VL53L5A1_RANGING_SENSOR_GetCapabilities(VL53L5A1_DEV_CENTER, &amp;amp;Cap);&lt;br /&gt;
&lt;br /&gt;
  Profile.RangingProfile = RS_PROFILE_8x8_CONTINUOUS;&lt;br /&gt;
  Profile.TimingBudget = TIMING_BUDGET; /* 5 ms &amp;lt; TimingBudget &amp;lt; 100 ms */&lt;br /&gt;
  Profile.Frequency = RANGING_FREQUENCY; /* Ranging frequency Hz (shall be consistent with TimingBudget value) */&lt;br /&gt;
  Profile.EnableAmbient = 0; /* Enable: 1, Disable: 0 */&lt;br /&gt;
  Profile.EnableSignal = 0; /* Enable: 1, Disable: 0 */&lt;br /&gt;
&lt;br /&gt;
  uint16_t id_class = 0;&lt;br /&gt;
  float input_user_buffer[DATA_INPUT_USER * AXIS_NUMBER]; // Buffer of input values&lt;br /&gt;
  float output_class_buffer[CLASS_NUMBER];&lt;br /&gt;
  zones_per_line = ((Profile.RangingProfile == RS_PROFILE_8x8_AUTONOMOUS) ||&lt;br /&gt;
         (Profile.RangingProfile == RS_PROFILE_8x8_CONTINUOUS)) ? 8 : 4;&lt;br /&gt;
  enum neai_state error_code = neai_classification_init(knowledge);&lt;br /&gt;
  if (error_code != NEAI_OK)&lt;br /&gt;
  {&lt;br /&gt;
		printf(&amp;quot;Erreur lib \n&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  /* set the profile if different from default one */&lt;br /&gt;
  VL53L5A1_RANGING_SENSOR_ConfigProfile(VL53L5A1_DEV_CENTER, &amp;amp;Profile);&lt;br /&gt;
&lt;br /&gt;
  status = VL53L5A1_RANGING_SENSOR_Start(VL53L5A1_DEV_CENTER, RS_MODE_BLOCKING_CONTINUOUS);&lt;br /&gt;
&lt;br /&gt;
  if (status != BSP_ERROR_NONE)&lt;br /&gt;
  {&lt;br /&gt;
    printf(&amp;quot;VL53L5A1_RANGING_SENSOR_Start failed\n&amp;quot;);&lt;br /&gt;
    while (1);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  while (1)&lt;br /&gt;
  {&lt;br /&gt;
    /* polling mode */&lt;br /&gt;
    status = VL53L5A1_RANGING_SENSOR_GetDistance(VL53L5A1_DEV_CENTER, &amp;amp;Result);&lt;br /&gt;
    int sous_buffer[DATA_INPUT_USER];&lt;br /&gt;
&lt;br /&gt;
    if (status == BSP_ERROR_NONE)&lt;br /&gt;
    {&lt;br /&gt;
      print_result(&amp;amp;Result, sous_buffer);&lt;br /&gt;
      //afficher_tableau(sous_buffer, DATA_INPUT_USER);&lt;br /&gt;
      fill_buffer(input_user_buffer, sous_buffer, compteur);&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    if (compteur == 15)&lt;br /&gt;
    {&lt;br /&gt;
    	//printf(&amp;quot;Class number :%d Data user input : %d axis : %d multiply : %d&amp;quot;,CLASS_NUMBER, DATA_INPUT_USER, AXIS_NUMBER, AXIS_NUMBER*DATA_INPUT_USER);&lt;br /&gt;
        neai_classification(input_user_buffer, output_class_buffer, &amp;amp;id_class);&lt;br /&gt;
    	//afficher_tableau(input_user_buffer, DATA_INPUT_USER*AXIS_NUMBER);&lt;br /&gt;
    	printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
    	printf(&amp;quot;%s\n&amp;quot;,id2class[id_class]);&lt;br /&gt;
    	compteur = 0;&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
    	compteur++;//printf(&amp;quot;Compteur = %d&amp;quot;,compteur);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (com_has_data())&lt;br /&gt;
    {&lt;br /&gt;
      handle_cmd(get_key());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    HAL_Delay(POLLING_PERIOD);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static void print_result(RANGING_SENSOR_Result_t *Result, int sous_buffer[DATA_INPUT_USER])&lt;br /&gt;
{&lt;br /&gt;
  int8_t j;&lt;br /&gt;
  int8_t k;&lt;br /&gt;
  int8_t l;&lt;br /&gt;
  int8_t buffer_position = 0;&lt;br /&gt;
  int8_t total_values = 0;&lt;br /&gt;
  uint8_t zones_per_line;&lt;br /&gt;
  zones_per_line = ((Profile.RangingProfile == RS_PROFILE_8x8_AUTONOMOUS) ||&lt;br /&gt;
         (Profile.RangingProfile == RS_PROFILE_8x8_CONTINUOUS)) ? 8 : 4;&lt;br /&gt;
&lt;br /&gt;
  for (j = 0; j &amp;lt; Result-&amp;gt;NumberOfZones; j += zones_per_line)&lt;br /&gt;
  {&lt;br /&gt;
    for (l = 0; l &amp;lt; RANGING_SENSOR_NB_TARGET_PER_ZONE; l++)&lt;br /&gt;
    {&lt;br /&gt;
      /* Print distance and status */&lt;br /&gt;
      for (k = (zones_per_line - 1); k &amp;gt;= 0; k--)&lt;br /&gt;
      {&lt;br /&gt;
        if (Result-&amp;gt;ZoneResult[j+k].NumberOfTargets &amp;gt; 0)&lt;br /&gt;
        {&lt;br /&gt;
          printf(&amp;quot;%d &amp;quot;,(int)Result-&amp;gt;ZoneResult[j+k].Distance[l]);&lt;br /&gt;
          sous_buffer[buffer_position] = (int)Result-&amp;gt;ZoneResult[j+k].Distance[l];&lt;br /&gt;
          buffer_position++;&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
          printf(&amp;quot;%d &amp;quot;, '10');&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  //printf(&amp;quot;total : %d &amp;quot;,total_values);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Codes internes à la Raspberry pi : ===&lt;br /&gt;
GestionData.py : Lis le port série, stocke les données, effectue une estimation du mouvement, affiche l'estimation provenant de la STM32 et envoie les données brutes à la VM via TCP&lt;br /&gt;
&lt;br /&gt;
COM3 pour les test depuis la machine windows,  ACM0 pour l'application finale sur la raspberry&lt;br /&gt;
&lt;br /&gt;
IPV6 de la VM laissée en commentaire&amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
import serial&lt;br /&gt;
import datetime&lt;br /&gt;
import csv&lt;br /&gt;
import socket&lt;br /&gt;
import joblib&lt;br /&gt;
import requests&lt;br /&gt;
import struct&lt;br /&gt;
&lt;br /&gt;
port = 'COM3'#'/dev/ttyACM0'&lt;br /&gt;
baudrate = 460800&lt;br /&gt;
ser = serial.Serial(port, baudrate)&lt;br /&gt;
&lt;br /&gt;
csv_filename = 'donnees_raspberry.txt'&lt;br /&gt;
max_lines = 200&lt;br /&gt;
clf = joblib.load('modele_mlp.pkl')&lt;br /&gt;
server_address = '2001:861:3541:4260:c69f:9d4:ccf5:7673'#'2001:660:4401:6050:216:3eff:febc:550c'&lt;br /&gt;
server_port = 12345&lt;br /&gt;
classes = [&amp;quot;Aucune presence&amp;quot;, &amp;quot;Mouvement de droite a gauche&amp;quot;,&amp;quot;Mouvement de gauche a droite&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
def DataToTab(ligne, taille_sous_liste=1024):&lt;br /&gt;
     tableau = [int(nombre) for nombre in ligne.split()]&lt;br /&gt;
     if (len(tableau)!=taille_sous_liste):&lt;br /&gt;
         return tableau, 1&lt;br /&gt;
     return tableau, 0&lt;br /&gt;
&lt;br /&gt;
with open(csv_filename, 'w', newline='') as csv_file:&lt;br /&gt;
    csv_writer = csv.writer(csv_file)&lt;br /&gt;
    line_count = 0&lt;br /&gt;
    client_socket = socket.socket(socket.AF_INET6,socket.SOCK_STREAM)&lt;br /&gt;
    client_socket.connect((server_address, server_port))&lt;br /&gt;
    try:&lt;br /&gt;
        while line_count &amp;lt; max_lines:&lt;br /&gt;
            data = ser.readline().decode('utf-8').strip()&lt;br /&gt;
            #print(&amp;quot;Ligne : &amp;quot;, line_count,&amp;quot;\n&amp;quot;)&lt;br /&gt;
            timestamp = datetime.datetime.now().strftime('%H:%M:%S')&lt;br /&gt;
            #print(f&amp;quot;{timestamp} - Données lues: {data}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
            headers = {'Content-type': 'text/plain'}&lt;br /&gt;
            body = f&amp;quot;{timestamp} - Données lues: {data}&amp;quot;&lt;br /&gt;
            tableau, error = DataToTab(data)&lt;br /&gt;
            if error == 1:&lt;br /&gt;
                print(&amp;quot;Taille de tableau non conforme&amp;quot;)&lt;br /&gt;
            else:&lt;br /&gt;
                pred = clf.predict([tableau])&lt;br /&gt;
                print(&amp;quot;Classe identifiee sur la Raspberry:&amp;quot;, classes[pred[0]])&lt;br /&gt;
                try:&lt;br /&gt;
                    donnees_brutes = struct.pack('!{}i'.format(len(tableau)), *tableau)&lt;br /&gt;
                    client_socket.sendall(donnees_brutes)&lt;br /&gt;
                except Exception as e:&lt;br /&gt;
                    print(f&amp;quot;Erreur : {e}&amp;quot;)&lt;br /&gt;
            csv_writer.writerow([data])&lt;br /&gt;
            &lt;br /&gt;
            classe = ser.readline().decode('utf-8').strip()&lt;br /&gt;
            print(&amp;quot;Classe identifiee par la STM:&amp;quot;, classe);&lt;br /&gt;
            line_count += 1&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    except KeyboardInterrupt:&lt;br /&gt;
        pass&lt;br /&gt;
    &lt;br /&gt;
    finally:&lt;br /&gt;
        client_socket.close()&lt;br /&gt;
        ser.close()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Codes internes à la VM (présents en réalité sur la machine personnelle) : ===&lt;br /&gt;
server_tcp.py : Ecoute sur le port donné, reçois les données brutes, les stocke, et estime le mouvement effectué&amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
import socket&lt;br /&gt;
import struct&lt;br /&gt;
import csv&lt;br /&gt;
import joblib&lt;br /&gt;
import datetime&lt;br /&gt;
packet_size = 1024&lt;br /&gt;
&lt;br /&gt;
classes = [&amp;quot;Aucune presence&amp;quot;, &amp;quot;Mouvement de droite a gauche&amp;quot;,&amp;quot;Mouvement de gauche a droite&amp;quot;]&lt;br /&gt;
csv_filename = 'donnees_recues.txt'&lt;br /&gt;
max_lines = 200&lt;br /&gt;
clf = joblib.load('modele_mlp.pkl')&lt;br /&gt;
&lt;br /&gt;
def start_tcp_server(ip, port):&lt;br /&gt;
    with open(csv_filename, 'w', newline='') as csv_file:&lt;br /&gt;
        csv_writer = csv.writer(csv_file)&lt;br /&gt;
        server_socket = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)&lt;br /&gt;
        server_socket.bind((ip, port))&lt;br /&gt;
        server_socket.listen(1)&lt;br /&gt;
        print(f&amp;quot;Serveur tcp en ecoute sur {ip}:{port}&amp;quot;)&lt;br /&gt;
        client_socket, client_address = server_socket.accept()&lt;br /&gt;
        line_count = 0&lt;br /&gt;
        try:&lt;br /&gt;
            while line_count &amp;lt; max_lines:&lt;br /&gt;
                donnees_brutes = client_socket.recv(packet_size * 4)&lt;br /&gt;
                liste_entiers = list(struct.unpack('!{}i'.format(packet_size), donnees_brutes))&lt;br /&gt;
                #print(&amp;quot;Recu :&amp;quot;, liste_entiers)&lt;br /&gt;
                csv_writer.writerow(liste_entiers)&lt;br /&gt;
                pred = clf.predict([liste_entiers])&lt;br /&gt;
                timestamp = datetime.datetime.now().strftime('%H:%M:%S')&lt;br /&gt;
                print(f&amp;quot;{timestamp}&amp;quot;)&lt;br /&gt;
                print(&amp;quot;Classe identifiee sur la VM:&amp;quot;, classes[pred[0]])&lt;br /&gt;
                line_count+=1&lt;br /&gt;
        except KeyboardInterrupt:&lt;br /&gt;
            pass&lt;br /&gt;
        finally:&lt;br /&gt;
            client_socket.close&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    server_ip = '2001:861:5642:4610:46fb:e35c:a75d:2b74'&lt;br /&gt;
    server_port = 12345&lt;br /&gt;
    start_tcp_server(server_ip, server_port)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Fvallee</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/ValleeSellali&amp;diff=4745</id>
		<title>SE5 ECEAI/eceai 2023/2024/ValleeSellali</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/ValleeSellali&amp;diff=4745"/>
		<updated>2024-01-28T13:08:48Z</updated>

		<summary type="html">&lt;p&gt;Fvallee : Video+codes+mise en page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Groupe Vallée-Sellali&lt;br /&gt;
&lt;br /&gt;
== Séance n°1: ==&lt;br /&gt;
Machine virtuelle créée sur chassiron :&lt;br /&gt;
&lt;br /&gt;
Hostname       :  ValSel&lt;br /&gt;
&lt;br /&gt;
Distribution    :  bookworm&lt;br /&gt;
&lt;br /&gt;
Stockage  : 10G&lt;br /&gt;
&lt;br /&gt;
Mémoire vive : 1G&lt;br /&gt;
&lt;br /&gt;
Mot de passe habituel&lt;br /&gt;
&lt;br /&gt;
Les fichiers /etc/network/interfaces, /etc/resolv.conf et /etc/apt/sources.list ont été modifiés comme demandés.&lt;br /&gt;
&lt;br /&gt;
Raspberry 4 :&lt;br /&gt;
&lt;br /&gt;
Communication via le port série possible&lt;br /&gt;
&lt;br /&gt;
Login : valsel Pwd : pasglop&lt;br /&gt;
&lt;br /&gt;
STM32F401RE : Nanoedge et IDE installés, conception d'un code pour tester le capteur en cours&lt;br /&gt;
&lt;br /&gt;
==  Séance n°2 (18/12/2023) : ==&lt;br /&gt;
Raspberry connectée au WiFi SE5&lt;br /&gt;
&lt;br /&gt;
Connexion ipv6 possible entre la VM et la raspberry&lt;br /&gt;
&lt;br /&gt;
Données du capteur lues et envoyées au port série&lt;br /&gt;
&lt;br /&gt;
Création d'un programme python client à destination de la raspberry qui : lit le port série, stocke les données reçues, envoie les données reçues en http vers le &amp;quot;serveur&amp;quot; présent sur la VM&lt;br /&gt;
&lt;br /&gt;
Création d'un programme python serveur à destination de la VM qui reçoit et stocke les données&lt;br /&gt;
&lt;br /&gt;
==  Séance 3 (19/12/2023) : ==&lt;br /&gt;
Création des datasets : main fermée et main ouverte (Une ligne = 16 * 16 données, environ 30 lignes par fichier)&lt;br /&gt;
&lt;br /&gt;
Choix de garder les capteurs en 4x4 pour un compromis vitesse de création des datasets/temps d'entrainement du modèle/efficacité du capteur de mouvement.&lt;br /&gt;
&lt;br /&gt;
Entrainement du modèle avec les datasets sur NanoEdge&lt;br /&gt;
&lt;br /&gt;
==  Séance 4 (20/12/2023) ==&lt;br /&gt;
Création de nouveaux datasets et de fichiers de tests : (100 lignes de 16 * 16 données)&lt;br /&gt;
&lt;br /&gt;
Création d'un script Python utilisant la bibliothèque sklearn pour implémenter un algorithme de classification SVM, à destination de la Raspberry et de la VM&lt;br /&gt;
&lt;br /&gt;
Le choix de main ouverte/main fermée se questionne, on utilise pas l'aspect mouvement que permet les algorithmes.&lt;br /&gt;
&lt;br /&gt;
Les algorithmes donnent un bon résultat avec une précision proche de 70%. La communication entre la VM et la zabeth sur laquelle on teste les fichiers pythons fonctionne.&lt;br /&gt;
&lt;br /&gt;
Du microcontrôleur, on reçoit les données brutes et l'estimation de l'état de la main. Le fichier python sur la zabeth, à destination future de la raspberry, reçoit ces données via le port série, les stocke dans un fichier txt, fait une estimation de l'état de la main, et envoie les données brutes à la VM en utilisant TCP/IP avec l'adresse IPV6 de la VM.&lt;br /&gt;
&lt;br /&gt;
La VM reçoit les données mais ne les traite pas encore.&lt;br /&gt;
&lt;br /&gt;
==  Travail hors des séances et rendu final : ==&lt;br /&gt;
Extension du programme sur la STM aux 64 capteurs.&lt;br /&gt;
&lt;br /&gt;
Nouveau choix de test qui prend en compte les mouvements.&lt;br /&gt;
&lt;br /&gt;
Création de nouveaux datasets adaptés : lignes de 64 * 16 données, une ligne correspond à une itération du mouvement, environ 170 lignes par datasets pour une prise en compte de plusieurs cas&lt;br /&gt;
&lt;br /&gt;
(passage rapide, passage lent, hauteurs différentes).&lt;br /&gt;
&lt;br /&gt;
Les mouvements sont : &lt;br /&gt;
&lt;br /&gt;
- Mouvement de gauche à droite&lt;br /&gt;
&lt;br /&gt;
- Mouvement de droite à gauche&lt;br /&gt;
&lt;br /&gt;
- Aucune présence&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir tester les modèles résultant de ces datasets, 3 fichiers de tests sont créés contenant chacun une trentaine d'itérations du mouvement.&lt;br /&gt;
&lt;br /&gt;
Avec Nanoedge, entraînement d'un nouveau modèle à destination de la STM. Le modèle le plus efficace avec nos fichiers de tests sont, contrairement aux premières séances, un modèle MLP (multilayer&lt;br /&gt;
&lt;br /&gt;
perceptron). Résultats avec nos fichiers de tests : précision de 90%&lt;br /&gt;
&lt;br /&gt;
En effet, les modèles SVM ne semblent pas adaptés à nos datasets =&amp;gt; Adaptation du code python de la raspberry pour utiliser lui aussi un modèle MLP, ce qui est plus efficace.&lt;br /&gt;
&lt;br /&gt;
Modèle résultant avec comme input les fichiers de tests : 70% de précision sur Droite à gauche, 68% de gauche à droite, 100% si aucune présence.&lt;br /&gt;
&lt;br /&gt;
Intégration du code GestionData.py dans la raspberry ainsi que du modèle créé par mlpAlgo.py (uniquement l'output)&lt;br /&gt;
&lt;br /&gt;
==== Réseau : ====&lt;br /&gt;
- La STM32 envoie les données brutes + l'estimation du mouvement issue de son modèle intégré par le port série (knowledge.h, nanoEdgeAi.h, libneai.a et appTof.c sont disponibles en annexe)&lt;br /&gt;
&lt;br /&gt;
- La Raspberry Pi reçoit ces données brutes, les stocke dans un fichier texte, estime le mouvement effectué, et affiche l'estimation en plus de celle de la STM. Ensuite, les données brutes sont transmises à la VM par TCP/IP en IPV6, à la condition que 1024 données soient présentes à chaque lecture. Si ce n'est pas le cas, les données &amp;quot;corrompues&amp;quot; ne sont pas transmises puisqu'inexploitables. (Voir GestionData.py en annexe)&lt;br /&gt;
&lt;br /&gt;
- La VM reçoit les données par paquet de 1024 entiers, stocke les données dans un fichier txt, et fait une estimation du mouvement en utilisant le même modèle que celui présent dans la raspberry pi.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Lors des tests, nous avons constaté que la communication TCP ne semblait pas permise depuis un ordinateur externe au réseau des zabeths vers la VM : le ping est possible, mais la communication ne semble pas. Nous avons donc fait le choix d'utiliser un ordinateur personnel pour montrer l'efficacité du projet : le fonctionnement est similaire, les données sont envoyées sur la machine personnelle en IPV6.&lt;br /&gt;
[[Fichier:TerminauxECEAI Vallee.png|vignette|570x570px]]&lt;br /&gt;
&lt;br /&gt;
===  Vidéo : ===&lt;br /&gt;
Image de l'écran capturé dans la vidéo : [[:Fichier:DemoVideo.mp4|DemoVideo.mp4]]&lt;br /&gt;
&lt;br /&gt;
[[:Fichier:TerminauxECEAI Vallee.png|TerminauxECEAI Vallee.png]][[Fichier:DemoVideo.mp4|vignette]]On constate : Si les données reçues ne contiennent pas 1024 données avant le \n, alors ces données ne sont pas transmises car non exploitables par les modèles de la RPi/VM. On obtient tout de même l'estimation de la STM32.&lt;br /&gt;
&lt;br /&gt;
Comme montré sur la vidéo, on constate que lorsqu'il n'y a aucun mouvement, les estimations sont bonnes.&lt;br /&gt;
&lt;br /&gt;
Pour les trois tests de gauche à droite, les estimations sont bonnes.&lt;br /&gt;
&lt;br /&gt;
Pour les trois tests de droite à gauche, les estimations sont bonnes, à l'exception de la dernière estimation donnée par la RPi et par la VM (vu que les modèles sont les mêmes et qu'ils utilisent les mêmes données à ce moment) : cela est du aux 70% de précision observés lors des tests.&lt;br /&gt;
&lt;br /&gt;
==  Annexe ==&lt;br /&gt;
Tous les codes rendus en annexe sont dans leur version finale et ont été utilisés au cours du projet.&lt;br /&gt;
&lt;br /&gt;
=== Codes externes ayant servis à l'entraînement : ===&lt;br /&gt;
Les fichiers de type data ou test ont été réalisés en lisant le port série et en insérant directement les données dans le fichier texte à condition que les données ne soient pas corrompues. &lt;br /&gt;
&lt;br /&gt;
mlpAlgo.py : programme permettant de générer un modèle utilisant l'algorithme MLP &amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
#Import mlp model&lt;br /&gt;
from sklearn import neural_network&lt;br /&gt;
from sklearn import metrics&lt;br /&gt;
import joblib&lt;br /&gt;
&lt;br /&gt;
GtoD_path = 'data_GtoD.txt'&lt;br /&gt;
DtoG_path = 'data_DtoG.txt'&lt;br /&gt;
GtoD_test_path = 'test_GtoD.txt'&lt;br /&gt;
DtoG_test_path = 'test_DtoG.txt'&lt;br /&gt;
rien_path = 'data_rien.txt'&lt;br /&gt;
rien_test_path = 'test_rien.txt'&lt;br /&gt;
&lt;br /&gt;
GtoD_train = []&lt;br /&gt;
DtoG_train = []&lt;br /&gt;
GtoD_target = []&lt;br /&gt;
DtoG_target = []&lt;br /&gt;
rien_train = []&lt;br /&gt;
rien_target = []&lt;br /&gt;
test = []&lt;br /&gt;
data = []&lt;br /&gt;
targets = []&lt;br /&gt;
target_test = []&lt;br /&gt;
&lt;br /&gt;
def ReadAndFill(nom_fichier, target_tab, target_int, taille_sous_liste=1024):&lt;br /&gt;
    try:&lt;br /&gt;
        # Ouverture du fichier en mode lecture&lt;br /&gt;
        with open(nom_fichier, 'r') as fichier:&lt;br /&gt;
            # Lecture du contenu du fichier ligne par ligne&lt;br /&gt;
            lignes = fichier.readlines()&lt;br /&gt;
&lt;br /&gt;
            # Pour chaque ligne, conversion en liste d'entiers&lt;br /&gt;
            tableau = [[int(nombre) for nombre in ligne.split()] for ligne in lignes]&lt;br /&gt;
            tableau_filtre = [sous_liste for sous_liste in tableau if len(sous_liste) == taille_sous_liste]&lt;br /&gt;
            target_tab = len(tableau_filtre) * [target_int]&lt;br /&gt;
&lt;br /&gt;
        return tableau_filtre, target_tab&lt;br /&gt;
    &lt;br /&gt;
    except FileNotFoundError:&lt;br /&gt;
        print(f&amp;quot;Le fichier {nom_fichier} n'a pas été trouvé.&amp;quot;)&lt;br /&gt;
        return []&lt;br /&gt;
    except Exception as e:&lt;br /&gt;
        print(f&amp;quot;Une erreur s'est produite : {e}&amp;quot;)&lt;br /&gt;
        return []&lt;br /&gt;
&lt;br /&gt;
# Exemple d'utilisation&lt;br /&gt;
GtoD_train, GtoD_target = ReadAndFill(GtoD_path, GtoD_target, 2)&lt;br /&gt;
DtoG_train, DtoG_target = ReadAndFill(DtoG_path, DtoG_target, 1)&lt;br /&gt;
rien_train, rien_target = ReadAndFill(rien_path, rien_target, 0)&lt;br /&gt;
data = GtoD_train + DtoG_train + rien_train&lt;br /&gt;
targets = GtoD_target + DtoG_target + rien_target&lt;br /&gt;
&lt;br /&gt;
#Create a svm Classifier&lt;br /&gt;
clf = neural_network.MLPClassifier(max_iter=5000000)&lt;br /&gt;
&lt;br /&gt;
#Train the model using the training sets&lt;br /&gt;
clf.fit(data, targets)&lt;br /&gt;
joblib.dump(clf, 'modele_mlp2.pkl')&lt;br /&gt;
&lt;br /&gt;
test, target_test = ReadAndFill(GtoD_test_path, target_test, 2)&lt;br /&gt;
&lt;br /&gt;
#Predict the response for test dataset&lt;br /&gt;
pred = clf.predict(test)&lt;br /&gt;
print(pred)&lt;br /&gt;
# Model Accuracy: how often is the classifier correct?&lt;br /&gt;
print(&amp;quot;Fichier de test actuel :&amp;quot;,GtoD_test_path)&lt;br /&gt;
print(&amp;quot;Accuracy:&amp;quot;,metrics.accuracy_score(target_test, pred))&lt;br /&gt;
&lt;br /&gt;
test, target_test = ReadAndFill(DtoG_test_path, target_test, 1)&lt;br /&gt;
&lt;br /&gt;
#Predict the response for test dataset&lt;br /&gt;
pred = clf.predict(test)&lt;br /&gt;
print(pred)&lt;br /&gt;
# Model Accuracy: how often is the classifier correct?&lt;br /&gt;
print(&amp;quot;Fichier de test actuel :&amp;quot;,DtoG_test_path)&lt;br /&gt;
print(&amp;quot;Accuracy:&amp;quot;,metrics.accuracy_score(target_test, pred))&lt;br /&gt;
&lt;br /&gt;
test, target_test = ReadAndFill(rien_test_path, target_test, 0)&lt;br /&gt;
&lt;br /&gt;
#Predict the response for test dataset&lt;br /&gt;
pred = clf.predict(test)&lt;br /&gt;
print(pred)&lt;br /&gt;
# Model Accuracy: how often is the classifier correct?&lt;br /&gt;
print(&amp;quot;Fichier de test actuel :&amp;quot;,rien_path)&lt;br /&gt;
print(&amp;quot;Accuracy:&amp;quot;,metrics.accuracy_score(target_test, pred))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;mlpPredic.py : Code similaire servant à tester de charger un modèle créé et sauvegardé auparavant &amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
#Import mlp model&lt;br /&gt;
from sklearn import neural_network&lt;br /&gt;
from sklearn import metrics&lt;br /&gt;
import joblib&lt;br /&gt;
&lt;br /&gt;
GtoD_test_path = 'test_GtoD.txt'&lt;br /&gt;
DtoG_test_path = 'test_DtoG.txt'&lt;br /&gt;
rien_test_path = 'test_rien.txt'&lt;br /&gt;
&lt;br /&gt;
test = []&lt;br /&gt;
data = []&lt;br /&gt;
targets = []&lt;br /&gt;
target_test = []&lt;br /&gt;
&lt;br /&gt;
def ReadAndFill(nom_fichier, target_tab, target_int, taille_sous_liste=1024):&lt;br /&gt;
    try:&lt;br /&gt;
        # Ouverture du fichier en mode lecture&lt;br /&gt;
        with open(nom_fichier, 'r') as fichier:&lt;br /&gt;
            # Lecture du contenu du fichier ligne par ligne&lt;br /&gt;
            lignes = fichier.readlines()&lt;br /&gt;
&lt;br /&gt;
            # Pour chaque ligne, conversion en liste d'entiers&lt;br /&gt;
            tableau = [[int(nombre) for nombre in ligne.split()] for ligne in lignes]&lt;br /&gt;
            tableau_filtre = [sous_liste for sous_liste in tableau if len(sous_liste) == taille_sous_liste]&lt;br /&gt;
            target_tab = len(tableau_filtre) * [target_int]&lt;br /&gt;
&lt;br /&gt;
        return tableau_filtre, target_tab&lt;br /&gt;
    &lt;br /&gt;
    except FileNotFoundError:&lt;br /&gt;
        print(f&amp;quot;Le fichier {nom_fichier} n'a pas été trouvé.&amp;quot;)&lt;br /&gt;
        return []&lt;br /&gt;
    except Exception as e:&lt;br /&gt;
        print(f&amp;quot;Une erreur s'est produite : {e}&amp;quot;)&lt;br /&gt;
        return []&lt;br /&gt;
&lt;br /&gt;
#Create a svm Classifier&lt;br /&gt;
clf = joblib.load('modele_mlp.pkl')&lt;br /&gt;
&lt;br /&gt;
test, target_test = ReadAndFill(GtoD_test_path, target_test, 2)&lt;br /&gt;
&lt;br /&gt;
#Predict the response for test dataset&lt;br /&gt;
pred = clf.predict(test)&lt;br /&gt;
print(pred)&lt;br /&gt;
# Model Accuracy: how often is the classifier correct?&lt;br /&gt;
print(&amp;quot;Fichier de test actuel :&amp;quot;,GtoD_test_path)&lt;br /&gt;
print(&amp;quot;Accuracy:&amp;quot;,metrics.accuracy_score(target_test, pred))&lt;br /&gt;
&lt;br /&gt;
test, target_test = ReadAndFill(DtoG_test_path, target_test, 1)&lt;br /&gt;
&lt;br /&gt;
#Predict the response for test dataset&lt;br /&gt;
pred = clf.predict(test)&lt;br /&gt;
print(pred)&lt;br /&gt;
# Model Accuracy: how often is the classifier correct?&lt;br /&gt;
print(&amp;quot;Fichier de test actuel :&amp;quot;,DtoG_test_path)&lt;br /&gt;
print(&amp;quot;Accuracy:&amp;quot;,metrics.accuracy_score(target_test, pred))&lt;br /&gt;
&lt;br /&gt;
test, target_test = ReadAndFill(rien_test_path, target_test, 0)&lt;br /&gt;
&lt;br /&gt;
#Predict the response for test dataset&lt;br /&gt;
pred = clf.predict(test)&lt;br /&gt;
print(pred)&lt;br /&gt;
# Model Accuracy: how often is the classifier correct?&lt;br /&gt;
print(&amp;quot;Fichier de test actuel :&amp;quot;,rien_test_path)&lt;br /&gt;
print(&amp;quot;Accuracy:&amp;quot;,metrics.accuracy_score(target_test, pred))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Codes internes à la STM : ===&lt;br /&gt;
app_tof.c : Code du process. Acquisition des données des 64 capteurs, 16 fois, envoi en temps réel des données et stockage temporaire des données pour faire une estimation avec le modèle interne à la stm32. Une fois les 1024 données récupérées, print d'un \n pour que &amp;quot;serial.readline()&amp;quot; des commandes python se termine.&lt;br /&gt;
&lt;br /&gt;
Envoi de l'estimation après 1024 données.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
static void MX_53L5A1_SimpleRanging_Process(void)&lt;br /&gt;
{&lt;br /&gt;
  uint32_t Id;&lt;br /&gt;
  int8_t compteur = 0;&lt;br /&gt;
  uint8_t zones_per_line;&lt;br /&gt;
&lt;br /&gt;
  VL53L5A1_RANGING_SENSOR_ReadID(VL53L5A1_DEV_CENTER, &amp;amp;Id);&lt;br /&gt;
  VL53L5A1_RANGING_SENSOR_GetCapabilities(VL53L5A1_DEV_CENTER, &amp;amp;Cap);&lt;br /&gt;
&lt;br /&gt;
  Profile.RangingProfile = RS_PROFILE_8x8_CONTINUOUS;&lt;br /&gt;
  Profile.TimingBudget = TIMING_BUDGET; /* 5 ms &amp;lt; TimingBudget &amp;lt; 100 ms */&lt;br /&gt;
  Profile.Frequency = RANGING_FREQUENCY; /* Ranging frequency Hz (shall be consistent with TimingBudget value) */&lt;br /&gt;
  Profile.EnableAmbient = 0; /* Enable: 1, Disable: 0 */&lt;br /&gt;
  Profile.EnableSignal = 0; /* Enable: 1, Disable: 0 */&lt;br /&gt;
&lt;br /&gt;
  uint16_t id_class = 0;&lt;br /&gt;
  float input_user_buffer[DATA_INPUT_USER * AXIS_NUMBER]; // Buffer of input values&lt;br /&gt;
  float output_class_buffer[CLASS_NUMBER];&lt;br /&gt;
  zones_per_line = ((Profile.RangingProfile == RS_PROFILE_8x8_AUTONOMOUS) ||&lt;br /&gt;
         (Profile.RangingProfile == RS_PROFILE_8x8_CONTINUOUS)) ? 8 : 4;&lt;br /&gt;
  enum neai_state error_code = neai_classification_init(knowledge);&lt;br /&gt;
  if (error_code != NEAI_OK)&lt;br /&gt;
  {&lt;br /&gt;
		printf(&amp;quot;Erreur lib \n&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  /* set the profile if different from default one */&lt;br /&gt;
  VL53L5A1_RANGING_SENSOR_ConfigProfile(VL53L5A1_DEV_CENTER, &amp;amp;Profile);&lt;br /&gt;
&lt;br /&gt;
  status = VL53L5A1_RANGING_SENSOR_Start(VL53L5A1_DEV_CENTER, RS_MODE_BLOCKING_CONTINUOUS);&lt;br /&gt;
&lt;br /&gt;
  if (status != BSP_ERROR_NONE)&lt;br /&gt;
  {&lt;br /&gt;
    printf(&amp;quot;VL53L5A1_RANGING_SENSOR_Start failed\n&amp;quot;);&lt;br /&gt;
    while (1);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  while (1)&lt;br /&gt;
  {&lt;br /&gt;
    /* polling mode */&lt;br /&gt;
    status = VL53L5A1_RANGING_SENSOR_GetDistance(VL53L5A1_DEV_CENTER, &amp;amp;Result);&lt;br /&gt;
    int sous_buffer[DATA_INPUT_USER];&lt;br /&gt;
&lt;br /&gt;
    if (status == BSP_ERROR_NONE)&lt;br /&gt;
    {&lt;br /&gt;
      print_result(&amp;amp;Result, sous_buffer);&lt;br /&gt;
      //afficher_tableau(sous_buffer, DATA_INPUT_USER);&lt;br /&gt;
      fill_buffer(input_user_buffer, sous_buffer, compteur);&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    if (compteur == 15)&lt;br /&gt;
    {&lt;br /&gt;
    	//printf(&amp;quot;Class number :%d Data user input : %d axis : %d multiply : %d&amp;quot;,CLASS_NUMBER, DATA_INPUT_USER, AXIS_NUMBER, AXIS_NUMBER*DATA_INPUT_USER);&lt;br /&gt;
        neai_classification(input_user_buffer, output_class_buffer, &amp;amp;id_class);&lt;br /&gt;
    	//afficher_tableau(input_user_buffer, DATA_INPUT_USER*AXIS_NUMBER);&lt;br /&gt;
    	printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
    	printf(&amp;quot;%s\n&amp;quot;,id2class[id_class]);&lt;br /&gt;
    	compteur = 0;&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
    	compteur++;//printf(&amp;quot;Compteur = %d&amp;quot;,compteur);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (com_has_data())&lt;br /&gt;
    {&lt;br /&gt;
      handle_cmd(get_key());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    HAL_Delay(POLLING_PERIOD);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static void print_result(RANGING_SENSOR_Result_t *Result, int sous_buffer[DATA_INPUT_USER])&lt;br /&gt;
{&lt;br /&gt;
  int8_t j;&lt;br /&gt;
  int8_t k;&lt;br /&gt;
  int8_t l;&lt;br /&gt;
  int8_t buffer_position = 0;&lt;br /&gt;
  int8_t total_values = 0;&lt;br /&gt;
  uint8_t zones_per_line;&lt;br /&gt;
  zones_per_line = ((Profile.RangingProfile == RS_PROFILE_8x8_AUTONOMOUS) ||&lt;br /&gt;
         (Profile.RangingProfile == RS_PROFILE_8x8_CONTINUOUS)) ? 8 : 4;&lt;br /&gt;
&lt;br /&gt;
  for (j = 0; j &amp;lt; Result-&amp;gt;NumberOfZones; j += zones_per_line)&lt;br /&gt;
  {&lt;br /&gt;
    for (l = 0; l &amp;lt; RANGING_SENSOR_NB_TARGET_PER_ZONE; l++)&lt;br /&gt;
    {&lt;br /&gt;
      /* Print distance and status */&lt;br /&gt;
      for (k = (zones_per_line - 1); k &amp;gt;= 0; k--)&lt;br /&gt;
      {&lt;br /&gt;
        if (Result-&amp;gt;ZoneResult[j+k].NumberOfTargets &amp;gt; 0)&lt;br /&gt;
        {&lt;br /&gt;
          printf(&amp;quot;%d &amp;quot;,(int)Result-&amp;gt;ZoneResult[j+k].Distance[l]);&lt;br /&gt;
          sous_buffer[buffer_position] = (int)Result-&amp;gt;ZoneResult[j+k].Distance[l];&lt;br /&gt;
          buffer_position++;&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
          printf(&amp;quot;%d &amp;quot;, '10');&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  //printf(&amp;quot;total : %d &amp;quot;,total_values);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Codes internes à la Raspberry pi : ===&lt;br /&gt;
GestionData.py : Lis le port série, stocke les données, effectue une estimation du mouvement, affiche l'estimation provenant de la STM32 et envoie les données brutes à la VM via TCP&lt;br /&gt;
&lt;br /&gt;
COM3 pour les test depuis la machine windows,  ACM0 pour l'application finale sur la raspberry&lt;br /&gt;
&lt;br /&gt;
IPV6 de la VM laissée en commentaire&amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
import serial&lt;br /&gt;
import datetime&lt;br /&gt;
import csv&lt;br /&gt;
import socket&lt;br /&gt;
import joblib&lt;br /&gt;
import requests&lt;br /&gt;
import struct&lt;br /&gt;
&lt;br /&gt;
port = 'COM3'#'/dev/ttyACM0'&lt;br /&gt;
baudrate = 460800&lt;br /&gt;
ser = serial.Serial(port, baudrate)&lt;br /&gt;
&lt;br /&gt;
csv_filename = 'donnees_raspberry.txt'&lt;br /&gt;
max_lines = 200&lt;br /&gt;
clf = joblib.load('modele_mlp.pkl')&lt;br /&gt;
server_address = '2001:861:3541:4260:c69f:9d4:ccf5:7673'#'2001:660:4401:6050:216:3eff:febc:550c'&lt;br /&gt;
server_port = 12345&lt;br /&gt;
classes = [&amp;quot;Aucune presence&amp;quot;, &amp;quot;Mouvement de droite a gauche&amp;quot;,&amp;quot;Mouvement de gauche a droite&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
def DataToTab(ligne, taille_sous_liste=1024):&lt;br /&gt;
     tableau = [int(nombre) for nombre in ligne.split()]&lt;br /&gt;
     if (len(tableau)!=taille_sous_liste):&lt;br /&gt;
         return tableau, 1&lt;br /&gt;
     return tableau, 0&lt;br /&gt;
&lt;br /&gt;
with open(csv_filename, 'w', newline='') as csv_file:&lt;br /&gt;
    csv_writer = csv.writer(csv_file)&lt;br /&gt;
    line_count = 0&lt;br /&gt;
    client_socket = socket.socket(socket.AF_INET6,socket.SOCK_STREAM)&lt;br /&gt;
    client_socket.connect((server_address, server_port))&lt;br /&gt;
    try:&lt;br /&gt;
        while line_count &amp;lt; max_lines:&lt;br /&gt;
            data = ser.readline().decode('utf-8').strip()&lt;br /&gt;
            #print(&amp;quot;Ligne : &amp;quot;, line_count,&amp;quot;\n&amp;quot;)&lt;br /&gt;
            timestamp = datetime.datetime.now().strftime('%H:%M:%S')&lt;br /&gt;
            #print(f&amp;quot;{timestamp} - Données lues: {data}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
            headers = {'Content-type': 'text/plain'}&lt;br /&gt;
            body = f&amp;quot;{timestamp} - Données lues: {data}&amp;quot;&lt;br /&gt;
            tableau, error = DataToTab(data)&lt;br /&gt;
            if error == 1:&lt;br /&gt;
                print(&amp;quot;Taille de tableau non conforme&amp;quot;)&lt;br /&gt;
            else:&lt;br /&gt;
                pred = clf.predict([tableau])&lt;br /&gt;
                print(&amp;quot;Classe identifiee sur la Raspberry:&amp;quot;, classes[pred[0]])&lt;br /&gt;
                try:&lt;br /&gt;
                    donnees_brutes = struct.pack('!{}i'.format(len(tableau)), *tableau)&lt;br /&gt;
                    client_socket.sendall(donnees_brutes)&lt;br /&gt;
                except Exception as e:&lt;br /&gt;
                    print(f&amp;quot;Erreur : {e}&amp;quot;)&lt;br /&gt;
            csv_writer.writerow([data])&lt;br /&gt;
            &lt;br /&gt;
            classe = ser.readline().decode('utf-8').strip()&lt;br /&gt;
            print(&amp;quot;Classe identifiee par la STM:&amp;quot;, classe);&lt;br /&gt;
            line_count += 1&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    except KeyboardInterrupt:&lt;br /&gt;
        pass&lt;br /&gt;
    &lt;br /&gt;
    finally:&lt;br /&gt;
        client_socket.close()&lt;br /&gt;
        ser.close()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Codes internes à la VM (présents en réalité sur la machine personnelle) : ===&lt;br /&gt;
server_tcp.py : Ecoute sur le port donné, reçois les données brutes, les stocke, et estime le mouvement effectué&amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
import socket&lt;br /&gt;
import struct&lt;br /&gt;
import csv&lt;br /&gt;
import joblib&lt;br /&gt;
import datetime&lt;br /&gt;
packet_size = 1024&lt;br /&gt;
&lt;br /&gt;
classes = [&amp;quot;Aucune presence&amp;quot;, &amp;quot;Mouvement de droite a gauche&amp;quot;,&amp;quot;Mouvement de gauche a droite&amp;quot;]&lt;br /&gt;
csv_filename = 'donnees_recues.txt'&lt;br /&gt;
max_lines = 200&lt;br /&gt;
clf = joblib.load('modele_mlp.pkl')&lt;br /&gt;
&lt;br /&gt;
def start_tcp_server(ip, port):&lt;br /&gt;
    with open(csv_filename, 'w', newline='') as csv_file:&lt;br /&gt;
        csv_writer = csv.writer(csv_file)&lt;br /&gt;
        server_socket = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)&lt;br /&gt;
        server_socket.bind((ip, port))&lt;br /&gt;
        server_socket.listen(1)&lt;br /&gt;
        print(f&amp;quot;Serveur tcp en ecoute sur {ip}:{port}&amp;quot;)&lt;br /&gt;
        client_socket, client_address = server_socket.accept()&lt;br /&gt;
        line_count = 0&lt;br /&gt;
        try:&lt;br /&gt;
            while line_count &amp;lt; max_lines:&lt;br /&gt;
                donnees_brutes = client_socket.recv(packet_size * 4)&lt;br /&gt;
                liste_entiers = list(struct.unpack('!{}i'.format(packet_size), donnees_brutes))&lt;br /&gt;
                #print(&amp;quot;Recu :&amp;quot;, liste_entiers)&lt;br /&gt;
                csv_writer.writerow(liste_entiers)&lt;br /&gt;
                pred = clf.predict([liste_entiers])&lt;br /&gt;
                timestamp = datetime.datetime.now().strftime('%H:%M:%S')&lt;br /&gt;
                print(f&amp;quot;{timestamp}&amp;quot;)&lt;br /&gt;
                print(&amp;quot;Classe identifiee sur la VM:&amp;quot;, classes[pred[0]])&lt;br /&gt;
                line_count+=1&lt;br /&gt;
        except KeyboardInterrupt:&lt;br /&gt;
            pass&lt;br /&gt;
        finally:&lt;br /&gt;
            client_socket.close&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    server_ip = '2001:861:5642:4610:46fb:e35c:a75d:2b74'&lt;br /&gt;
    server_port = 12345&lt;br /&gt;
    start_tcp_server(server_ip, server_port)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Fvallee</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:TerminauxECEAI_Vallee.png&amp;diff=4744</id>
		<title>Fichier:TerminauxECEAI Vallee.png</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:TerminauxECEAI_Vallee.png&amp;diff=4744"/>
		<updated>2024-01-28T13:03:16Z</updated>

		<summary type="html">&lt;p&gt;Fvallee : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;terminaux capturés de la vidéo de démo associée&lt;/div&gt;</summary>
		<author><name>Fvallee</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/ValleeSellali&amp;diff=4741</id>
		<title>SE5 ECEAI/eceai 2023/2024/ValleeSellali</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/ValleeSellali&amp;diff=4741"/>
		<updated>2024-01-28T12:47:08Z</updated>

		<summary type="html">&lt;p&gt;Fvallee : Video&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Groupe Vallée-Sellali&lt;br /&gt;
&lt;br /&gt;
Séance n°1:&lt;br /&gt;
&lt;br /&gt;
Machine virtuelle créée sur chassiron :&lt;br /&gt;
&lt;br /&gt;
Hostname       :  ValSel&lt;br /&gt;
&lt;br /&gt;
Distribution    :  bookworm&lt;br /&gt;
&lt;br /&gt;
Stockage  : 10G&lt;br /&gt;
&lt;br /&gt;
Mémoire vive : 1G&lt;br /&gt;
&lt;br /&gt;
Mot de passe habituel&lt;br /&gt;
&lt;br /&gt;
Les fichiers /etc/network/interfaces, /etc/resolv.conf et /etc/apt/sources.list ont été modifiés comme demandés.&lt;br /&gt;
&lt;br /&gt;
Raspberry 4 :&lt;br /&gt;
&lt;br /&gt;
Communication via le port série possible&lt;br /&gt;
&lt;br /&gt;
Login : valsel Pwd : pasglop&lt;br /&gt;
&lt;br /&gt;
STM32F401RE : Nanoedge et IDE installés, conception d'un code pour tester le capteur en cours&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Séance n°2 (18/12/2023) :&lt;br /&gt;
&lt;br /&gt;
Raspberry connectée au WiFi SE5&lt;br /&gt;
&lt;br /&gt;
Connexion ipv6 possible entre la VM et la raspberry&lt;br /&gt;
&lt;br /&gt;
Données du capteur lues et envoyées au port série&lt;br /&gt;
&lt;br /&gt;
Création d'un programme python client à destination de la raspberry qui : lit le port série, stocke les données reçues, envoie les données reçues en http vers le &amp;quot;serveur&amp;quot; présent sur la VM&lt;br /&gt;
&lt;br /&gt;
Création d'un programme python serveur à destination de la VM qui reçoit et stocke les données&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Séance 3 (19/12/2023) :&lt;br /&gt;
&lt;br /&gt;
Création des datasets : main fermée et main ouverte (Une ligne = 16 * 16 données, environ 30 lignes par fichier)&lt;br /&gt;
&lt;br /&gt;
Choix de garder les capteurs en 4x4 pour un compromis vitesse de création des datasets/temps d'entrainement du modèle/efficacité du capteur de mouvement.&lt;br /&gt;
&lt;br /&gt;
Entrainement du modèle avec les datasets sur NanoEdge&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Séance 4 (20/12/2023)&lt;br /&gt;
&lt;br /&gt;
Création de nouveaux datasets et de fichiers de tests : (100 lignes de 16 * 16 données)&lt;br /&gt;
&lt;br /&gt;
Création d'un script Python utilisant la bibliothèque sklearn pour implémenter un algorithme de classification SVM, à destination de la Raspberry et de la VM&lt;br /&gt;
&lt;br /&gt;
Le choix de main ouverte/main fermée se questionne, on utilise pas l'aspect mouvement que permet les algorithmes.&lt;br /&gt;
&lt;br /&gt;
Les algorithmes donnent un bon résultat avec une précision proche de 70%. La communication entre la VM et la zabeth sur laquelle on teste les fichiers pythons fonctionne.&lt;br /&gt;
&lt;br /&gt;
Du microcontrôleur, on reçoit les données brutes et l'estimation de l'état de la main. Le fichier python sur la zabeth, à destination future de la raspberry, reçoit ces données via le port série, les stocke dans un fichier txt, fait une estimation de l'état de la main, et envoie les données brutes à la VM en utilisant TCP/IP avec l'adresse IPV6 de la VM.&lt;br /&gt;
&lt;br /&gt;
La VM reçoit les données mais ne les traite pas encore.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Travail hors des séances et rendu final :&lt;br /&gt;
&lt;br /&gt;
Extension du programme sur la STM aux 64 capteurs.&lt;br /&gt;
&lt;br /&gt;
Nouveau choix de test qui prend en compte les mouvements.&lt;br /&gt;
&lt;br /&gt;
Création de nouveaux datasets adaptés : lignes de 64 * 16 données, une ligne correspond à une itération du mouvement, environ 170 lignes par datasets pour une prise en compte de plusieurs cas&lt;br /&gt;
&lt;br /&gt;
(passage rapide, passage lent, hauteurs différentes).&lt;br /&gt;
&lt;br /&gt;
Les mouvements sont : &lt;br /&gt;
&lt;br /&gt;
- Mouvement de gauche à droite&lt;br /&gt;
&lt;br /&gt;
- Mouvement de droite à gauche&lt;br /&gt;
&lt;br /&gt;
- Aucune présence&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir tester les modèles résultant de ces datasets, 3 fichiers de tests sont créés contenant chacun une trentaine d'itérations du mouvement.&lt;br /&gt;
&lt;br /&gt;
Avec Nanoedge, entraînement d'un nouveau modèle à destination de la STM. Le modèle le plus efficace avec nos fichiers de tests sont, contrairement aux premières séances, un modèle MLP (multilayer&lt;br /&gt;
&lt;br /&gt;
perceptron). Résultats avec nos fichiers de tests : précision de 90%&lt;br /&gt;
&lt;br /&gt;
En effet, les modèles SVM ne semblent pas adaptés à nos datasets =&amp;gt; Adaptation du code python de la raspberry pour utiliser lui aussi un modèle MLP, ce qui est plus efficace.&lt;br /&gt;
&lt;br /&gt;
Modèle résultant avec comme input les fichiers de tests : 70% de précision sur Droite à gauche, 68% de gauche à droite, 100% si aucune présence.&lt;br /&gt;
&lt;br /&gt;
Intégration du code GestionData.py dans la raspberry ainsi que du modèle créé par mlpAlgo.py (uniquement l'output)&lt;br /&gt;
&lt;br /&gt;
Réseau : &lt;br /&gt;
&lt;br /&gt;
- La STM32 envoie les données brutes + l'estimation du mouvement issue de son modèle intégré par le port série (knowledge.h, nanoEdgeAi.h, libneai.a et appTof.c sont disponibles en annexe)&lt;br /&gt;
&lt;br /&gt;
- La Raspberry Pi reçoit ces données brutes, les stocke dans un fichier texte, estime le mouvement effectué, et affiche l'estimation en plus de celle de la STM. Ensuite, les données brutes sont transmises à la VM par TCP/IP en IPV6, à la condition que 1024 données soient présentes à chaque lecture. Si ce n'est pas le cas, les données &amp;quot;corrompues&amp;quot; ne sont pas transmises puisqu'inexploitables. (Voir GestionData.py en annexe)&lt;br /&gt;
&lt;br /&gt;
- La VM reçoit les données par paquet de 1024 entiers, stocke les données dans un fichier txt, et fait une estimation du mouvement en utilisant le même modèle que celui présent dans la raspberry pi.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Lors des tests, nous avons constaté que la communication TCP ne semblait pas permise depuis un ordinateur externe au réseau des zabeths vers la VM : le ping est possible, mais la communication ne semble pas. Nous avons donc fait le choix d'utiliser un ordinateur personnel pour montrer l'efficacité du projet : le fonctionnement est similaire, les données sont envoyées sur la machine personnelle en IPV6.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;Vidéo :&lt;br /&gt;
[[Fichier:DemoVideo.mp4|vignette]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;Annexe&lt;br /&gt;
&lt;br /&gt;
Tous les codes rendus en annexe sont dans leur version finale et ont été utilisés au cours du projet.&lt;br /&gt;
&lt;br /&gt;
Codes externes ayant servis à l'entraînement : &lt;br /&gt;
&lt;br /&gt;
Les fichiers de type data ou test ont été réalisés en lisant le port série et en insérant directement les données dans le fichier texte à condition que les données ne soient pas corrompues. &lt;br /&gt;
&lt;br /&gt;
mlpAlgo.py : programme permettant de générer un modèle utilisant l'algorithme MLP &amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
#Import mlp model&lt;br /&gt;
from sklearn import neural_network&lt;br /&gt;
from sklearn import metrics&lt;br /&gt;
import joblib&lt;br /&gt;
&lt;br /&gt;
GtoD_path = 'data_GtoD.txt'&lt;br /&gt;
DtoG_path = 'data_DtoG.txt'&lt;br /&gt;
GtoD_test_path = 'test_GtoD.txt'&lt;br /&gt;
DtoG_test_path = 'test_DtoG.txt'&lt;br /&gt;
rien_path = 'data_rien.txt'&lt;br /&gt;
rien_test_path = 'test_rien.txt'&lt;br /&gt;
&lt;br /&gt;
GtoD_train = []&lt;br /&gt;
DtoG_train = []&lt;br /&gt;
GtoD_target = []&lt;br /&gt;
DtoG_target = []&lt;br /&gt;
rien_train = []&lt;br /&gt;
rien_target = []&lt;br /&gt;
test = []&lt;br /&gt;
data = []&lt;br /&gt;
targets = []&lt;br /&gt;
target_test = []&lt;br /&gt;
&lt;br /&gt;
def ReadAndFill(nom_fichier, target_tab, target_int, taille_sous_liste=1024):&lt;br /&gt;
    try:&lt;br /&gt;
        # Ouverture du fichier en mode lecture&lt;br /&gt;
        with open(nom_fichier, 'r') as fichier:&lt;br /&gt;
            # Lecture du contenu du fichier ligne par ligne&lt;br /&gt;
            lignes = fichier.readlines()&lt;br /&gt;
&lt;br /&gt;
            # Pour chaque ligne, conversion en liste d'entiers&lt;br /&gt;
            tableau = [[int(nombre) for nombre in ligne.split()] for ligne in lignes]&lt;br /&gt;
            tableau_filtre = [sous_liste for sous_liste in tableau if len(sous_liste) == taille_sous_liste]&lt;br /&gt;
            target_tab = len(tableau_filtre) * [target_int]&lt;br /&gt;
&lt;br /&gt;
        return tableau_filtre, target_tab&lt;br /&gt;
    &lt;br /&gt;
    except FileNotFoundError:&lt;br /&gt;
        print(f&amp;quot;Le fichier {nom_fichier} n'a pas été trouvé.&amp;quot;)&lt;br /&gt;
        return []&lt;br /&gt;
    except Exception as e:&lt;br /&gt;
        print(f&amp;quot;Une erreur s'est produite : {e}&amp;quot;)&lt;br /&gt;
        return []&lt;br /&gt;
&lt;br /&gt;
# Exemple d'utilisation&lt;br /&gt;
GtoD_train, GtoD_target = ReadAndFill(GtoD_path, GtoD_target, 2)&lt;br /&gt;
DtoG_train, DtoG_target = ReadAndFill(DtoG_path, DtoG_target, 1)&lt;br /&gt;
rien_train, rien_target = ReadAndFill(rien_path, rien_target, 0)&lt;br /&gt;
data = GtoD_train + DtoG_train + rien_train&lt;br /&gt;
targets = GtoD_target + DtoG_target + rien_target&lt;br /&gt;
&lt;br /&gt;
#Create a svm Classifier&lt;br /&gt;
clf = neural_network.MLPClassifier(max_iter=5000000)&lt;br /&gt;
&lt;br /&gt;
#Train the model using the training sets&lt;br /&gt;
clf.fit(data, targets)&lt;br /&gt;
joblib.dump(clf, 'modele_mlp2.pkl')&lt;br /&gt;
&lt;br /&gt;
test, target_test = ReadAndFill(GtoD_test_path, target_test, 2)&lt;br /&gt;
&lt;br /&gt;
#Predict the response for test dataset&lt;br /&gt;
pred = clf.predict(test)&lt;br /&gt;
print(pred)&lt;br /&gt;
# Model Accuracy: how often is the classifier correct?&lt;br /&gt;
print(&amp;quot;Fichier de test actuel :&amp;quot;,GtoD_test_path)&lt;br /&gt;
print(&amp;quot;Accuracy:&amp;quot;,metrics.accuracy_score(target_test, pred))&lt;br /&gt;
&lt;br /&gt;
test, target_test = ReadAndFill(DtoG_test_path, target_test, 1)&lt;br /&gt;
&lt;br /&gt;
#Predict the response for test dataset&lt;br /&gt;
pred = clf.predict(test)&lt;br /&gt;
print(pred)&lt;br /&gt;
# Model Accuracy: how often is the classifier correct?&lt;br /&gt;
print(&amp;quot;Fichier de test actuel :&amp;quot;,DtoG_test_path)&lt;br /&gt;
print(&amp;quot;Accuracy:&amp;quot;,metrics.accuracy_score(target_test, pred))&lt;br /&gt;
&lt;br /&gt;
test, target_test = ReadAndFill(rien_test_path, target_test, 0)&lt;br /&gt;
&lt;br /&gt;
#Predict the response for test dataset&lt;br /&gt;
pred = clf.predict(test)&lt;br /&gt;
print(pred)&lt;br /&gt;
# Model Accuracy: how often is the classifier correct?&lt;br /&gt;
print(&amp;quot;Fichier de test actuel :&amp;quot;,rien_path)&lt;br /&gt;
print(&amp;quot;Accuracy:&amp;quot;,metrics.accuracy_score(target_test, pred))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;mlpPredic.py : Code similaire servant à tester de charger un modèle créé et sauvegardé auparavant &amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
#Import mlp model&lt;br /&gt;
from sklearn import neural_network&lt;br /&gt;
from sklearn import metrics&lt;br /&gt;
import joblib&lt;br /&gt;
&lt;br /&gt;
GtoD_test_path = 'test_GtoD.txt'&lt;br /&gt;
DtoG_test_path = 'test_DtoG.txt'&lt;br /&gt;
rien_test_path = 'test_rien.txt'&lt;br /&gt;
&lt;br /&gt;
test = []&lt;br /&gt;
data = []&lt;br /&gt;
targets = []&lt;br /&gt;
target_test = []&lt;br /&gt;
&lt;br /&gt;
def ReadAndFill(nom_fichier, target_tab, target_int, taille_sous_liste=1024):&lt;br /&gt;
    try:&lt;br /&gt;
        # Ouverture du fichier en mode lecture&lt;br /&gt;
        with open(nom_fichier, 'r') as fichier:&lt;br /&gt;
            # Lecture du contenu du fichier ligne par ligne&lt;br /&gt;
            lignes = fichier.readlines()&lt;br /&gt;
&lt;br /&gt;
            # Pour chaque ligne, conversion en liste d'entiers&lt;br /&gt;
            tableau = [[int(nombre) for nombre in ligne.split()] for ligne in lignes]&lt;br /&gt;
            tableau_filtre = [sous_liste for sous_liste in tableau if len(sous_liste) == taille_sous_liste]&lt;br /&gt;
            target_tab = len(tableau_filtre) * [target_int]&lt;br /&gt;
&lt;br /&gt;
        return tableau_filtre, target_tab&lt;br /&gt;
    &lt;br /&gt;
    except FileNotFoundError:&lt;br /&gt;
        print(f&amp;quot;Le fichier {nom_fichier} n'a pas été trouvé.&amp;quot;)&lt;br /&gt;
        return []&lt;br /&gt;
    except Exception as e:&lt;br /&gt;
        print(f&amp;quot;Une erreur s'est produite : {e}&amp;quot;)&lt;br /&gt;
        return []&lt;br /&gt;
&lt;br /&gt;
#Create a svm Classifier&lt;br /&gt;
clf = joblib.load('modele_mlp.pkl')&lt;br /&gt;
&lt;br /&gt;
test, target_test = ReadAndFill(GtoD_test_path, target_test, 2)&lt;br /&gt;
&lt;br /&gt;
#Predict the response for test dataset&lt;br /&gt;
pred = clf.predict(test)&lt;br /&gt;
print(pred)&lt;br /&gt;
# Model Accuracy: how often is the classifier correct?&lt;br /&gt;
print(&amp;quot;Fichier de test actuel :&amp;quot;,GtoD_test_path)&lt;br /&gt;
print(&amp;quot;Accuracy:&amp;quot;,metrics.accuracy_score(target_test, pred))&lt;br /&gt;
&lt;br /&gt;
test, target_test = ReadAndFill(DtoG_test_path, target_test, 1)&lt;br /&gt;
&lt;br /&gt;
#Predict the response for test dataset&lt;br /&gt;
pred = clf.predict(test)&lt;br /&gt;
print(pred)&lt;br /&gt;
# Model Accuracy: how often is the classifier correct?&lt;br /&gt;
print(&amp;quot;Fichier de test actuel :&amp;quot;,DtoG_test_path)&lt;br /&gt;
print(&amp;quot;Accuracy:&amp;quot;,metrics.accuracy_score(target_test, pred))&lt;br /&gt;
&lt;br /&gt;
test, target_test = ReadAndFill(rien_test_path, target_test, 0)&lt;br /&gt;
&lt;br /&gt;
#Predict the response for test dataset&lt;br /&gt;
pred = clf.predict(test)&lt;br /&gt;
print(pred)&lt;br /&gt;
# Model Accuracy: how often is the classifier correct?&lt;br /&gt;
print(&amp;quot;Fichier de test actuel :&amp;quot;,rien_test_path)&lt;br /&gt;
print(&amp;quot;Accuracy:&amp;quot;,metrics.accuracy_score(target_test, pred))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Codes internes à la STM :  &lt;br /&gt;
&lt;br /&gt;
Codes internes à la Raspberry pi :  &lt;br /&gt;
&lt;br /&gt;
Codes internes à la VM (présents en réalité sur la machine personnelle) :&lt;/div&gt;</summary>
		<author><name>Fvallee</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:DemoVideo.mp4&amp;diff=4737</id>
		<title>Fichier:DemoVideo.mp4</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:DemoVideo.mp4&amp;diff=4737"/>
		<updated>2024-01-28T12:44:43Z</updated>

		<summary type="html">&lt;p&gt;Fvallee : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Test ECEAI par le groupe Florian Vallée/Amine Sellali, SE5 2023/2024&lt;/div&gt;</summary>
		<author><name>Fvallee</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/ValleeSellali&amp;diff=4732</id>
		<title>SE5 ECEAI/eceai 2023/2024/ValleeSellali</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/ValleeSellali&amp;diff=4732"/>
		<updated>2024-01-28T11:10:03Z</updated>

		<summary type="html">&lt;p&gt;Fvallee : Travail Hors Seance&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Groupe Vallée-Sellali&lt;br /&gt;
&lt;br /&gt;
Séance n°1:&lt;br /&gt;
&lt;br /&gt;
Machine virtuelle créée sur chassiron :&lt;br /&gt;
&lt;br /&gt;
Hostname       :  ValSel&lt;br /&gt;
&lt;br /&gt;
Distribution    :  bookworm&lt;br /&gt;
&lt;br /&gt;
Stockage  : 10G&lt;br /&gt;
&lt;br /&gt;
Mémoire vive : 1G&lt;br /&gt;
&lt;br /&gt;
Mot de passe habituel&lt;br /&gt;
&lt;br /&gt;
Les fichiers /etc/network/interfaces, /etc/resolv.conf et /etc/apt/sources.list ont été modifiés comme demandés.&lt;br /&gt;
&lt;br /&gt;
Raspberry 4 :&lt;br /&gt;
&lt;br /&gt;
Communication via le port série possible&lt;br /&gt;
&lt;br /&gt;
Login : valsel Pwd : pasglop&lt;br /&gt;
&lt;br /&gt;
STM32F401RE : Nanoedge et IDE installés, conception d'un code pour tester le capteur en cours&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Séance n°2 (18/12/2023) :&lt;br /&gt;
&lt;br /&gt;
Raspberry connectée au WiFi SE5&lt;br /&gt;
&lt;br /&gt;
Connexion ipv6 possible entre la VM et la raspberry&lt;br /&gt;
&lt;br /&gt;
Données du capteur lues et envoyées au port série&lt;br /&gt;
&lt;br /&gt;
Création d'un programme python client à destination de la raspberry qui : lit le port série, stocke les données reçues, envoie les données reçues en http vers le &amp;quot;serveur&amp;quot; présent sur la VM&lt;br /&gt;
&lt;br /&gt;
Création d'un programme python serveur à destination de la VM qui reçoit et stocke les données&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Séance 3 (19/12/2023) :&lt;br /&gt;
&lt;br /&gt;
Création des datasets : main fermée et main ouverte (Une ligne = 16 * 16 données, environ 30 lignes par fichier)&lt;br /&gt;
&lt;br /&gt;
Choix de garder les capteurs en 4x4 pour un compromis vitesse de création des datasets/temps d'entrainement du modèle/efficacité du capteur de mouvement.&lt;br /&gt;
&lt;br /&gt;
Entrainement du modèle avec les datasets sur NanoEdge&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Séance 4 (20/12/2023)&lt;br /&gt;
&lt;br /&gt;
Création de nouveaux datasets et de fichiers de tests : (100 lignes de 16 * 16 données)&lt;br /&gt;
&lt;br /&gt;
Création d'un script Python utilisant la bibliothèque sklearn pour implémenter un algorithme de classification SVM, à destination de la Raspberry et de la VM&lt;br /&gt;
&lt;br /&gt;
Le choix de main ouverte/main fermée se questionne, on utilise pas l'aspect mouvement que permet les algorithmes.&lt;br /&gt;
&lt;br /&gt;
Les algorithmes donnent un bon résultat avec une précision proche de 70%. La communication entre la VM et la zabeth sur laquelle on teste les fichiers pythons fonctionne.&lt;br /&gt;
&lt;br /&gt;
Du microcontrôleur, on reçoit les données brutes et l'estimation de l'état de la main. Le fichier python sur la zabeth, à destination future de la raspberry, reçoit ces données via le port série, les stocke dans un fichier txt, fait une estimation de l'état de la main, et envoie les données brutes à la VM en utilisant TCP/IP avec l'adresse IPV6 de la VM.&lt;br /&gt;
&lt;br /&gt;
La VM reçoit les données mais ne les traite pas encore.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Travail hors des séances et rendu final :&lt;br /&gt;
&lt;br /&gt;
Extension du programme sur la STM aux 64 capteurs.&lt;br /&gt;
&lt;br /&gt;
Nouveau choix de test qui prend en compte les mouvements.&lt;br /&gt;
&lt;br /&gt;
Création de nouveaux datasets adaptés : lignes de 64 * 16 données, une ligne correspond à une itération du mouvement, environ 170 lignes par datasets pour une prise en compte de plusieurs cas&lt;br /&gt;
&lt;br /&gt;
(passage rapide, passage lent, hauteurs différentes).&lt;br /&gt;
&lt;br /&gt;
Les mouvements sont : &lt;br /&gt;
&lt;br /&gt;
- Mouvement de gauche à droite&lt;br /&gt;
&lt;br /&gt;
- Mouvement de droite à gauche&lt;br /&gt;
&lt;br /&gt;
- Aucune présence&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir tester les modèles résultant de ces datasets, 3 fichiers de tests sont créés contenant chacun une trentaine d'itérations du mouvement.&lt;br /&gt;
&lt;br /&gt;
Avec Nanoedge, entraînement d'un nouveau modèle à destination de la STM. Le modèle le plus efficace avec nos fichiers de tests sont, contrairement aux premières séances, un modèle MLP (multilayer&lt;br /&gt;
&lt;br /&gt;
perceptron). Résultats avec nos fichiers de tests : précision de 90%&lt;br /&gt;
&lt;br /&gt;
En effet, les modèles SVM ne semblent pas adaptés à nos datasets =&amp;gt; Adaptation du code python de la raspberry pour utiliser lui aussi un modèle MLP, ce qui est plus efficace.&lt;br /&gt;
&lt;br /&gt;
Modèle résultant avec comme input les fichiers de tests : 70% de précision sur Droite à gauche, 68% de gauche à droite, 100% si aucune présence.&lt;br /&gt;
&lt;br /&gt;
Intégration du code GestionData.py dans la raspberry ainsi que du modèle créé par mlpAlgo.py (uniquement l'output)&lt;br /&gt;
&lt;br /&gt;
Réseau : &lt;br /&gt;
&lt;br /&gt;
- La STM32 envoie les données brutes + l'estimation du mouvement issue de son modèle intégré par le port série (knowledge.h, nanoEdgeAi.h, libneai.a et appTof.c sont disponibles en annexe)&lt;br /&gt;
&lt;br /&gt;
- La Raspberry Pi reçoit ces données brutes, les stocke dans un fichier texte, estime le mouvement effectué, et affiche l'estimation en plus de celle de la STM. Ensuite, les données brutes sont transmises à la VM par TCP/IP en IPV6, à la condition que 1024 données soient présentes à chaque lecture. Si ce n'est pas le cas, les données &amp;quot;corrompues&amp;quot; ne sont pas transmises puisqu'inexploitables. (Voir GestionData.py en annexe)&lt;br /&gt;
&lt;br /&gt;
- La VM reçoit les données par paquet de 1024 entiers, stocke les données dans un fichier txt, et fait une estimation du mouvement en utilisant le même modèle que celui présent dans la raspberry pi.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Lors des tests, nous avons constaté que la communication TCP ne semblait pas permise depuis un ordinateur externe au réseau des zabeths vers la VM : le ping est possible, mais la communication ne semble pas. Nous avons donc fait le choix d'utiliser un ordinateur personnel pour montrer l'efficacité du projet : le fonctionnement est similaire, les données sont envoyées sur la machine personnelle en IPV6.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Vidéo :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Annexe&lt;br /&gt;
&lt;br /&gt;
Tous les codes rendus en annexe sont dans leur version finale et ont été utilisés au cours du projet.&lt;br /&gt;
&lt;br /&gt;
Codes externes ayant servis à l'entraînement : &lt;br /&gt;
&lt;br /&gt;
Codes internes à la STM : &lt;br /&gt;
&lt;br /&gt;
Codes internes à la Raspberry pi : &lt;br /&gt;
&lt;br /&gt;
Codes internes à la VM (présents en réalité sur la machine personnelle) :&lt;/div&gt;</summary>
		<author><name>Fvallee</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Atelier_SysRes_SE5_2023/2024_E8&amp;diff=3935</id>
		<title>Atelier SysRes SE5 2023/2024 E8</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Atelier_SysRes_SE5_2023/2024_E8&amp;diff=3935"/>
		<updated>2024-01-16T17:23:51Z</updated>

		<summary type="html">&lt;p&gt;Fvallee : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Cassage de clef WEP d'un point d'accès Wifi'''&lt;br /&gt;
&lt;br /&gt;
Sur Zabeth 8&lt;br /&gt;
&lt;br /&gt;
Afficher les MAC des cracottes :&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
aimon -ng start wlan0&lt;br /&gt;
airodump-ng --ivs wlan0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Choix de la cracotte14&lt;br /&gt;
&lt;br /&gt;
BSSID 04:DA:D2:9C:50:5D&lt;br /&gt;
&lt;br /&gt;
wlan0mon absent, bloquant pour la suite &lt;br /&gt;
&lt;br /&gt;
Impossible d'obtenir la clé avec les outputs de :&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
airodump-ng -b 04:DA:D2:9C:50:5D -w output wlan0&lt;br /&gt;
aircrack-ng -b 04:DA:D2:9C:50:5D output*.cap&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Fichier:Cracotte14.png|vignette|864x864px]]&lt;/div&gt;</summary>
		<author><name>Fvallee</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:Cracotte14.png&amp;diff=3934</id>
		<title>Fichier:Cracotte14.png</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:Cracotte14.png&amp;diff=3934"/>
		<updated>2024-01-16T17:23:18Z</updated>

		<summary type="html">&lt;p&gt;Fvallee : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;cracotte&lt;/div&gt;</summary>
		<author><name>Fvallee</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Atelier_SysRes_SE5_2023/2024_E8&amp;diff=3933</id>
		<title>Atelier SysRes SE5 2023/2024 E8</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Atelier_SysRes_SE5_2023/2024_E8&amp;diff=3933"/>
		<updated>2024-01-16T17:20:47Z</updated>

		<summary type="html">&lt;p&gt;Fvallee : Page créée avec « '''Cassage de clef WEP d'un point d'accès Wifi'''  Sur Zabeth 8  Afficher les MAC des cracottes :&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt; aimon -ng start wlan0 airodump-ng --ivs wlan0 &amp;lt;/syntaxhighlight&amp;gt;Choix de la cracotte14  BSSID 04:DA:D2:9C:50:5D  wlan0mon absent, bloquant pour la suite   Impossible d'obtenir la clé avec les outputs de :&amp;lt;syntaxhighlight&amp;gt; airodump-ng -b 04:DA:D2:9C:50:5D -w output wlan0 aircrack-ng -b 04:DA:D2:9C:50:5D output*.cap &amp;lt;/syntaxhigh... »&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Cassage de clef WEP d'un point d'accès Wifi'''&lt;br /&gt;
&lt;br /&gt;
Sur Zabeth 8&lt;br /&gt;
&lt;br /&gt;
Afficher les MAC des cracottes :&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
aimon -ng start wlan0&lt;br /&gt;
airodump-ng --ivs wlan0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Choix de la cracotte14&lt;br /&gt;
&lt;br /&gt;
BSSID 04:DA:D2:9C:50:5D&lt;br /&gt;
&lt;br /&gt;
wlan0mon absent, bloquant pour la suite &lt;br /&gt;
&lt;br /&gt;
Impossible d'obtenir la clé avec les outputs de :&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
airodump-ng -b 04:DA:D2:9C:50:5D -w output wlan0&lt;br /&gt;
aircrack-ng -b 04:DA:D2:9C:50:5D output*.cap&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Fvallee</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/ValleeSellali&amp;diff=3709</id>
		<title>SE5 ECEAI/eceai 2023/2024/ValleeSellali</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/ValleeSellali&amp;diff=3709"/>
		<updated>2024-01-01T13:00:50Z</updated>

		<summary type="html">&lt;p&gt;Fvallee : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Groupe Vallée-Sellali&lt;br /&gt;
&lt;br /&gt;
Séance n°1:&lt;br /&gt;
&lt;br /&gt;
Machine virtuelle créée sur chassiron :&lt;br /&gt;
&lt;br /&gt;
Hostname       :  ValSel&lt;br /&gt;
&lt;br /&gt;
Distribution    :  bookworm&lt;br /&gt;
&lt;br /&gt;
Stockage  : 10G&lt;br /&gt;
&lt;br /&gt;
Mémoire vive : 1G&lt;br /&gt;
&lt;br /&gt;
Mot de passe habituel&lt;br /&gt;
&lt;br /&gt;
Les fichiers /etc/network/interfaces, /etc/resolv.conf et /etc/apt/sources.list ont été modifiés comme demandés.&lt;br /&gt;
&lt;br /&gt;
Raspberry 4 :&lt;br /&gt;
&lt;br /&gt;
Communication via le port série possible&lt;br /&gt;
&lt;br /&gt;
Login : valsel Pwd : pasglop&lt;br /&gt;
&lt;br /&gt;
STM32F401RE : Nanoedge et IDE installés, conception d'un code pour tester le capteur en cours&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Séance n°2 (18/12/2023) :&lt;br /&gt;
&lt;br /&gt;
Raspberry connectée au WiFi SE5&lt;br /&gt;
&lt;br /&gt;
Connexion ipv6 possible entre la VM et la raspberry&lt;br /&gt;
&lt;br /&gt;
Données du capteur lues et envoyées au port série&lt;br /&gt;
&lt;br /&gt;
Création d'un programme python client à destination de la raspberry qui : lit le port série, stocke les données reçues, envoie les données reçues en http vers le &amp;quot;serveur&amp;quot; présent sur la VM&lt;br /&gt;
&lt;br /&gt;
Création d'un programme python serveur à destination de la VM qui reçoit et stocke les données&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Séance 3 (19/12/2023) :&lt;br /&gt;
&lt;br /&gt;
Création des datasets : main fermée et main ouverte (Une ligne = 16 * 16 données, environ 30 lignes par fichier)&lt;br /&gt;
&lt;br /&gt;
Choix de garder les capteurs en 4x4 pour un compromis vitesse de création des datasets/temps d'entrainement du modèle/efficacité du capteur de mouvement.&lt;br /&gt;
&lt;br /&gt;
Entrainement du modèle avec les datasets sur NanoEdge&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Séance 4 (20/12/2023)&lt;br /&gt;
&lt;br /&gt;
Création de nouveaux datasets et de fichiers de tests : (100 lignes de 16 * 16 données)&lt;br /&gt;
&lt;br /&gt;
Création d'un script Python utilisant la bibliothèque sklearn pour implémenter un algorithme de classification SVM, à destination de la Raspberry et de la VM&lt;/div&gt;</summary>
		<author><name>Fvallee</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/ValleeSellali&amp;diff=3603</id>
		<title>SE5 ECEAI/eceai 2023/2024/ValleeSellali</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/ValleeSellali&amp;diff=3603"/>
		<updated>2023-12-20T13:19:19Z</updated>

		<summary type="html">&lt;p&gt;Fvallee : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Groupe Vallée-Sellali&lt;br /&gt;
&lt;br /&gt;
Séance n°1:&lt;br /&gt;
&lt;br /&gt;
Machine virtuelle créée sur chassiron :&lt;br /&gt;
&lt;br /&gt;
Hostname       :  ValSel&lt;br /&gt;
&lt;br /&gt;
Distribution    :  bookworm&lt;br /&gt;
&lt;br /&gt;
Stockage  : 10G&lt;br /&gt;
&lt;br /&gt;
Mémoire vive : 1G&lt;br /&gt;
&lt;br /&gt;
Mot de passe : glopglop&lt;br /&gt;
&lt;br /&gt;
Les fichiers /etc/network/interfaces, /etc/resolv.conf et /etc/apt/sources.list ont été modifiés comme demandés.&lt;br /&gt;
&lt;br /&gt;
Raspberry 4 :&lt;br /&gt;
&lt;br /&gt;
Communication via le port série possible&lt;br /&gt;
&lt;br /&gt;
Login : valsel Pwd : pasglop&lt;br /&gt;
&lt;br /&gt;
STM32F401RE : Nanoedge et IDE installés, conception d'un code pour tester le capteur en cours&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Séance n°2 (18/12/2023) :&lt;br /&gt;
&lt;br /&gt;
Raspberry connectée au WiFi SE5&lt;br /&gt;
&lt;br /&gt;
Connexion ipv6 possible entre la VM et la raspberry&lt;br /&gt;
&lt;br /&gt;
Données du capteur lues et envoyées au port série&lt;br /&gt;
&lt;br /&gt;
Création d'un programme python client à destination de la raspberry qui : lit le port série, stocke les données reçues, envoie les données reçues en http vers le &amp;quot;serveur&amp;quot; présent sur la VM&lt;br /&gt;
&lt;br /&gt;
Création d'un programme python serveur à destination de la VM qui reçoit et stocke les données&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Séance 3 (19/12/2023) :&lt;br /&gt;
&lt;br /&gt;
Création des datasets : main fermée et main ouverte (Une ligne = 16 * 16 données, environ 30 lignes par fichier)&lt;br /&gt;
&lt;br /&gt;
Choix de garder les capteurs en 4x4 pour un compromis vitesse de création des datasets/temps d'entrainement du modèle/efficacité du capteur de mouvement.&lt;br /&gt;
&lt;br /&gt;
Entrainement du modèle avec les datasets sur NanoEdge&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Séance 4 (20/12/2023)&lt;br /&gt;
&lt;br /&gt;
Création de nouveaux datasets et de fichiers de tests : (100 lignes de 16 * 16 données)&lt;br /&gt;
&lt;br /&gt;
Création d'un script Python utilisant la bibliothèque sklearn pour implémenter un algorithme de classification SVM, à destination de la Raspberry et de la VM&lt;/div&gt;</summary>
		<author><name>Fvallee</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/ValleeSellali&amp;diff=3537</id>
		<title>SE5 ECEAI/eceai 2023/2024/ValleeSellali</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/ValleeSellali&amp;diff=3537"/>
		<updated>2023-12-20T07:11:46Z</updated>

		<summary type="html">&lt;p&gt;Fvallee : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Groupe Vallée-Sellali&lt;br /&gt;
&lt;br /&gt;
Séance n°1:&lt;br /&gt;
&lt;br /&gt;
Machine virtuelle créée sur chassiron :&lt;br /&gt;
&lt;br /&gt;
Hostname       :  ValSel&lt;br /&gt;
&lt;br /&gt;
Distribution    :  bookworm&lt;br /&gt;
&lt;br /&gt;
Stockage  : 10G&lt;br /&gt;
&lt;br /&gt;
Mémoire vive : 1G&lt;br /&gt;
&lt;br /&gt;
Mot de passe : glopglop&lt;br /&gt;
&lt;br /&gt;
Les fichiers /etc/network/interfaces, /etc/resolv.conf et /etc/apt/sources.list ont été modifiés comme demandés.&lt;br /&gt;
&lt;br /&gt;
Raspberry 4 :&lt;br /&gt;
&lt;br /&gt;
Communication via le port série possible&lt;br /&gt;
&lt;br /&gt;
Login : valsel Pwd : pasglop&lt;br /&gt;
&lt;br /&gt;
STM32F401RE : Nanoedge et IDE installés, conception d'un code pour tester le capteur en cours&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Séance n°2 (18/12/2023) :&lt;br /&gt;
&lt;br /&gt;
Raspberry connectée au WiFi SE5&lt;br /&gt;
&lt;br /&gt;
Connexion ipv6 possible entre la VM et la raspberry&lt;br /&gt;
&lt;br /&gt;
Données du capteur lues et envoyées au port série&lt;br /&gt;
&lt;br /&gt;
Création d'un programme python client à destination de la raspberry qui : lit le port série, stocke les données reçues, envoie les données reçues en http vers le &amp;quot;serveur&amp;quot; présent sur la VM&lt;br /&gt;
&lt;br /&gt;
Création d'un programme python serveur à destination de la VM qui reçoit et stocke les données&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Séance 3 (19/12/2023) :&lt;br /&gt;
&lt;br /&gt;
Création des datasets : main fermée et main ouverte (Une ligne = 16 * 16 données, environ 30 lignes par fichier)&lt;br /&gt;
&lt;br /&gt;
Choix de garder les capteurs en 4x4 pour un compromis vitesse de création des datasets/temps d'entrainement du modèle/efficacité du capteur de mouvement.&lt;br /&gt;
&lt;br /&gt;
Entrainement du modèle avec les datasets sur NanoEdge&lt;/div&gt;</summary>
		<author><name>Fvallee</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/ValleeSellali&amp;diff=3488</id>
		<title>SE5 ECEAI/eceai 2023/2024/ValleeSellali</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/ValleeSellali&amp;diff=3488"/>
		<updated>2023-12-18T16:32:49Z</updated>

		<summary type="html">&lt;p&gt;Fvallee : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Groupe Vallée-Sellali&lt;br /&gt;
&lt;br /&gt;
Séance n°1:&lt;br /&gt;
&lt;br /&gt;
Machine virtuelle créée sur chassiron :&lt;br /&gt;
&lt;br /&gt;
Hostname       :  ValSel&lt;br /&gt;
&lt;br /&gt;
Distribution    :  bookworm&lt;br /&gt;
&lt;br /&gt;
Stockage  : 10G&lt;br /&gt;
&lt;br /&gt;
Mémoire vive : 1G&lt;br /&gt;
&lt;br /&gt;
Mot de passe : glopglop&lt;br /&gt;
&lt;br /&gt;
Les fichiers /etc/network/interfaces, /etc/resolv.conf et /etc/apt/sources.list ont été modifiés comme demandés.&lt;br /&gt;
&lt;br /&gt;
Raspberry 4 :&lt;br /&gt;
&lt;br /&gt;
Communication via le port série possible&lt;br /&gt;
&lt;br /&gt;
Login : valsel Pwd : pasglop&lt;br /&gt;
&lt;br /&gt;
STM32F401RE : Nanoedge et IDE installés, conception d'un code pour tester le capteur en cours&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Séance n°2 :&lt;br /&gt;
&lt;br /&gt;
Raspberry connectée au WiFi SE5&lt;br /&gt;
&lt;br /&gt;
Connexion ipv6 possible entre la VM et la raspberry&lt;br /&gt;
&lt;br /&gt;
Données du capteur lues et envoyées au port série&lt;br /&gt;
&lt;br /&gt;
Création d'un programme python client à destination de la raspberry qui : lit le port série, stocke les données reçues, envoie les données reçues en http vers le &amp;quot;serveur&amp;quot; présent sur la VM&lt;br /&gt;
&lt;br /&gt;
Création d'un programme python serveur à destination de la VM qui reçoit et stocke les données&lt;/div&gt;</summary>
		<author><name>Fvallee</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/ValleeSellali&amp;diff=3487</id>
		<title>SE5 ECEAI/eceai 2023/2024/ValleeSellali</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/ValleeSellali&amp;diff=3487"/>
		<updated>2023-12-18T16:31:41Z</updated>

		<summary type="html">&lt;p&gt;Fvallee : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Groupe Vallée-Sellali&lt;br /&gt;
&lt;br /&gt;
Séance n°1:&lt;br /&gt;
&lt;br /&gt;
Machine virtuelle créée sur chassiron :&lt;br /&gt;
&lt;br /&gt;
Hostname       :  ValSel&lt;br /&gt;
&lt;br /&gt;
Distribution    :  bookworm&lt;br /&gt;
&lt;br /&gt;
Stockage  : 10G&lt;br /&gt;
&lt;br /&gt;
Mémoire vive : 1G&lt;br /&gt;
&lt;br /&gt;
Mot de passe : glopglop&lt;br /&gt;
&lt;br /&gt;
Les fichiers /etc/network/interfaces, /etc/resolv.conf et /etc/apt/sources.list ont été modifiés comme demandés.&lt;br /&gt;
&lt;br /&gt;
Raspberry 4 :&lt;br /&gt;
&lt;br /&gt;
Communication via le port série possible&lt;br /&gt;
&lt;br /&gt;
Login : pifou Pwd : pasglop&lt;br /&gt;
&lt;br /&gt;
STM32F401RE : Nanoedge et IDE installés, conception d'un code pour tester le capteur en cours&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Séance n°2 :&lt;br /&gt;
&lt;br /&gt;
Raspberry connectée au WiFi SE5&lt;br /&gt;
&lt;br /&gt;
Connexion ipv6 possible entre la VM et la raspberry&lt;br /&gt;
&lt;br /&gt;
Données du capteur lues et envoyées au port série&lt;br /&gt;
&lt;br /&gt;
Création d'un programme python client à destination de la raspberry qui : lit le port série, stocke les données reçues, envoie les données reçues en http vers le &amp;quot;serveur&amp;quot; présent sur la VM&lt;br /&gt;
&lt;br /&gt;
Création d'un programme python serveur à destination de la VM qui reçoit et stocke les données&lt;/div&gt;</summary>
		<author><name>Fvallee</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/ValleeSellali&amp;diff=3481</id>
		<title>SE5 ECEAI/eceai 2023/2024/ValleeSellali</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/ValleeSellali&amp;diff=3481"/>
		<updated>2023-12-18T16:26:34Z</updated>

		<summary type="html">&lt;p&gt;Fvallee : Page créée avec « Groupe Vallée-Sellali  Séance n°1:  Machine virtuelle créée sur chassiron :  Hostname       :  ValSel  Distribution    :  bookworm  Stockage  : 10G  Mémoire vive : 1G  Mot de passe : glopglop  Les fichiers /etc/network/interfaces, /etc/resolv.conf et /etc/apt/sources.list ont été modifiés comme demandés.  Raspberry 4 :  Communication via le port série possible  Login : pifou Pwd : pasglop  STM32F401RE : Nanoedge et IDE installés, conc... »&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Groupe Vallée-Sellali&lt;br /&gt;
&lt;br /&gt;
Séance n°1:&lt;br /&gt;
&lt;br /&gt;
Machine virtuelle créée sur chassiron :&lt;br /&gt;
&lt;br /&gt;
Hostname       :  ValSel&lt;br /&gt;
&lt;br /&gt;
Distribution    :  bookworm&lt;br /&gt;
&lt;br /&gt;
Stockage  : 10G&lt;br /&gt;
&lt;br /&gt;
Mémoire vive : 1G&lt;br /&gt;
&lt;br /&gt;
Mot de passe : glopglop&lt;br /&gt;
&lt;br /&gt;
Les fichiers /etc/network/interfaces, /etc/resolv.conf et /etc/apt/sources.list ont été modifiés comme demandés.&lt;br /&gt;
&lt;br /&gt;
Raspberry 4 :&lt;br /&gt;
&lt;br /&gt;
Communication via le port série possible&lt;br /&gt;
&lt;br /&gt;
Login : pifou Pwd : pasglop&lt;br /&gt;
&lt;br /&gt;
STM32F401RE : Nanoedge et IDE installés, conception d'un code pour tester le capteur en cours&lt;/div&gt;</summary>
		<author><name>Fvallee</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI_2023/2024&amp;diff=3479</id>
		<title>SE5 ECEAI 2023/2024</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI_2023/2024&amp;diff=3479"/>
		<updated>2023-12-18T16:25:53Z</updated>

		<summary type="html">&lt;p&gt;Fvallee : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;SE5 ECEAI 2023/2024&lt;br /&gt;
&lt;br /&gt;
Groupe Delannoy - Lemaire : [[SE5 ECEAI/eceai 2023/2024/jcie]]&lt;br /&gt;
&lt;br /&gt;
Groupe Rodenburg - Thomas → [[Gabidann|SE5 ECEAI/eceai 2023/2024/gabidann]]&lt;br /&gt;
&lt;br /&gt;
Groupe Halaoui - Farault : [[SE5 ECEAI/eceai 2023/2024/FaraultHalaoui]]&lt;br /&gt;
&lt;br /&gt;
Groupe Godard - Delcourt : [[SE5 ECEAI/eceai 2023/2024/GodardDelcourt]]&lt;br /&gt;
&lt;br /&gt;
Groupe Naudot - Riffaut : [[SE5 ECEAI/eceai_2023/2024/NaudotRiffaut]]&lt;br /&gt;
&lt;br /&gt;
Groupe Amoros - Delaby : [[SE5 ECEAI/eceai 2023/2024/AmorosDelaby]]&lt;br /&gt;
&lt;br /&gt;
Groupe Charleux - Habre : [[SE5 ECEAI/eceai 2023/2024/CharleuxHabre]]&lt;br /&gt;
&lt;br /&gt;
Groupe Balbastre - Simon : [[SE5 ECEAI/eceai 2023/2024/BalbastreSimon]]&lt;br /&gt;
&lt;br /&gt;
Groupe Patrikeev - Mouton : [[SE5 ECEAI/eceai 2023/2024/Patrikeev-Mouton]]&lt;br /&gt;
&lt;br /&gt;
Groupe Brenier - Nguyen : [[SE5 ECEAI/eceai 2023/2024/Brenier-Nguyen]]&lt;br /&gt;
&lt;br /&gt;
Groupe Vallée - Sellali : [[SE5 ECEAI/eceai 2023/2024/ValleeSellali]]&lt;/div&gt;</summary>
		<author><name>Fvallee</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI_2023/2024&amp;diff=3474</id>
		<title>SE5 ECEAI 2023/2024</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI_2023/2024&amp;diff=3474"/>
		<updated>2023-12-18T16:22:17Z</updated>

		<summary type="html">&lt;p&gt;Fvallee : /* Groupe Vallée-Sellali */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;SE5 ECEAI 2023/2024&lt;br /&gt;
&lt;br /&gt;
Groupe Delannoy - Lemaire : [[SE5 ECEAI/eceai 2023/2024/jcie]]&lt;br /&gt;
&lt;br /&gt;
Groupe Rodenburg - Thomas → [[Gabidann|SE5 ECEAI/eceai 2023/2024/gabidann]]&lt;br /&gt;
&lt;br /&gt;
Groupe Halaoui - Farault : [[SE5 ECEAI/eceai 2023/2024/FaraultHalaoui]]&lt;br /&gt;
&lt;br /&gt;
Groupe Godard - Delcourt : [[SE5 ECEAI/eceai 2023/2024/GodardDelcourt]]&lt;br /&gt;
&lt;br /&gt;
Groupe Naudot - Riffaut : [[SE5 ECEAI/eceai_2023/2024/NaudotRiffaut]]&lt;br /&gt;
&lt;br /&gt;
Groupe Amoros - Delaby : [[SE5 ECEAI/eceai 2023/2024/AmorosDelaby]]&lt;br /&gt;
&lt;br /&gt;
Groupe Charleux - Habre : [[SE5 ECEAI/eceai 2023/2024/CharleuxHabre]]&lt;br /&gt;
&lt;br /&gt;
Groupe Balbastre - Simon : [[SE5 ECEAI/eceai 2023/2024/BalbastreSimon]]&lt;br /&gt;
&lt;br /&gt;
Groupe Patrikeev - Mouton : [[SE5 ECEAI/eceai 2023/2024/Patrikeev-Mouton]]&lt;br /&gt;
&lt;br /&gt;
Groupe Brenier - Nguyen : [[SE5 ECEAI/eceai 2023/2024/Brenier-Nguyen]]&lt;br /&gt;
&lt;br /&gt;
Groupe Vallée - Sellali :&lt;/div&gt;</summary>
		<author><name>Fvallee</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI_2023/2024&amp;diff=3264</id>
		<title>SE5 ECEAI 2023/2024</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI_2023/2024&amp;diff=3264"/>
		<updated>2023-12-04T16:58:21Z</updated>

		<summary type="html">&lt;p&gt;Fvallee : /*seance1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;SE5 ECEAI 2023/2024&lt;br /&gt;
[[SE5 ECEAI/eceai 2023/2024/jcie]]&lt;br /&gt;
== Groupe Patrikeev-Mouton ==&lt;br /&gt;
'''Séance n°1:''' &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Une machin virtuelle a été crée sur le serveur chassiron avec la commande :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;coffee&amp;quot;&amp;gt;&lt;br /&gt;
xen-create-image --hostname g19 --force --dist bookworm --size 10G --memory 1G --dir /usr/local/xen --password glopglop --dhcp --bridge bridgeStudents&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La machine virtuelle possède les propriétés suivantes:&lt;br /&gt;
&lt;br /&gt;
Hostname       :  g19&lt;br /&gt;
&lt;br /&gt;
Distribution    :  bookworm&lt;br /&gt;
&lt;br /&gt;
Stockage        : 10G&lt;br /&gt;
&lt;br /&gt;
Mémoire vive : 1G&lt;br /&gt;
&lt;br /&gt;
Mot de passe : glopglop&lt;br /&gt;
&lt;br /&gt;
Les fichier /etc/network/interfaces, /etc/resolv.conf et /etc/apt/sources.list on étés configurés comme demandé dans le sujet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* La Raspberry Pi 4 a été configurée et connectée au WiFi WIFI_IE_1.&lt;br /&gt;
&lt;br /&gt;
Mot de passe : pasglop&lt;br /&gt;
&lt;br /&gt;
Login : pifou&lt;br /&gt;
&lt;br /&gt;
La communication entre la Raspberry et la machine virtuelle a été vérifiée avec une commande de ping.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Le STM32F401RE et le capteur de distance (Nucleo-53L5A1): &lt;br /&gt;
&lt;br /&gt;
Les valeurs lues par le capteurs sont renvoyés par le port série du contrôleur STM32 vers le logiciel nanoedge.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Groupe Vallée-Sellali ==&lt;br /&gt;
'''Séance n°1:'''&lt;br /&gt;
&lt;br /&gt;
Machine virtuelle créée sur chassiron : &lt;br /&gt;
&lt;br /&gt;
Hostname       :  ValSel&lt;br /&gt;
&lt;br /&gt;
Distribution    :  bookworm&lt;br /&gt;
&lt;br /&gt;
Stockage        : 10G&lt;br /&gt;
&lt;br /&gt;
Mémoire vive : 1G&lt;br /&gt;
&lt;br /&gt;
Mot de passe : glopglop&lt;br /&gt;
&lt;br /&gt;
Les fichiers /etc/network/interfaces,  /etc/resolv.conf et /etc/apt/sources.list ont été modifiés comme demandés.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Raspberry 4 :&lt;br /&gt;
&lt;br /&gt;
Communication via le port série possible&lt;br /&gt;
&lt;br /&gt;
Login : pifou Pwd : pasglop&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
STM32F401RE : Nanoedge et IDE installés, conception d'un code pour tester le capteur en cours&lt;/div&gt;</summary>
		<author><name>Fvallee</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_syst%C3%A8me/r%C3%A9seau_2023/2024&amp;diff=1936</id>
		<title>SE5 système/réseau 2023/2024</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_syst%C3%A8me/r%C3%A9seau_2023/2024&amp;diff=1936"/>
		<updated>2023-10-06T14:58:45Z</updated>

		<summary type="html">&lt;p&gt;Fvallee : /* Répartition des binômes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= PRA SE5 =&lt;br /&gt;
&lt;br /&gt;
== Menu de la première séance ==&lt;br /&gt;
&lt;br /&gt;
Pour la  première séance du 06/10/2023 il vous est demandé d'effectuer individuellement les opérations listées ci-dessous.&lt;br /&gt;
* création d'une machine virtuelle sur le serveur &amp;lt;code&amp;gt;capbreton&amp;lt;/code&amp;gt; ;&lt;br /&gt;
* création d'un conteneur &amp;quot;à la main&amp;quot; sur votre station de travail &amp;lt;code&amp;gt;zabeth&amp;lt;/code&amp;gt; :&lt;br /&gt;
** créez un conteneur isolé au maximum (sauf pour les utilisateur) avec la méthode décrite en cours,&lt;br /&gt;
** création d'un commutateur virtuel privé sur la &amp;lt;code&amp;gt;zabeth&amp;lt;/code&amp;gt; dans le réseau IPv4 &amp;lt;code&amp;gt;192.168.68.0/24&amp;lt;/code&amp;gt;, l'adresse &amp;lt;code&amp;gt;192.168.68.1&amp;lt;/code&amp;gt; est affectée au commutateur lui-même,&lt;br /&gt;
** création d'une interface Ethernet virtuelle, une extrémité doit être envoyée dans le conteneur, l'autre dans le commutateur virtuel privé,&lt;br /&gt;
** mise en place d'une mascarade sur la &amp;lt;code&amp;gt;zabeth&amp;lt;/code&amp;gt;, vérifiez que le conteneur a accès aux mêmes machines que la  &amp;lt;code&amp;gt;zabeth&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Par binôme vous devez créer une machine virtuelle mandataire connectée sur le commutateur virtuel SE5 et sur le commutateur virtuel privé des machines virtuelles de services concernées (voir deuxième section du sujet).&lt;br /&gt;
&lt;br /&gt;
Globalement vous devez configurer le routeur principal de la promotion (voir la troisième section du sujet). Pour votre promotion il s'agit du Catalyst 9200 situé en E304. Il faut le connecter en fibre vers le serveur &amp;lt;code&amp;gt;capbreton&amp;lt;/code&amp;gt; de la E306 dans le commutateur virtuel SE5 et aussi en fibre vers le local technique SR52 sur un port dans le VLAN 531. Vous pouvez configurer le commutateur via l'utilitaire &amp;lt;code&amp;gt;minicom&amp;lt;/code&amp;gt; à partir de la machine &amp;lt;code&amp;gt;zabeth09&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Répartition des élèves pour la première séance :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Station de travail !! Elève&lt;br /&gt;
|-&lt;br /&gt;
| zabeth02 || Elias SIMON&lt;br /&gt;
|-&lt;br /&gt;
| zabeth03 || Mathis RIFFAUT&lt;br /&gt;
|-&lt;br /&gt;
| zabeth04 || Dann RODENBURG&lt;br /&gt;
|-&lt;br /&gt;
| zabeth05 || Benjamin NGUYEN&lt;br /&gt;
|-&lt;br /&gt;
| zabeth06 || Halaoui mohammed&lt;br /&gt;
|-&lt;br /&gt;
| zabeth07 || Blgrim Haitam&lt;br /&gt;
|-&lt;br /&gt;
| zabeth08 || Florian Vallée&lt;br /&gt;
|-&lt;br /&gt;
| zabeth09 (routeur) || Julien Charleux&lt;br /&gt;
|-&lt;br /&gt;
| zabeth10 || Amine SELLALI&lt;br /&gt;
|-&lt;br /&gt;
| zabeth11 || Paul Amoros&lt;br /&gt;
|-&lt;br /&gt;
| zabeth12 || Maël Delaby&lt;br /&gt;
|-&lt;br /&gt;
| zabeth13 || Black Baptiste&lt;br /&gt;
|-&lt;br /&gt;
| zabeth14 || Timothé Brenier&lt;br /&gt;
|-&lt;br /&gt;
| zabeth15 || Jeanne Delcourt&lt;br /&gt;
|-&lt;br /&gt;
| zabeth16 || Estelle Godard&lt;br /&gt;
|-&lt;br /&gt;
| zabeth17 || Jason DELANNOY&lt;br /&gt;
|-&lt;br /&gt;
| zabeth18 || Chloé Lemaire&lt;br /&gt;
|-&lt;br /&gt;
| zabeth19 || Gabriel THOMAS&lt;br /&gt;
|-&lt;br /&gt;
| zabeth20 || Albin MOUTON&lt;br /&gt;
|-&lt;br /&gt;
| zabeth21 || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| zabeth22 || Maxime Balbastre&lt;br /&gt;
|-&lt;br /&gt;
| zabeth26 || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| zabeth27 || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| zabeth28 || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| zabeth30 || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Répartition des binômes ==&lt;br /&gt;
&lt;br /&gt;
Concertez-vous pour trouver des noms de machines de services et de machines mandataires dans deux thèmes.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Cahier !! Nom machine services &lt;br /&gt;
!IP machine services !! Nom de domaine !! Nom machine mandataire &lt;br /&gt;
!IP machine mandataires!! Elève &lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E1 | Cahier n°1]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E2 | Cahier n°2]]&lt;br /&gt;
| Elom|| || || || || Elias SIMON&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E3 | Cahier n°3]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E4 | Cahier n°4]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E5 | Cahier n°5]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E6 | Cahier n°6]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E7 | Cahier n°7]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E8 | Cahier n°8]]&lt;br /&gt;
| Fondor|| || || mushu|| || Florian Vallée&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E9 | Cahier n°9]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E10 | Cahier n°10]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E11 | Cahier n°11]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E12 | Cahier n°12]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E13 | Cahier n°13]]&lt;br /&gt;
| Bogden|| || || BlancheNeige|| || Black Baptiste&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E14 | Cahier n°14]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E15 | Cahier n°15]]&lt;br /&gt;
| jiruus|| || || cruella|| || Jeanne Delcourt&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E16 | Cahier n°16]]&lt;br /&gt;
| exegol|| || || cruella|| || Estelle Godard&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E17 | Cahier n°17]]&lt;br /&gt;
| Jakku|| || || Jafar|| || Jason DELANNOY&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E18 | Cahier n°18]]&lt;br /&gt;
| naboo|| || || bouh|| || Chloé Lemaire&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E19 | Cahier n°19]]&lt;br /&gt;
| geonosis|| || || bouh|| || Gabriel THOMAS&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E20 | Cahier n°20]]&lt;br /&gt;
| alderaan|| || || Jafar|| || Albin MOUTON&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E21 | Cahier n°21]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E22 | Cahier n°22]]&lt;br /&gt;
| kashyyyk|| || || mushu|| || Maxime BALBASTRE&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E23 | Cahier n°23]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E24 | Cahier n°24]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Contrôle continu ==&lt;/div&gt;</summary>
		<author><name>Fvallee</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_syst%C3%A8me/r%C3%A9seau_2023/2024&amp;diff=1920</id>
		<title>SE5 système/réseau 2023/2024</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_syst%C3%A8me/r%C3%A9seau_2023/2024&amp;diff=1920"/>
		<updated>2023-10-06T14:15:01Z</updated>

		<summary type="html">&lt;p&gt;Fvallee : /* Menu de la première séance */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= PRA SE5 =&lt;br /&gt;
&lt;br /&gt;
== Menu de la première séance ==&lt;br /&gt;
&lt;br /&gt;
Pour la  première séance du 06/10/2023 il vous est demandé d'effectuer individuellement les opérations listées ci-dessous.&lt;br /&gt;
* création d'une machine virtuelle sur le serveur &amp;lt;code&amp;gt;capbreton&amp;lt;/code&amp;gt; ;&lt;br /&gt;
* création d'un conteneur &amp;quot;à la main&amp;quot; sur votre station de travail &amp;lt;code&amp;gt;zabeth&amp;lt;/code&amp;gt; :&lt;br /&gt;
** créez un conteneur isolé au maximum (sauf pour les utilisateur) avec la méthode décrite en cours,&lt;br /&gt;
** création d'un commutateur virtuel privé sur la &amp;lt;code&amp;gt;zabeth&amp;lt;/code&amp;gt; dans le réseau IPv4 &amp;lt;code&amp;gt;192.168.68.0/24&amp;lt;/code&amp;gt;, l'adresse &amp;lt;code&amp;gt;192.168.68.1&amp;lt;/code&amp;gt; est affectée au commutateur lui-même,&lt;br /&gt;
** création d'une interface Ethernet virtuelle, une extrémité doit être envoyée dans le conteneur, l'autre dans le commutateur virtuel privé,&lt;br /&gt;
** mise en place d'une mascarade sur la &amp;lt;code&amp;gt;zabeth&amp;lt;/code&amp;gt;, vérifiez que le conteneur a accès aux mêmes machines que la  &amp;lt;code&amp;gt;zabeth&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Par binôme vous devez créer une machine virtuelle mandataire connectée sur le commutateur virtuel SE5 et sur le commutateur virtuel privé des machines virtuelles de services concernées (voir deuxième section du sujet).&lt;br /&gt;
&lt;br /&gt;
Globalement vous devez configurer le routeur principal de la promotion (voir la troisième section du sujet). Pour votre promotion il s'agit du Catalyst 9200 situé en E304. Il faut le connecter en fibre vers le serveur &amp;lt;code&amp;gt;capbreton&amp;lt;/code&amp;gt; de la E306 dans le commutateur virtuel SE5 et aussi en fibre vers le local technique SR52 sur un port dans le VLAN 531. Vous pouvez configurer le commutateur via l'utilitaire &amp;lt;code&amp;gt;minicom&amp;lt;/code&amp;gt; à partir de la machine &amp;lt;code&amp;gt;zabeth09&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Répartition des élèves pour la première séance :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Station de travail !! Elève&lt;br /&gt;
|-&lt;br /&gt;
| zabeth02 || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| zabeth03 || Mathis RIFFAUT&lt;br /&gt;
|-&lt;br /&gt;
| zabeth04 || Dann RODENBURG&lt;br /&gt;
|-&lt;br /&gt;
| zabeth05 || Benjamin NGUYEN&lt;br /&gt;
|-&lt;br /&gt;
| zabeth06 || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| zabeth07 || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| zabeth08 || Florian Vallée&lt;br /&gt;
|-&lt;br /&gt;
| zabeth09 (routeur) || Julien Charleux&lt;br /&gt;
|-&lt;br /&gt;
| zabeth10 || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| zabeth11 || Paul Amoros&lt;br /&gt;
|-&lt;br /&gt;
| zabeth12 || Maël Delaby&lt;br /&gt;
|-&lt;br /&gt;
| zabeth13 || Black Baptiste&lt;br /&gt;
|-&lt;br /&gt;
| zabeth14 || Timothé Brenier&lt;br /&gt;
|-&lt;br /&gt;
| zabeth15 || Jeanne Delcourt&lt;br /&gt;
|-&lt;br /&gt;
| zabeth16 || Estelle Godard&lt;br /&gt;
|-&lt;br /&gt;
| zabeth17 || Jason DELANNOY&lt;br /&gt;
|-&lt;br /&gt;
| zabeth18 || Chloé Lemaire&lt;br /&gt;
|-&lt;br /&gt;
| zabeth19 || Gabriel THOMAS&lt;br /&gt;
|-&lt;br /&gt;
| zabeth20 || Albin MOUTON&lt;br /&gt;
|-&lt;br /&gt;
| zabeth21 || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| zabeth22 || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| zabeth26 || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| zabeth27 || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| zabeth28 || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| zabeth30 || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Répartition des binômes ==&lt;br /&gt;
&lt;br /&gt;
Concertez-vous pour trouver des noms de machines de services et de machines mandataires dans deux thèmes.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Cahier !! Nom machine services &lt;br /&gt;
!IP machine services !! Nom de domaine !! Nom machine mandataire &lt;br /&gt;
!IP machine mandataires!! Elève &lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E1 | Cahier n°1]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E2 | Cahier n°2]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E3 | Cahier n°3]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E4 | Cahier n°4]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E5 | Cahier n°5]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E6 | Cahier n°6]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E7 | Cahier n°7]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E8 | Cahier n°8]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E9 | Cahier n°9]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E10 | Cahier n°10]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E11 | Cahier n°11]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E12 | Cahier n°12]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E13 | Cahier n°13]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E14 | Cahier n°14]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E15 | Cahier n°15]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E16 | Cahier n°16]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E17 | Cahier n°17]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E18 | Cahier n°18]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E19 | Cahier n°19]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E20 | Cahier n°20]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E21 | Cahier n°21]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E22 | Cahier n°22]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E23 | Cahier n°23]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E24 | Cahier n°24]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Contrôle continu ==&lt;/div&gt;</summary>
		<author><name>Fvallee</name></author>
	</entry>
</feed>