// Some peripherals re-use UUIDs for multiple characteristics so we need to check the properties
  // and UUID of all characteristics instead of using service.getCharacteristic(characteristicUUID)
  private BluetoothGattCharacteristic findWritableCharacteristic(
      BluetoothGattService service, UUID characteristicUUID, int writeType) {
    try {
      BluetoothGattCharacteristic characteristic = null;

      // get write property
      int writeProperty = BluetoothGattCharacteristic.PROPERTY_WRITE;
      if (writeType == BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE) {
        writeProperty = BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE;
      }

      List<BluetoothGattCharacteristic> characteristics = service.getCharacteristics();
      for (BluetoothGattCharacteristic c : characteristics) {
        if ((c.getProperties() & writeProperty) != 0 && characteristicUUID.equals(c.getUuid())) {
          characteristic = c;
          break;
        }
      }

      // As a last resort, try and find ANY characteristic with this UUID, even if it doesn't have
      // the correct properties
      if (characteristic == null) {
        characteristic = service.getCharacteristic(characteristicUUID);
      }

      return characteristic;
    } catch (Exception e) {
      Log.e(LOG_TAG, "Errore su findWritableCharacteristic", e);
      return null;
    }
  }
  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;
  }
  // Some peripherals re-use UUIDs for multiple characteristics so we need to check the properties
  // and UUID of all characteristics instead of using service.getCharacteristic(characteristicUUID)
  private BluetoothGattCharacteristic findReadableCharacteristic(
      BluetoothGattService service, UUID characteristicUUID) {
    BluetoothGattCharacteristic characteristic = null;

    int read = BluetoothGattCharacteristic.PROPERTY_READ;

    List<BluetoothGattCharacteristic> characteristics = service.getCharacteristics();
    for (BluetoothGattCharacteristic c : characteristics) {
      if ((c.getProperties() & read) != 0 && characteristicUUID.equals(c.getUuid())) {
        characteristic = c;
        break;
      }
    }

    // As a last resort, try and find ANY characteristic with this UUID, even if it doesn't have the
    // correct properties
    if (characteristic == null) {
      characteristic = service.getCharacteristic(characteristicUUID);
    }

    return characteristic;
  }
  // Some devices reuse UUIDs across characteristics, so we can't use
  // service.getCharacteristic(characteristicUUID)
  // instead check the UUID and properties for each characteristic in the service until we find the
  // best match
  // This function prefers Notify over Indicate
  private BluetoothGattCharacteristic findNotifyCharacteristic(
      BluetoothGattService service, UUID characteristicUUID) {
    BluetoothGattCharacteristic characteristic = null;

    try {
      // Check for Notify first
      List<BluetoothGattCharacteristic> characteristics = service.getCharacteristics();
      for (BluetoothGattCharacteristic c : characteristics) {
        if ((c.getProperties() & BluetoothGattCharacteristic.PROPERTY_NOTIFY) != 0
            && characteristicUUID.equals(c.getUuid())) {
          characteristic = c;
          break;
        }
      }

      if (characteristic != null) return characteristic;

      // If there wasn't Notify Characteristic, check for Indicate
      for (BluetoothGattCharacteristic c : characteristics) {
        if ((c.getProperties() & BluetoothGattCharacteristic.PROPERTY_INDICATE) != 0
            && characteristicUUID.equals(c.getUuid())) {
          characteristic = c;
          break;
        }
      }

      // As a last resort, try and find ANY characteristic with this UUID, even if it doesn't have
      // the correct properties
      if (characteristic == null) {
        characteristic = service.getCharacteristic(characteristicUUID);
      }

      return characteristic;
    } catch (Exception e) {
      Log.e(LOG_TAG, "Errore su caratteristica " + characteristicUUID, e);
      return null;
    }
  }