Linux Embedded

Le blog des technologies libres et embarquées

Une Introduction au NFC

La Technologie NFC ( pour Near Field Communication ) est une technologie que l'on trouve sur les téléphones Android modernes mais qui est assez méconnue. Peu de gens savent s'en servir et peu de développeurs l'intègrent à leur application ou aux périphériques qu'ils développent.

C'est assez dommage car les API Android sont particulièrement simples et, avec un minimum d'imagination, le NFC permet de faire facilement des choses très pratiques avec son téléphone.

Introduction au NFC

Le NFC est une technologie de communication point à point très courte portée ( quelques centimètres ) qui permet de courts échanges de données en mettant les terminaux en contact. Cette technologie est une extension de la technologie RFID auquel elle ajoute la communication bi-directionelle. De nos jours on trouve des périphériques utilisables avec les lecteurs NFC des téléphones un peu partout, par exemple :

  • Les badges d'accès d'immeubles sont souvent des devices RFID
  • Les passeports récents contiennent une puce RFID qu'il est possible de lire.
  • Il est facile de trouver sur e-bay des étiquettes NFC que l'on peut lire et écrire grâce à un périphérique Android. Le play-store regorge d'applications qui permettent de faire réagir votre téléphone à la lecture de ces étiquettes.
  • On trouve également des périphériques Bluetooth dont l'appairage est automatisé via NFC.

Le NFC a un débit assez faible ( un maximum de l'ordre de 400 kbits/s ) et nécessite que les périphériques restent en contact. L'envoi d'une simple image prise par l'appareil photo d'un téléphone nécessite donc que les terminaux soient maintenus en contact plusieurs secondes. Ce n'est pas une technologie utilisable pour les communications complexes et il faut en limiter l'usage à des échanges brefs avec le minimum d'intervention de l'utilisateur.

L'une des idées de base du protocole NFC est que le contact physique prouve l'intention de communiquer. Il n'est pas nécessaire de demander confirmation à l'utilisateur car des périphériques NFC ne peuvent pas se toucher accidentellement. Les périphériques NFC se détectent l'un l'autre et cette détection évite d'avoir à ajouter un bouton spécifique dans les applications : Si l'utilisateur met son téléphone en contact avec un badge c'est qu'il veut communiquer avec celui-ci.

NFC et Android : Présentation vue de l'utilisateur.

Les contraintes du NFC font que ce protocole ne peut pas être utilisé pour faire n'importe quoi. L'UI "touch to beam" d'Android permet d'uniformiser l'utilisation du NFC. Le NFC permet d'envoyer ce qui est à l'écran.

  • Dans le carnet d'adresse, on envoie le contact affiché.
  • Dans le play-store, on envoie un lien vers l'application.
  • Dans la galerie on envoie l'image affichée.

Pour l'utilisateur, le NFC passe par deux options de configuration

  • Activation du NFC (qui active la réception automatique sur détection d'un tag)
  • Activation de beam (c'est à dire autoriser les applications à émettre leur contenu sur détection d'un autre appareil Android)

Lorsque deux appareils Android sont mis en contact, le système Android présente l'écran "touch to beam" aux deux utilisateurs. Le premier utilisateur à appuyer sur son écran émet son contenu, l'autre le recevra. Selon la nature du contenu, celui-ci pourra être traité par une application standard (envoi de fichiers) ou par l'application qui est au premier plan sur le terminal émetteur (contenu spécifique à l'application).

Il est intéressant de noter que le système NFC n'est actif que lorsque l'écran est déverrouillé. Il est donc très difficile de récupérer des données d'un téléphone Android sans que son propriétaire soit activement derrière l'écran. Nous voyons à nouveau l'idée que la détection d'un tag NFC est considéré comme une intention de l'utilisateur.

Du point de vue consommation, le NFC étant totalement désactivé en veille, il est difficile de mesurer une quelconque baisse d'autonomie. Le NFC est toujours activé en même temps que l'écran et celui-ci est un des plus gros consommateurs de batterie. La consommation du NFC est difficilement mesurable en pratique.

NFC : La couche physique

Les communications NFC ont lieu via une boucle magnétique (communication en champ proche) et non pas une antenne classique (communication en champ lointain). L'un des deux périphériques est l'initiateur (ou lecteur) et l'autre la cible (ou tag, ou carte). L'initiateur génère un champ magnétique qui crée un courant dans la boucle magnétique de la cible. Comme la communication a lieu en champ proche, la cible peut prélever suffisamment d'énergie du champ magnétique pour s'alimenter.

La communication se fait par modulation d'amplitude. La cible (ou l'initiateur) va moduler l'amplitude du champs RF créé par l'initiateur et cette variation portera l'information entre les deux terminaux. Il est donc aisé pour l'initiateur de repérer la présence de la cible.

