Raspberry Pi et domotique

raspberry-ban
Afin d’appareiller nos maisons respectives, nous cherchions une solution domotique abordable.
Après avoir fait le tour du net et des magasins de bricolage, nous nous sommes fixés sur les équipements avec une fréquence de 433Mhz. Ces équipements sont économiques, les protocoles utilisés sont statiques et il est très simple de trouver de quoi communiquer avec.

Le projet

Nous avons profité d’un projet lancé par l’ENSICAEN en partenariat avec Radiospare. Nous souhaitons d’ailleurs les remercier tous les deux pour nous avoir accompagner tant financièrement que techniquement durant ce projet.

La base du projet est la réalisation d’un projet domotique avec Raspberry Pi.

Nous avons choisi de réaliser un petit module à greffer sur les ports du Raspberry Pi afin de pouvoir éteindre et allumer des équipements en RF433 (volets roulants, prises, lumières, etc…).
Une fois ce module réalisé, nous avons développé une interface web afin de pouvoir utiliser et scénariser les équipements.

L’architecture

Nous avons développé notre module à l’aide d’un composant permettant de moduler et démoduler les signaux RF433, le RTX MID 3V.

Afin de capturer les signaux, nous avions besoin d’un système temps réel. La première solution consiste à installer un OS temps réel sur le Raspberry Pi. La seconde consiste à utiliser un micro-contrôleur. Nous sommes partis sur la seconde solution et avons développé sur un PIC18F24k50. Il présente l’avantage d’être petit, économique et de disposer de suffisamment de RAM.

architexture_hard

Les signaux

Les signaux qui permettent de commander les équipements sont statiques. Ceci implique que pour chaque commande allumer et éteindre, le signal émit est identique. La figure ci dessous représente un signal quelconque.

signal

L’objectif de notre module est donc de faire un enregistreur de signal capable de le réémettre. Nous avons remarqué que le signal de commande était réémis plusieurs fois de suite par les émetteurs du commerce. Ceci est dû au fait que le protocole est à sens unique. Il n’y a donc pas de validation (ACK) une fois le signal reçu. Ces espaces vides sont cependant présents sur plusieurs protocoles RF433 que nous avons observé à l’oscilloscope (équipements des marques DIO et Carrefour).

Afin d’acquérir correctement le signal émis à l’intention de ces équipements, nous utilisons l’algorithme suivant :

  1. Lire état (haut/bas)
  2. Si état haut continuer, sinon revenir à 1
  3. Enregistrer le plus longtemps possible
  4. Chercher la plus longue série d’états bas consécutifs
  5. Chercher la plus proche série d’états bas consécutifs de longueur équivalente
  6. Le signal se trouve entre les deux séries d’états bas

Il suffit ensuite d’émettre plusieurs fois ce signal pour allumer ou éteindre un équipement. Cet algorithme a été implémenté en C. L’enregistrement fonctionne sur le module et la recherche du signal (étape 4 à 6) tourne sur le Raspberry Pi.

Le module

Le module se connecte sur les PIN du Raspberry Pi. La communication entre le Raspberry Pi et le PIC18F24k50 est assuré au travers du port série. Pour cela, il a été nécessaire d’utiliser une astuce pour retirer la console du port série d’un Raspberry Pi.
Le module tient dans un boîtier de Raspberry Pi avec une antenne de 8.175 cm de long.
IMG_20141122_172059

Les prochains travaux consisterons à améliorer l’antenne afin d’optimiser la porté en réception afin de permettre l’ajout de nouveaux modules.

Interface Web

Afin de mettre en place l’interface web, nous avons installé un serveur Nginx. La base php et les interfaces ont été développés par Antoine Choquet.

home

equipements

Quand est ce que ça sort

Nous réalisons encore quelques tests avec l’antenne, ce qui peut entraîner quelques changements sur le PCB. En parallèle, nous testons encore un peu le scripts d’installation. Tout ça devrait être prêt dans le courant de décembre, avant noël. Comme toujours, les sources et les schematics seront libres.

Open data, les calendriers

android

