@Override
    public final void onDescriptorWrite(
        final BluetoothGatt gatt, final BluetoothGattDescriptor descriptor, final int status) {
      if (status == BluetoothGatt.GATT_SUCCESS) {
        Logger.i(
            mLogSession,
            "Data written to descr. "
                + descriptor.getUuid()
                + ", value: "
                + ParserUtils.parse(descriptor));

        if (isServiceChangedCCCD(descriptor)) {
          Logger.a(mLogSession, "Service Changed notifications enabled");
          if (!readBatteryLevel()) nextRequest();
        } else if (isBatteryLevelCCCD(descriptor)) {
          final byte[] value = descriptor.getValue();
          if (value != null && value.length > 0 && value[0] == 0x01) {
            Logger.a(mLogSession, "Battery Level notifications enabled");
            nextRequest();
          } else Logger.a(mLogSession, "Battery Level notifications disabled");
        } else {
          nextRequest();
        }
      } else if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) {
        if (gatt.getDevice().getBondState() != BluetoothDevice.BOND_NONE) {
          DebugLogger.w(TAG, ERROR_AUTH_ERROR_WHILE_BONDED);
          mCallbacks.onError(ERROR_AUTH_ERROR_WHILE_BONDED, status);
        }
      } else {
        DebugLogger.e(TAG, "onDescriptorWrite error " + status);
        onError(ERROR_WRITE_DESCRIPTOR, status);
      }
    }
 public void enableNotification(int index, UUID service, UUID characteristic) {
   BluetoothGattService Service;
   BluetoothGattCharacteristic Characteristic;
   BluetoothGattDescriptor Descriptor;
   if (index < 0 || index > mBluetoothGatt.length) {
     Log.e(TAG, "Read char index out of bound");
     return;
   }
   if (mBluetoothGatt[index] == null) {
     Log.e(TAG, "GATT isn't connected");
     return;
   }
   if (service != null && characteristic != null) {
     Service = mBluetoothGatt[index].getService(service);
     if (Service == null) {
       Log.e(TAG, "Service not found");
       return;
     }
     Characteristic = Service.getCharacteristic(characteristic);
     if (Characteristic == null) {
       Log.e(TAG, "Characteristic not found");
       return;
     }
     mBluetoothGatt[index].setCharacteristicNotification(Characteristic, true);
     Descriptor = Characteristic.getDescriptor(CCCD);
     Descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
     mBluetoothGatt[index].writeDescriptor(Descriptor);
     Log.i(TAG, "CCCD set");
   }
 }
 // Called when services have been discovered on the remote device.
 // It seems to be necessary to wait for this discovery to occur before
 // manipulating any services or characteristics.
 @Override
 public void onServicesDiscovered(BluetoothGatt gatt, int status) {
   super.onServicesDiscovered(gatt, status);
   if (status == BluetoothGatt.GATT_SUCCESS) {
     // writeLine("Service discovery completed!");
   } else {
     // writeLine("Service discovery failed with status: " + status);
   }
   // Save reference to each characteristic.
   tx = gatt.getService(UART_UUID).getCharacteristic(TX_UUID);
   rx = gatt.getService(UART_UUID).getCharacteristic(RX_UUID);
   // Setup notifications on RX characteristic changes (i.e. data received).
   // First call setCharacteristicNotification to enable notification.
   if (!gatt.setCharacteristicNotification(rx, true)) {
     // writeLine("Couldn't set notifications for RX characteristic!");
   }
   // Next update the RX characteristic's client descriptor to enable notifications.
   if (rx.getDescriptor(CLIENT_UUID) != null) {
     BluetoothGattDescriptor desc = rx.getDescriptor(CLIENT_UUID);
     desc.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
     if (!gatt.writeDescriptor(desc)) {
       // writeLine("Couldn't write RX client descriptor value!");
     }
   } else {
     // writeLine("Couldn't get RX client descriptor!");
   }
 }
Exemple #4
0
  private static boolean setCharacteristicNotification(
      BluetoothGatt bluetoothGatt, BluetoothGattCharacteristic characteristic, boolean enabled) {
    if (bluetoothGatt == null) {
      Log.w(TAG, "BluetoothAdapter not initialized");
      return false;
    }

    bluetoothGatt.setCharacteristicNotification(characteristic, enabled);

    try {
      BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString(UUIDDes));
      if (descriptor != null) {
        descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
        return (bluetoothGatt.writeDescriptor(descriptor));
      } else {
        Log.e(TAG, "descriptor is null");
        return false;
      }
    } catch (NullPointerException e) {
      e.printStackTrace();
    } catch (IllegalArgumentException e) {
      e.printStackTrace();
    }

    return true;
  }
