Mir:ror mon beau Mir:ror…Comment puis-je te comprendre ?

mirorDans mon précédent article, je présentais mir:ror, le petit lecteur RFID commercialisé par la société Violet.  Après avoir survolé leur application « Mirware » et mis en évidence les limites de son utilisation, je vais mettre « les mains dans le cambouis » pour essayer de comprendre comment communiquer avec Mir:ror.  L’idée étant de pouvoir coder de petits outils capables de réagir à des tags RFID.

D’un point de vu système, Mir:ror est directement reconnu sous Linux et accessible via le handler de périphérique /dev/hidrawX (où X est le numéro de périphérique, normalement « 0 » si c’est le premier appareil du genre connecté).

La petite application « discover-device« , fournie avec Mirware, permet de le détecter automatiquement :

discover-device

Attention tout de même aux droits, le périphérique n’est par défaut accessible que par root, il faudra lui changer les droits ou utiliser le script « installer.sh » pour le faire, avant de pouvoir l’exploiter avec un utilisateur standard.

Commençons par voir ce qu’il se passe avec un simple « cat » du fichier :

cat-miror

Des hiéroglyphes s’affichent lorsque nous approchons ou retirons un tag… C’est plutôt bon signe, et visiblement c’est binaire ! Nous devrions y voir plus clair avec un affichage en hexadécimal.  Hexdump est idéal pour ça !

hexdump

La première ligne (0000 0000 0000 0000 0000 0000 0000 0000 *) nous indique que tant qu’il ne se passe rien, on lit des zéros… Où…Qu’on lit des zéros tant qu’il ne se passe rien ! (c’est plutôt normal).
Les deux lignes suivantes (0102 0000 d008 1a02 5303 4202 00d2 0000 – 0000 0000 0000 0000 0000 0000 0000 0000) s’affichent lorsqu’un tag est approché, les deux dernières ( 0202 0000 d008 1a02 5303 4202 00d2 0000 – 0000 0000 0000 0000 0000 0000 0000 0000 ) lorsqu’on éloigne le tag.

Après plusieurs tests, j’en déduis assez facilement que les deux premiers octets (0102 ou 0202) codent l’évènement. J’en ai repéré 4 types :

Les 12 octets suivants semblent identifier la puce RFID.

A titre de test, écrivons rapidement un petit bout de code C, prenant le device en paramètre et affichant les évènements et le tag associé :

// Jopa - Petit test du Mir:ror : test_mirror.c
#include <stdio.h>
#include <stdlib.h>
 
int main(int argc, char *argv[]) {
  FILE *mirror;
  short unsigned int block;
  short unsigned int event;
  char tag[25];
  int i;
 
  //Vérification du paramètre (device)
  if (argc!=2) {
        printf ("Usage : %s mirror_device \n\n",argv[0]);
        exit(-1);
  }
 
  // Ouverture du fichier device
  mirror = fopen(argv[1],"rb");
  if (!mirror) {
        printf("Accès à  %s impossible !\n",argv[1]);
        exit(-1);
  }
 
  // Boucle en lecture
  while (1) {
     fread(&event,2,1,mirror);
     if (event!=0) {
        // Evenement detecté, lecture de l'ID
        for (i=0;i<6;i++) {
            fread(&block,2,1,mirror);
            sprintf(&tag[i*4],"%04X",block);
        }
 
 //Affichage en fonction de l'événement
        switch (event) {
            // Tag On
            case 0x102 :
                printf("%s : ON\n",tag);
                break;
 
             //Tag Off
             case 0x202 :
                 printf("%s : OFF\n",tag);
                 break;
 
             //Mirror envers
             case 0x501 :
                 printf("MIR:ROR ENVERS\n");
                 break;
 
             //Mirror endroit
             case 0x401 :
                   printf("MIR:ROR ENDROIT\n");
                    break;
 
             //Default
             default :
                   printf("Evénement inconnu\n");
        } //switch
      } //if (event
   } //while (1)
} // main()

En quelques lignes, nous ouvrons le périphérique dont le handler est passé en paramètre et bouclons sur sa lecture, 2 octets par 2 octets.
Quand autre chose que « 0 » est détecté, c’est forcément un changement d’état. Nous lisons ensuite l’identifiant de la puce RFID.
La dernière partie affiche un message en fonction de l’évènement détecté.

Il ne reste plus qu’à le compiler et le tester :
$ gcc test_mirror.c -o test_mirror
$ ./test_mirror

test_mirror

Pour compléter l’exemple, nous pouvons rajouter l’exécution d’un script associé au tag et à son approche ou son éloignement. Les scripts pourraient être stockés dans le répertoire de l’utilisateur et porter l’<id>-on.sh ou l’<id>-off.sh comme nom. Pour l’exemple :

#!/bin/sh
firefox http://www.jopa.fr
#!/bin/sh
thunderbird

$ chmod +x ~/0000D0081A025303420200D2-*.sh

