![]() |
Projet e-stock
0.2
BTS SNIR LaSalle Avignon 2020
|
Le système e-stock est un système de gestion permettant la de contrôler et gérer l'utilisation de produits stockés dans une armoire et d'en assurer là traçabilité de l'attribution du matériel et des consommables stockés. Puis de sécuriser l'accès par un contrôle d'accès par badge RFID.
Le lecteur OMNIKEY® 5427CK de HID Global fonctionne dans tous les environnements PC. Indépendant du système d'exploitation et du cas d'usage, les modes CCID ou l'interface Keyboard Wedge fournit la solution idéale sans installer ou assurer des drivers. Cela supprime les problèmes complexes de gestion du cycle de vie du logiciel sur site.
La fonctionnalité d'émulation clavier soit en "QWERTY" ou en "QWERTZ", permet de récupérer et de traiter des données de la carte pour les entrer directement dans les applications en émulant sur la séquence de touches clavier correspondante.
Exemple de trame de badge lu : RFID:30DDA983
Le lecteur prend en charge les technologies haute et basse fréquence dans un seul dispositif, il s'intègre donc facilement dans les environnements multi-technologies et simplifie les migrations de technologies de cartes.
Pour l'organisation du projet et la communication entre tous les membres du groupe, nous avons utilisé :
Les utilisateurs peuvent s'authentifier par lecture d'un badge RFID ou par identifiants, et ont la possibilité de rechercher un article, de consulter le stock ainsi que commander l'ouverture/fermeture des casiers.
Voir la répartition des tâches dans le projet.
Tâches à réaliser | Priorité | Itération |
---|---|---|
Authentification par badge | haute | 1 |
Authentification par identifiant | basse | 1 |
Rechercher un article | haute | 1 |
Consulter les stocks | moyenne | 2 |
Commander l'ouverture des casiers | moyenne | 3 |
Afficher l'état des casiers | moyenne | 3 |
Il est essentiel pour le client de pouvoir réaliser une Authentification par badge. L'Authentification par identifiant permet à un utilisateur de se connecter sans son badge. Comme c'est une fonctionalité de secours, elle a une priorité basse. La tâche sera tout de même réalisée dans l'itération 1 car elle est associée techniquement à l'Authentification par badge.
Les outils logiciels :
Désignation | Caractéristiques |
---|---|
Système de gestion de base de données | MariaDB |
Atelier de génie logiciel | Bouml v7.9 |
Logiciel de gestion de version | Subversion (RiouxSVN) |
Générateurs de documentation | Doxygen version 1.8 |
Environnement de développement | Qt Creator et Qt Designer |
API GUI | Qt 5.11.2 |
La Raspberry Pi 3 :
Désignation | Caractéristiques |
---|---|
Ordinateur | Raspberry Pi 3 |
Écran | Écran tactile 7'' 800x480 |
Système d'exploitation | GNU/Linux Raspbian |
Le lecteur RFID :
Désignation | Caractéristiques |
---|---|
Modèle | OMNIKEY 5427 CK |
Clavier virtuelle | "QWERTY" |
Prise en charge | Haute et basse fréquence |
Dans cette partie, les cas d'utilisation sont :
Le protocole e-stock définit l'ensemble des trames permettant de communiquer entre le SE (Système Embarqué EC) et la Raspberry Pi (IR) avec une liaison série. Il est orienté ASCII.
Le protocole e-stock est basée sur des trames requête/réponse.
Les trames sont composées d'un en-tête pour identifier leur type. L'entête est "`CASIERS`". Le délimiteur de fin de champ est le ';
'. Le délimiteur de fin de trame "`\r\n`".
Trame de requête Raspberry Pi → SE :
CASIERS;requete;n_casier;\r\n
n_casier
: 1
à 8
et 0
= broadcastrequete
: 1
pour une commande d'ouverture de casier et 2
pour une demande d'étatTrame de réponse SE → Raspberry Pi :
CASIERS;reponse;n_casier;donnée;\r\n
n_casier
: 1
à 8
Requête | reponse | donnée |
---|---|---|
pour une commande d'ouverture du casier | 1 | 0 = erreur, 1 = ok |
pour une demande d'état | 2 | 0 = ouvert, 1 = fermé, 2 = inconnu |
Remarque : dans le cas d'une requête en broadcast, les champs n_casier;donnée;
sont répétés pour chaque casier.
La maquette de l'IHM était la suivante :
L'utilisateur doit quand il veut accéder au contenu de l'armoire s'authentifier soit par badge RFID soit par ses identifiants.
Pour s'authentifier avec un badge RFID (c'est le choix par défaut) : il doit présenter son badge
Pour s'authentifier par ces identifiants : il doit saisir son identifiant et son mot de passe
L'utilisateur une fois connecté pourra effectuer une recherche de l'article qu'il souhaite et consulter les stocks de l'article concerné :
L'utilisateur a le choix pour s'authentifier, il peut utiliser :
editingFinished()
qui va déclencher l'authentification par badge ;clicked()
et déclenchera l'authentification par identifiant.Dans de ce scénario, seule la classe Ihm intervient car c'est son rôle d'interagir avec l'utilisateur :
Voir le diagramme de classes complet.
Voir :
Une fois le "badge" réceptionné par la classe Rfid, il faut corriger le contenu de la trame car le lecteur de badge est configuré en clavier virtuel "QWERTY". Il faut traduire les caractères en "AZERTY" avec la méthode Rfid::corrigerBadge()
.
Puis on vérifie que le début de la trame "badge" contient "RFID:" sinon on envoie une erreur avec Rfid::erreurBadgeInvalide()
et on l'affiche avec Ihm::afficherErreurBadge()
. Si la trame contient un entête valide, extrait l'UID et on le signale. Il faut ensuite le vérifier avec Supervision::verifierAuthentificationBadge()
.
Puis on récupère les données liées au badge dans la base de données avec Supervision::recupererDonneesUtilisateur()
qui appelle la méthode Bdd::recuperer()
pour exécuter la requête SQL. On vérifie la présence de données utilisateur sinon on envoie l'erreur utilisateur invalide avec Supervision::reponseDemandeDeConnexion()
. Si les données sont présentes, on vérifie ensuite la date de validité du compte pour envoyer une réponse qui sera ensuite traitée par l'Ihm avec Ihm::traiterDemandeDeConnexion()
. En fonction de la réponse, on appellera soit la méthode Ihm::allerFenetreMenu()
soit on affichera une boîte de dialogue d'erreur. Pour finir, Supervision connectera l'utilisateur avec les données récupérées précédemment.
Voici le diagramme de classes pour ce scénario :
La méthode Ihm::authentifierParBadge()
permet de signaler la trame d'un badge lu par le lecteur si celle-ci n'est pas vide :
La méthode Rfid::corrigerBadge()
traduit les "caractères QWERTY" de la trame du badge vers l'"AZERTY" :
La méthode Supervision::verifierAuthentificationBadge()
va vérifier les données utilisateur récupérés à partir d'une requête SQL et connecter l'utilisateur si besoin :
La méthode Supervision::recupererDonneesUtilisateur()
effectue une demande à la classe Bdd qui effectuera une requête SQL et retournera les données obtenues :
La méthode Supervision::verifierDonneesUtilisateur()
vérifie que les données ne sont pas vides puis ensuite que la date de validité est correcte :
La méthode Supervision::connecterUtilisateur()
vérifiera si un utilisateur n'est pas déjà connecté sinon créera un objet Utilisateur avec ces données :
Pour l'authentification par badge, on utilise la requête SQL suivante :
Cette requête permet de récupérer les informations de l'utilisateur en fonction de l'UID du badge.
On récupère la saisie des identifiants de l'utilisateur et on le signale avec Ihm::identifiantDetecte()
qui déclenche Supervision::verifierAuthentificationIdentifiant()
en lui passant en paramètre l'identifiant et le mot de passe. Cette méthode va ensuite crypter le mot de passe avec Supervision::crypterMotDepasse()
, puis récupérer les données de la base de données en fonction de l'identifiant et du mot de passe crypté avec la méthode Bdd::recuperer()
. On fera appel à la méthode Supervision::verifierDonneesUtilisateur()
qui vérifie la présence de données utilisateur sinon on envoie l'erreur utilisateur invalide avec Supervision::reponseDemandeDeConnexion()
. Si les données sont présentes, on vérifie ensuite la date de validité du compte pour envoyer une réponse qui sera ensuite traitée par l'Ihm avec Ihm::traiterDemandeDeConnexion()
. En fonction de la réponse, on appellera soit la méthode Ihm::allerFenetreMenu()
soit on affichera une boîte de dialogue d'erreur. Pour finir, Supervision connectera l'utilisateur avec les données récupérées précédemment.
Voici le diagramme de classes pour ce scénario :
La méthode authentifierParIdentifiant()
qui permet d'envoyer les champs identifiant et mot de passe s'ils ne sont pas vides :
La méthode verifierAuthentificationIdentifiant()
demandera les informations utilisateur relatives à l'identifiant et au mot de passe crypté, si les données sont correctes on connectera l'utilisateur si nécessaire :
La méthode privée crypterMotDepasse()
effectue le cryptage du mot de passe seulement si celui-ci n'est pas vide :
Pour l'authentification par identifiant, on utilise la requête SQL suivante :
Cette requête permet de récupérer les informations de l'utilisateur en fonction de son identifiant et mot de passe.
L'utilisateur saisi un nom de l'article et déclenche l'exécution de la méthode Ihm::rechercherArticle()
en cliquant sur le bouton "Rechercher". On transmet le traitement à la classe Supervision en appelant Supervision::rechercherArticle()
avec en paramètre le nom d'article à rechercher.
Supervision récupérera les articles qui corresponde avec la méthode Bdd::recuperer()
. Puis elle renverra la liste des articles à l'Ihm avec la méthode Ihm::mettreAJourListeArticle()
. Cette dernière a pour rôle de mettre à jour la liste déroulante contenant la liste d'articles trouvés suite à la recherche effectuée.
Voici le diagramme de classes pour ce scénario :
La méthode rechercherArticle()
de la classe Ihm qui récupère le contenu de la recherche et le signale à la classe Supervision :
La méthode rechercherArticle()
de la classe Supervision va demander à la classe Bdd de récupérer la liste des articles qui "ressemble" au contenu recherché :
La méthode mettreAJourListeArticles()
met à jour la liste des articles trouvés dans la liste déroulante. Une déconnexion/connexion signal/slot est nécessaire pour éviter un déclenchement pendant la mise à jour :
Pour récupérer les informations de l'article en fonction du nom, on effectue une requête SQL qui utilise LIKE
. Les informations sur l'article recherché nécessite d'effectuer une jointure entre les tables "Stock" et "Article" :
L'utilisateur sélectionne un article dans la liste déroulante. Cela déclenche le slot Ihm::selectionnerArticle()
qui appelle Supervision::selectionnerArticle()
avec en paramètre le nom de l'article sélectionné. Un objet Article est alors instancié. Il faut récupérer le nombre de casiers de l'armoire car il est possible qu'un article soit réparti dans plusieurs casiers. On appelle alors la méthode static Article::recupererNombreCasiersPourNomArticle()
.
Pour chaque casier, on récupère les données de l'article avec Article::recupererDonneesArticleParNumeroCasier()
puis, si des données ont été récupérées, on appelle Ihm::afficherDonneesArticleSelectionne()
pour les afficher.
Voici le diagramme de classes pour ce scénario :
La méthode selectionnerArticle()
de la classe Ihm envoie le nom de l'article sélectionné dans la liste déroulante à partir de son index :
La méthode selectionnerArticle()
de la classe Supervision récupère les données de l'article différemment si l'article est dans un casier ou plusieurs, puis les envoie à l'ihm pour les afficher :
La méthode afficherDonneesArticleSelectionne()
pour un article affiche simplement les données dans l'interface graphique :
La méthode afficherDonneesArticleSelectionne()
pour un article dans plusieurs casiers traite l'ensemble des données reçues pour déterminer la quantité et disponibilités totales afin de les afficher :
Dans ce scénario, on utilise plusieurs requêtes SQL :
Test | Article | Résultats attendus | Résultats obtenus | Validation |
---|---|---|---|---|
Recherche mot approché (casse) | fluke | Fluke i30s Fluke 179 | Fluke i30s Fluke 179 | Oui |
Recherche mot exact | Fluke i30s | Fluke i30s | Fluke i30s | Oui |
Recherche d'un article non existant | test | Aucun article | Aucun article | Oui |
Test | Article | Résultats attendus | Résultats obtenus | Validation |
---|---|---|---|---|
Consultation un article dans un casier | Fluke 179 | Quantité : 2 Disponible : 2 Casier : 2 | Quantité : 2 Disponible : 2 Casier : 2 | Oui |
Consultation un article dans plusieurs casiers | Fluke i30s | Quantité : 8 Disponible : 6 Casier : 1 et 3 | Quantité : 8 Disponible : 6 Casier : 1 et 3 | Oui |
Test | Identifiant/Mot de passe | Résultats attendus | Résultats obtenus | Validation |
---|---|---|---|---|
Identifiant et mot de passe valide | jbeaumont/"" | Affichage fenêtre stock | Affichage fenêtre stock | Oui |
Identifiant et mot de passe valide et date invalide | bounoir.f/"" | Affichage "Erreur : le compte n'est plus valide" | Affichage "Erreur : le compte n'est plus valide" | Oui |
Identifiant valide et mot de passe invalide | jbeaumont/test | Affichage "Erreur : utilisateur non valide" | Affichage "Erreur : utilisateur non valide" | Oui |
Identifiant valide et mot de passe invalide | test/"" | Affichage "Erreur : utilisateur non valide" | Affichage "Erreur : utilisateur non valide" | Oui |
Test | Badge | Résultats attendus | Résultats obtenus | Validation |
---|---|---|---|---|
Badge non valide | RGFD:30DDA983 | Affichage "Erreur badge invalide" | Affichage "Erreur badge invalide" | Oui |
Badge valide | 30DDA983 | Affichage fenêtre stock | Affichage fenêtre stock | Oui |
Badge valide mais date de validité invalide | 62A3F560 | Affichage "Erreur : le compte n'est plus valide" | Affichage "Erreur : le compte n'est plus valide" | Oui |
Badge non présent dans la base de données | 335C3086 | Affichage "Erreur : utilisateur non valide" | Affichage "Erreur : utilisateur non valide" | Oui |
Fonctionnalités réalisées :
Fonctionnalités en cours :