Dans cet article nous verrons comment récupérer les données d’un google agenda afin de le rendre exploitable par une application android ou java. Je l’utilise moi même pour le système d’intelligence artificiel qui contrôle ma maison. Je peux ainsi prévoir mes prochains rendez vous et connaitre mes rendez vous de la journée lorsque je me lève. Afin de réaliser le parsing des données, j’utilise la librairie iCal4j qui est assez bien documenté et pour lequel le net regorge d’exemple.

Le format iCalendar

Le format est iCal est un format qui permet de représenter les agendas. Il s’agit d’un format normalisé. La page Wikipedia à ce sujet est assez bien réalisée et je vous laisse le soin de la visualiser.

Google propose d’exporter vos agendas dans ce format. Vous ne devriez pas rencontrez de difficulté si vous suivez les instructions des services de google à cette adresse. Attention à bien lire jusqu’au bout et à partager votre agenda (le rendre public) pour pouvoir accèder aux données.

Vous devez maintenant avoir un lien iCal qui ressemble à celui ci : « https://www.google.com/calendar/ical/mon.compte%40gmail.com/public/basic.ics »

Quelques exemples

Si vous avez pris le temps de lire la page Wikipedia, vous connaissez maintenant les différents composants que l’ont peux récupérer. Si vous ne l’avez pas encore fait je vous invite à le faire, c’est très rapide et ceci vous permettra de comprendre comment fonctionne le standard.

J’aimerai récupérer mon prochain rendez vous afin de l’afficher par exemple. Si celui ci a lieu dans plus de 7 jours, alors je n’en prends pas compte et indique à l’utilisateur qu’il n’a pas de rendez vous prévu dans les 7 prochains jours.

Pour cela il est nécessaire de :

  1. Récupérer un flux vers l’url de mon google agenda au format iCal
  2. Parser ce flux de données
  3. Filtrer les données pour récupérer les VEVENTs qui ont lieu dans les 7 prochains jours
  4. Afficher le premier VEVENT ou bien un message si il n’y a pas de rendez vous dans les 7 prochains jours

ce qui donne le code correspondant :

//1 Récupérer le flux de icalendar à partir de mon google agenda
URL googleCalendar = new URL("https://www.google.com/calendar/ical/mon.compte%40gmail.com/public/basic.ics");
BufferedReader in = new BufferedReader(new InputStreamReader(googleCalendar.openStream()));
 
//2 Parser le flux de données
CalendarBuilder builder = new CalendarBuilder();
Calendar calendar = builder.build(in);
 
//3 Filtrer les données pour récupérer les VEVENTs qui ont lieu dans les 7 prochains jours
Period period = new Period(new DateTime(today.getTime()), new Dur(7, 0, 0, 0));
Filter filter = new Filter(new PeriodRule(period));
Collection<?> eventsToday = filter.filter(calendar.getComponents(Component.VEVENT));
 
