onCharacteristicChanged 未被击中。 Android蓝牙
onCharacteristicChanged not being hit. Android BLE
我有一个应用程序正在使用 BLE 连接我的设备。从连接到设备、发现服务、编写特征和描述符,一切正常。但由于某种原因,onCharacteristicChanged 没有触发。目标是从特征中的特征检索数据。我尝试使用来自同一服务的不同特征,这与检索数据一样有效。不确定为什么这个特定的特性在其他特性起作用时不起作用。
这是我的代码:
//描述符
public 最终静态 UUID UUID_CLIENT_CHARACTERISTIC_CONFIG = UUID.fromString(GattAttributes.CLIENT_CHARACTERISTIC_CONFIG);
// Huneo Service
public final static UUID UUID_HUNEO_SERVICE = UUID.fromString(GattAttributes.HUNEO_SERVICE);
public final static UUID UUID_HUNEO_VIBRATOR = UUID.fromString(GattAttributes.HUNEO_VIBRATOR);
public final static UUID UUID_HUNEO_MONITOR = UUID.fromString(GattAttributes.HUNEO_MONITOR);
public final static UUID UUID_HUNEO_RATES = UUID.fromString(GattAttributes.HUNEO_RATES);
public final static UUID UUID_HUNEO_LED = UUID.fromString(GattAttributes.HUNEO_LED);
public final static UUID UUID_HUNEO_ACCEL = UUID.fromString(GattAttributes.HUNEO_ACCEL);
public final static UUID UUID_HUNEO_GYRO = UUID.fromString(GattAttributes.HUNEO_GYRO);
public final static UUID UUID_HUNEO_COMBINED = UUID.fromString(GattAttributes.HUNEO_COMBINED);
// Battery Service
public final static UUID UUID_BATTERY_SERVICE = UUID.fromString(GattAttributes.BATTERY_SERVICE);
public final static UUID UUID_BATTERY_LEVEL = UUID.fromString(GattAttributes.BATTERY_LEVEL);
// Device Info Service
public final static UUID UUID_DEVICE_INFO_SERVICE = UUID.fromString(GattAttributes.DEVICE_INFO_SERVICE);
public final static UUID UUID_MODEL_NUMBER = UUID.fromString(GattAttributes.MODEL_NUMBER);
public final static UUID UUID_SERIAL_NUMBER = UUID.fromString(GattAttributes.SERIAL_NUMBER);
public final static UUID UUID_FIRMWARE_REV = UUID.fromString(GattAttributes.FIRMWARE_REV);
public final static UUID UUID_HARDWARE_REV = UUID.fromString(GattAttributes.HARDWARE_REV);
public final static UUID UUID_MANUFACTURER_NAME = UUID.fromString(GattAttributes.MANUFACTURER_NAME);
private final static String TAG = "UNITY";
private static final int STATE_DISCONNECTED = 0;
private static final int STATE_CONNECTING = 1;
private static final int STATE_CONNECTED = 2;
private final BluetoothDevice mDevice;
private final IBinder mBinder = new LocalBinder();
private TaskCompletionSource<Void> mConnectionTask = new TaskCompletionSource<>();
private TaskCompletionSource<String> mFirmwareRevTask = new TaskCompletionSource<>();
private TaskCompletionSource<Void> mServicesDiscovered = new TaskCompletionSource<>();
private TaskCompletionSource<Integer> mBatteryLevelTask = new TaskCompletionSource<>();
private TaskCompletionSource<SensorValues> mStartStreamingTask = new TaskCompletionSource<>();
private TaskCompletionSource<String> mSerialNumberTask = new TaskCompletionSource<>();
private SensorValues mSensorValues = new SensorValues();
private BluetoothGatt mBluetoothGatt;
private int mConnectionState = STATE_DISCONNECTED;
private boolean mIsStreaming = false;
// Implements callback methods for GATT events that the app cares about. For example,
// connection change and services discovered.
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
mConnectionState = STATE_CONNECTED;
Log.i(TAG, "Connected to GATT server.");
// Attempts to discover services after successful connection.
Log.i(TAG, "Attempting to start service discovery:" + mBluetoothGatt.discoverServices());
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
mConnectionState = STATE_DISCONNECTED;
mIsStreaming = false;
Log.i(TAG, "Disconnected from GATT server.");
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
mServicesDiscovered.setResult(null);
startStreaming();
Log.w(TAG, "onServicesDiscovered success.");
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
String characteristicUuid = characteristic.getUuid().toString();
if (characteristicUuid.equals(GattAttributes.FIRMWARE_REV)) {
String firmwareRev = characteristic.getStringValue(0);
mFirmwareRevTask.setResult(firmwareRev);
}
if (characteristicUuid.equals(GattAttributes.BATTERY_LEVEL)) {
int batteryLevel = characteristic.getIntValue(FORMAT_UINT8, 0);
mBatteryLevelTask.setResult(batteryLevel);
}
if (characteristicUuid.equals(GattAttributes.SERIAL_NUMBER)) {
String serialNumber = characteristic.getStringValue(0);
mSerialNumberTask.setResult(serialNumber);
}
}
}
@Override
public void onCharacteristicWrite(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
if (characteristic.getUuid().equals(UUID_HUNEO_MONITOR)) {
if (characteristic.getIntValue(FORMAT_UINT8, 0) == 1) {
startCombined();
} else {
stopCombined();
}
}
}
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
String characteristicUuid = characteristic.getUuid().toString();
//Combined value changed
if (characteristicUuid.equals(GattAttributes.HUNEO_COMBINED)) {
byte[] data = characteristic.getValue();
int id = unsignedShortToInt(data[0], data[1]);
int x = unsignedShortToInt(data[2], data[3]);
int y = unsignedShortToInt(data[4], data[5]);
int z = unsignedShortToInt(data[6], data[7]);
mSensorValues.combined = new CartesianValues(id,x,y,z);
mStartStreamingTask.setResult(mSensorValues);
}
}
@Override
public void onDescriptorWrite(BluetoothGatt gatt,
BluetoothGattDescriptor descriptor,
int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
//Combined
if (descriptor.getCharacteristic().getUuid().equals(UUID_HUNEO_COMBINED)) {
mIsStreaming = Arrays.equals(descriptor.getValue(), BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mStartStreamingTask.setResult(null);
}
}
}
};
public AlwaysOnHuneoBoard(BluetoothDevice device) {
this.mDevice = device;
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
// After using a given device, you should make sure that BluetoothGatt.close() is called
// such that resources are cleaned up properly. In this particular example, close() is
// invoked when the UI is disconnected from the Service.
close();
return super.onUnbind(intent);
}
public static class LocalBinder extends Binder {
}
/**
* Connect to the device
*
* @param ct CancellationToken that will make task return if cancelled
* @return when task is complete the device is connected
*/
public Task<Void> connectAsync(CancellationToken ct) {
if (ct.isCancellationRequested()) {
Log.w(TAG, "Connection cancelled");
mConnectionTask.setCancelled();
return mConnectionTask.getTask();
}
if (mDevice == null) {
Log.w(TAG, "BluetoothDevice not initialized");
mConnectionTask.setError(new Exception("BluetoothDevice not initialized"));
return mConnectionTask.getTask();
}
// Previously connected device. BluetoothGatt not closed. Try to reconnect.
if (mBluetoothGatt != null) {
Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
if (mBluetoothGatt.connect()) {
mConnectionState = STATE_CONNECTING;
mConnectionTask.setResult(null);
return mConnectionTask.getTask();
}
}
mBluetoothGatt = mDevice.connectGatt(this, false, mGattCallback);
Log.d(TAG, "Trying to create a new connection.");
mConnectionState = STATE_CONNECTING;
mConnectionTask.setResult(null);
return mConnectionTask.getTask();
}
/**
* Disconnects an existing connection or cancel a pending connection. The disconnection result
* is reported asynchronously through the
* {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
* callback.
*/
public void disconnect() {
if (mDevice == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothDevice not initialized");
return;
}
mBluetoothGatt.disconnect();
}
/**
* After using a given BLE device, the app must call this method to ensure resources are
* released properly.
*/
public void close() {
if (mBluetoothGatt == null) {
return;
}
mBluetoothGatt.close();
mBluetoothGatt = null;
}
/**
* Determines if connected to the BLE device.
*
* @return true if connected, false otherwise.
*/
public boolean isConnected() {
return mConnectionState == STATE_CONNECTED;
}
/**
* Get the calibration for the sensor
*
* @return integer representation of the calibration
*/
public int getCalibration() {
return 100;
}
/**
* Get the firmware version of the sensor
*
* @return string representing the devices firmware version
*/
public String getFirmwareVersion() {
try {
// Wait for services to be discovered
mServicesDiscovered.getTask().onSuccessTask(t -> {
BluetoothGattService deviceInfoService = mBluetoothGatt.getService(UUID_DEVICE_INFO_SERVICE);
BluetoothGattCharacteristic characteristic = deviceInfoService.getCharacteristic(UUID_FIRMWARE_REV);
mBluetoothGatt.readCharacteristic(characteristic);
mFirmwareRevTask.setResult(null);
return mFirmwareRevTask.getTask();
// Wait for deviceRevTask to be completed
}).waitForCompletion(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
return "";
}
return mFirmwareRevTask.getTask().getResult();
}
/**
* Get the device mac address
*
* @return string representation of the mac address
*/
public String getMacAddress() {
return mDevice.getAddress();
}
/**
* Get the model of the device
*
* @return string representation of the device model
*/
public String getModel() {
return mDevice.getName();
}
public SensorValues getCombinedSensorValues() {
if (!isConnected()) {
Log.i("Unity", "Sensor disconnected, using default sensor values.");
return mSensorValues;
}
if (!mIsStreaming) {
Log.i("Unity", "Sensor not streaming, using default sensor values.");
return mSensorValues;
}
try {
mStartStreamingTask.getTask().waitForCompletion();
} catch (InterruptedException ex) {
ex.printStackTrace();
disconnect();
}
return mSensorValues;
}
/**
* Read the current battery level from the device
*
* @return Task containing the sensors battery level as an integer
*/
public Task<Integer> getBatteryLevelAsync() {
// Wait for services to be discovered
return mServicesDiscovered.getTask().onSuccessTask(t -> {
BluetoothGattService deviceInfoService = mBluetoothGatt.getService(UUID_BATTERY_SERVICE);
BluetoothGattCharacteristic characteristic = deviceInfoService.getCharacteristic(UUID_BATTERY_LEVEL);
mBluetoothGatt.readCharacteristic(characteristic);
return mBatteryLevelTask.getTask();
});
}
public Task<String> getSerialNumber() {
return mServicesDiscovered.getTask().onSuccessTask(t -> {
BluetoothGattService deviceInfoService = mBluetoothGatt.getService(UUID_DEVICE_INFO_SERVICE);
BluetoothGattCharacteristic characteristic = deviceInfoService.getCharacteristic(UUID_SERIAL_NUMBER);
mBluetoothGatt.readCharacteristic(characteristic);
return mSerialNumberTask.getTask();
});
}
/**
* Issue command to sensor to begin streaming combined data
*/
public void startStreaming() {
if (mIsStreaming) {
return;
}
//Enable notifications for combined, set result
//Write 0 to Monitor Characteristic
BluetoothGattService huneoService = mBluetoothGatt.getService(UUID_HUNEO_SERVICE);
BluetoothGattCharacteristic monitorCharacteristic = huneoService.getCharacteristic(UUID_HUNEO_MONITOR);
monitorCharacteristic.setValue(1, FORMAT_UINT8, 0);
mBluetoothGatt.writeCharacteristic(monitorCharacteristic);
}
/**
* Issue command to sensor to stop streaming accel and gyro data
*/
public void stopStreaming() {
if (!mIsStreaming) {
return;
}
//Disable notifications for combined
BluetoothGattService huneoService = mBluetoothGatt.getService(UUID_HUNEO_SERVICE);
BluetoothGattCharacteristic monitorCharacteristic = huneoService.getCharacteristic(UUID_HUNEO_MONITOR);
monitorCharacteristic.setValue(0, FORMAT_UINT8, 0);
mBluetoothGatt.writeCharacteristic(monitorCharacteristic);
}
/**
* Trigger vibration haptics on the sensor
*/
public void triggerHaptics() {
mServicesDiscovered.getTask().onSuccessTask(t -> {
BluetoothGattService huneoService = mBluetoothGatt.getService(UUID_HUNEO_SERVICE);
// Set vibration characteristic to 1
BluetoothGattCharacteristic characteristic = huneoService.getCharacteristic(UUID_HUNEO_VIBRATOR);
characteristic.setValue(0, FORMAT_UINT8, 0);
mBluetoothGatt.writeCharacteristic(characteristic);
return t;
});
}
//Start Combined Notifications
private void startCombined() {
mServicesDiscovered.getTask().onSuccessTask(t -> {
BluetoothGattService huneoService = mBluetoothGatt.getService(UUID_HUNEO_SERVICE);
// Set Combined characteristic to send notifications
BluetoothGattCharacteristic combinedCharacteristic = huneoService.getCharacteristic(UUID_HUNEO_COMBINED);
mBluetoothGatt.setCharacteristicNotification(combinedCharacteristic, true);
//Set Combined Client Characteristic Config Descriptor to enable notifications
BluetoothGattDescriptor combinedDescriptor = combinedCharacteristic.getDescriptor(UUID.fromString(GattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
combinedDescriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(combinedDescriptor);
return t;
});
}
//Stop Combined notifications
private void stopCombined() {
mServicesDiscovered.getTask().onSuccessTask(t -> {
BluetoothGattService huneoService = mBluetoothGatt.getService(UUID_HUNEO_SERVICE);
// Set Accelerometer characteristic to send notifications
BluetoothGattCharacteristic combinedCharacteristic = huneoService.getCharacteristic(UUID_HUNEO_COMBINED);
mBluetoothGatt.setCharacteristicNotification(combinedCharacteristic, false);
// Set Accelerometer Client Characteristic Config Descriptor to enable notifications
BluetoothGattDescriptor combinedDescriptor = combinedCharacteristic.getDescriptor(UUID.fromString(GattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
combinedDescriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(combinedDescriptor);
return t;
});
}
// Convert two bytes into a short
private int unsignedShortToInt(byte firstByte, byte secondByte) {
ByteBuffer bb = ByteBuffer.allocate(2);
bb.order(ByteOrder.LITTLE_ENDIAN);
bb.put(firstByte);
bb.put(secondByte);
short shortVal = bb.getShort(0);
return shortVal >= 0 ? shortVal : 0x10000 + shortVal;
}
}
希望有人能帮助我。我没主意了。
找到解决方案。第三方忘记提到我必须设置正确的值才能启用该特性。我试过了,它奏效了!终于得到了数据值。
我有一个应用程序正在使用 BLE 连接我的设备。从连接到设备、发现服务、编写特征和描述符,一切正常。但由于某种原因,onCharacteristicChanged 没有触发。目标是从特征中的特征检索数据。我尝试使用来自同一服务的不同特征,这与检索数据一样有效。不确定为什么这个特定的特性在其他特性起作用时不起作用。
这是我的代码: //描述符 public 最终静态 UUID UUID_CLIENT_CHARACTERISTIC_CONFIG = UUID.fromString(GattAttributes.CLIENT_CHARACTERISTIC_CONFIG);
// Huneo Service
public final static UUID UUID_HUNEO_SERVICE = UUID.fromString(GattAttributes.HUNEO_SERVICE);
public final static UUID UUID_HUNEO_VIBRATOR = UUID.fromString(GattAttributes.HUNEO_VIBRATOR);
public final static UUID UUID_HUNEO_MONITOR = UUID.fromString(GattAttributes.HUNEO_MONITOR);
public final static UUID UUID_HUNEO_RATES = UUID.fromString(GattAttributes.HUNEO_RATES);
public final static UUID UUID_HUNEO_LED = UUID.fromString(GattAttributes.HUNEO_LED);
public final static UUID UUID_HUNEO_ACCEL = UUID.fromString(GattAttributes.HUNEO_ACCEL);
public final static UUID UUID_HUNEO_GYRO = UUID.fromString(GattAttributes.HUNEO_GYRO);
public final static UUID UUID_HUNEO_COMBINED = UUID.fromString(GattAttributes.HUNEO_COMBINED);
// Battery Service
public final static UUID UUID_BATTERY_SERVICE = UUID.fromString(GattAttributes.BATTERY_SERVICE);
public final static UUID UUID_BATTERY_LEVEL = UUID.fromString(GattAttributes.BATTERY_LEVEL);
// Device Info Service
public final static UUID UUID_DEVICE_INFO_SERVICE = UUID.fromString(GattAttributes.DEVICE_INFO_SERVICE);
public final static UUID UUID_MODEL_NUMBER = UUID.fromString(GattAttributes.MODEL_NUMBER);
public final static UUID UUID_SERIAL_NUMBER = UUID.fromString(GattAttributes.SERIAL_NUMBER);
public final static UUID UUID_FIRMWARE_REV = UUID.fromString(GattAttributes.FIRMWARE_REV);
public final static UUID UUID_HARDWARE_REV = UUID.fromString(GattAttributes.HARDWARE_REV);
public final static UUID UUID_MANUFACTURER_NAME = UUID.fromString(GattAttributes.MANUFACTURER_NAME);
private final static String TAG = "UNITY";
private static final int STATE_DISCONNECTED = 0;
private static final int STATE_CONNECTING = 1;
private static final int STATE_CONNECTED = 2;
private final BluetoothDevice mDevice;
private final IBinder mBinder = new LocalBinder();
private TaskCompletionSource<Void> mConnectionTask = new TaskCompletionSource<>();
private TaskCompletionSource<String> mFirmwareRevTask = new TaskCompletionSource<>();
private TaskCompletionSource<Void> mServicesDiscovered = new TaskCompletionSource<>();
private TaskCompletionSource<Integer> mBatteryLevelTask = new TaskCompletionSource<>();
private TaskCompletionSource<SensorValues> mStartStreamingTask = new TaskCompletionSource<>();
private TaskCompletionSource<String> mSerialNumberTask = new TaskCompletionSource<>();
private SensorValues mSensorValues = new SensorValues();
private BluetoothGatt mBluetoothGatt;
private int mConnectionState = STATE_DISCONNECTED;
private boolean mIsStreaming = false;
// Implements callback methods for GATT events that the app cares about. For example,
// connection change and services discovered.
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
mConnectionState = STATE_CONNECTED;
Log.i(TAG, "Connected to GATT server.");
// Attempts to discover services after successful connection.
Log.i(TAG, "Attempting to start service discovery:" + mBluetoothGatt.discoverServices());
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
mConnectionState = STATE_DISCONNECTED;
mIsStreaming = false;
Log.i(TAG, "Disconnected from GATT server.");
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
mServicesDiscovered.setResult(null);
startStreaming();
Log.w(TAG, "onServicesDiscovered success.");
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
String characteristicUuid = characteristic.getUuid().toString();
if (characteristicUuid.equals(GattAttributes.FIRMWARE_REV)) {
String firmwareRev = characteristic.getStringValue(0);
mFirmwareRevTask.setResult(firmwareRev);
}
if (characteristicUuid.equals(GattAttributes.BATTERY_LEVEL)) {
int batteryLevel = characteristic.getIntValue(FORMAT_UINT8, 0);
mBatteryLevelTask.setResult(batteryLevel);
}
if (characteristicUuid.equals(GattAttributes.SERIAL_NUMBER)) {
String serialNumber = characteristic.getStringValue(0);
mSerialNumberTask.setResult(serialNumber);
}
}
}
@Override
public void onCharacteristicWrite(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
if (characteristic.getUuid().equals(UUID_HUNEO_MONITOR)) {
if (characteristic.getIntValue(FORMAT_UINT8, 0) == 1) {
startCombined();
} else {
stopCombined();
}
}
}
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
String characteristicUuid = characteristic.getUuid().toString();
//Combined value changed
if (characteristicUuid.equals(GattAttributes.HUNEO_COMBINED)) {
byte[] data = characteristic.getValue();
int id = unsignedShortToInt(data[0], data[1]);
int x = unsignedShortToInt(data[2], data[3]);
int y = unsignedShortToInt(data[4], data[5]);
int z = unsignedShortToInt(data[6], data[7]);
mSensorValues.combined = new CartesianValues(id,x,y,z);
mStartStreamingTask.setResult(mSensorValues);
}
}
@Override
public void onDescriptorWrite(BluetoothGatt gatt,
BluetoothGattDescriptor descriptor,
int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
//Combined
if (descriptor.getCharacteristic().getUuid().equals(UUID_HUNEO_COMBINED)) {
mIsStreaming = Arrays.equals(descriptor.getValue(), BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mStartStreamingTask.setResult(null);
}
}
}
};
public AlwaysOnHuneoBoard(BluetoothDevice device) {
this.mDevice = device;
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
// After using a given device, you should make sure that BluetoothGatt.close() is called
// such that resources are cleaned up properly. In this particular example, close() is
// invoked when the UI is disconnected from the Service.
close();
return super.onUnbind(intent);
}
public static class LocalBinder extends Binder {
}
/**
* Connect to the device
*
* @param ct CancellationToken that will make task return if cancelled
* @return when task is complete the device is connected
*/
public Task<Void> connectAsync(CancellationToken ct) {
if (ct.isCancellationRequested()) {
Log.w(TAG, "Connection cancelled");
mConnectionTask.setCancelled();
return mConnectionTask.getTask();
}
if (mDevice == null) {
Log.w(TAG, "BluetoothDevice not initialized");
mConnectionTask.setError(new Exception("BluetoothDevice not initialized"));
return mConnectionTask.getTask();
}
// Previously connected device. BluetoothGatt not closed. Try to reconnect.
if (mBluetoothGatt != null) {
Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
if (mBluetoothGatt.connect()) {
mConnectionState = STATE_CONNECTING;
mConnectionTask.setResult(null);
return mConnectionTask.getTask();
}
}
mBluetoothGatt = mDevice.connectGatt(this, false, mGattCallback);
Log.d(TAG, "Trying to create a new connection.");
mConnectionState = STATE_CONNECTING;
mConnectionTask.setResult(null);
return mConnectionTask.getTask();
}
/**
* Disconnects an existing connection or cancel a pending connection. The disconnection result
* is reported asynchronously through the
* {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
* callback.
*/
public void disconnect() {
if (mDevice == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothDevice not initialized");
return;
}
mBluetoothGatt.disconnect();
}
/**
* After using a given BLE device, the app must call this method to ensure resources are
* released properly.
*/
public void close() {
if (mBluetoothGatt == null) {
return;
}
mBluetoothGatt.close();
mBluetoothGatt = null;
}
/**
* Determines if connected to the BLE device.
*
* @return true if connected, false otherwise.
*/
public boolean isConnected() {
return mConnectionState == STATE_CONNECTED;
}
/**
* Get the calibration for the sensor
*
* @return integer representation of the calibration
*/
public int getCalibration() {
return 100;
}
/**
* Get the firmware version of the sensor
*
* @return string representing the devices firmware version
*/
public String getFirmwareVersion() {
try {
// Wait for services to be discovered
mServicesDiscovered.getTask().onSuccessTask(t -> {
BluetoothGattService deviceInfoService = mBluetoothGatt.getService(UUID_DEVICE_INFO_SERVICE);
BluetoothGattCharacteristic characteristic = deviceInfoService.getCharacteristic(UUID_FIRMWARE_REV);
mBluetoothGatt.readCharacteristic(characteristic);
mFirmwareRevTask.setResult(null);
return mFirmwareRevTask.getTask();
// Wait for deviceRevTask to be completed
}).waitForCompletion(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
return "";
}
return mFirmwareRevTask.getTask().getResult();
}
/**
* Get the device mac address
*
* @return string representation of the mac address
*/
public String getMacAddress() {
return mDevice.getAddress();
}
/**
* Get the model of the device
*
* @return string representation of the device model
*/
public String getModel() {
return mDevice.getName();
}
public SensorValues getCombinedSensorValues() {
if (!isConnected()) {
Log.i("Unity", "Sensor disconnected, using default sensor values.");
return mSensorValues;
}
if (!mIsStreaming) {
Log.i("Unity", "Sensor not streaming, using default sensor values.");
return mSensorValues;
}
try {
mStartStreamingTask.getTask().waitForCompletion();
} catch (InterruptedException ex) {
ex.printStackTrace();
disconnect();
}
return mSensorValues;
}
/**
* Read the current battery level from the device
*
* @return Task containing the sensors battery level as an integer
*/
public Task<Integer> getBatteryLevelAsync() {
// Wait for services to be discovered
return mServicesDiscovered.getTask().onSuccessTask(t -> {
BluetoothGattService deviceInfoService = mBluetoothGatt.getService(UUID_BATTERY_SERVICE);
BluetoothGattCharacteristic characteristic = deviceInfoService.getCharacteristic(UUID_BATTERY_LEVEL);
mBluetoothGatt.readCharacteristic(characteristic);
return mBatteryLevelTask.getTask();
});
}
public Task<String> getSerialNumber() {
return mServicesDiscovered.getTask().onSuccessTask(t -> {
BluetoothGattService deviceInfoService = mBluetoothGatt.getService(UUID_DEVICE_INFO_SERVICE);
BluetoothGattCharacteristic characteristic = deviceInfoService.getCharacteristic(UUID_SERIAL_NUMBER);
mBluetoothGatt.readCharacteristic(characteristic);
return mSerialNumberTask.getTask();
});
}
/**
* Issue command to sensor to begin streaming combined data
*/
public void startStreaming() {
if (mIsStreaming) {
return;
}
//Enable notifications for combined, set result
//Write 0 to Monitor Characteristic
BluetoothGattService huneoService = mBluetoothGatt.getService(UUID_HUNEO_SERVICE);
BluetoothGattCharacteristic monitorCharacteristic = huneoService.getCharacteristic(UUID_HUNEO_MONITOR);
monitorCharacteristic.setValue(1, FORMAT_UINT8, 0);
mBluetoothGatt.writeCharacteristic(monitorCharacteristic);
}
/**
* Issue command to sensor to stop streaming accel and gyro data
*/
public void stopStreaming() {
if (!mIsStreaming) {
return;
}
//Disable notifications for combined
BluetoothGattService huneoService = mBluetoothGatt.getService(UUID_HUNEO_SERVICE);
BluetoothGattCharacteristic monitorCharacteristic = huneoService.getCharacteristic(UUID_HUNEO_MONITOR);
monitorCharacteristic.setValue(0, FORMAT_UINT8, 0);
mBluetoothGatt.writeCharacteristic(monitorCharacteristic);
}
/**
* Trigger vibration haptics on the sensor
*/
public void triggerHaptics() {
mServicesDiscovered.getTask().onSuccessTask(t -> {
BluetoothGattService huneoService = mBluetoothGatt.getService(UUID_HUNEO_SERVICE);
// Set vibration characteristic to 1
BluetoothGattCharacteristic characteristic = huneoService.getCharacteristic(UUID_HUNEO_VIBRATOR);
characteristic.setValue(0, FORMAT_UINT8, 0);
mBluetoothGatt.writeCharacteristic(characteristic);
return t;
});
}
//Start Combined Notifications
private void startCombined() {
mServicesDiscovered.getTask().onSuccessTask(t -> {
BluetoothGattService huneoService = mBluetoothGatt.getService(UUID_HUNEO_SERVICE);
// Set Combined characteristic to send notifications
BluetoothGattCharacteristic combinedCharacteristic = huneoService.getCharacteristic(UUID_HUNEO_COMBINED);
mBluetoothGatt.setCharacteristicNotification(combinedCharacteristic, true);
//Set Combined Client Characteristic Config Descriptor to enable notifications
BluetoothGattDescriptor combinedDescriptor = combinedCharacteristic.getDescriptor(UUID.fromString(GattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
combinedDescriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(combinedDescriptor);
return t;
});
}
//Stop Combined notifications
private void stopCombined() {
mServicesDiscovered.getTask().onSuccessTask(t -> {
BluetoothGattService huneoService = mBluetoothGatt.getService(UUID_HUNEO_SERVICE);
// Set Accelerometer characteristic to send notifications
BluetoothGattCharacteristic combinedCharacteristic = huneoService.getCharacteristic(UUID_HUNEO_COMBINED);
mBluetoothGatt.setCharacteristicNotification(combinedCharacteristic, false);
// Set Accelerometer Client Characteristic Config Descriptor to enable notifications
BluetoothGattDescriptor combinedDescriptor = combinedCharacteristic.getDescriptor(UUID.fromString(GattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
combinedDescriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(combinedDescriptor);
return t;
});
}
// Convert two bytes into a short
private int unsignedShortToInt(byte firstByte, byte secondByte) {
ByteBuffer bb = ByteBuffer.allocate(2);
bb.order(ByteOrder.LITTLE_ENDIAN);
bb.put(firstByte);
bb.put(secondByte);
short shortVal = bb.getShort(0);
return shortVal >= 0 ? shortVal : 0x10000 + shortVal;
}
}
希望有人能帮助我。我没主意了。
找到解决方案。第三方忘记提到我必须设置正确的值才能启用该特性。我试过了,它奏效了!终于得到了数据值。