Loupe

[Window 8.1 / WP 8.1] Utiliser le Bluetooth Low Energy avec vos app mobiles

1. Présentation

LE BLE

bluetoothsmart

Pour rappel, le BLE (Bluetooth Low Energy) ou Bluetooth Smart est une technologie implémentée dans certains nouveaux appareils et qui optimise la consommation de batterie. Autre chose que l’on sait peu, c’est que ces appareils peuvent également servir de client et/ou serveur GATT. En mode serveur, cela signifie que l’appareil expose certains services, et qu’il les consomme s’il est client.

 

Windows 8.1 et Windows Phone 8.1

Dans les applications destinées au Store, il est désormais possible de gérer les communications avec les appareils BLE.

Mes premiers essais avec le BLE ont commencé avec la souris Arc Touch Mouse (Surface Edition) mais peu de services étaient disponibles et ceux-ci avaient une utilité limitée pour des scenarios complexes.

Je me suis donc tourné vers le Sensor Tag CC2541 de Texas Instrument qui n’est pas très cher et permet de commencer rapidement à jouer. De plus la documentation du fabricant est très complète (cf: http://processors.wiki.ti.com/images/a/a8/BLE_SensorTag_GATT_Server.pdf).

SensorTagDocumentation

Il contient 6 capteurs : un accéléromètre, un magnétomètre, un gyroscope, des capteur d’humidité, de température, de pression et expose les services associés.

 

2. Let’s code

Dans cet article je vais vous montrer comment intégrer quelques fonctionnalités de consommation des services GATT du Sensor Tag. Les exemples de codes sont identiques que vous soyez dans une application Windows Phone 8.1 ou Windows 8.1. Il est donc possible de créer une Universal App ayant les mêmes fonctionnalités et mutualisant ce code.

Appairage

Appairer son appareil BLE à son device de développement est primordial puisque sans cela vous ne serez pas capable de le “découvrir” même s’il est allumé et positionné à côté.

Pour appairer, allumez votre appareil, allez dans les paramètres Bluetooth de Win8.1 ou WP8.1 et cliquer sur “Pairer”. Pour le Sensor tag, un code vous sera demandé et il s’agit par défaut du 0000.

 

Le Manifest et la déclaration des services GATT

Une fois vos appareils liés vous pouvez commencer à coder. Pour cela, créer une application Universal (ou pas d’ailleurs) et ouvrez le (ou les) manifests en mode code (via un clic droit).

AppxManifest_1

 

AppxManifest_Viewcode

 

Dans la partie Capabilities, ajoutez les lignes suivantes :

  <Capabilities>
    <Capability Name="internetClient" />
    <m2:DeviceCapability Name="bluetooth.genericAttributeProfile">
      <m2:Device Id="any">
        <!-- Humidity -->
        <m2:Function Type="serviceId:F000AA20-0451-4000-B000-000000000000"/>
      </m2:Device>
    </m2:DeviceCapability>
  </Capabilities>

Le service Id F000AA20-0451-4000-B000-000000000000 correspondant au service d’humidité.

Des mots-clés sont disponibles si vous souhaitez utiliser des services plus génériques tels que celui de l’indicateur de batterie si votre device l’expose :

<m2:Function Type="name:battery"/>

 

Cette étape est indispensable et son oubli peut provoquer de véritables crises de nerfs lors du débug de votre application.

 

L’initialisation du device

Dans le code behind de la votre MainPage, ajoutez les lignes suivantes :

InitDeviceAsync();

 

Puis rajoutez la méthode d’initialisation :

        private async void InitDeviceAsync()
        {
            var serviceUIID = new Guid("F000AA20-0451-4000-B000-000000000000");
            
            //Find the devices that expose the service  
            var devices = await DeviceInformation.FindAllAsync(GattDeviceService.GetDeviceSelectorFromUuid(serviceUIID));
            var device = devices.FirstOrDefault(d => d.Name == "TI BLE Sensor Tag");

            if (device != null)
            {
                //Connect to the service 
                var service = await GattDeviceService.FromIdAsync(device.Id);
            }
        }

Ce code utilise le service d’humidité et cherche tous les devices connus (appairés) qui l’exposent. Parmi ceux là nous ne récupérons que celui dont le nom correspond à notre capteur. Nous nous connectons ensuite au service du capteur en question.

Au premier lancement de l’application, l’appel de la méthode await GattDeviceService.FromIdAsync(device.Id); provoquera, sur Windows 8.1, un requête à l’utilisateur. Il doit en effet autoriser l’utilisation du device.

BLE_Authorization

 

 

La lecture de données

Une fois le device reconnu et connecté nous allons cibler la caractéristique associée et récupérer toutes les valeurs que le device nous enverra :

if (service == null) return;

//Get the service data characteristic  
var characData = service.GetCharacteristics(characUIID)[0];

//Subcribe value changed  
characData.ValueChanged += charac_ValueChanged;

//Set configuration to notify  
await characData.WriteClientCharacteristicConfigurationDescriptorAsync(GattClientCharacteristicConfigurationDescriptorValue.Notify);

//Get the configuration characteristic  
var config = service.GetCharacteristics(configUIID)[0];

//Write 1 to start the sensor  
await config.WriteValueAsync((new byte[] { 1 }).AsBuffer());

 

Nous pouvons alors lire et interpréter les valeurs retournées par de le device conformément à la documentation fournie par le constructeur :

private async void charac_ValueChanged(GattCharacteristic characteristic, GattValueChangedEventArgs args)
{
    int a = await ShortUnsignedAtOffset(characteristic, 2);
    a = a - (a % 4);
    var humidityValue = ((-6f) + 125f * (a / 65535f));

    Debug.WriteLine("Humidity : {0}", (humidityValue/100).ToString("P"));
}

private static async Task<int> ShortUnsignedAtOffset(GattCharacteristic characteristic, int offset)
{
     var values = (await characteristic.ReadValueAsync()).Value.ToArray();
     uint lowerByte = values[offset];
     uint upperByte = values[offset + 1]; ; // Note: interpret MSB as signed.

     var longValue = (upperByte << 8) + lowerByte;
     return Convert.ToInt32(longValue);
}

 

Relançons l’application et nous voyons alors dans la fenêtre de sortie, les valeurs du taux d’humidité.

Output_Humidity

 

 

Conclusion

Il est relativement facile de prendre en main le BLE et l’unification du code pour les Universal Apps permet de créer des applications dans les 2 Stores très rapidement.

Mais il reste encore quelques défauts :

  • Pas de gestion du BLE en background pour nos applications, ce qui limite tout de même grandement son intérêt
  • L’appairage reste une barrière pour certains utilisateurs
  • Il faut souvent tâtonner pour découvrir les services et caractéristique d’un appareil en l’absence d’une documentation correcte du fabricant.

 

A vous de jouer.

 

 

Edit :

Cet article utilise des Guids de services et caractéristiques, mais si vous souhaitez utiliser des services plus génériques tels que l’indicateur de niveau de batterie, votre code sera moins obscur :

Dans le manifest :

<m2:Function Type="name:battery"/>

Dans votre code, vous pouvez alors récupérer plus aisément les services et caractéristiques :

DeviceInformation.FindAllAsync(GattDeviceService.GetDeviceSelectorFromUuid(GattServiceUuids.Battery))
et
service.GetCharacteristics(GattCharacteristicUuids.BatteryLevel)[0];

Testez donc l’auto-complétion pour découvrir les services génériques disponibles.

Ces billets pourraient aussi vous intéresser

Vous nous direz ?!

Commentaires

comments powered by Disqus