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;
  }
 @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 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);
          //					}
        }
      }
    } //
  }