//4 Afficher le premier VEVENT ou bien un message si il n'y a pas de rendez vous dans les 7 prochains jours
Iterator<?> i = eventsToday.iterator();
if (!i.hasNext()) {
   System.out.println("Pas de rendez vous dans les 7 prochains jours");
} else {
   Component component = (Component) i.next();
 
   DateTime dateStart = new DateTime(component.getProperty("DTSTART").getValue());
   //DateTime dateEnd = new DateTime(component.getProperty("DTEND").getValue());
   String description = component.getProperty("DESCRIPTION").getValue();
   String location = component.getProperty("LOCATION").getValue();
   String name = component.getProperty("SUMMARY").getValue();
DateFormat formater = new SimpleDateFormat("dd MMMM yyyy 'à' hh 'heure et' mm 'minutes'",new Locale("FR", "fr"));
 
sentence = "Vous avez rendez-vous " + name + " le " + formater.format(dateStart) + ".";
if(null != location && !location.isEmpty()) {
   sentence = sentence + " Il se tiendra à " + location + ".";
}
 
if(null != description && !description.isEmpty()) {
   sentence = sentence + " La description asocié est " + description + ".";
}
 
System.out.println(sentence);

Afin d’obtenir d’avantage d’exemples, je vous invite à parcourir la page du wiki de iCal4j : http://wiki.modularity.net.au/ical4j/index.php?title=Examples
Vous y trouverez des exemples pour ajouter / récupérer des VEVENT, VCARD, générer un iCal etc…

Open data, parsing XML

android

On entend beaucoup parler de l’open data. Ce concept qui veut ouvrir les données afin que tout le monde puisse les réutiliser est en théorie une grande idée qui permet au plus créatif de réaliser l’application de leur rêve.

On voit fleurir un peu partout des hackathons qui proposent d’utiliser ces données et lorsqu’il s’agit de s’en servir, les développeurs déchantent assez rapidement. Le principe de l’open data consiste bien souvent à balancer les données dans un format difficile à utiliser.

Pour cet article, nous allons réaliser un convertisseur de devises à l’aide de données accessibles publiquement. Vous pouvez trouver le convertisseur sur le playstore à cette adresse
Vous pouvez aussi accèder directement aux sources sur github

Trouver les données

Sur internet les sites qui proposent les taux de change en temps réels sont assez nombreux. Il s’agit même d’un véritable business utilisé par les traders. Pour notre convertisseur, nous souhaitons avoir une source fiable et gratuite. Le format est aussi asez important, il faut si possible utiliser un format courant comme le XML ou le json. Afin de s’assurer de la fiabilité des données, il n’y a je pense qu’une seule chose à faire, avoir une source de confiance. Afin de trouver des données publiques, je commence toujours par lister l’ensemble des organismes publiques qui me viennent à l’idée et qui pourraient mettre cette donnée en ligne.

Dans notre cas nous cherchons les taux de change, j’ai donc choisi d’orienter mes recherches vers :

  • Les banques centrales
  • Les banques d’état
  • Tout les services de l’état qui pourraient avoir à faire de prés ou de loin à de la monnaie (ministère des affaires étrangères, etc)

A cette liste, je conseille d’ajouter systèmatiquement les organismes de normalisation tel que l’ISO ou l’ANSI. Ces organismes regorgent de données publiques qui sont dans des formats très faciles à gérer (xml ou csv).

Utiliser la donnée

Après ces recherches je suis rapidement tombé sur le site de la banque centrale européenne qui offre un accès en XML aux taux de changede la journée.

La source est fiable et offre en plus de cela des exemples pour les développeurs en php. Je souhaite réaliser une application android, mais les exemples sont souvent un gage de qualité (ou laisse penser que les données on au moins étaient testé).

Voici le fichier XML proposé :

<gesmes:Envelope>
<gesmes:subject>Reference rates</gesmes:subject>
<gesmes:Sender><gesmes:name>European Central Bank</gesmes:name></gesmes:Sender>
<Cube>
<Cube time="2014-08-07">
<Cube currency="USD" rate="1.3368"/>
<Cube currency="JPY" rate="136.76"/>
<Cube currency="BGN" rate="1.9558"/>
<Cube currency="CZK" rate="27.853"/>
...
</Cube>
</Cube>
</gesmes:Envelope>

La banque centrale européenne propose les taux de change par rapport à l’Euro. Afin d’obtenir les autres taux de change, nous réalisons une simple règle de trois.

Pour parser le xml, j’utilise la librairie jdom. Le code proposé sur le github est assez parlant, si vous rencontrez des problèmes n’hésitez pas à poster un commentaire. Le problème suivant est que nous souhaiterions avoir le nom de la monnaie plutôt que le symbole. Pour cela nous retournons à l’étape précèdente et récupérons une autre source.

La source proviens de l’iso (http://www.currency-iso.org/dam/downloads/table_a1.xml), de cette manière je récupére les données suivantes :

<ISO_4217 Pblshd="2014-03-28">
<CcyTbl>
<CcyNtry>
<CtryNm>AFGHANISTAN</CtryNm>
<CcyNm>Afghani</CcyNm>
<Ccy>AFN</Ccy>
<CcyNbr>971</CcyNbr>
<CcyMnrUnts>2</CcyMnrUnts>
</CcyNtry>
<CcyNtry>
<CtryNm>ÅLAND ISLANDS</CtryNm>
<CcyNm>Euro</CcyNm>
<Ccy>EUR</Ccy>
<CcyNbr>978</CcyNbr>
<CcyMnrUnts>2</CcyMnrUnts>
</CcyNtry>
<CcyNtry>
<CtryNm>ALBANIA</CtryNm>
<CcyNm>Lek</CcyNm>
<Ccy>ALL</Ccy>
<CcyNbr>008</CcyNbr>
<CcyMnrUnts>2</CcyMnrUnts>
</CcyNtry>
...

Afin de réaliser l’application j’aurai souhaité avoir un fichier xml comme celui ci :

<?xml version="1.0" encoding="UTF-8"?>
<CurrenciesCode>
...
  <Currency code="CNY">Yuan Renminbi</Currency>
  <Currency code="JPY">Yen</Currency>
  <Currency code="XBD">Bond Markets Unit European Unit of Account 17 (E.U.A.-17)</Currency>
  <Currency code="UGX">Uganda Shilling</Currency>
  <Currency code="RON">New Romanian Leu</Currency>
  <Currency code="UYI">Uruguay Peso en Unidades Indexadas (URUIURUI)</Currency>
  <Currency code="TTD">Trinidad and Tobago Dollar</Currency>
  <Currency code="SHP">Saint Helena Pound</Currency>
  <Currency code="MOP">Pataca</Currency>
...

Pour ce faire, j’ai donc choisi de réaliser une conversion des données et d’inclure directement le fichier dans mon projet android. Je ne pense pas que les devises changent en permanence de nom et dans le cas de l’apparition d’une nouvelle devise, il suffira de mettre à jour l’application avec un fichier mis à jour. Si vous souhaitez récupérer ce fichier, il est présent dans les sources github dans le fichier assets.

Conclusion

Cet article reprend les grand principes pour travailler avec des données publiques. La méthodologie est celle que j’utilise, le choix des données est très important, je vous recommande de toujours choisir des grands organismes qui souhaitent garder à jour les données (et qui on un interêt à le faire).
N’hésitez pas lorsque cela est nécessaire à retraiter la donnée. Ce traitement permet d’alléger votre application mais ne peut se faire que sur les données statiques.

It’s oversimple isn’t it?

Créer une enceinte programable pour Raspberry pi

electro

Dans cet article, nous allons voir comment modifier une enceinte que l’on trouve dans le commerce afin de l’utiliser avec le raspberry pi.

Pour une application, je souhaitais ajouter la voix à mon raspberry et je devais changer l’enceinte de mon réveil. Pour cela, j’ai utilisé une enceinte autoalimentée que l’on peut recharger en USB. Cette solution a deux inconvénients majeurs :

  • L’enceinte grésille lorsqu’elle est alimentée mais qu’aucun son n’est envoyé sur la prise jack
  • On passe notre temps à recharger l’enceinte si elle n’est pas connectée au pi ou alors on occupe un port usb.

La solution serait donc de pouvoir programmer l’allumage et l’extinction de notre enceinte.

Piloter l’enceinte

Afin de rendre l’enceinte pilotable, j’ai choisi d’agir directement sur l’alimentation.
L’idée est d’utiliser le raspberry pi pour alimenter l’enceinte. Afin de pouvoir faire celà, il faut supprimer la batterie de l’enceinte. Si votre enceinte n’a pas de batterie, vous pouvez passer cette étape.

En démontant l’enceinte j’obtiens ce que l’on voit sur l’image suivante :
IMG_20140820_202701

J’ai donc coupé les deux fils reliant la batterie. Je l’ai fait de mainière à pouvoir les ressouder si dans le futur je souhaite réutiliser l’enceinte en mode portable.

Après cela, j’ai remonté l’enceinte et je me suis attaqué à la réalisation d’un cable USB-mini USB comme ceux qui alimentent nos téléphones portables. Choississez un câble assez gros, le soudage n’en sera que plus facile. Il faut maintenant permettre au pi de contrôler cette alimentation. L’alimentation USB est en 5V. Les GPIO du raspberry pi ne sont que en 3V, il va donc falloir faire un petit montage afin d’effectuer cette conversion. Pour cela, j’utilise le composant SFH6206. Voici le schéma :

Screenshot from 2014-08-22 09:48:10

Une fois assemblé, j’obtiens le montage suivant :

IMG_20140821_085943

La programation

Nous allons utiliser les GPIO, pour cela j’ai développé un petit programme en C à l’aide de la librairie bcm2835. Vous pouvez retrouver un exemple d’installation et de compilation dans cet article.

#include <bcm2835.h>
#include <stdio.h>
#include <stdlib.h>
 
#define PIN_ALIM_SPEAKER RPI_GPIO_P1_07
 
int main(int argc, char ** argv) {
   if (!bcm2835_init()) {
        return EXIT_FAILURE;
   }
 
   //On alimente l'enceinte
   bcm2835_gpio_fsel(PIN_ALIM_SPEAKER, BCM2835_GPIO_FSEL_OUTP);
   bcm2835_gpio_write(PIN_ALIM_SPEAKER, HIGH);
 
   //... Jouer un son
 
   //On éteint l'enceinte
   bcm2835_gpio_write(PIN_ALIM_SPEAKER, LOW);
   bcm2835_close();
   return EXIT_SUCCESS;
}

Rendu final

Afin de cacher un peu le montage, j’ai utilisé un vieux boitier de disque dur externe.


OVERSIMPLE : Un réveil avec un raspberry pi par oversimple

Le stockage des mots de passes

android

Il y a quelques jours, je regardai le projet lancé par hackaday de faire un password keeper qui soit offline : Mooltipass

Je me suis dis que c’était quand même bien pratique et que j’en aurai bien besoin sur mon téléphone mobile. Comme ça faisait pas mal de temps que je n’avais pas développé sur Android, c’était l’occasion de réfléchir au plus gros problème que l’on retrouve sur les mobiles, ils ne disposent pas d’un espace sécurisé.

Vous pouvez récupérer l’application sur google play directement à cette adresse : Téléchargement

Le mécanisme de protection

Afin de réaliser ce projet, j’ai supposé que le mobile n’était pas vérolé à priori et qu’aucun touchlogger n’était présent sur celui ci.

En plus de cela, j’ai supposé que l’utilisateur été suffisamment doué pour choisir un mot de passe solide dont on peut sauvegarder le hash sans qu’il soit casser rapidement.

L’idée est donc de chiffrer l’ensemble des mots de passe de l’utilisateur en utilisant un secret que seul l’utilisateur connait.

Pour cela nous allons utiliser les API java cryptographiques et utiliser l’algorithme AES.

Afin de générer le secret pré partagé, nous allons utiliser une phrase secrete. Ce secret consiste en une phrase que seul l’utilisateur connait. Nous utiliserons alors une fonction de hashage pour générer la clé de chiffrement à partir de la phrase secrète de l’utilisateur. A cela nous ajoutons un salt, ceci permet de diversifier le secret pré partagé en fonction de son usage.

La fonction de diversification a été codé comme suis :

private byte[] diversify(String password, String salt) {
	password = password + salt;
	byte[] key = new byte[16];
	MessageDigest sha1 = null;
	try {
		sha1 = MessageDigest.getInstance("SHA");
	} catch (NoSuchAlgorithmException e) {
		e.printStackTrace();
	}
	sha1.update(password.getBytes());
	byte[] hash = sha1.digest();
	System.arraycopy(hash, 0, key, 0, 16);
	return key;
}

Le stockage des données

Afin de stocker les données, nous allons transporter la clé dérivée pour la session courante et utiliser une base de données Android pour stocker les mots de passe. L’ensemble du contenu de la base de données est bien entendu chiffré avant insertion.

Chaque entrée est identifiée par les champs suivants :

public class PasswordReference {
 
	private int id;
	private String description;
	private String login;
	private String password;

L’id est stocké en clair, pour les autres champs, nous utilisons un salt différents pour chacun.

Attaques possibles

La première attaque possible est de regarder par dessus l’épaule. Ainsi l’utilisateur récupère le secret pré partagé.
Une seconde attaque serait d’utiliser un key logguer. Afin de palier à ce genre d’attaque, il faudrait ajouter un deuxième paramètre dans la génération du secret pré partagé. Ce deuxième paramètre serait un code pin avec clavier dynamique. Ainsi un touchlogger deviendrait inefficace pour récupérer le code pin.

Cependant cette technique n’empêcherait pas de bruteforcer les solutions restantes et avec un code pin à 4 chiffres, ça ne fait que 10 000 essais.
L’attaque par bruteforce reste la dernière possible et celle ci peut être évitée à condition de choisir un mot de passe sure et de le changer régulièrement.

Sources

L’ensemble des sources de ce petit programme peut être télécharger sur github à l’adresse suivante : https://github.com/julien14/secretKeeper
Bien sur le programme est libre et sous licence GPL. Enjoy !

La réalité augmentée c’est facile avec Android

android

La réalité augmentée c’est à la mode et ça parait super compliqué. Dans les faits, réaliser une librairie de réalité augmentée, c’est placé correctement des points sur une image en fonction de la position de l’utilisateur. La dite image est retranscrite à partir du capteur CCD du téléphone mobile (comprenais la caméra quoi).

Nous n’allons pas réaliser la librairie mais plutôt réutiliser l’excellent travail de aka pishman3579. Vous pouvez trouver son projet sur gihub ici.

Réaliser la librairie

Avant de commencer, nous allons utiliser son application afin de générer une librairie android. Pour cela commencer par cloner le dépôt github.

git clone https://github.com/phishman3579/android-augment-reality-framework.git

Ensuite dans les propriétés Android, coché isLibrary :

isLibrary

Enfin, vous allez devoir supprimer le fichier Demo.java qui apparaît maintenant avec des erreurs. Ceci est normal, nous le réimplémenterons dans votre application.

Voilà, vous venez maintenant de créer votre librairie de réalité augmentée.

Utiliser la librairie

Commencer par créer un nouveau projet Android et par linker la librairie de réalité augmentée à ce projet :

addLib

Une fois que ceci est fait, ajouter les permissions suivantes à votre manifest :

    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.WAKE_LOCK"/>

Créer maintenant un activitée en réutilisant le fichier Demo.java que vous avez supprimé. Vous pouvez le copier coller ici.

Modifier votre fichier manifest.xml afin de préciser que cette activity se lance sans tilte bar et en mode landscape:

<activity android:name=".activity.MainActivity"
    android:label="@string/app_name"
    android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
    android:screenOrientation="landscape">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>            
</activity>

Conclusion

Si vous compilez vous pouvez observer autour de vous les données récupérées depuis wikipédia. Il est très facile de modifier ce fichier afin d’y ajouter votre propre set d’event récupéré depuis un serveur web ou bien localement. Je vous laisse regarder les fichiers ainsi que le fichier de démo qui est assez explicite. Quoi qu’il en soit si vous avez des questions n’hésitez pas à nous laisser un petit commentaire, nous nous ferons un plaisir de vous répondre.

Réaliser un lecteur de badge avec rasberry pi (Partie 2)

raspberry-ban

Introduction

La semaine dernière, nous en étions restés à la compilation de la librairie libnfc. Si vous avez besoin de vous rafraîchir la mémoire c’est par ici. Aujourd’hui nous allons voir comment lire un badge tel que les badges d’entrée d’immeuble avec un programme en C qui tournera sur raspberry Pi.

Lecture de l’uid

Tout d’abord, il est important de savoir que seul un numéro de série est lu par beaucoup de lecteurs de cartes pour le contrôle d’accès. Ceci n’est absolument pas sécurisé et il est possible d’acheter des cartes (sur le marché chinois) permettant de copier ces badges en utilisant le programme d’exemple nfc-mfsetuid disponible dans le dossier exemple. D’ailleurs, les serruriers ne font qu’une simple copie de votre badge vers un nouveau avant de le verrouiller en écriture.

Il serait tout a fait possible de réaliser un protocole sécurisé mais pour cela, il faudrait des badges équipés de capacité cryptographique et donc plus chers. Les badge d’entrée les plus fréquemment utilisés sont des badges Mifare qui ne coûtent vraiment pas grand chose : MIFARE 4K NXP blanche haute qualité Par 5000 = 0.90 € unitaire trouvé sur google.

Nous allons faire comme eux et simplement lire l’uid. Nous ne prétendrons cependant pas que ce soit sécurisé. Pour cela allons dans le dossier exemples/ et lançons le programme suivant :

sudo ./nfc-poll

Et voilà vous venez de lire l’UID de votre badge !

Code C

Nous allons maintenant repartir du programme nfc-poll afin de le personnaliser et de le réutiliser dans notre application. Toujours dans le dossier exemple :

mkdir badgeReader/utils/
cp nfc-poll.c badgeReader/badgeReader.c
cp ../utils/nfc-utils.h examples/badgeReader/utils/
cp ../utils/nfc-utils.c examples/badgeReader/utils/
cd badgeReader/
gcc badgeReader.c utils/nfc-utils.c -lnfc -o myBadgeReader.o
sudo ./myBadgeReader

Félicitation, vous venez de compiler votre première application avec libnfc. Je vous conseille de garder ce squelette de coté, il constitue une bonne base pour commencer avec le NFC.

Vérifier l’UID

Bien, pour l’instant, nous ne faisions que d’afficher l’UID en réutilisant les programmes déjà présents. nous allons maintenant le récupérer et le comparer afin de vérifier si la personne est autorisée à entrer ou non.

Copier le squelette précédemment construit et remplacer le fichier badgeReader.c par celui écrit ci dessous :

/**
 * @file badgeReader.c
 * @brief read a badge and print a message if the badge is the one attended
 */
 
#include <err.h>
#include <signal.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
 
#include <nfc/nfc.h>
#include <nfc/nfc-types.h>
 
#include "utils/nfc-utils.h"
 
static nfc_device *pnd = NULL;
 
int main(int argc, const char *argv[])
{
	const unsigned char referenceUID[7] ={0x04, 0x3c,  0x76,  0x7a,  0xa6,  0x27,  0x80};
	const unsigned char referenceUIDsz = 7;	
 
	const unsigned char uiPollNr = 20;
	const unsigned char uiPeriod = 2;
 
	/* Defines the modulation types
	 * for the mifare types, only the type A is requested */
	const nfc_modulation nmModulations[1] = {
		{ .nmt = NMT_ISO14443A, .nbr = NBR_106 },
	};
 
	int i;
	const size_t szModulations = 1;
 
	nfc_target nt;
	int res = 0;
 
	nfc_context *context;
	nfc_init(&context);
 
	/* We open the pn53x */
	pnd = nfc_open(context, NULL);
 
	if (pnd == NULL) {
		ERR("%s", "Unable to open NFC device.");
		exit(EXIT_FAILURE);
	}
 
	if (nfc_initiator_init(pnd) < 0) {
		nfc_perror(pnd, "nfc_initiator_init");
		exit(EXIT_FAILURE);
	}
 
	if ((res = nfc_initiator_poll_target(pnd, nmModulations, szModulations, uiPollNr, uiPeriod, &nt))  < 0) {
		nfc_perror(pnd, "nfc_initiator_poll_target");
		nfc_close(pnd);
		nfc_exit(context);
		exit(EXIT_FAILURE);
	}
 
	if (res > 0) {
		printf("Read UID     : ");
		print_hex(nt.nti.nai.abtUid, nt.nti.nai.szUidLen);
		printf("Expected UID : ");
		print_hex(referenceUID, referenceUIDsz);
 
	} else {
		printf("No target found.\n");
	}
	nfc_close(pnd);
	nfc_exit(context);
	exit(EXIT_SUCCESS);
}

Vous pouvez maintenant comparer vos deux UID dans un programme.

Conclusion

Pourquoi ne pas ajouter un module comme celui ci à votre raspberry pi et continuer les développement vers quelques chose de plus sécurisé avec l’ajout d’un code PIN par exemple.

It’s oversimple, isn’t it?