Exemple #5
0
        /*
         * Enable notification of changes on the data characteristic for each sensor
         * by writing the ENABLE_NOTIFICATION_VALUE flag to that characteristic's
         * configuration descriptor.
         */
        private void setNotifyNextSensor(BluetoothGatt gatt) {
          BluetoothGattCharacteristic characteristic;
          switch (mState) {
            case 0:
              Log.d(TAG, "Set notify on Data characteristic");
              characteristic = gatt.getService(MAIN_SERVICE).getCharacteristic(DATA_CHAR);
              break;

            default:
              // mHandler.sendEmptyMessage(MSG_DISMISS);
              Log.i(TAG, "All Sensors Enabled");
              reset();
              return;
          }

          bytesp1 = new ArrayList<>();
          bytesp2 = new ArrayList<>();
          bytesv = new ArrayList<>();

          // Enable local notifications
          gatt.setCharacteristicNotification(characteristic, true);
          // Enabled remote notifications
          BluetoothGattDescriptor desc = characteristic.getDescriptor(CONFIG_DESCRIPTOR);
          desc.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
          gatt.writeDescriptor(desc);
        }
 @Override
 public void onDescriptorWrite(
     BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
   super.onDescriptorWrite(gatt, descriptor, status);
   Log.d(TAG, "onDescriptorWrite");
   switch (status) {
     case BluetoothGatt.GATT_SUCCESS:
       getBluetoothLe()
           .getBleEventCallback()
           .onCharacteristicNotificationEnabled(gatt, descriptor);
       break;
     case BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION:
     case BluetoothGatt.GATT_INSUFFICIENT_ENCRYPTION:
       // bonds automatically
       Log.w(
           TAG,
           "Failed to write descriptor because of "
               + "GATT_INSUFFICIENT_AUTHENTICATION"
               + " and "
               + "GATT_INSUFFICIENT_ENCRYPTION: "
               + descriptor.getUuid());
       getBluetoothLe()
           .getBleEventCallback()
           .onCharacteristicNotificationEnablingFail(gatt, descriptor, status);
       break;
     default:
       Log.w(TAG, "Failed to write descriptor: " + descriptor.getUuid());
       getBluetoothLe()
           .getBleEventCallback()
           .onCharacteristicNotificationEnablingFail(gatt, descriptor, status);
       break;
   }
 }
  /**
   * Enables or disables notification on a give characteristic.
   *
   * @param characteristic Characteristic to act on.
   * @param enabled If true, enable notification. False otherwise.
   */
  public void setCharacteristicNotification(
      BluetoothGattCharacteristic characteristic, boolean enabled) {
    if (mBluetoothAdapter == null || mBluetoothGatt == null) {
      Log.w(TAG, "BluetoothAdapter not initialized");
      return;
    }
    mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);

    // This is specific to Heart Rate Measurement.
    if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) {
      BluetoothGattDescriptor descriptor =
          characteristic.getDescriptor(
              UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
      descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
      mBluetoothGatt.writeDescriptor(descriptor);
    }

    // specific for pm2.5
    if (UUID_FFE0.equals(characteristic.getUuid())) {
      BluetoothGattDescriptor descriptor =
          characteristic.getDescriptor(
              UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
      descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
      mBluetoothGatt.writeDescriptor(descriptor);
    }
  }
 /** Write the hello input descriptor to the device */
 private void writeHelloInputCharacteristic() {
   // Set the enable/disable notification settings
   BluetoothGattCharacteristic notifyCharacteristic =
       GattUtils.getCharacteristic(
           mPickedDeviceGatt,
           Constants.HELLO_SERVICE_UUID,
           Constants.HELLO_CHARACTERISTIC_INPUT_UUID);
   int notificationState = mSpinnerHelloInput.getSelectedItemPosition();
   if (notificationState >= 0 && notificationState <= 2) {
     BluetoothGattDescriptor descriptor =
         GattUtils.getDescriptor(
             mPickedDeviceGatt,
             Constants.HELLO_SERVICE_UUID,
             Constants.HELLO_CHARACTERISTIC_INPUT_UUID,
             Constants.CLIENT_CONFIG_DESCRIPTOR_UUID);
     if (notificationState > 0) {
       mPickedDeviceGatt.setCharacteristicNotification(notifyCharacteristic, true);
       if (notificationState == 1) {
         descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
       } else if (notificationState == 2) {
         descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
       }
     } else {
       mPickedDeviceGatt.setCharacteristicNotification(notifyCharacteristic, false);
       descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
     }
     mRequestQueue.addWriteDescriptor(mPickedDeviceGatt, descriptor);
     mRequestQueue.execute();
   }
 }
    @Override
    public final void onCharacteristicChanged(
        final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
      final String data = ParserUtils.parse(characteristic);

      if (isBatteryLevelCharacteristic(characteristic)) {
        Logger.i(
            mLogSession,
            "Notification received from " + characteristic.getUuid() + ", value: " + data);
        final int batteryValue =
            characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0);
        Logger.a(mLogSession, "Battery level received: " + batteryValue + "%");
        mCallbacks.onBatteryValueReceived(batteryValue);
      } else {
        final BluetoothGattDescriptor cccd =
            characteristic.getDescriptor(CLIENT_CHARACTERISTIC_CONFIG_DESCRIPTOR_UUID);
        final boolean notifications =
            cccd == null
                || cccd.getValue() == null
                || cccd.getValue().length != 2
                || cccd.getValue()[0] == 0x01;

        if (notifications) {
          Logger.i(
              mLogSession,
              "Notification received from " + characteristic.getUuid() + ", value: " + data);
          onCharacteristicNotified(gatt, characteristic);
        } else { // indications
          Logger.i(
              mLogSession,
              "Indication received from " + characteristic.getUuid() + ", value: " + data);
          onCharacteristicIndicated(gatt, characteristic);
        }
      }
    }
 @NonNull
 @Override
 public List<UUID> getDescriptors() {
   final List<UUID> identifiers = new ArrayList<>();
   for (final BluetoothGattDescriptor descriptor : wrappedCharacteristic.getDescriptors()) {
     identifiers.add(descriptor.getUuid());
   }
   return identifiers;
 }
  public void listenToCaliperMeasurements(final BluetoothGattCharacteristic characteristic) {
    if (characteristic == null) {
      Log.e(
          TAG,
          "Haven't discovered this feature yet, please wait until it has connected once, and or try disconnecting and reconnecting.");
      return;
    }

    Log.d(TAG, "Starting to listen to notifications from " + characteristic.getUuid());
    final int charaProp = characteristic.getProperties();
    if ((charaProp | BluetoothGattCharacteristic.PROPERTY_READ) > 0) {
      // If there is an active notification on a characteristic, clear
      // it first so it doesn't update the data field on the user interface.
      if (mNotifyCharacteristic != null) {
        mBluetoothLeService.setCharacteristicNotification(mNotifyCharacteristic, false);
        mNotifyCharacteristic = null;
      }
      mBluetoothLeService.readCharacteristic(characteristic);
    }
    if ((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
      mNotifyCharacteristic = characteristic;
      mBluetoothLeService.setCharacteristicNotification(characteristic, true);

      // Set descriptor to enable notifications
      BluetoothGattDescriptor descriptor =
          characteristic.getDescriptor(
              UUID.fromString(SCalEvoBluetoothSpecifications.CLIENT_CHARACTERISTIC_CONFIG));
      if (descriptor == null) {
        Log.e(
            TAG,
            "descriptor "
                + SCalEvoBluetoothSpecifications.CLIENT_CHARACTERISTIC_CONFIG
                + "was null, looking for others.");

        List<BluetoothGattDescriptor> descriptors = characteristic.getDescriptors();
        String uuid;
        for (BluetoothGattDescriptor aDescriptor : descriptors) {
          uuid = aDescriptor.getUuid().toString();
          Log.e(TAG, "BluetoothGattDescriptor " + uuid);
          descriptor = aDescriptor;
        }
        if (descriptor == null) {
          Log.e(
              TAG,
              "Couldn't find any descriptors for this characteristic, cant enable notifications");
          return;
        } else {
          Log.e(TAG, "Trying the last descriptor to enable notifications");
        }
      }
      descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
      mBluetoothLeService.writeDescriptor(descriptor);
      Toast.makeText(this, "Ready", Toast.LENGTH_SHORT).show();
      Log.e(TAG, "Ready to read from characteristic " + characteristic.getUuid());
    }
  }
  public JSONObject asJSONObject(BluetoothGatt gatt) {

    JSONObject json = asJSONObject();

    try {
      JSONArray servicesArray = new JSONArray();
      JSONArray characteristicsArray = new JSONArray();
      json.put("services", servicesArray);
      json.put("characteristics", characteristicsArray);

      if (connected && gatt != null) {
        for (BluetoothGattService service : gatt.getServices()) {
          servicesArray.put(UUIDHelper.uuidToString(service.getUuid()));

          for (BluetoothGattCharacteristic characteristic : service.getCharacteristics()) {
            JSONObject characteristicsJSON = new JSONObject();
            characteristicsArray.put(characteristicsJSON);

            characteristicsJSON.put("service", UUIDHelper.uuidToString(service.getUuid()));
            characteristicsJSON.put(
                "characteristic", UUIDHelper.uuidToString(characteristic.getUuid()));
            // characteristicsJSON.put("instanceId", characteristic.getInstanceId());

            characteristicsJSON.put("properties", Helper.decodeProperties(characteristic));
            // characteristicsJSON.put("propertiesValue", characteristic.getProperties());

            if (characteristic.getPermissions() > 0) {
              characteristicsJSON.put("permissions", Helper.decodePermissions(characteristic));
              // characteristicsJSON.put("permissionsValue", characteristic.getPermissions());
            }

            JSONArray descriptorsArray = new JSONArray();

            for (BluetoothGattDescriptor descriptor : characteristic.getDescriptors()) {
              JSONObject descriptorJSON = new JSONObject();
              descriptorJSON.put("uuid", UUIDHelper.uuidToString(descriptor.getUuid()));
              descriptorJSON.put("value", descriptor.getValue()); // always blank

              if (descriptor.getPermissions() > 0) {
                descriptorJSON.put("permissions", Helper.decodePermissions(descriptor));
                // descriptorJSON.put("permissionsValue", descriptor.getPermissions());
              }
              descriptorsArray.put(descriptorJSON);
            }
            if (descriptorsArray.length() > 0) {
              characteristicsJSON.put("descriptors", descriptorsArray);
            }
          }
        }
      }
    } catch (JSONException e) { // TODO better error handling
      e.printStackTrace();
    }

    return json;
  }
  private void enableNotifications(BluetoothGatt gatt, UUID serviceUuid, UUID dataUuid) {
    UUID CCC = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");

    BluetoothGattService service = gatt.getService(serviceUuid);
    BluetoothGattCharacteristic dataCharacteristic = service.getCharacteristic(dataUuid);
    gatt.setCharacteristicNotification(dataCharacteristic, true); // Enabled locally

    BluetoothGattDescriptor config = dataCharacteristic.getDescriptor(CCC);
    config.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
    gatt.writeDescriptor(config); // Enabled remotely
  }
 @Permissions
 @Override
 public int getDescriptorPermissions(@NonNull UUID identifier) {
   final BluetoothGattDescriptor descriptor = wrappedCharacteristic.getDescriptor(identifier);
   if (descriptor != null) {
     final @Permissions int permissions = descriptor.getPermissions();
     return permissions;
   } else {
     return PERMISSION_NULL;
   }
 }
  public void showServicesAndCharacteristics() {
    for (BluetoothGattService service : this.io.gatt.getServices()) {
      Log.d(TAG, "onServicesDiscovered:" + service.getUuid());

      for (BluetoothGattCharacteristic characteristic : service.getCharacteristics()) {
        Log.d(TAG, "  char:" + characteristic.getUuid());

        for (BluetoothGattDescriptor descriptor : characteristic.getDescriptors()) {
          Log.d(TAG, "    descriptor:" + descriptor.getUuid());
        }
      }
    }
  }
 /**
  * Enables or disables notification on a give characteristic.
  *
  * @param characteristic Characteristic to act on.
  * @param enabled If true, enable notification. False otherwise.
  */
 public void setCharacteristicNotification(
     BluetoothGattCharacteristic characteristic, boolean enabled) {
   if (mBluetoothAdapter == null || mBluetoothGatt == null) {
     Log.w(TAG, "BluetoothAdapter not initialized");
     return;
   }
   mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
   BluetoothGattDescriptor descriptor =
       characteristic.getDescriptor(UUID.fromString(GattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
   if (descriptor != null) {
     System.out.println("write descriptor");
     descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
     mBluetoothGatt.writeDescriptor(descriptor);
   }
 }
 private void onClientCharacteristicConfigurationDescriptorFound(
     BluetoothGattCharacteristic characteristic, BluetoothGattDescriptor descriptor) {
   Log.d();
   mBluetoothGatt.setCharacteristicNotification(characteristic, true);
   descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
   mBluetoothGatt.writeDescriptor(descriptor);
 }
        @Override
        public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor arg0, int status) {

          BluetoothGattCharacteristic mHRMcharac = arg0.getCharacteristic();
          if (!enableNotification(true, mHRMcharac)) {
            reportConnectFailed("Failed to enable notification in onDescriptorRead");
          }
        }
 private void onHeartRateMeasurementCharacteristicFound(
     BluetoothGattCharacteristic characteristic) {
   Log.d();
   boolean found = false;
   for (BluetoothGattDescriptor descriptor : characteristic.getDescriptors()) {
     Log.d("descriptor=" + descriptor.getUuid());
     if (getAssignedNumber(descriptor.getUuid())
         == GATT_DESCRIPTOR_CLIENT_CHARACTERISTIC_CONFIGURATION) {
       onClientCharacteristicConfigurationDescriptorFound(characteristic, descriptor);
       found = true;
       break;
     }
   }
   if (!found) {
     onClientCharacteristicConfigurationDescriptorNotFound();
   }
 }
  /**
   * This method tries to enable notifications on the Battery Level characteristic.
   *
   * @param enable <code>true</code> to enable battery notifications, false to disable
   * @return true if request has been sent
   */
  public boolean setBatteryNotifications(final boolean enable) {
    final BluetoothGatt gatt = mBluetoothGatt;
    if (gatt == null) {
      return false;
    }

    final BluetoothGattService batteryService = gatt.getService(BATTERY_SERVICE);
    if (batteryService == null) return false;

    final BluetoothGattCharacteristic batteryLevelCharacteristic =
        batteryService.getCharacteristic(BATTERY_LEVEL_CHARACTERISTIC);
    if (batteryLevelCharacteristic == null) return false;

    // Check characteristic property
    final int properties = batteryLevelCharacteristic.getProperties();
    if ((properties & BluetoothGattCharacteristic.PROPERTY_NOTIFY) == 0) return false;

    gatt.setCharacteristicNotification(batteryLevelCharacteristic, enable);
    final BluetoothGattDescriptor descriptor =
        batteryLevelCharacteristic.getDescriptor(CLIENT_CHARACTERISTIC_CONFIG_DESCRIPTOR_UUID);
    if (descriptor != null) {
      if (enable) {
        descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
        Logger.a(mLogSession, "Enabling battery level notifications...");
        Logger.v(mLogSession, "Enabling notifications for " + BATTERY_LEVEL_CHARACTERISTIC);
        Logger.d(
            mLogSession,
            "gatt.writeDescriptor("
                + CLIENT_CHARACTERISTIC_CONFIG_DESCRIPTOR_UUID
                + ", value=0x01-00)");
      } else {
        descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
        Logger.a(mLogSession, "Disabling battery level notifications...");
        Logger.v(mLogSession, "Disabling notifications for " + BATTERY_LEVEL_CHARACTERISTIC);
        Logger.d(
            mLogSession,
            "gatt.writeDescriptor("
                + CLIENT_CHARACTERISTIC_CONFIG_DESCRIPTOR_UUID
                + ", value=0x00-00)");
      }
      return gatt.writeDescriptor(descriptor);
    }
    return false;
  }
  /**
   * Enables or disables notification on a give characteristic.
   *
   * @param characteristic Characteristic to act on.
   * @param enabled If true, enable notification. False otherwise.
   */
  public void setCharacteristicNotification(
      BluetoothGattCharacteristic characteristic, boolean enabled) {
    if (mBluetoothAdapter == null || mBluetoothGatt == null) {
      Log.w(TAG, "BluetoothAdapter not initialized");
      return;
    }
    mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);

    // This is specific to Ajna Device

    if (UUID_QUATERNERION_PACKET_CHAR.equals(characteristic.getUuid())
        || UUID_QUATERNERION_DATA_CHAR.equals(characteristic.getUuid())
        || UUID_OTHER_DATA_CHAR.equals(characteristic.getUuid())) {
      BluetoothGattDescriptor descriptor =
          characteristic.getDescriptor(
              UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
      descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
      mBluetoothGatt.writeDescriptor(descriptor);
    }
  }
  // ----------------------------------------------------------------------------------------------------------------
  // Enable notification on a characteristic
  // For information only. This application uses Indication, not Notification
  public void setCharacteristicNotification(
      BluetoothGattCharacteristic characteristic, boolean enabled) {
    if (mBluetoothAdapter == null
        || mBluetoothGatt == null) { // Check that we have a GATT connection
      Log.w(TAG, "BluetoothAdapter not initialized");
      return;
    }
    mBluetoothGatt.setCharacteristicNotification(
        characteristic, enabled); // Enable notification and indication for the characteristic

    //        if (UUID_MLDP_DATA_PRIVATE_CHARACTERISTIC.equals(characteristic.getUuid())) {
    BluetoothGattDescriptor descriptor =
        characteristic.getDescriptor(
            UUID_CHARACTERISTIC_NOTIFICATION_CONFIG); // Get the descripter that enables
                                                      // notification on the server
    descriptor.setValue(
        BluetoothGattDescriptor
            .ENABLE_NOTIFICATION_VALUE); // Set the value of the descriptor to enable notification
    mBluetoothGatt.writeDescriptor(descriptor); // Write the descriptor
    //        }
  }
  private boolean enableNotification(boolean onoff, BluetoothGattCharacteristic charac) {
    if (btGatt == null) return false;

    if (!btGatt.setCharacteristicNotification(charac, onoff)) {
      System.err.println("btGatt.setCharacteristicNotification() failed");
      return false;
    }

    BluetoothGattDescriptor clientConfig = charac.getDescriptor(CCC);
    if (clientConfig == null) {
      System.err.println("clientConfig == null");
      return false;
    }

    if (onoff) {
      clientConfig.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
    } else {
      clientConfig.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
    }
    return btGatt.writeDescriptor(clientConfig);
  }
  /**
   * Enables indications on given characteristic
   *
   * @return true is the request has been sent, false if one of the arguments was <code>null</code>
   *     or the characteristic does not have the CCCD.
   */
  protected final boolean enableIndications(final BluetoothGattCharacteristic characteristic) {
    final BluetoothGatt gatt = mBluetoothGatt;
    if (gatt == null || characteristic == null) return false;

    // Check characteristic property
    final int properties = characteristic.getProperties();
    if ((properties & BluetoothGattCharacteristic.PROPERTY_INDICATE) == 0) return false;

    gatt.setCharacteristicNotification(characteristic, true);
    final BluetoothGattDescriptor descriptor =
        characteristic.getDescriptor(CLIENT_CHARACTERISTIC_CONFIG_DESCRIPTOR_UUID);
    if (descriptor != null) {
      descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
      Logger.v(mLogSession, "Enabling indications for " + characteristic.getUuid());
      Logger.d(
          mLogSession,
          "gatt.writeDescriptor("
              + CLIENT_CHARACTERISTIC_CONFIG_DESCRIPTOR_UUID
              + ", value=0x02-00)");
      return gatt.writeDescriptor(descriptor);
    }
    return false;
  }
  public static JSONArray decodePermissions(BluetoothGattDescriptor descriptor) {

    // NOTE: props strings need to be consistent across iOS and Android
    JSONArray props = new JSONArray();
    int permissions = descriptor.getPermissions();

    if ((permissions & BluetoothGattDescriptor.PERMISSION_READ) != 0x0) {
      props.put("Read");
    }

    if ((permissions & BluetoothGattDescriptor.PERMISSION_WRITE) != 0x0) {
      props.put("Write");
    }

    if ((permissions & BluetoothGattDescriptor.PERMISSION_READ_ENCRYPTED) != 0x0) {
      props.put("ReadEncrypted");
    }

    if ((permissions & BluetoothGattDescriptor.PERMISSION_WRITE_ENCRYPTED) != 0x0) {
      props.put("WriteEncrypted");
    }

    if ((permissions & BluetoothGattDescriptor.PERMISSION_READ_ENCRYPTED_MITM) != 0x0) {
      props.put("ReadEncryptedMITM");
    }

    if ((permissions & BluetoothGattDescriptor.PERMISSION_WRITE_ENCRYPTED_MITM) != 0x0) {
      props.put("WriteEncryptedMITM");
    }

    if ((permissions & BluetoothGattDescriptor.PERMISSION_WRITE_SIGNED) != 0x0) {
      props.put("WriteSigned");
    }

    if ((permissions & BluetoothGattDescriptor.PERMISSION_WRITE_SIGNED_MITM) != 0x0) {
      props.put("WriteSignedMITM");
    }

    return props;
  }
  private void displayGattServices(List<BluetoothGattService> gattServices) {
    if (gattServices == null) return;

    for (BluetoothGattService gattService : gattServices) {
      // -----Service的字段信息-----//
      int type = gattService.getType();
      Log.e(TAG, "-->service type:" + Utils.getServiceType(type));
      Log.e(TAG, "-->includedServices size:" + gattService.getIncludedServices().size());
      Log.e(TAG, "-->service uuid:" + gattService.getUuid());

      // -----Characteristics的字段信息-----//
      List<BluetoothGattCharacteristic> gattCharacteristics = gattService.getCharacteristics();
      for (final BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
        Log.e(TAG, "---->char uuid:" + gattCharacteristic.getUuid());

        int permission = gattCharacteristic.getPermissions();
        Log.e(TAG, "---->char permission:" + Utils.getCharPermission(permission));

        int property = gattCharacteristic.getProperties();
        Log.e(TAG, "---->char property:" + Utils.getCharPropertie(property));

        byte[] data = gattCharacteristic.getValue();
        if (data != null && data.length > 0) {
          Log.e(TAG, "---->char value:" + Utils.bytesToHexString(data));
        }

        if (gattService.getUuid().toString().equals(UUID_KEY_SERVICE)) { // 如果是温度计的service
          // UUID_KEY_DATA是可以跟蓝牙模块串口通信的Characteristic
          if (gattCharacteristic.getUuid().toString().equals(UUID_KEY_DATA_RECIV)) {
            // 测试读取当前Characteristic数据,会触发mOnDataAvailable.onCharacteristicRead()
            mHandler.postDelayed(
                new Runnable() {
                  @Override
                  public void run() {
                    mBLE_reciv.readCharacteristic(gattCharacteristic);
                  }
                },
                500);

            // 接受Characteristic被写的通知,收到蓝牙模块的数据后会触发mOnDataAvailable.onCharacteristicWrite()
            mBLE_reciv.setCharacteristicNotification(gattCharacteristic, true);
            BluetoothGattDescriptor localBluetoothGattDescriptor =
                gattCharacteristic.getDescriptor(UUID.fromString(CCC));
            localBluetoothGattDescriptor.setValue(
                BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
            mBluetoothGatt.writeDescriptor(localBluetoothGattDescriptor);
            appState.gattCharacteristic_reciv_dianzichen = gattCharacteristic;
            // 设置数据内容
            //            			gattCharacteristic.setValue("0");
            // 往蓝牙模块写入数据
            //            			appState.mBLE_reciv_dianzichen.writeCharacteristic(gattCharacteristic);
          }

          // UUID_KEY_DATA是可以跟蓝牙模块串口通信的Characteristic
          if (gattCharacteristic.getUuid().toString().equals(UUID_KEY_DATA_SEND)) {
            // 测试读取当前Characteristic数据,会触发mOnDataAvailable.onCharacteristicRead()
            mHandler.postDelayed(
                new Runnable() {
                  @Override
                  public void run() {
                    mBLE_send.readCharacteristic(gattCharacteristic);
                    // Log.i("info", "appState.mBLE_send_dianzichen 尝试读数据");
                  }
                },
                500);

            // 接受Characteristic被写的通知,收到蓝牙模块的数据后会触发mOnDataAvailable.onCharacteristicWrite()
            mBLE_send.setCharacteristicNotification(gattCharacteristic, true);
            // 设置数据内容
            // gattCharacteristic.setValue("send data->");
            // 往蓝牙模块写入数据
            // mBLE_send.writeCharacteristic(gattCharacteristic);

            if (!appState.firstActivityRunning) {
              appState.gattCharacteristic_send_dianzichen = gattCharacteristic;

              appState.file.write2SDFromInput("inurse/", "Dianzichen.txt", appState.deviceAddress);

              Intent it = new Intent(this, DianzichenActivity.class);
              startActivityForResult(it, 0); // 配合onActivityResult,当FirstActivity退出时获得一个0值,然后自己也退出
              //            				moveTaskToBack(true); //这一句是整个程序返回桌面
              appState.firstActivityRunning = true;
            }
          }
        } // 结束 if ( gattService.getUuid().toString().equals(UUID_KEY_SERVICE) )

        // -----Descriptors的字段信息-----//
        List<BluetoothGattDescriptor> gattDescriptors = gattCharacteristic.getDescriptors();
        for (BluetoothGattDescriptor gattDescriptor : gattDescriptors) {
          Log.e(TAG, "-------->desc uuid:" + gattDescriptor.getUuid());
          int descPermission = gattDescriptor.getPermissions();
          Log.e(TAG, "-------->desc permission:" + Utils.getDescPermission(descPermission));

          byte[] desData = gattDescriptor.getValue();
          if (desData != null && desData.length > 0) {
            Log.e(TAG, "-------->desc value:" + Utils.bytesToHexString(data));
          }

          // soloman 接收的uuid要设置CCC通知enable,并回写到BluetoothGatt
          //					if (gattDescriptor.getUuid().toString().equals(CCC)){
          //						gattDescriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
          //						mBluetoothGatt.writeDescriptor(gattDescriptor);
          //					}
        }
      }
    } //
  }
  private void enableNotify() {
    BluetoothGattService service = getSupportedGattService();
    if (null == service) {
      LogUtil.info(TAG, "BluetoothGattService service is null");
      boolean isconnectok = connect();
      if (!isconnectok) {
        connect();
      }
      return;
    }
    BluetoothGattCharacteristic gattCharacteristic = null;
    switch (DEVICE_TYPE) {
      case 1:
        gattCharacteristic =
            service.getCharacteristic(UUID.fromString(BLEConstants.UUID_CHARACTERISTIC));
        break;
      case 2:
        gattCharacteristic =
            service.getCharacteristic(
                UUID.fromString(BLEConstants.UUID_BLOOD_PRESSURE_CHARACTERISTIC));
        break;
      case 3:
        gattCharacteristic =
            service.getCharacteristic(UUID.fromString(BLEConstants.UUID_BLOODSUGAR_CHARACTERISTIC));
        break;
      default:
        gattCharacteristic =
            service.getCharacteristic(UUID.fromString(BLEConstants.UUID_CHARACTERISTIC));
        break;
    }
    if (null == gattCharacteristic) {
      LogUtil.info(TAG, "BluetoothGattCharacteristic gattCharacteristic is null");
      return;
    }

    boolean bool = mBluetoothGatt.setCharacteristicNotification(gattCharacteristic, true);
    LogUtil.info(TAG, "setCharacteristicNotification:" + bool);
    BluetoothGattDescriptor descriptor = null;
    switch (DEVICE_TYPE) {
      case 1:
        descriptor =
            gattCharacteristic.getDescriptor(UUID.fromString(BLEConstants.UUID_DESCRIPTER));
      case 2:
        descriptor =
            gattCharacteristic.getDescriptor(
                UUID.fromString(BLEConstants.UUID_BLOOD_PRESSURE_DESCRIPTER));
        break;
      case 3:
        descriptor =
            gattCharacteristic.getDescriptor(
                UUID.fromString(BLEConstants.UUID_BLOODSUGAR_DESCRIPTER));
        break;

      default:
        descriptor =
            gattCharacteristic.getDescriptor(UUID.fromString(BLEConstants.UUID_DESCRIPTER));
        break;
    }
    if (null != descriptor) {
      descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
      mBluetoothGatt.writeDescriptor(descriptor);
    }
  }
  // Demonstrates how to iterate through the supported GATT Services/Characteristics.
  // In this sample, we populate the data structure that is bound to the ExpandableListView
  // on the UI.
  private void displayGattServices(List<BluetoothGattService> gattServices) {
    if (gattServices == null) return;

    if (mDataReceivedCharacteristic != null) {
      Log.e(TAG, "Dont need to re list the characteristics, we already found them.");
      return;
    }
    String uuid = null;
    String unknownServiceString = getResources().getString(R.string.unknown_service);
    String unknownCharaString = getResources().getString(R.string.unknown_characteristic);
    ArrayList<HashMap<String, String>> gattServiceData = new ArrayList<HashMap<String, String>>();
    ArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData =
        new ArrayList<ArrayList<HashMap<String, String>>>();
    mGattCharacteristics = new ArrayList<ArrayList<BluetoothGattCharacteristic>>();

    // Loops through available GATT Services.
    for (BluetoothGattService gattService : gattServices) {
      HashMap<String, String> currentServiceData = new HashMap<String, String>();
      uuid = gattService.getUuid().toString();
      Log.e("BluetoothService", uuid);

      currentServiceData.put(
          LIST_NAME, SCalEvoBluetoothSpecifications.lookup(uuid, unknownServiceString));
      currentServiceData.put(LIST_UUID, uuid);
      gattServiceData.add(currentServiceData);

      ArrayList<HashMap<String, String>> gattCharacteristicGroupData =
          new ArrayList<HashMap<String, String>>();
      List<BluetoothGattCharacteristic> gattCharacteristics = gattService.getCharacteristics();
      ArrayList<BluetoothGattCharacteristic> charas = new ArrayList<BluetoothGattCharacteristic>();

      // Loops through available Characteristics.
      for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
        charas.add(gattCharacteristic);
        HashMap<String, String> currentCharaData = new HashMap<String, String>();
        uuid = gattCharacteristic.getUuid().toString();
        Log.e("BluetoothCharacteristic", uuid);
        currentCharaData.put(
            LIST_NAME, SCalEvoBluetoothSpecifications.lookup(uuid, unknownCharaString));
        currentCharaData.put(LIST_UUID, uuid);
        gattCharacteristicGroupData.add(currentCharaData);
        if (SCalEvoBluetoothSpecifications.DATA_RECEIVED.equals(uuid)) {
          mDataReceivedCharacteristic = gattCharacteristic;
        } else if (SCalEvoBluetoothSpecifications.ANSWER_TO_REQUEST_OR_COMMAND.equals(uuid)) {
          mAnswerToDataRequestOrCommandCharacteristic = gattCharacteristic;
        } else if (SCalEvoBluetoothSpecifications.DATA_REQUEST_OR_COMMAND.equals(uuid)) {
          mDataRequestOrCommandCharacteristic = gattCharacteristic;
        }

        List<BluetoothGattDescriptor> descriptors = gattCharacteristic.getDescriptors();
        for (BluetoothGattDescriptor aDescriptor : descriptors) {
          uuid = aDescriptor.getUuid().toString();
          Log.e(TAG, "BluetoothGattDescriptor " + uuid);
        }
      }
      mGattCharacteristics.add(charas);
      gattCharacteristicData.add(gattCharacteristicGroupData);
    }

    SimpleExpandableListAdapter gattServiceAdapter =
        new SimpleExpandableListAdapter(
            this,
            gattServiceData,
            android.R.layout.simple_expandable_list_item_2,
            new String[] {LIST_NAME, LIST_UUID},
            new int[] {android.R.id.text1, android.R.id.text2},
            gattCharacteristicData,
            android.R.layout.simple_expandable_list_item_2,
            new String[] {LIST_NAME, LIST_UUID},
            new int[] {android.R.id.text1, android.R.id.text2});
    mGattServicesList.setAdapter(gattServiceAdapter);

    listenToCalipersDataButton();
  }
  /**
   * @Title: displayGattServices @Description: TODO(处理蓝牙服务)
   *
   * @param 无
   * @return void
   * @throws
   */
  @SuppressLint("NewApi")
  private void displayGattServices(List<BluetoothGattService> gattServices) {

    if (gattServices == null) return;
    String uuid = null;
    //		String unknownServiceString = "unknown_service";
    //		String unknownCharaString = "unknown_characteristic";

    // 服务数据,可扩展下拉列表的第一级数据
    ArrayList<HashMap<String, String>> gattServiceData = new ArrayList<HashMap<String, String>>();

    // 特征数据(隶属于某一级服务下面的特征值集合)
    ArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData =
        new ArrayList<ArrayList<HashMap<String, String>>>();

    // 部分层次,所有特征值集合
    mGattCharacteristics = new ArrayList<ArrayList<BluetoothGattCharacteristic>>();

    // Loops through available GATT Services.
    for (BluetoothGattService gattService : gattServices) {

      // 获取服务列表
      HashMap<String, String> currentServiceData = new HashMap<String, String>();
      uuid = gattService.getUuid().toString();

      // 查表,根据该uuid获取对应的服务名称。SampleGattAttributes这个表需要自定义。

      gattServiceData.add(currentServiceData);

      System.out.println("Service uuid:" + uuid);

      ArrayList<HashMap<String, String>> gattCharacteristicGroupData =
          new ArrayList<HashMap<String, String>>();

      // 从当前循环所指向的服务中读取特征值列表
      List<BluetoothGattCharacteristic> gattCharacteristics = gattService.getCharacteristics();

      ArrayList<BluetoothGattCharacteristic> charas = new ArrayList<BluetoothGattCharacteristic>();

      // Loops through available Characteristics.
      // 对于当前循环所指向的服务中的每一个特征值
      for (final BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
        charas.add(gattCharacteristic);
        HashMap<String, String> currentCharaData = new HashMap<String, String>();
        uuid = gattCharacteristic.getUuid().toString();

        if (gattCharacteristic.getUuid().toString().equals(HEART_RATE_MEASUREMENT)) {
          // 测试读取当前Characteristic数据,会触发mOnDataAvailable.onCharacteristicRead()
          mhandler.postDelayed(
              new Runnable() {

                @Override
                public void run() {
                  // TODO Auto-generated method stub
                  mBluetoothLeService.readCharacteristic(gattCharacteristic);
                }
              },
              200);

          // 接受Characteristic被写的通知,收到蓝牙模块的数据后会触发mOnDataAvailable.onCharacteristicWrite()
          mBluetoothLeService.setCharacteristicNotification(gattCharacteristic, true);
          target_chara = gattCharacteristic;
          // 设置数据内容
          // 往蓝牙模块写入数据
          // mBluetoothLeService.writeCharacteristic(gattCharacteristic);
        }
        List<BluetoothGattDescriptor> descriptors = gattCharacteristic.getDescriptors();
        for (BluetoothGattDescriptor descriptor : descriptors) {
          System.out.println("---descriptor UUID:" + descriptor.getUuid());
          // 获取特征值的描述
          mBluetoothLeService.getCharacteristicDescriptor(descriptor);
        }

        gattCharacteristicGroupData.add(currentCharaData);
      }
      // 按先后顺序,分层次放入特征值集合中,只有特征值
      mGattCharacteristics.add(charas);
      // 构件第二级扩展列表(服务下面的特征值)
      gattCharacteristicData.add(gattCharacteristicGroupData);
    }
  }
  /**
   * Returns true if this descriptor is from the Battery Level characteristic.
   *
   * @param descriptor the descriptor to be checked
   * @return true if the descriptor belongs to the Battery Level characteristic
   */
  private boolean isBatteryLevelCCCD(final BluetoothGattDescriptor descriptor) {
    if (descriptor == null) return false;

    return BATTERY_LEVEL_CHARACTERISTIC.equals(descriptor.getCharacteristic().getUuid());
  }