La .Taverne de l'Invisible

Une page de Le Lab de la taverne

Le Mir:ror en Python

Par Darko Stankovski, 05/12/2010 (Mise à jour 25/03/2026) — Intermediaire

Le Mir:ror était un lecteur de puces RFID édité par la société Violet, dont le produit phare était le lapin Nabaztag. Dans la lignée des produits communicants, le Mir:ror permet de déclencher ces actions en fonction des puces RFID qui sont posées dessus. Malheureusement, Violet proposait une gestion similaire au Nabaztag, c'est à dire que la configuration se fiasait en ligne et nécessitait d'être connecté à Internet.

Se posaient alors les problèmes classique des données hébergées chez un tiers, mais aussi la pérennité du service, question confirmée par le rachat de Violet par la société Mindscape suite à son redressement judiciaire et l'arrêt de ces services.

Heureusement, le Mir:ror peut facilement être utilisé en local, et nous allons voir comment.

Avant de rentrer dans le vif du sujet, notez que cet article date de 2010 et aborde d'une part une plate-forme qui ne se fait plus mais aussi du code de 2010…

Le Mir:ror est en réalité un périphérique très simple qui envoi un flux de données sur sa connexion USB. Ainsi, on va juste chercher à identifier ces flux de données. Mais auparavant, un petit peu de préparation.

Préparation

L'article Analyse du Mir:ror du GNU/Linux Magazine France hors série de décembre 2010/janvier 2011 détaille assez bien l'identification du périphérique. Un dmesg indique que le Mir:ror est branché en /dev/hidraw1. Si vous voulez vérifier, la commande

dmesg | grep Mirror

devrait retourner la ligne suivante :

generic-usb 0003:1DA8:1301.0002: hiddev96,hidraw1: USB HID v1.00 Device [Violet Mirror] on usb-0000:00:1d.2-2/input0

et on peut vérifier sa présence par

ls /dev/hidraw1

Ce répertoire n'est accessible que par Root, ce qui limite les possibilités d’interaction. La solution la plus simple pour gérer l’accessibilité au périphérique est proposée par le projet Domogik sur sa page de configuration du plug-in pour le Mir:ror. On va ainsi créer une règle UDEV par en éditant le fichier /etc/udev/rules.d/mirror.rules (en root) et en y ajoutant la ligne :

KERNEL=="hidraw*", ATTRS{idVendor}=="1da8", ATTRS{idProduct}=="1301", SYMLINK+="mirror", MODE="0666"

Le Mir:ror sera donc accessible par tout le monde sur /dev/mirror (ce qui est déjà plus lisible). Il suffit de recharger les règles par/etc/init.d/udev restart sur les distributions à base de Debian ou udevadm control restart sur Archlinux.

Utiliser le Mir:ror

Sans rentrer dans les détails ici, l'article du Linux Mag' le détaillant assez bien, les données sont émises par le Mir:ror par paquets de 16 bits. Il va donc falloir lire ces paquets et les interpréter. N'importe quelle techno convient à la lecture de ces paquets. La première solution que j'avais trouvé était en C sur le blog JoPa.fr (n'existe plus). Il s'avère qu'il y a un petit projet sur Google Code : erawrim (n'existe plus non plus…) qui est très similaire. L'article du Linux Mag' reprend le concept en Python et s'approche de l'implémentation qui en est faite dans Domogik.

Le concept est très simple. On va lire les paquets, conserver ceux qui ne sont pas nuls, et agir en conséquence. Pour lire les paquets, on écoute sur l'entrée du Mir:ror. En Python, cela se résume à ces lignes (follement inspirées de l'article du Linux Mag') :

import binascii

mirror = open("/dev/mirror", "rb")

while True:
    data = mirror.read(16)
    if data != '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00':
        rfid_id = binascii.hexlify(donnee)[4:]
        if data[0:2] == '\x02\x01': # Puce posée
            print("Pose puce", rfid_id)

        elif data[0:2] == '\x02\x02': #Puce retirée
            print("Retrait puce", rfid_id)

Ici on se contente d'afficher l'identifiant de la puce RFID lorsqu'elle est posée sur le Mir:ror ou lorsqu'elle est retirée. La stratégie communément appliquée pour réaliser des actions en fonction de la pose ou du retrait d'une puce consiste à créer des fichiers en shell contenant les instructions à exécuter, les fichier étant nommées par l'identifiant de la puce et l'action. Ainsi, à la place du print dans le bloc d'action de la puce posée, on pourrait avoir :

os.system(rfid_id + "-in.sh")

et :

s.system(rfid_id + "-out.sh")

pour la puce retirée.

Évidemment, il faudrait consolider ce code pour éviter les messages d'erreur des puces non connues. Le plus simple est que dans les deux cas on appelle une fonction qui effectuera le test par exemple :

def executeRfidAction(scriptName):
    if not os.path.isfile(scriptName):

        if pynotify.init("icon-summary-body"):
            n = pynotify.Notification(
                "Action not found",
                "The file %s was not found." % (os.path.join(prop.scriptPath, scriptName)),
                "/path/to/my/icon.png")
            n.show()
        print("Le fichier {} n'existe pas, créez le.".format(scriptName))

    else:
        os.system(os.path.join(prop.scriptPath, scriptName))

et là nous allons avoir une jolie notification qui va bien. J'ai conservé le print pour faciliter le copier/coller du nom de la fonction, mais à chacun d'adapter cette partie (création automatique du fichier, notification plus sexy...).

En conclusion, un cas pratique...

... et qui amuse les ptigeek 2.x : une puce donnée permet d'allumer ou éteindre une lampe contrôlée par une installation X10. Il suffit de mettre dans les scripts correspondant heyu on a1 et heyu off a1 (a1 est évidemment à remplacer par le bon identifiant), et quand on pose le lapinou, la lumière s'allume, quand on le retire, elle s'éteint. Effet garanti.

Voila donc comment créer un proto. Il ne reste plus qu'à l'adapter à ses envies.

Licence Creative Commons

Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Pas de Modification 4.0 International