public void removeNotify(
      UUID serviceUUID, UUID characteristicUUID, Callback success, Callback fail) {

    Log.d(LOG_TAG, "removeNotify");

    if (gatt == null) {
      fail.invoke("BluetoothGatt is null");
      return;
    }

    BluetoothGattService service = gatt.getService(serviceUUID);
    BluetoothGattCharacteristic characteristic =
        findNotifyCharacteristic(service, characteristicUUID);
    // String key = generateHashKey(serviceUUID, characteristic);

    if (characteristic != null) {

      if (gatt.setCharacteristicNotification(characteristic, false)) {
        success.invoke();
      } else {
        // TODO we can probably ignore and return success anyway since we removed the notification
        // callback
        fail.invoke("Failed to stop notification for " + characteristicUUID);
      }

    } else {
      fail.invoke("Characteristic " + characteristicUUID + " not found");
    }
  }
 @Override
 protected void onDestroy() {
   if (mGatt == null) {
     return;
   }
   mGatt.close();
   mGatt = null;
   super.onDestroy();
 }
  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;
  }
 /**
  * Connect to GATT Server hosted by this device. Caller acts as GATT client. The callback is used
  * to deliver results to Caller, such as connection status as well as any further GATT client
  * operations. The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct
  * GATT client operations.
  *
  * @param callback GATT callback handler that will receive asynchronous callbacks.
  * @param autoConnect Whether to directly connect to the remote device (false) or to automatically
  *     connect as soon as the remote device becomes available (true).
  * @throws IllegalArgumentException if callback is null
  */
 public BluetoothGatt connectGatt(
     Context context, boolean autoConnect, BluetoothGattCallback callback) {
   // TODO(Bluetooth) check whether platform support BLE
   //     Do the check here or in GattServer?
   BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
   IBluetoothManager managerService = adapter.getBluetoothManager();
   try {
     IBluetoothGatt iGatt = managerService.getBluetoothGatt();
     if (iGatt == null) {
       // BLE is not supported
       return null;
     }
     BluetoothGatt gatt = new BluetoothGatt(context, iGatt, this);
     gatt.connect(autoConnect, callback);
     return gatt;
   } catch (RemoteException e) {
     Log.e(TAG, "", e);
   }
   return null;
 }
  @Override
  public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {

    Log.d(
        LOG_TAG,
        "onConnectionStateChange da "
            + status
            + " a "
            + newState
            + " peripheral:"
            + device.getAddress());

    this.gatt = gatt;

    if (newState == BluetoothGatt.STATE_CONNECTED) {

      connected = true;
      gatt.discoverServices();

    } else if (newState == BluetoothGatt.STATE_DISCONNECTED) {

      if (connected) {
        connected = false;

        if (gatt != null) {
          gatt.close();
          gatt = null;
        }

        WritableMap map = Arguments.createMap();
        map.putString("peripheral", device.getAddress());
        sendEvent("BleManagerDisconnectPeripheral", map);
        Log.d(LOG_TAG, "BleManagerDisconnectPeripheral peripheral:" + device.getAddress());
      }
      if (connectFailCallback != null) {
        connectFailCallback.invoke();
        connectFailCallback = null;
        connectCallback = null;
      }
    }
  }
 public void disconnect() {
   connectCallback = null;
   connected = false;
   if (gatt != null) {
     gatt.close();
     gatt = null;
     Log.d(LOG_TAG, "Disconnect");
     WritableMap map = Arguments.createMap();
     map.putString("peripheral", device.getAddress());
     sendEvent("BleManagerDisconnectPeripheral", map);
   } else Log.d(LOG_TAG, "GATT is null");
 }
  public void doWrite(BluetoothGattCharacteristic characteristic, byte[] data) {

    // Log.d(LOG_TAG, "doWrite");

    characteristic.setValue(data);

    if (gatt.writeCharacteristic(characteristic)) {
      // Log.d(LOG_TAG, "doWrite completato");
    } else {
      Log.d(LOG_TAG, "errore doWrite");
    }
  }
  public void read(
      UUID serviceUUID, UUID characteristicUUID, Callback successCallback, Callback failCallback) {

    if (gatt == null) {
      failCallback.invoke("BluetoothGatt is null");
      return;
    }

    BluetoothGattService service = gatt.getService(serviceUUID);
    BluetoothGattCharacteristic characteristic =
        findReadableCharacteristic(service, characteristicUUID);

    if (characteristic == null) {
      failCallback.invoke("Characteristic " + characteristicUUID + " not found.");
    } else {
      readCallback = successCallback;
      readFailCallback = failCallback;
      if (!gatt.readCharacteristic(characteristic)) {
        readCallback = null;
        failCallback.invoke("Read failed");
      }
    }
  }
 @Override
 public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
   Log.i("onConnectionStateChange", "Status: " + status);
   switch (newState) {
     case BluetoothProfile.STATE_CONNECTED:
       Log.i("gattCallback", "STATE_CONNECTED");
       gatt.discoverServices();
       break;
     case BluetoothProfile.STATE_DISCONNECTED:
       Log.e("gattCallback", "STATE_DISCONNECTED");
       break;
     default:
       Log.e("gattCallback", "STATE_OTHER");
   }
 }
 @Override
 public void onCharacteristicRead(
     BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
   Log.i("onCharacteristicRead", characteristic.toString());
   gatt.disconnect();
 }
 @Override
 public void onServicesDiscovered(BluetoothGatt gatt, int status) {
   List<BluetoothGattService> services = gatt.getServices();
   Log.i("onServicesDiscovered", services.toString());
   gatt.readCharacteristic(services.get(1).getCharacteristics().get(0));
 }
  public void write(
      UUID serviceUUID,
      UUID characteristicUUID,
      byte[] data,
      Callback successCallback,
      Callback failCallback,
      int writeType) {

    Log.d(LOG_TAG, "write interno peripheral");

    if (gatt == null) {
      failCallback.invoke("BluetoothGatt is null");

    } else {

      BluetoothGattService service = gatt.getService(serviceUUID);
      BluetoothGattCharacteristic characteristic =
          findWritableCharacteristic(service, characteristicUUID, writeType);
      characteristic.setWriteType(writeType);

      if (characteristic == null) {
        failCallback.invoke("Characteristic " + characteristicUUID + " not found.");
      } else {

        if (writeQueue.size() > 0) {
          failCallback.invoke("Scrittura con byte ancora in coda");
        }

        if (writeCallback != null) {
          failCallback.invoke("Altra scrittura in corso");
        }

        if (writeQueue.size() == 0 && writeCallback == null) {

          if (BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT == writeType) {
            writeCallback = successCallback;
            writeFailCallback = failCallback;
          } else successCallback.invoke();

          if (data.length > 20) {
            int dataLength = data.length;
            int count = 0;
            byte[] firstMessage = null;
            while (count < dataLength && (dataLength - count > 20)) {
              if (count == 0) {
                firstMessage = Arrays.copyOfRange(data, count, count + 20);
              } else {
                byte[] splitMessage = Arrays.copyOfRange(data, count, count + 20);
                writeQueue.add(splitMessage);
              }
              count += 20;
            }
            if (count < dataLength) {
              // Rimangono byte in coda
              byte[] splitMessage = Arrays.copyOfRange(data, count, data.length);
              Log.d(LOG_TAG, "Lunghezza ultimo messaggio: " + splitMessage.length);
              writeQueue.add(splitMessage);
            }

            Log.d(LOG_TAG, "Messaggi in coda: " + writeQueue.size());
            doWrite(characteristic, firstMessage);
          } else {
            characteristic.setValue(data);

            if (gatt.writeCharacteristic(characteristic)) {
              Log.d(LOG_TAG, "write completato");
            } else {
              writeCallback = null;
              failCallback.invoke("Write failed");
            }
          }
        }
      }
    }
  }
  // This seems way too complicated
  public void registerNotify(
      UUID serviceUUID, UUID characteristicUUID, Callback success, Callback fail) {

    Log.d(LOG_TAG, "registerNotify");

    if (gatt == null) {
      fail.invoke("BluetoothGatt is null");
      return;
    }

    BluetoothGattService service = gatt.getService(serviceUUID);
    BluetoothGattCharacteristic characteristic =
        findNotifyCharacteristic(service, characteristicUUID);
    // String key = generateHashKey(serviceUUID, characteristic);

    if (characteristic != null) {
      Log.d(LOG_TAG, "characteristic ok");

      if (gatt.setCharacteristicNotification(characteristic, true)) {

        BluetoothGattDescriptor descriptor =
            characteristic.getDescriptor(UUID.fromString(CHARACTERISTIC_NOTIFICATION_CONFIG));
        if (descriptor != null) {
          Log.d(LOG_TAG, "trovato descriptor");

          // prefer notify over indicate
          if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_NOTIFY) != 0) {
            Log.d(LOG_TAG, "Characteristic " + characteristicUUID + " set NOTIFY");
            descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
          } else if ((characteristic.getProperties()
                  & BluetoothGattCharacteristic.PROPERTY_INDICATE)
              != 0) {
            Log.d(LOG_TAG, "Characteristic " + characteristicUUID + " set INDICATE");
            descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
          } else {
            Log.d(
                LOG_TAG,
                "Characteristic "
                    + characteristicUUID
                    + " does not have NOTIFY or INDICATE property set");
          }

          if (gatt.writeDescriptor(descriptor)) {
            // Tutto ok
            Log.d(LOG_TAG, "registerNotify completato");
            success.invoke();
          } else {
            fail.invoke(
                "Failed to set client characteristic notification for " + characteristicUUID);
          }

        } else {
          fail.invoke("Set notification failed for " + characteristicUUID);
        }

      } else {
        fail.invoke("Failed to register notification for " + characteristicUUID);
      }

    } else {
      fail.invoke("Characteristic " + characteristicUUID + " not found");
    }
  }