android - things - bluetooth le gatt
BLE GATT onCharacteristicChanged no llamado despuĆ©s de suscribirse a la notificaciĆ³n (2)
Entonces, finalmente descubrí mi error :) Como puede ver arriba, uso un UUID con la misma base para mi descriptor que mis características (comenzando con 3f54XXXX-....
)
Lo cambié a public static final UUID X_ACCEL_DESCRIPTOR_UUID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
y ahora todo está funcionando como se esperaba.
No hice esto antes porque pensé que debería haber un descriptor para cada característica. Pero, de hecho, de acuerdo con la configuración de características del cliente, ...
[...] el descriptor debe ser persistente a través de conexiones para dispositivos vinculados. El descriptor de configuración de características del cliente es único para cada cliente.
Así que revisé el ejemplo de la aplicación para Android RedBearLab y vi que el UUID del descriptor es igual a los publicados en otras respuestas SO.
Esto también explica por qué mi aplicación recibió notificaciones después de que las habilité en la aplicación BLE Scanner: como el descriptor será persistente entre conexiones para dispositivos vinculados, la aplicación BLE Scanner también usó este UUID para el descriptor y habilitó las notificaciones para el cliente (= mi teléfono).
esta es mi primera publicación en SO.
Tengo algunos problemas para suscribirme a las notificaciones del GATT en Android 5.0.2.
Lo que intento hacer es conectar un Arduino con un BLE Shield a mi teléfono Android. Tengo un sensor conectado al Arduino y quiero enviar los datos del Arduino a mi teléfono usando el escudo BLE. Hay un nRF8001 en el escudo que es el servidor, mi teléfono / aplicación es el cliente.
Lo que hice hasta ahora fue crear una aplicación para Android que busque dispositivos BLE. Se puede conectar a un dispositivo y leer o escribir características. Entonces, puedo leer "manualmente" la característica llamando a gatt.readCharacteristic(mCharacteristic);
. Esto me permite obtener los valores del sensor del Arduino. También creé un servicio personalizado usando nRFGo Studio. Sé que esta parte funciona, ya que puedo descubrir, conectarme e incluso recibir notificaciones sobre cambios de la característica mediante el uso de la aplicación BLE Scanner, que está disponible en Google Play. Pero suscribirte a las notificaciones en mi propia aplicación no funcionará. Bueno, al menos la suscripción funciona, pero onCharacteristicChanged(...)
nunca se llama. Lo que es gracioso es el hecho de que si me suscribo a la característica en mi aplicación y luego me suscribo a ella con la aplicación del escáner BLE repentinamente se onCharacteristicChanged(...)
hasta que me desconecte de nuevo a través de la aplicación del escáner BLE. (Puedo ver esto por el registro)
Mi código de Android es el siguiente: La devolución de llamada del GATT:
private final BluetoothGattCallback mGattCallback =
new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status,
int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
sendBroadcastConnected();
Log.i("BLE", "Connected to GATT server.");
Log.i("BLE", "Attempting to start service discovery:" + bleManager.startServiceDiscovery());
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
sendBroadcastDisconnected();
Log.i("BLE", "Disconnected from GATT server.");
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
Log.w("BLE", "onServicesDiscovered ");
setNotifySensor(gatt);
}
}
private void setNotifySensor(BluetoothGatt gatt) {
BluetoothGattCharacteristic characteristic = gatt.getService(Globals.MPU_SERVICE_UUID).getCharacteristic(Globals.X_ACCEL_CHARACTERISTICS_UUID);
gatt.setCharacteristicNotification(characteristic, true);
BluetoothGattDescriptor desc = characteristic.getDescriptor(Globals.X_ACCEL_DESCRIPTOR_UUID);
Log.i("BLE", "Descriptor is " + desc); // this is not null
desc.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
Log.i("BLE", "Descriptor write: " + gatt.writeDescriptor(desc)); // returns true
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
if(Globals.X_ACCEL_CHARACTERISTICS_UUID.equals(characteristic.getUuid())){
Log.w("BLE", "CharacteristicRead - xaccel service uuid: " + characteristic.getService().getUuid());
Log.w("BLE", "CharacteristicRead - xaccel value: " + characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8,0));
}
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
Log.i("BLE", "Received characteristics changed event : "+characteristic.getUuid());
if(Globals.X_ACCEL_CHARACTERISTICS_UUID.equals(characteristic.getUuid())){
Log.i("BLE", "Received new value for xAccel.");
}
}
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
}
@Override
public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
}
@Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
}
};
Así es como me conecto al GATT:
bt_device = createBluetoothDevice(DEVICE_ADRESS);
BluetoothGatt mBluetoothGatt = bt_device.connectGatt(context, false, mGattCallback);
Todo este código se ejecuta en un servicio en segundo plano que se inicia después de que se selecciona un dispositivo BLE.
Lo que probé fue implementar cosas como las que se muestran en la Guía de API de Google Dev y también probé esta solución (sin éxito). Ni buscar en Google, leer preguntas ya hechas en SO (por ejemplo, este ) o echar un vistazo en Nordic Developer Zone ayudaron mucho en este caso.
Finalmente, mi pregunta es: ¿Qué he hecho mal? ¿Me estoy perdiendo de algo? Simplemente no puedo entenderlo y me está volviendo loco durante dos días. No sé dónde más podría buscar una solución, así que espero que me puedan ayudar ...
EDITAR Clase Globals:
// BLE Services
public static final UUID MPU_SERVICE_UUID = UUID.fromString("3f540001-1ee0-4245-a7ef-35885ccae141");
// BLE Characteristics
public static final UUID X_ACCEL_CHARACTERISTICS_UUID = UUID.fromString("3f540002-1ee0-4245-a7ef-35885ccae141");
// BLE Descriptors
public static final UUID X_ACCEL_DESCRIPTOR_UUID = UUID.fromString("3f542902-1ee0-4245-a7ef-35885ccae141");
EDITAR Lo que hago en BLE Scanner: simplemente escaneo para dispositivos BLE. Encuentra mi dispositivo y luego de tocarlo me muestra todos mis servicios que configuré en la placa Arduino. Después de seleccionar un servicio, me muestra todas las características que he especificado para este Servicio. Y cuando toco una característica, me muestra su UUID y el UUID de su Servicio. Además, la aplicación BLE Scanner me permite suscribirme a la notificación o leer la característica. Cuando me suscribo, el valor se actualiza continuamente.
customBluetoothGatt.setCharacteristicNotification (característica, habilitada);
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
boolean success = customBluetoothGatt.writeDescriptor(descriptor);
Ahora establece la propiedad del descriptor ENABLE_INDICATION_VALUE