Adaptons un peu le code en ajoutant une variable pour le nom du script et une commande « system » dans le « switch/case ».

   // Jopa - Test Mir:ror
 
#include <stdio.h>
#include <stdlib.h>
 
int main(int argc, char *argv[]) {
  FILE *mirror;
  short unsigned int block;
  short unsigned int event;
  char tag[25];
  // Ajout d'un variable script
  char script[256];
  int i;
 
  //Vérification du paramètre (device)
  if (argc!=2) {
        printf ("Usage : %s mirror_device \n\n",argv[0]);
        exit(-1);
  }
 
  // Ouverture du fichier device
  mirror = fopen(argv[1],"rb");
  if (!mirror) {
        printf("Accès à  %s impossible !\n",argv[1]);
        exit(-1);
  }
 
  // Boucle en lecture
  while (1) {
     fread(&event,2,1,mirror);
     if (event!=0) {
        // Evenement detecté, lecture de l'ID
        for (i=0;i<6;i++) {
            fread(&block,2,1,mirror);
            sprintf(&tag[i*4],"%04X",block);
        }
 
 //Affichage en fonction de l'événement
        switch (event) {
            // Tag On
            case 0x102 :
                printf("%s : ON\n",tag);
                //Construction du nom de script et exécution
                sprintf(script,"./%s-on.sh",tag);
                system(script);
                break;
 
             //Tag Off
             case 0x202 :
                 printf("%s : OFF\n",tag);
                 //Construction du nom de script et exécution
                 sprintf(script,"./%s-off.sh",tag);
                 system(script);
                 break;
 
             //Mirror envers
             case 0x501 :
                 printf("MIR:ROR ENVERS\n");
                 break;
 
             //Mirror endroit
             case 0x401 :
                   printf("MIR:ROR ENDROIT\n");
                    break;
 
             //Default
             default :
                   printf("Evénement inconnu");
        } //switch
      } //if (event
   } //while (1)
} // main()

Ceci n’est bien entendu qu’un exemple, écrit rapidement et pas forcément très propre. Mais il permet de mettre en évidence la simplicité avec laquelle il est possible d’accéder à des informations RFID et ouvre la porte sur des développements qui peuvent être rapidement prometteurs.

Laissez votre message après le bip...Biiiiip

Commentaires

Très intéressant. Je ne connaissais pas ce principe. Les possibilités sont nombreuses surtout en domotique et/ou pour du contrôle parental par exemple. Je vais creuser la question;)

euh dans les sources t’aurais pas un peut zapé ce qui a après les « #include »? stdlib.h et stdio.h peut être?
Les « \n » sont également mal passé :/

Euh….Effectivement…merci ! C’est mon pluggin d’affichage de code qui me joue des tours…
C’est corrigé !

Je pense que je vais m’en acheter un pour le fun 😀

Merci pour ses sources extraimement clair, et pour tous les autres articles.

Je voulais savoir le comportement de la CPU lors de l’exécution de la boucle ? Peut on imaginer de laisser tourner en permanence sans perturber le système.

Bonne continuation dans tes tests.

J’ai fait tourner ton programme sur une carte avec un arm (MC9328MXL) sous linux compilé avec linux-arm-gcc. Le souci est que je n’arrive pas lire l’identifiant du tag (je n’ai que des zeros) par contre le premier mot de 16 bits est bien lu car je détecte les événements (on, off, …)
J’ai reussi a contourner le pb en vidant le buffer une fois d’un coup :fread(&block,2,8,mirror). Ensuite avec sprintf je recupere l’identifiant. As tu une idée du bug ?
Merci

Pour reprendre ton expression pour une fonction il y a plein d’utilitaires; il y un, non deux, je crois, petits fous qui on mis ça en ligne :
http://code.google.com/p/erawrim/

En gros ça fait tout pareil comme toi mais ça met une infra en place toute prête, reste qu’il faut faire le boulot de scripting.

c’est raw et je suis sûr que cela n’attend que des contributeurs pour le rendre aussi sexy que mirware 😉

cordialement,

Bonjour,

J’envisage d’utiliser mir:ror sur mes GNU/Linux. Du coup, je cherche des softs pour l’intégrer au mieux. Cet article est génial comme point de départ. J’ai aussi repéré erawrim dans les commentaires, mais celui-ci n’est plus vraiment accessible.

Est-ce que vous connaissez des projets qui sont allés un peu plus loin dans l’intégration ? Personnellement, si rien n’existe, j’envisage de développer un daemon D-Bus, pour permettre le développement de gadgets sur le bureau.

Merci d’avance pour toutes les références que vous voudrez bien partager avec moi.

[…] convient à la lecture de ces paquets. La première solution que j’avais trouvé était en C sur le blog JoPa.fr. Il s’avère qu’il y a un petit projet sur Google Code : erawrim qui est très […]

Laisser un commentaire

(requis)

(requis)