BLE sous le microscope (ATT, GATT…)

BLE sous microscope (ATT et GATT...)

BLE sous microscope (ATT et GATT...)

Partie 1, aperçu

Il s'est déjà écoulé un certain temps depuis la publication de la première spécification Bluetooth 4.0. Et bien que le sujet BLE soit très intéressant, il continue de repousser de nombreux développeurs en raison de sa complexité. Dans mes articles précédents, j'ai principalement examiné le niveau le plus bas, le Link Layer et le Physical Layer. Cela a permis d'éviter d'aborder des concepts compliqués et déroutants tels que le protocole d'attributs (ATT) et le profil générique d'attributs (GATT). Cependant, il n'y a pas moyen d'échapper à cela : sans comprendre ces concepts, il est impossible de développer des appareils compatibles. Aujourd'hui, je voudrais partager ces connaissances avec vous. Dans mon article, je vais m'appuyer sur tutoriel un guide pour débutants du site Nordic. Alors, commençons.

Pourquoi tout est-il si compliqué ?

À mon avis, il était évident dès le départ que le contrôle des appareils via des smartphones est un sujet très prometteur et durable. C'est pourquoi il a été décidé de le structurer dès le départ et au maximum, afin que les fabricants de différents gadgets ne créent pas leurs propres protocoles qui seraient ensuite incompatibles. D'où vient la complexité. Dès le premier stade, le protocole BLE a essayé d'incorporer tout ce qui était possible, peu importe si cela serait utile par la suite ou non. De plus, la possibilité d'élargir la liste des appareils pour l'avenir a été prévue.

Jetons un œil à l'image qui montre le schéma du protocole BLE. Il est composé de plusieurs couches. La couche la plus inférieure, la couche physique (PHY), est responsable du canal radio de l'appareil. Le Link Layer (LL) contient toute la séquence de bytes dans le message transmis. Dans les articles précédents, nous avons étudié spécifiquement cette couche. L'interface de contrôle d'hôte (HCI) est le protocole d'échange entre les couches ou les puces BLE, si le contrôleur et l'hôte sont implémentés sur différentes puces. La formation des paquets, le découpage en trames, le contrôle des erreurs et l'assemblage des paquets sont pris en charge par le protocole de contrôle logique de lien et d'adaptation (L2CAP). Le protocole de gestion de la sécurité (SMP) est responsable du chiffrement des paquets. Le profil d'accès générique (GAP) gère l'échange initial de données entre les appareils pour déterminer « Qui est qui ». Il couvre également le scanning et la publicité. Dans cet article, je vais m'attarder sur les deux autres parties restantes du protocole - GATT et ATT. GATT est une couche sur ATT, donc ils sont étroitement entrelacés.

BLE sous microscope (ATT et GATT...)

Pour simplifier le discours, je voudrais faire appel à une analogie. Je l'ai entendue quelque part et je souhaite l'appuyer. Imaginez un appareil BLE comme une bibliothèque avec plusieurs étagères. Chaque étagère représente un sujet distinct. Par exemple, nous avons des étagères de science-fiction, de mathématiques, d'encyclopédies. Sur chaque étagère se trouvent des livres sur le sujet indiqué. Et dans certains livres, il y a même des signets avec des notes. De plus, nous avons un petit catalogue papier de tous les livres. Si vous vous souvenez des bibliothèques scolaires — c'est un tiroir étroit avec des fiches en papier. Dans cette analogie, la bibliothèque représente le profil de notre appareil. Les étagères représentent les services, les livres représentent les caractéristiques, et le catalogue représente le tableau des attributs. Les signets dans les livres sont des descripteurs, que je décrirai également plus en détail plus tard.

Tous ceux qui développent des appareils savent que dans de nombreux projets, il existe des morceaux de code similaires. En effet, de nombreux appareils ont des fonctionnalités similaires. Par exemple, si des appareils fonctionnent sur batterie, le problème de la recharge et du contrôle de leur niveau sera le même. Il en va de même pour les capteurs. En fait, l'approche orientée objet en programmation « permet de créer des objets qui combinent propriétés et comportements en une seule entité autonome, qui peut ensuite être réutilisée plusieurs fois ». À mon avis, une tentative d'approche similaire a été faite dans BLE. Un groupe d'intérêt spécial Bluetooth (SIG) a développé des profils. Les appareils de différents fabricants ayant les mêmes profils devraient fonctionner sans difficulté ensemble. Les profils sont composés de services, et les services de caractéristiques complétées par des descripteurs. En général, cela peut ressembler à ceci :

BLE sous microscope (ATT et GATT...)

