Je travaille sur un périphérique à capteur BluetoothLE, pour lequel je dois former une diffusion de données un-à-plusieurs. Selon la spécification, les périphériques ne peuvent avoir qu'un seul maître, et en raison des limites de la puce et de la pile sur lesquelles je conçois, un maître ne peut avoir que trois esclaves. D'après ce que je comprends, Android ne peut pas devenir un esclave BLE de toute façon, donc avoir mon appareil en tant que maître n'est pas une option.
La spécification BT4 et la documentation du fabricant parlent d'un autre mode de fonctionnement, appelé mode de diffusion. En mode diffusion, une connexion n'est jamais établie et les données d'application sont transmises dans le cadre du paquet publicitaire. Cela correspondra exactement à mes besoins, car de nombreux téléphones Android/iOS peuvent simultanément numériser chaque paquet. Un paquet publicitaire est transmis plusieurs fois en rafales, donc je soupçonne que la réception des données est principalement fiable. Si un paquet est perdu ici et là, il peut être toléré.
Lorsque cela devient intéressant, c'est que je veux que ces paquets transportent des données de capteur en direct, qui se mettent à jour à une fréquence de 10-20 Hz. D'après les exemples que j'ai trouvés sur le Web, le BLE dans ce mode est principalement utilisé pour les implémentations de type "iBeacon", où ils diffusent des données statiques. Je ne trouve aucune information sur la façon dont les paquets publicitaires sont filtrés dans la pile Android. Il se peut qu'ils renvoient un résultat par adresse matérielle Bluetooth, ou cela pourrait être la combinaison unique d'adresse et de données. La deuxième option fonctionnerait pour cette application. Si le démarrage et l'arrêt de l'analyse réinitialise le filtre, je peux également faire fonctionner quelque chose.
La documentation Android Android ne mentionne rien sur le fonctionnement du filtrage des périphériques dans la méthode de scan. J'ai pu trouver un message sur le net essayant de résoudre ce même problème, qui a une réponse non résolue: - BLE: Découverte multiple du même périphérique pendant le scan . Dans iOS, mon collègue m'informe qu'il y a un paramètre qui peut être passé à la fonction de scan qui rend cela possible.
J'ai tenté de retracer le code depuis l'appel startLeScan () dans la source Android, mais le code est assez complexe et l'utilisation de l'abstraction a rendu difficile l'identification de l'implémentation de l'objet qui le contient. Le plus éloigné que j'ai obtenu est un objet IBluetoothGatt renvoyé par la méthode de classe BluetoothManagerService getBluetoothGatt (). Cet objet reçoit la demande de démarrage de l'analyse. Il est instancié autour de ligne 790 de BluetoothManagerService. Java sur la révision actuelle en direct sur github. L'objet est casté à partir du résultat d'un message, donc je soupçonne que le résultat est spécifique au téléphone/pilote. Il est au-delà de mon expertise de pouvoir le retrouver plus loin.
Une autre question que je voudrais résoudre est la rapidité avec laquelle la numérisation peut être activée et désactivée. Le balayage est une opération gourmande en énergie, mais la diffusion des données se fera périodiquement sur une minuterie en temps réel assez précise. Par conséquent, ce serait une excellente optimisation si le balayage peut être activé et désactivé, de sorte que la diffusion et le balayage soient synchronisés, le scanner étant arrêté les 90% + du temps. Cela devra probablement être testé expérimentalement.
Je fais toujours des recherches de faisabilité pour voir si cela est possible pour notre accessoire pour Android. Mon téléphone actuel ne peut pas encore exécuter la version 4.3, donc je n'ai aucun moyen de tester/pirater cela expérimentalement.
Avec Android 4.3 et 4.4 jusqu'à présent, cela semble être un gâchis: certains appareils appellent onLeScan (périphérique BluetoothDevice, int rssi, octet [] scanRecord) plusieurs fois pour un appareil dans une analyse, d'autres non. Il n'y a aucun moyen de configurer le filtrage comme dans iOS (voir la réponse d'Arkadiusz Konior). Donc, je commence maintenant une liste, car je ne peux pas poser une telle question à mes utilisateurs sur leur appareil.
Cependant, le redémarrage de l'analyse ne pose également aucun problème sur les périphériques "sans filtrage". Donc, je recommence la numérisation sur chaque appareil maintenant.
Pas de filtrage (Appel continu sur LeScan ())
Dispositifs de filtrage (s'applique au standard)
Comportement de filtrage inconnu (veuillez aider à associer l'appareil à un certain groupe)
Le texte des pages 2535-2536 de la spécification Bluetooth (Core_v4.1.pdf) concernant les rapports publicitaires en double n'est pas clair. Cependant, le texte de la page 1258 est clair. Il spécifie un paramètre Filter_Duplicates à la commande HCI_LE_Set_Scan_Enable. Dans Android version 4.4 (KitKat), ce paramètre est 0x00 (filtrage des doublons désactivé).
Il existe un moyen simple de savoir si un filtrage est effectué dans la puce Bluetooth à partir de Android versions 4.4 (KitKat). Faites du téléphone un téléphone de développeur, entrez les options de développeur et cochez "Activer Bluetooth HCI snoop log ". Ensuite, désactivez et activez Bluetooth une fois pour faire mordre les paramètres. À partir de maintenant, tous les paquets HCI entre le processeur d'application et la puce Bluetooth seront stockés sur le téléphone dans un fichier qui est extrait par adb pull storage/émulé/legacy/btsnoop_hci.log. Ce n'est pas un fichier texte et vous avez besoin d'un programme de http://www.fte.com/products/default.aspx ou de cableshark pour afficher btsnoop_hci.log. Pour wirehark vous avez besoin d'une version assez récente, car les anciennes versions ne prennent pas en charge BLE. Mon expérience est qu'il n'y a jamais de filtrage dans la puce Bluetooth, c'est-à-dire que l'événement HCI "LE Advertising Report Event" est envoyé pour chaque ADV_IND et ADV_NONCONN_IND que la puce Bluetooth Cela vaut pour les téléphones équipés de puces Bluetooth Qualcomm/Atheros WCN 3680 et B roadcom BCM 4339.
Correction: le chemin d'accès à btsnoop_hci.log peut être différent selon le fabricant du téléphone. Vous pouvez trouver le chemin correct par adb Shell cat etc/bluetooth/bt_stack.conf | grep BtSnoopFileName
Je développe l'application pour Android 4.3 (Nexus 4 & 7) en utilisant BLE et à partir de mes observations, le scan retourne le même appareil plusieurs fois s'il n'y a pas eu de DEMANDE DE NUMÉRISATION renvoyée au périphérique.
L'appareil peut faire de la publicité de 2 manières: passive et active. En mode passif, le périphérique ne fait que publier toutes ses données et n'écoute pas après l'envoi de paquets périodiques. C'est juste envoyer, dormir, envoyer, dormir ... En mode actif, le capteur annonce aussi mais le message est aussi court que possible. Après l'avoir envoyé, il passe à l'écoute pendant très peu de temps. Lorsque le scan détecte le message court, il envoie immédiatement la commande SCAN REQUEST au périphérique et obtient une réponse avec plus de détails. Pour autant que je puisse voir Android n'envoie pas la DEMANDE DE NUMÉRISATION plusieurs fois au cours d'une numérisation.
Supposons que nous ayons 2 appareils à portée. L'un est f.e. Capteur de température nRF Nordic (publicité passive) et un autre appareil connectable. J'ai reçu la réponse de scan suivante:
11-10 21:32:54.281: D/BluetoothAdapter(13468): startLeScan(): null
11-10 21:32:54.281: D/BluetoothAdapter(13468): onClientRegistered() - status=0 clientIf=4
11-10 21:32:54.321: D/BluetoothAdapter(13468): onScanResult() - Device=CD:61:1A:A8:BC:BE RSSI=-94
11-10 21:32:55.122: D/BluetoothAdapter(13468): onScanResult() - Device=CB:32:81:CF:FD:00 RSSI=-61
11-10 21:32:56.414: D/BluetoothAdapter(13468): onScanResult() - Device=CB:32:81:CF:FD:00 RSSI=-62
11-10 21:32:57.715: D/BluetoothAdapter(13468): onScanResult() - Device=CB:32:81:CF:FD:00 RSSI=-61
11-10 21:32:59.016: D/BluetoothAdapter(13468): onScanResult() - Device=CB:32:81:CF:FD:00 RSSI=-63
11-10 21:33:01.609: D/BluetoothAdapter(13468): onScanResult() - Device=CB:32:81:CF:FD:00 RSSI=-63
11-10 21:33:02.901: D/BluetoothAdapter(13468): onScanResult() - Device=CB:32:81:CF:FD:00 RSSI=-63
11-10 21:33:04.212: D/BluetoothAdapter(13468): onScanResult() - Device=CB:32:81:CF:FD:00 RSSI=-62
11-10 21:33:04.282: D/BluetoothAdapter(13468): stopLeScan()
Comme vous pouvez le voir, l'appareil connectable n'est apparu qu'une seule fois et l'autre 7 fois.
Une autre question que je voudrais résoudre est la rapidité avec laquelle la numérisation peut être activée et désactivée. Le balayage est une opération gourmande en énergie, mais la diffusion des données se fera périodiquement sur une minuterie en temps réel assez précise. Par conséquent, ce serait une excellente optimisation si le balayage peut être activé et désactivé, de sorte que la diffusion et le balayage soient synchronisés, le scanner étant arrêté les 90% + du temps. Cela devra probablement être testé expérimentalement.
La fréquence de balayage dépend de l'appareil. De plus, la publicité se fait généralement sur 3 canaux: 37, 38 et 39 pour augmenter la probabilité d'être trouvé. Cependant, cela peut être une bonne idée d'obtenir plusieurs fois des paquets publicitaires à partir d'appareils "actifs".
La spécification Bluetooth réelle dit:
Les rapports de publicité en double ne doivent pas être envoyés à l'hôte. Un rapport de publicité en double est un rapport de publicité pour la même adresse de périphérique tandis que la couche de liaison reste à l'état d'analyse. Les données publicitaires peuvent changer; les données publicitaires ou les données de réponse de scan ne sont pas considérées comme importantes lors de la détermination des rapports publicitaires en double.
Selon la spécification, cela s'applique pendant une période d'analyse, ce qui suggère que la bonne façon de contourner ce problème est d'arrêter et de redémarrer l'analyse chaque fois que vous recevez une publicité.
D'après mon expérience avec BLE, il semble que l'envoi de données variables dans des publicités n'est tout simplement pas une très bonne idée. Presque tout suppose que les données des publicités ne changent pas. Si vous souhaitez réellement envoyer des données variables (par exemple des lectures de thermomètre), il est préférable de se connecter à l'appareil et de le faire via une caractéristique. Il est plus fiable et utilise beaucoup moins d'énergie. L'inconvénient est que vous ne pouvez vous connecter qu'à 8 appareils à la fois.
Les publicités sont destinées à détecter la présence d'appareils et à les identifier.
Dans iOS, cet indicateur est nommé CBCentralManagerScanOptionAllowDuplicatesKey
. Le passer à la fonction de scan provoque une notification pour chaque paquet de publicité. Je n'ai pas trouvé de drapeau similaire dans Android.