Si les deux périphériques peuvent être initiateurs, ils alternent dans ce rôle et peuvent donc communiquer en mode pair à pair.

Mentionnons également l’existence de chargeurs utilisant la boucle de réception NFC pour charger le mobile. Cette pratique ne fait pas partie des standards NFC mais est supportée (sous le nom chargeurs QI) par de nombreux terminaux.

NFC : La couche logicielle

Au niveau logiciel, le NFC souffre d'un historique chargé. De nombreuses normes et protocoles venant d'implémentations non-compatibles peuplent l'environnement. Heureusement les API masquent le plus gros de cette complexité. Je vous recommande cet article pour en savoir plus.

Pour le développeur d'applications Android, le NFC peut être traité de trois façons :

  • Si vous souhaitez envoyer un fichier, l'API fournit une fonction pour enregistrer la liste des URI à envoyer sur détection. Vous pouvez également enregistrer un callback qui fournira cette liste d'URI. Le système se chargera automatiquement de la transmission des fichiers (en s'appairant temporairement via bluetooth pour la transmission) et proposera à l'utilisateur d'ouvrir le fichier à la réception via des applications standards pour ce type de fichier.
  • Si vous souhaitez envoyer un message simple de type NDEF (voir ci-dessous) vous pouvez également enregistrer le message ou enregistrer un callback. Le système décodera les messages entrant pour vous et trouvera l'activité à utiliser en réception en fonction du contenu du message. Il est facile d'envoyer des informations particulières à votre application par message NDEF
  • Enfin, si personne ne traite le message NDEF reçu ou si le tag détecté n'utilise pas le protocole NDEF, le système trouvera une application pour traiter le message en fonction du protocole utilisé par le tag. Ici vous devrez gérer directement la communication bas-niveau (établissement de connexion, lecture/écriture, fermeture de connexion).

Les message NDEF

Les communications NFC sont généralement très brèves. On reçoit ou l'on émet un unique message de type NDEF et celui-ci est généralement prévu pour être le plus court possible.

Un message NDEF est composé d'un certain nombre de Records Chaque record est composé comme suit :

Bit 7     6       5       4       3       2       1       0
------  ------  ------  ------  ------  ------  ------  ------
[ MB ]  [ ME ]  [ CF ]  [ SR ]  [ IL ]  [        TNF        ]
[                         TYPE LENGTH                       ]
[                       PAYLOAD LENGTH                      ]
[                          ID LENGTH                        ]
[                         RECORD TYPE                       ]
[                              ID                           ]
[                           PAYLOAD                         ]

Nous n'allons pas aller dans les détails de la signification de chacun de ces champs. Notons simplement les points suivants

  • Le champ TNF code sur trois bits la nature de champ type.
  • Le champ Type-length et Type décrivent le type de donnée transmise
  • Le champ Payload contient la charge utile
  • Le champ ID contient un identifiant unique du message. Il est peu utilisé en pratique.

Voici par ailleurs quelques constantes du champ TNF pour vous donner une idée de ce que peut contenir un message NDEF

  • TNF_EXTERNAL : le champ type identifie de façon unique une application et un type pour cette application. Le contenu du payload n'est pas défini. Cette valeur permet d'implémenter votre propre protocole pour votre application
  • TNF_WELL_KNOWN : Le champ type contient une constante décrivant un sous-type parmi un certain nombre défini par les normes NFC (text, URI, certains messages protocolaires). Le contenu du payload est défini par le standard en fonction du type.
  • TNF_MIME_MEDIA : le champ type contient une spécification mime, le champ payload contient l'objet transféré.

Envoi par NFC depuis une application Android

Comme souvent avec Android, l'API nous évite de trop nous plonger dans les détails bas-niveau. Voici un exemple de code qui envoie un message contenant deux record (un mime avec du text et un TNF_EXTERNAL spécifique à Android) lorsque l'application est au premier plan et qu'un autre appareil est proche

public class Beam extends Activity implements CreateNdefMessageCallback {
  NfcAdapter mNfcAdapter;
  TextView textView;
  @Override
  public void onCreate(Bundle savedInstanceState) {
    ...
    mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
    if (mNfcAdapter == null) {
      ...
    }
    mNfcAdapter.setNdefPushMessageCallback(this, this);
  }
  @Override
  public NdefMessage createNdefMessage(NfcEvent event) {
    String text = ("Beam me up, Android!\n\n" +   "Beam Time: "
                    + System.currentTimeMillis());
    NdefMessage msg = new NdefMessage(
      new NdefRecord[] {
        createMime("application/vnd.com.example.android.beam",
        text.getBytes()),
        NdefRecord.createApplicationRecord("com.example.android.beam")
      });
    return msg;
  }
}

Ce code est relativement simple, mais arrêtons nous un instant sur la fonction NdefRecord.createApplicationRecord. Cette fonction crée un message spécifique à Android (appelé Android Application Record ou AAR) qui sera reconnu par le système Android et qui permet de garantir que ce sera notre application qui traitera le message à l'autre bout (elle est identifiée par son nom de paquetage). Si l'application n'est pas installée, le système Android récepteur ouvrira l'application play-store pour proposer à l'utilisateur d'installer notre application.

Notons qu'il est possible d'enregistrer directement le message via un appel à NdefAdapter.setNdefPushMessage plutôt que de travailler par callback.

Réception de messages par une Application Android

Si l'envoi de messages est relativement simple, la réception est un peu plus compliqué. Le système va commencer par regarder les différentes technologies utilisées.

Si Le tag fournit un message NDEF le système va chercher une application pour traiter ce message.

  • Si le message contient un record AAR, le message sera traité par l'activité correspondante. Si l'application n'est pas installée le système ouvrira le play-store pour proposer d'installer l'application.
  • Si le message contient un record de type mime, le système recherchera une activité ayant un intent filter pour ce type
  • Sinon, le message sera traité comme un message non-NDEF

L'application recevra un intent ACTION_NDEF_DISCOVERED contenant le message reçu.

Si le message n'est pas un message NDEF ou si le message n'a pas été traité par l'étape précédente, le système cherchera une application capable de traiter la technologie utilisée par le tag NFC. A nouveau des intent-filter dans le Manifest.xml servent à déterminer l'activité à utiliser. Ici il n'est plus possible de filtrer sur le contenu du message (Android n'analyse pas le contenu des protocoles autres que NDEF) et l'API d'accès sera beaucoup plus bas-niveau (établissement de connexion puis transmission, puis déconnexion). C'est également cette étape qui permet d'accéder aux couches basses des tag NFC passifs pour les formater ou les écrire.

