BluetoothGatt.writeCharacteristic () успешно первый раз, но возвращает false после - PullRequest
0 голосов
/ 03 января 2019

Я создаю приложение 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();
          }
    }
}
...