Я создаю приложение Android, которое считывает данные с некоторых устройств BLE, процесс запуска приложения:
- Обнаружение устройств.
- проверка их сопряжения, если они не спарены.
- подключитесь к первым устройствам, затем прочитайте данные этих устройств, затем остановитесь и оставайтесь на связи (если в первый раз, когда я хочу подключиться к устройству, я звоню
connectGatt()
, иначеесли уже подключен вызов gatt.discoverServices()
) - переключение на вторые устройства (подключение + чтение + запись + остановка чтения)
когда я получаю последнее устройство, я останавливаю процесс дляВ то время как я повторяю процесс с самого начала
Весь процесс в первый раз работает нормально для всех устройств, но когда процесс возвращается к первому устройству и я вызываю gatt.discoverServices()
вместо connectGatt()
Я получаю все Услуги, а также Характеристики, но мой gatt.writeCharacteristic()
дает сбой и возвращает false.
Может кто-нибудь помочь узнать, почему он не работает и как решить эту проблему.
вот какмой код выглядит
if (DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getBluetoothGatt() == null) {
// if(true){
log4jfile.info(" BluetoothGATT = null : call connectGatt");
BluetoothService.reading_device = device.getAddress();
bluetoothGatt = device.connectGatt(this, false, bluetoothGattCallback)
if (DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getBluetoothGatt() == null) {
DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).setBluetoothGatt(bluetoothGatt);
}
} else {
if (mBluetoothManager.getConnectedDevices(BluetoothProfile.GATT).contains(device)) {
log4jfile.info(" BluetoothGATT != null : call discoverServices");
DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getBluetoothGatt().discoverServices();
} else {
log4jfile.info(" BluetoothGATT != null : call connect");
DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getBluetoothGatt().connect();
}
}
Примечание:
я не звоню connectGatt()
много раз для одного и того же устройства, потому что номер BluetoothGatt, который мыможет создать в Android 32.
я не буду звонить bluetoothGatt.close()
после того, как я закончу, потому что я хочу оставаться на связи с моими устройствами все время.
РЕДАКТИРОВАТЬ
bluetoothGatt = device.connectGatt(this, false, new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
log4jfile.info("onConnectionStateChange, status : " + status + " parseConnection : " + GattStatusParse.parseConnection(status) + " or " + GattStatusParse.parseConnection(status));
DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).setSuccess_Counter(DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getSuccess_Counter() + 1);
isConnected = BluetoothProfile.STATE_CONNECTED == newState;
if (status == BluetoothGatt.GATT_SUCCESS) {
for (BluetoothDeviceWrapper blw : DeviceListAdapter.devices) {
if (blw.getDevice().getAddress().equals(device.getAddress())) {
blw.setConnectionFailed(false);
}
}
if (isConnected) {
log4jfile.info(" GATT connected " + device.getAddress() + " state of the opération : " + status + " connexion state : " + newState);
if (!connectedBluethoothDevice.contains(device)) {
connectedBluethoothDevice.add(device);
}
Log.i(TAG, "GATT connected." + connectedBluethoothDevice.toString());
gatt.discoverServices();
//LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
BluetoothService.reading_device = device.getAddress();
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
} else {
log4jfile.info(" GATT disconnected " + device.getAddress() + " state of the opération : " + status + " connexion state : " + newState);
if (connectedBluethoothDevice.contains(device)) {
connectedBluethoothDevice.remove(device);
}
Log.i(TAG, "GATT disconnected." + connectedBluethoothDevice.toString());
//NotificationService_.intent(BluetoothService.this).stop();
notificationManager.notify(442, getNotification(device));
BluetoothService.reading_device = "";
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
}
} else {
if (connectedBluethoothDevice.contains(device)) {
// mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
int mConnectionState = mBluetoothManager.getConnectionState(device, BluetoothProfile.GATT);
if (mConnectionState == BluetoothProfile.STATE_DISCONNECTED || mConnectionState == BluetoothProfile.STATE_DISCONNECTING) {
connectedBluethoothDevice.remove(device);
}
}
for (BluetoothDeviceWrapper blw : DeviceListAdapter.devices) {
if (blw.getDevice().getAddress().equals(device.getAddress())) {
blw.setConnectionFailed(true);
}
}
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
BluetoothService.FAILED_CONNECTION = BluetoothService.FAILED_CONNECTION + 1;
DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).setFail_Counter(DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getFail_Counter() + 1);
log4jfile.info("connection _ Failed : " + BluetoothService.FAILED_CONNECTION);
if (1 <= BluetoothService.FAILED_CONNECTION && BluetoothService.FAILED_CONNECTION < Integer.parseInt(NombreDeTentativeDeConnexion)) {
if (MainActivity.current == 0) {
MainActivity.current = DeviceListAdapter.devicesFounder.size() - 1;
} else {
MainActivity.current = MainActivity.current - 1;
}
if (!MainActivity.stoppedServices) {
Log.e(TAG, "sendBroadcast DEVICE_READ_DONE 2");
final Intent myIntent = new Intent(DEVICE_READ_DONE);
sendBroadcast(myIntent);
stopSelf();
}
} else {
BluetoothService.FAILED_CONNECTION = 0;
if (!MainActivity.stoppedServices) {
Log.e(TAG, "sendBroadcast DEVICE_READ_DONE 3");
final Intent myIntent = new Intent(DEVICE_READ_DONE);
sendBroadcast(myIntent);
stopSelf();
}
}
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
startForeground(442, getNotification(device));
log4jfile.info("Services discovered. status : " + status + " , parse status : " + GattStatusParse.parse(status));
BluetoothService.reading_device = gatt.getDevice().getAddress();
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) {
log4jfile.info("GATT_INSUFFICIENT_AUTHENTICATION");
handleAuthenticationError(gatt);
return;
}
discoverCharacteristics(gatt);
}
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
System.gc();
log4jfile.info("Characteristic written, status: " + status + " , parse status : " + GattStatusParse.parse(status));
//BluetoothService.reading_device=gatt.getDevice().getAddress();
if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) {
log4jfile.error("GATT_INSUFFICIENT_AUTHENTICATION");
handleAuthenticationError(gatt);
return;
}
final byte command = characteristic.getValue()[0];
switch (command) {
case WRITE_TIME:
log4jfile.info("Time written.");
final BluetoothGattCharacteristic batteryCharacteristic = readableCharacteristics.get(Characteristic.BATTERY.getUuid());
gatt.setCharacteristicNotification(batteryCharacteristic, true);
for (BluetoothGattDescriptor descriptor : batteryCharacteristic.getDescriptors()) {
if (descriptor.getUuid().toString().startsWith("00002904")) {
descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
gatt.writeDescriptor(descriptor);
}
}
break;
case WRITE_NOTIFICATION:
log4jfile.info("Notification sent.");
if (notificationsQueue.isEmpty()) {
log4jfile.info("Reading characteristics...");
//BluetoothService.reading_device=gatt.getDevice().getAddress();
readNextCharacteristics(gatt);
} else {
log4jfile.info("writing next notification...");
alertIn.setValue(notificationsQueue.poll());
gatt.writeCharacteristic(alertIn);
}
break;
default:
log4jfile.info("No such ALERT IN command: " + command);
break;
}
}
@Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
log4jfile.info("onDescriptorWrite write, status: " + status + " , parse status : " + GattStatusParse.parse(status));
readCharacteristic(gatt, Characteristic.MANUFACTURER);
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt, final BluetoothGattCharacteristic gattCharacteristic, int status) {
log4jfile.info("onCharacteristicRead, device : " + gatt.getDevice().getAddress() + " status : " + status + " , parse status : " + GattStatusParse.parse(status));
System.gc();
if (!MainActivity.stoppedServices && gatt.getDevice().getAddress().equals(BluetoothService.reading_device)) {
if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) {
handleAuthenticationError(gatt);
return;
}
final String characteristicUuid = gattCharacteristic.getUuid().toString();
final Characteristic characteristic = Characteristic.byUuid(characteristicUuid);
switch (characteristic) {
case MANUFACTURER:
manufacturerInfo.manufacturer = gattCharacteristic.getStringValue(0);
readCharacteristic(gatt, Characteristic.FW_REVISION);
break;
case FW_REVISION:
manufacturerInfo.firmwareRevision = gattCharacteristic.getStringValue(0);
readCharacteristic(gatt, Characteristic.MODE);
break;
default:
//BluetoothService.reading_device=gatt.getDevice().getAddress();
//LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
log4jfile.info("Characteristic read: " + characteristic.name() + " device " + gatt.getDevice().getAddress() + " basculeTimer :" + BluetoothService.basculeTimer);
if (1 > BluetoothService.FAILED_CONNECTION || BluetoothService.FAILED_CONNECTION >= 3) {
BluetoothService.FAILED_CONNECTION = 0;
}
BluetoothService.basculeTimer++;
if (BluetoothService.basculeTimer == 0 || BluetoothService.basculeTimer == 10) {
// BluetoothService.reading_device=gatt.getDevice().getAddress();
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
}
if (!gatt.getDevice().getAddress().equals(BluetoothService.reading_device)) {
// BluetoothService.reading_device = bluetoothGatt.getDevice().getAddress();
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
}
//BluetoothService.reading_device=gatt.getDevice().getAddress();
if (characteristic == Characteristic.MODE) {
final Mode newMode = Mode.bySymbol(gattCharacteristic.getValue()[0]);
log4jfile.info("mode change : " + newMode.name());
if (mode != newMode) {
onModeChanged(newMode);
}
} else {
onBluetoothDataReceived(characteristic, gattCharacteristic.getValue());
}
// if (shouldUpdateTime) {
// updateTime(gatt.getDevice());
// }
if (notificationsQueue.isEmpty()) {
log4jfile.info(" notificationsQueue isEmpty ==> readNextCharacteristics");
readNextCharacteristics(gatt);
} else {
log4jfile.info(" notificationsQueue NotisEmpty ==> writeCharacteristic");
alertIn.setValue(notificationsQueue.poll());
gatt.writeCharacteristic(alertIn);
}
break;
}
}
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic gattCharacteristic) {
System.gc();
final String characteristicUuid = gattCharacteristic.getUuid().toString();
final Characteristic characteristic = Characteristic.byUuid(characteristicUuid);
log4jfile.info("Characteristic changed: " + characteristic.name());
if (characteristic == Characteristic.BATTERY) {
onBluetoothDataReceived(Characteristic.BATTERY, gattCharacteristic.getValue());
}
}
});
private void discoverCharacteristics(final BluetoothGatt gatt) {
log4jfile.info("discoverCharacteristics. services length : " + gatt.getServices().size());
//BluetoothService.reading_device = gatt.getDevice().getAddress();
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
if (gatt.getServices().size() == 0) {
log4jfile.info("No services found.");
//LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.DEVICE_READ_DONE));
}
for (BluetoothGattService gattService : gatt.getServices()) {
if(gatt.getDevice().getAddress().equals(BluetoothService.reading_device)){
storeCharacteristicsFromService(gattService,gatt.getDevice());
}
}
}
private void storeCharacteristicsFromService(BluetoothGattService gattService,BluetoothDevice device) {
log4jfile.info("storeCharacteristicsFromService , length : " + gattService.getCharacteristics().size());
for (BluetoothGattCharacteristic gattCharacteristic : gattService.getCharacteristics()) {
final String characteristicUuid = gattCharacteristic.getUuid().toString();
final Characteristic characteristic = Characteristic.byUuid(characteristicUuid);
if (characteristic == Characteristic.ALERT_IN) {
log4jfile.info( "ALERT_IN DISCOVERED");
DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).setAlertIn(null);
DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).setAlertIn(gattCharacteristic);
alertIn = gattCharacteristic;
setTime();
if(device.getAddress().equals(BluetoothService.reading_device)) {
updateTime(device);
}
NotificationService_.intent(BluetoothService.this).start();
} else if (characteristic != null) {
log4jfile.info("characteristic " + characteristic);
log4jfile.info(characteristic.getType() + ": " + characteristic.name());
readableCharacteristics.put(characteristicUuid, gattCharacteristic);
} else {
log4jfile.info("UNKNOWN: " + characteristicUuid);
}
}
}
public void setTime() {
Log.d(TAG, "Setting time...");
if (!isConnected || alertIn == null) {
Log.w(TAG, "Time not set.");
return;
}
shouldUpdateTime = true;
}
void updateTime(BluetoothDevice device) {
log4jfile.info("updateTime ..."+device.getAddress());
shouldUpdateTime = false;
final byte[] time = new byte[20];
final long currentTime = System.currentTimeMillis();
final long currentTimeWithTimeZoneOffset = (currentTime + TimeZone.getDefault().getOffset(currentTime)) / 1000;
final ByteBuffer buffer = ByteBuffer.allocate(8);
buffer.order(ByteOrder.LITTLE_ENDIAN).asLongBuffer().put(currentTimeWithTimeZoneOffset);
final byte[] utcBytes = buffer.array();
final byte length = 0x04;
time[0] = WRITE_TIME;
time[1] = length;
time[2] = utcBytes[0];
time[3] = utcBytes[1];
time[4] = utcBytes[2];
time[5] = utcBytes[3];
Boolean result=false;
DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getAlertIn().setValue(time);
DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getAlertIn().setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
log4jfile.info(DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getBluetoothGatt().getDevice().getAddress());
while (!result){
result=DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getBluetoothGatt().writeCharacteristic(DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getAlertIn());
log4jfile.info("write return "+result+" alertIn :"+DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getAlertIn().getStringValue(0));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}