Prenons, par exemple, le schéma du profil moniteur de fréquence cardiaque (bracelet de fitness). Il se compose de deux services et de plusieurs caractéristiques. Cela permet de comprendre immédiatement la hiérarchie du profil. La caractéristique de point de contrôle remet à zéro le total des calories brûlées.

1. Le service de fréquence cardiaque comprend trois caractéristiques (0x180D) :
    a) Caractéristique obligatoire de la fréquence cardiaque (0х2A37)
    b) Caractéristique optionnelle de la position du capteur corporel (0x2A38)
    c) Caractéristique conditionnelle de point de contrôle de fréquence cardiaque (0x2A39)
2. Service de gestion de batterie (0x180F) :
    a) Caractéristique obligatoire du niveau de charge de la batterie (0x2A19)

UUID

Pour que nous puissions faire référence de manière unique aux éléments de profil (services, caractéristiques et descripteurs), il est nécessaire de les numéroter d'une certaine manière. À cet effet, le concept d'Universally Unique ID (UUID) ou Identifiant unique universel a été introduit. Entre parenthèses, chaque ligne indique en effet l'UUID. Et ici, il y a une particularité. Pour les UUID, il a été décidé d'utiliser un code de 16 et 128 bits. Pourquoi, vous demandez-vous ? Dans le protocole BLE, tout est soumis à la conservation de l'énergie. Ainsi, une dimension de 16 bits est tout à fait raisonnable. Il est peu probable qu'il y ait plus de 65 000 services et caractéristiques uniques à créer dans un avenir proche. Pour l'instant, tout ce que nous pouvions, nous l'avons déjà compté (rappelez-vous d'où cela vient - « il vous a compté aussi » :-)) Éléments numérotés profils, services, caractéristiques et descripteurs vous pouvez consulter via les liens.

Cependant, je pense que tout le monde se souvient de l'histoire des 4 octets d'adresse IP sur Internet. Au départ, on pensait que c'était suffisant, mais nous n'avons toujours pas réussi à passer à une adresse à 6 octets. Pour éviter de répéter cette erreur et donner aux bricoleurs un champ d'action, la SIG a immédiatement décidé d'introduire également des UUID de 128 bits. Cela me rappelle personnellement la bande non licenciée de 433 MHz, qui a été laissée aux différents inventeurs du canal radio. Dans notre cas, un identifiant de 128 bits pour les services et caractéristiques a été attribué. Cela signifie que nous pouvons utiliser pratiquement n'importe quelle valeur de 128 bits pour nos services et appareils. De toute façon, la probabilité de créer un UUID identique tend vers zéro.

En réalité, les UUID courts de 16 bits ont leur extension jusqu'à une valeur de 128 bits. Dans la spécification, cette extension est appelée Bluetooth Base UUID et a la valeur 00000000-0000-1000-8000-00805F9B34FB. Par exemple, si un UUID d'attribut de 16 bits a la valeur 0x1234, alors l'UUID équivalent de 128 bits aura la valeur 00001234-0000-1000-8000-00805F9B34FB. De plus, la formule correspondante est fournie :

                                128_bit_value = 16_bit_value * 2^96 + Bluetooth_Base_UUID

D'où vient ce nombre magique, je ne le sais pas. Si l'un des lecteurs sait, qu'il l'écrive dans les commentaires (L'utilisateur avec le pseudo Sinopteek l'a déjà fait. Voir les commentaires). En ce qui concerne la création d'UUID de 128 bits, il est en principe possible d'utiliser un générateur, qui le fera pour vous.

ATT et GATT…

C'est ici que commence la partie la plus intéressante. Je rappelle que ATT est basé sur la relation client-serveur. Nous examinons maintenant le dispositif du serveur. Il contient des informations telles que les valeurs des capteurs, l'état de l'interrupteur, les données de localisation, etc. Maintenant que tous les « participants à notre parade » sont numérotés, il faut les organiser d'une manière ou d'une autre dans la mémoire de l'appareil. Pour cela, nous les plaçons dans un tableau appelé tableau d'attributs. Gardez cela en tête. C'est le cœur même du BLE. C'est ce que nous allons approfondir par la suite. Maintenant, chaque ligne sera appelée un attribut. Ce tableau se trouve au cœur de la pile et, généralement, nous n'avons pas d'accès direct à lui. Nous l'initialisons et y accédons, mais ce qui se passe à l'intérieur reste caché derrière sept sceaux.

Regardons l'image de la spécification, mais avant cela, je tiens à souligner la confusion fréquente concernant les termes, notamment les descripteurs. Le rôle du descripteur est de compléter la description d'une caractéristique. Lorsqu'il est nécessaire d'élargir ses capacités, on utilise alors des descripteurs. Ils sont également des attributs et, comme les services et les caractéristiques, sont placés dans le tableau d'attributs. Nous les examinerons en détail dans la deuxième partie de l'article. Cependant, parfois, le terme descripteur désigne le numéro de ligne dans le tableau d'attributs. Il est bon d'en tenir compte. Pour éviter toute confusion, nous utiliserons le terme « pointeur d'attribut » à ces fins.
BLE sous microscope (ATT et GATT...)

Ainsi, un attribut est une valeur discrète qui possède les propriétés suivantes :
1. Pointeur d'attribut (Attribute Handle) — c'est l'indice du tableau correspondant à l'attribut
2. Type d'attribut (Attribute Type) — c'est l'UUID qui décrit son type
3. Valeur d'attribut (Attribute Value) — ce sont les données indexées par le pointeur d'attribut
4. Permissions d'attribut (Attribute Permissions) — c'est une partie de l'attribut, les permissions qui ne peuvent pas être lues ou écrites en utilisant le protocole d'attributs

Comment comprendre tout cela ? Un pointeur d'attribut est, en quelque sorte, son numéro dans notre tableau.
Il permet au client de faire référence à un attribut dans les demandes de lecture ou d'écriture. Nous pouvons numéroter nos lignes (attributs) de 0x0001 à 0xFFFF. Dans notre association avec une bibliothèque, c'est le numéro de la fiche dans le catalogue papier. De la même manière, comme dans le catalogue d'une bibliothèque, les fiches sont classées par numéro croissant. Chaque ligne suivante doit avoir un numéro supérieur à celui de la précédente. Tout comme dans une bibliothèque, certaines fiches peuvent parfois être perdues ; il en va de même pour nous : il peut y avoir des lacunes dans le numérotage des lignes. Cela est acceptable. L'essentiel est qu'elles soient en ordre croissant.

Le type d'attribut détermine ce que représente cet attribut. Par analogie avec le langage C,
où il existe des variables booléennes, numériques et des chaînes, ici aussi. Par le type d'attribut, nous savons
avec quoi nous avons à faire et comment nous devons travailler avec cet attribut par la suite. Ci-dessous, nous examinerons certains types d'attributs spécifiques. Par exemple, «déclaration de service» (0x2800), «déclaration de caractéristiques» (0x2803), «déclaration de descripteur» (0x2902).

La valeur de l'attribut est en fait sa valeur, excusez la tautologie. Si le type d'attribut est une chaîne, alors la valeur de l'attribut peut être, par exemple, le slogan «Hello World !!!». Si le type d'attribut est une «déclaration de service», alors sa valeur est le service lui-même. Parfois, il s'agit d'informations sur où trouver d'autres attributs et leurs propriétés.

Les autorisations d'attributs permettent au serveur de comprendre si l'accès en lecture ou en écriture est autorisé.
Notez que ces autorisations s'appliquent uniquement à la valeur de l'attribut, et non au pointeur, au type et au champ d'autorisation lui-même. C'est-à-dire que si l'écriture de l'attribut est autorisée, nous pouvons remplacer, par exemple, la ligne «Hello World !!!» par la ligne «Good morning». Mais nous ne pouvons pas interdire l'écriture d'une nouvelle ligne ou changer le type d'attribut et désigner la ligne comme une «déclaration de service». Lorsqu'un client se connecte au serveur, il demande ses attributs. Cela permet au client de savoir ce que le serveur peut offrir. Cependant, il n'est pas nécessaire de lire et d'écrire les valeurs.

À quoi cela ressemble

Le concept de GATT consiste à regrouper les attributs dans la table des attributs dans un ordre très spécifique et logique. Examinons de plus près le profil de fréquence cardiaque ci-dessous. La colonne la plus à gauche de cette table est facultative. Elle nous décrit simplement ce qu'est cette ligne (attribut). Toutes les autres colonnes nous sont déjà familières.

BLE sous microscope (ATT et GATT...)

En haut de chaque groupe, nous avons toujours un attribut d'annonce de service. Son type est toujours égal à 0x2800, et le pointeur dépend du nombre d'attributs déjà présents dans la table. Ses autorisations sont toujours en lecture seule, sans aucune vérification d'authenticité ou d'autorisation. Nous parlerons de ces concepts un peu plus tard. La valeur est un autre UUID qui définit de quel service il s'agit. Dans la table, la valeur est égale à 0x180D, qui est définie par Bluetooth SIG comme le service de fréquence cardiaque.

Suite à l'annonce du service, il y a l'annonce de la caractéristique. Sa forme ressemble à celle de l'annonce du service. Son UUID a toujours la valeur 0x2803, et les autorisations sont également toujours en lecture seule, sans vérification d'authenticité ou d'autorisation. Regardons le champ de la valeur de l'attribut, qui inclut certaines données. Il contient toujours un pointeur, un UUID et un ensemble de propriétés. Ces trois éléments décrivent l'annonce suivante de la valeur caractéristique. Le pointeur indique naturellement où se trouve l'annonce de la valeur caractéristique dans la table des attributs. L'UUID décrit quel type d'information ou de valeur nous pouvons attendre. Par exemple, la valeur de température, l'état d'un interrupteur ou toute autre valeur arbitraire. Enfin, les propriétés décrivent comment interagir avec la valeur caractéristique.

Ici, nous sommes confrontés à un autre piège. Il est lié aux autorisations des attributs et aux propriétés des caractéristiques. Regardons l'image des propriétés du champ binaire dans la spécification.

BLE sous microscope (ATT et GATT...)

Comme vous pouvez le voir, il y a également des champs permettant la lecture et l'écriture. Vous vous demandez peut-être pourquoi nous avons des autorisations en lecture/écriture pour l'attribut et la propriété.
Quelles sont les permissions de lecture/écriture pour la valeur d'une caractéristique ? Ne devraient-elles pas toujours être identiques ? En réalité, les propriétés de la valeur d'une caractéristique ne sont que des recommandations pour le client, utilisées dans le GATT et les couches applicatives. Ce sont simplement des indications sur ce que le client peut attendre de l'attribut de déclaration de la caractéristique. Examinons cela de plus près. Quels types de permissions existent pour l'attribut ?

1. Permissions d'accès :
     — lecture
     — écriture
     — lecture et écriture
2. Permission d'authentification :
     — authentification requise
     — authentification non requise
3. Permission d'autorisation :
     — autorisation requise
     — autorisation non requise

La principale différence entre les permissions des attributs et les propriétés des caractéristiques est que les premières s'appliquent aux serveurs, tandis que les secondes s'appliquent aux clients. Un serveur peut avoir la permission de lire la valeur d'une caractéristique, mais il peut y avoir une exigence d'authentification ou d'autorisation. Ainsi, lors de la demande des propriétés d'une caractéristique par le client, nous constaterons que la lecture est autorisée. Mais lors de la tentative de lecture, nous obtiendrons une erreur. Il est donc juste de dire que les permissions prévalent sur les propriétés. En tant que client, nous ne pouvons pas obtenir d'informations sur les permissions de l'attribut.

Descripteur

Revenons à notre tableau. Après la déclaration de la valeur d'une caractéristique, les déclarations d'attributs suivantes peuvent être possibles :
1. Nouvelle déclaration de caractéristique (il peut y avoir plusieurs caractéristiques dans le service)
2. Nouvelle déclaration de service (il peut y en avoir plusieurs dans le tableau)
3. Déclaration de descripteur

En ce qui concerne la caractéristique de mesure de la fréquence cardiaque, dans notre tableau, l'annonce de la valeur de la caractéristique est accompagnée de l'annonce du descripteur. Un descripteur est un attribut contenant des informations supplémentaires sur la caractéristique. Il existe plusieurs types de descripteurs. Nous les examinerons en détail dans la deuxième partie de cet article. Pour l'instant, nous ne toucherons qu'au descripteur de configuration des caractéristiques client (Client Characteristic Configuration Descriptor — CCCD). Son UUID est égal à 0x2902. Grâce à ce descripteur, le client a la possibilité d’activer l’indication ou la notification sur le serveur. La différence entre les deux est légère, mais elle existe. La notification ne nécessite pas de confirmation de réception de la part du client. L’indication, en revanche, l'exige, même si elle se produit au niveau GATT, sans atteindre le niveau de l'application. Pourquoi cela, me demanderez-vous ? Hélas, je ne le sais pas. Je dirai seulement que les spécialistes de Nordic recommandent d'utiliser la notification. D'autant plus que la vérification de l'intégrité du paquet (à l'aide de CRC) se produit dans les deux cas.

Conclusion

À la fin de l'article, je voudrais dire ceci. Le dernier tableau est quelque peu déroutant. Cependant, je me suis arrêté sur celui-ci parce qu'il est présenté dans article, sur lequel je m'appuie. Dans la deuxième partie de mon article, je prévois d'approfondir la spécification BlueTooth 4.0. Là, nous trouverons des schémas et des illustrations plus corrects. Dans la troisième partie, je souhaite examiner le journal obtenu grâce au programme Wireshark à partir de l'un des gadgets et voir « en direct » toute la théorie que nous étudions.

Employé du Groupe de Sociétés « César Satellite »
Vladimir Pecherskiy

Source : habr.com

Acheter un hébergement fiable pour les sites avec protection DDoS, serveurs VPS VDS 🔥 Acheter un hébergement fiable pour les sites avec protection DDoS, serveurs VPS VDS | ProHoster