Le NFC sous Linux

Le kernel linux dispose d'une stack NFC depuis la version 3.1. La couche kernel fournit un mécanisme de communication via une nouvelle famille de socket (AF_NFC) et de la communication OOB via netlink.

Les applications peuvent se connecter directement sur ces socket mais il est plus commode d'installer le daemon neard. Neard se charge de gérer les évenements NFC et de réagir en conséquence. Il offre une API D-Bus pour permettre aux autres applications de gérer les événements et se charge de parser les trames NDEF à votre place. Il est également capable de gérer l'appairage bluetooth ou wifi avec l'aide de bluez ou connman.

 

Il est intéressant de mentionner que le projet neard fournit également une bibliothèque neardal qui gèrera pour vous la communication D-Bus avec neard.

Conclusion

Le NFC est une technologie encore jeune dont les possibilité laissent un vaste champ d'opportunités à exploiter. L'ajout de cette technologie dans une application Android est très aisé et la stack Linux est bien développée et complète. Le matériel n'est pas très coûteux. Un lecteur USB coûte une trentaine d'euros sur ebay et les stickers et badges NFC ne coûtent que quelques euros pièces. Tout ceci rend cette technologie très abordable et il serait dommage de s'en priver...

Bibliographie

    • le 05 janvier 2014 à 20:54

      […] La Technologie NFC ( pour Near Field Communication ) est une technologie que l'on trouve sur les téléphones Android modernes mais qui est assez méconnue.  […]

    • le 05 janvier 2014 à 21:53

      […] La Technologie NFC ( pour Near Field Communication ) est une technologie que l'on trouve sur les téléphones Android modernes mais qui est assez méconnue.  […]

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée.