diff --git a/Application/src/main/java/fr/centralesupelec/students/clientble/BluetoothLeService.java b/Application/src/main/java/fr/centralesupelec/students/clientble/BluetoothLeService.java index 02de920..a1c1007 100644 --- a/Application/src/main/java/fr/centralesupelec/students/clientble/BluetoothLeService.java +++ b/Application/src/main/java/fr/centralesupelec/students/clientble/BluetoothLeService.java @@ -1,6 +1,6 @@ /* * Copyright (C) 2013 The Android Open Source Project - * Copyright (C) 2017 Louis-Guillaume Dubois + * Copyright (C) 2017 CentraleSupélec * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -57,6 +57,7 @@ public class BluetoothLeService extends Service { private static final int STATE_CONNECTING = 1; private static final int STATE_CONNECTED = 2; + // Nom des actions envoyées lors des Intents broadcastés public final static String ACTION_GATT_CONNECTED = "fr.cenralesupelec.students.clientble.ACTION_GATT_CONNECTED"; public final static String ACTION_GATT_DISCONNECTED = @@ -73,6 +74,8 @@ public class BluetoothLeService extends Service { // Implements callback methods for GATT events that the app cares about. For example, // connection change and services discovered. + // Envoie des Intents broadcastés pour permettre à SimpleDetailActivity de récupérer + // les valeurs reçues de l’appareil BLE. private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { @@ -103,6 +106,13 @@ public class BluetoothLeService extends Service { } } + /** + * Renvoie dans une Intent broadcastée la valeur lue de la caractéristique + * demandée. + * @param gatt + * @param characteristic + * @param status + */ @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, @@ -111,8 +121,10 @@ public class BluetoothLeService extends Service { if (status == BluetoothGatt.GATT_SUCCESS) { if (GattConstants.SENSOR_CHARACTERISTIC_UUID.equals(uuid)) { + // Valeur du potentiomètre. broadcastUpdate(ACTION_SENSOR_VALUE_AVAILABLE, characteristic); } else if (GattConstants.WRITABLE_CHARACTERISTIC_UUID.equals(uuid)) { + // Valeur de la caractéristique longue. broadcastUpdate(ACTION_WRITABLE_VALUE_AVAILABLE, characteristic); } else { Log.w(TAG, "UUID non reconnue."); @@ -120,6 +132,13 @@ public class BluetoothLeService extends Service { } } + /** + * Renvoie dans une Intent broadcastée la valeur écrite de la caractéristique + * demandée. + * @param gatt + * @param characteristic + * @param status + */ @Override public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, @@ -128,8 +147,10 @@ public class BluetoothLeService extends Service { if (status == BluetoothGatt.GATT_SUCCESS) { Log.d(TAG, "Réusssite de l’écriture de la caractéristique."); if (GattConstants.SENSOR_CHARACTERISTIC_UUID.equals(uuid)) { + // Valeur du potentiomètre – ne devrait pas se produire (lecture seule.) broadcastUpdate(ACTION_SENSOR_VALUE_AVAILABLE, characteristic); } else if (GattConstants.WRITABLE_CHARACTERISTIC_UUID.equals(uuid)) { + // Valeur de la caractéristique longue et éditable. broadcastUpdate(ACTION_WRITABLE_VALUE_AVAILABLE, characteristic); } } else { @@ -137,6 +158,12 @@ public class BluetoothLeService extends Service { } } + /** + * Renvoie dans une Intent broadcastée la valeur mise à jour d’une caractéristique + * (en cas de notification par exemple.) + * @param gatt + * @param characteristic + */ @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { @@ -152,50 +179,81 @@ public class BluetoothLeService extends Service { } }; + /** + * Méthode d’envoi d’une Intent broadcastée. + * @param action nom de l’action + */ private void broadcastUpdate(final String action) { Log.d(TAG, "broadcastUpdate(String) appelé."); final Intent intent = new Intent(action); sendBroadcast(intent); } + /** + * Méthode d’envoi d’une Intent broadcastée, avec la valeur d’une caractéristique. + * @param action nom de l’action + * @param characteristic caractéristique lue, écrite ou mise à jour (notifiée) + */ private void broadcastUpdate(final String action, final BluetoothGattCharacteristic characteristic) { + final Intent intent = new Intent(action); Log.d(TAG, "broadcastUpdate(String, BluetoothGattChar.) appelé."); + + // Valeur brute de la caractéristique. final byte[] data = characteristic.getValue(); + if (data != null && data.length > 0) { + // Si c’est la valeur du potentiomètre if (GattConstants.SENSOR_CHARACTERISTIC_UUID.equals(characteristic.getUuid())) { + // Lecture de l’entier non signé, d’un ou deux octets (lecture par le CAN sur 16 bits.) final long value = (data.length == 2) ? (data[0] << 8) & 0x0000ff00 | (data[1] << 0) & 0x000000ff : (data[0] << 0) & 0x000000ff; - final long max = 65535; // 2^16 - 1 + final long max = 65535; // 2^16 - 1 : valeur maximale (16 bits) + // Envoi d’un pourcentage final double percent = ((double) (100 * value)) / ((double) max); + // Envoi sous forme d’une chaîne de caractère, avec la date, pour affichage direct. final String date = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.LONG).format(new Date()); intent.putExtra(EXTRA_DATA, String.format("%.3f %%\n(%s)", percent, date)); } else { + // Sinon, caractéristique longue éditable. final StringBuilder stringBuilder = new StringBuilder(data.length); - //stringBuilder.append(String.format("%d", data));/ - //stringBuilder.append(" --- "); + // Représentation au format hexadécimal. for (byte byteChar : data) stringBuilder.append(String.format("%02X ", byteChar)); Log.d(TAG, String.format(stringBuilder.toString())); + // Envoi de la représentation ASCII puis sur une autre ligne, en hexadécimal. intent.putExtra(EXTRA_DATA, new String(data) + "\n" + stringBuilder.toString()); } } sendBroadcast(intent); } + /** + * Classe permettant à une activité d’appeler les méthodes du service. + */ public class LocalBinder extends Binder { BluetoothLeService getService() { return BluetoothLeService.this; } } + /** + * Demande de lien à une activité. + * @param intent + * @return + */ @Override public IBinder onBind(Intent intent) { return mBinder; } + /** + * Arrêt du lien avec une activité. + * @param intent + * @return + */ @Override public boolean onUnbind(Intent intent) { // After using a given device, you should make sure that BluetoothGatt.close() is called @@ -205,6 +263,9 @@ public class BluetoothLeService extends Service { return super.onUnbind(intent); } + /** + * Instance de la classe de liaison avec une activité. + */ private final IBinder mBinder = new LocalBinder(); /** @@ -314,6 +375,11 @@ public class BluetoothLeService extends Service { mBluetoothGatt.readCharacteristic(characteristic); } + /** + * Écriture d’une caractéristique sur le serveur BLE de l’appareil connecté. + * @param characteristic caractéristique où écrire + * @param data données brutes à envoyer pour écriture + */ public void writeCharacterisitic(BluetoothGattCharacteristic characteristic, byte[] data) { if (mBluetoothAdapter == null || mBluetoothGatt == null) { Log.w(TAG, "BluetoothAdapter not initialized"); @@ -335,7 +401,9 @@ public class BluetoothLeService extends Service { Log.w(TAG, "BluetoothAdapter not initialized"); return; } - Log.d(TAG, "setChar.Notification() appelé"); + Log.d(TAG, "setCharacteristicNotification() appelé"); + // Ne pas oublier d’écrire le descripteur de la caractéristique pour que les serveur + // BLE de l’appareil connecté envoie les notifications. if (GattConstants.SENSOR_CHARACTERISTIC_UUID.equals(characteristic.getUuid())) { BluetoothGattDescriptor descriptor = characteristic.getDescriptor(GattConstants.CHARACTERISTIC_CONFIG_UUID); descriptor.setValue( @@ -343,12 +411,16 @@ public class BluetoothLeService extends Service { : BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE ); try { + // Parfois plusieurs essais sont nécessaires (l’interface BLE peut être + // occupée avec d’autres opérations.) while (!mBluetoothGatt.writeDescriptor(descriptor)) sleep(500); } catch (Exception e) { e.printStackTrace(); } } + // Demande à l’appareil Android d’écouter et de prendre en compte les notifications + // envoyées par l’appareil connecté. mBluetoothGatt.setCharacteristicNotification(characteristic, enabled); } @@ -363,6 +435,10 @@ public class BluetoothLeService extends Service { return mBluetoothGatt.getServices(); } + /** + * Retourne notre service privé. + * @return + */ public BluetoothGattService getPrivateService() { if (mBluetoothGatt == null) return null; return mBluetoothGatt.getService(GattConstants.PRIVATE_SERVICE_UUID); diff --git a/Application/src/main/java/fr/centralesupelec/students/clientble/DeviceControlActivity.java b/Application/src/main/java/fr/centralesupelec/students/clientble/DeviceControlActivity.java index 3c9df39..a7842cd 100644 --- a/Application/src/main/java/fr/centralesupelec/students/clientble/DeviceControlActivity.java +++ b/Application/src/main/java/fr/centralesupelec/students/clientble/DeviceControlActivity.java @@ -41,6 +41,8 @@ import java.util.HashMap; import java.util.List; /** + * Activité proposée dans l’application de démonstration, non utilisée dans notre application. + * * For a given BLE device, this Activity provides the user interface to connect, display data, * and display GATT services and characteristics supported by the device. The Activity * communicates with {@code BluetoothLeService}, which in turn interacts with the diff --git a/Application/src/main/java/fr/centralesupelec/students/clientble/DeviceScanActivity.java b/Application/src/main/java/fr/centralesupelec/students/clientble/DeviceScanActivity.java index 80abe98..2b6288f 100644 --- a/Application/src/main/java/fr/centralesupelec/students/clientble/DeviceScanActivity.java +++ b/Application/src/main/java/fr/centralesupelec/students/clientble/DeviceScanActivity.java @@ -1,6 +1,6 @@ /* * Copyright (C) 2013 The Android Open Source Project - * Copyright (C) 2017 Louis-Guillaume Dubois + * Copyright (C) 2017 CentraleSupélec * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/Application/src/main/java/fr/centralesupelec/students/clientble/GattConstants.java b/Application/src/main/java/fr/centralesupelec/students/clientble/GattConstants.java index 56414e2..ebba173 100644 --- a/Application/src/main/java/fr/centralesupelec/students/clientble/GattConstants.java +++ b/Application/src/main/java/fr/centralesupelec/students/clientble/GattConstants.java @@ -21,7 +21,7 @@ import java.util.HashMap; import java.util.UUID; /** - * This class includes a small subset of standard GATT attributes for demonstration purposes. + * Stockage des UUID des services et caractéristiques BLE interrogées. */ public class GattConstants { private static HashMap attributes = new HashMap(); @@ -40,7 +40,7 @@ public class GattConstants { UUID.fromString(SENSOR_CHARACTERISTIC_UUID_STRING); // UUID (v4, cf. supra) de notre caractéristiuqe privée, lisible, éditable et notifiable, - // de trois octets. + // de vingt octets. public static final String WRITABLE_CHARACTERISTIC_UUID_STRING = "c093685d-005f-4d3c-8240-6d3020a2c608"; public static final UUID WRITABLE_CHARACTERISTIC_UUID = @@ -54,7 +54,7 @@ public class GattConstants { public static final UUID CHARACTERISTIC_CONFIG_UUID = UUID.fromString(CHARACTERISTIC_CONFIG_UUID_STRING); - // UUID de services connus — utilisés dans DeviceControlActivity + // UUID de services connus — utilisés dans DeviceControlActivity uniquement static { // Sample Services. attributes.put("0000180a-0000-1000-8000-00805f9b34fb", "Device Information"); @@ -73,7 +73,7 @@ public class GattConstants { attributes.put(WRITABLE_CHARACTERISTIC_UUID_STRING, "3-byte rw notif. char."); } - // recherche du nom de services connus — utilisé dans DeviceControlActivity + // recherche du nom de services connus — utilisé dans DeviceControlActivity uniquement public static String lookup(String uuid, String defaultName) { String name = attributes.get(uuid); return name == null ? defaultName : name;