<commit_before>/*
	Copyright 2013-2014, JUMA Technology

	Licensed under the Apache License, Version 2.0 (the "License");
	you may not use this file except in compliance with the License.
	You may obtain a copy of the License at

		http://www.apache.org/licenses/LICENSE-2.0

	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.
*/

package org.bcsphere.bluetooth;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.UUID;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONObject;

import org.bcsphere.bluetooth.tools.Tools;

import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothAdapter.LeScanCallback;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattServer;
import android.bluetooth.BluetoothGattServerCallback;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.util.Log;

@SuppressLint("NewApi")
public class BluetoothG43plus implements IBluetooth{
	private static final String TAG = "BluetoothG43plus";
	private BluetoothManager mBluetoothManager;
	private BluetoothAdapter mBluetoothAdapter;
	private BluetoothGattServer mBluetoothGattServer;
	private Context mContext;
	private boolean isScanning = false;
	private List<BluetoothDevice> deviceList = new ArrayList<BluetoothDevice>();;
	private JSONArray deviceInfoList = new JSONArray() ;
	private int scanSum = 0;
	private boolean isOpenGattServer = false;
	private int gattServerSum = 0;
	private HashMap<String, CallbackContext> connectCC = new HashMap<String, CallbackContext>();
	private HashMap<String, CallbackContext> disconnectCC = new HashMap<String, CallbackContext>();
	private HashMap<String, CallbackContext> getServicesCC = new HashMap<String, CallbackContext>();
	private HashMap<String, CallbackContext> writeValueCC = new HashMap<String, CallbackContext>();
	private HashMap<String, CallbackContext> readValueCC = new HashMap<String, CallbackContext>();
	private HashMap<BluetoothGattCharacteristic, CallbackContext> setNotificationCC = new HashMap<BluetoothGattCharacteristic, CallbackContext>();
	private HashMap<String, CallbackContext> getDeviceAllDataCC = new HashMap<String, CallbackContext>();
	private HashMap<String ,CallbackContext> getRSSICC = new HashMap<String, CallbackContext>();
	private HashMap<String, CallbackContext> addEventListenerCC = new HashMap<String, CallbackContext>();
	private CallbackContext addServiceCC;
	private HashMap<String, BluetoothGattService> localServices = new HashMap<String, BluetoothGattService>();
	private HashMap<String, Integer> recordServiceIndex = new HashMap<String, Integer>();
	private HashMap<String, Integer> recordCharacteristicIndex = new HashMap<String, Integer>();
	private HashMap< String ,Boolean> connectedDevice = new HashMap<String, Boolean>(); 
	private HashMap<String, BluetoothGatt> mBluetoothGatts = new HashMap<String, BluetoothGatt>();
	private HashMap<String, List<BluetoothGattService>> deviceServices = new HashMap<String, List<BluetoothGattService>>();
	@Override
	public void setContext(Context context) {
		Log.i(TAG, "setContext");
		this.mContext = context;
		mBluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
		mBluetoothAdapter = mBluetoothManager.getAdapter();
	}

	@Override
	public void startScan(JSONArray json, CallbackContext callbackContext) {
		Log.i(TAG, "startScan");
		if (isScanning) {
			Tools.sendSuccessMsg(callbackContext);
			scanSum = scanSum + 1;
			return;
		}
		if (deviceList != null) {
			deviceList = null;
			deviceList = new ArrayList<BluetoothDevice>();
		}
		if (deviceInfoList != null) {
			deviceInfoList = null;
			deviceInfoList = new JSONArray();
		}
		UUID[] uuids = Tools.getUUIDs(json);
		if (uuids == null || uuids.length < 1) {
			mBluetoothAdapter.startLeScan(mLeScanCallback);
			Tools.sendSuccessMsg(callbackContext);
			scanSum = scanSum + 1;
			isScanning = true;
		}else {
			mBluetoothAdapter.startLeScan(uuids, mLeScanCallback);
			Tools.sendSuccessMsg(callbackContext);
			scanSum = scanSum + 1;	
			isScanning = true;
		}
	}

	@Override
	public void getScanData(JSONArray json, CallbackContext callbackContext) {
		Log.i(TAG, "getScanData");
		if (!isScanning) {
			Tools.sendErrorMsg(callbackContext);
			return;
		}
		callbackContext.success(deviceInfoList);
	}

	@Override
	public void stopScan(JSONArray json, CallbackContext callbackContext) {
		Log.i(TAG, "stopScan");
		if (!isScanning) {
			Tools.sendSuccessMsg(callbackContext);
			return;
		}
		scanSum = scanSum - 1;
		if (scanSum == 0 ) {
			mBluetoothAdapter.stopLeScan(mLeScanCallback);
			isScanning = false;
			Tools.sendSuccessMsg(callbackContext);
		}else {
			Tools.sendSuccessMsg(callbackContext);
		}
	}

	@Override
	public void connect(JSONArray json, CallbackContext callbackContext) {
		Log.i(TAG, "connect");
		String deviceID = Tools.getData(json, Tools.DEVICE_ID);
		if (connectedDevice.get(deviceID) != null) {
			Tools.sendSuccessMsg(callbackContext);
			return;
		}
		connectCC.put(deviceID, callbackContext);
		BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(deviceID);
		mBluetoothGatts.put(device.getAddress(), device.connectGatt(mContext, false, mGattCallback));
	}

	@Override
	public void disconnect(JSONArray json, CallbackContext callbackContext) {
		Log.i(TAG, "disconnect");
		String deviceID = Tools.getData(json, Tools.DEVICE_ID);
		if (connectedDevice.get(deviceID) == null) {
			Tools.sendSuccessMsg(callbackContext);
			return;
		}
		disconnectCC.put(deviceID, callbackContext);
		mBluetoothGatts.get(deviceID).disconnect();
	}

	@Override
	public void getConnectedDevices(JSONArray json,
			CallbackContext callbackContext) {
		Log.i(TAG, "getConnectedDevices");
		JSONArray ary = new JSONArray();
		List<BluetoothDevice> devices = mBluetoothManager.getConnectedDevices(BluetoothProfile.GATT);
		for (int i = 0; i < devices.size(); i++) {
			JSONObject obj = new JSONObject();
			Tools.addProperty(obj, Tools.DEVICE_ID, devices.get(i).getAddress());
			Tools.addProperty(obj, Tools.DEVICE_NAME, devices.get(i).getName());
			ary.put(obj);
		}
		callbackContext.success(ary);
	}

	@Override
	public void getPairedDevices(JSONArray json, CallbackContext callbackContext) {
		Log.i(TAG, "getPairedDevices");
		JSONArray ary = new JSONArray();
		Set<BluetoothDevice> devices = mBluetoothAdapter.getBondedDevices();
		Iterator<BluetoothDevice> it = devices.iterator();
		while (it.hasNext()) {
			BluetoothDevice device = (BluetoothDevice) it.next();
			JSONObject obj = new JSONObject();
			Tools.addProperty(obj, Tools.DEVICE_ID, device.getAddress());
			Tools.addProperty(obj, Tools.DEVICE_NAME, device.getName());
			ary.put(obj);
		}
		callbackContext.success(ary);
	}

	@Override
	public void createPair(JSONArray json, CallbackContext callbackContext) {
		Log.i(TAG, "createPair");
		String deviceID = Tools.getData(json, Tools.DEVICE_ID);
		JSONObject obj = new JSONObject();
		BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(deviceID);
		try {
			if (Tools.creatBond(device.getClass(), device)) {
				Tools.addProperty(obj, Tools.DEVICE_ID, device.getAddress());
				callbackContext.success(obj);
			}else {
				Tools.addProperty(obj, Tools.DEVICE_ID, device.getAddress());
				callbackContext.error(obj);
			}
		} catch (Exception e) {

		}
	}

	@Override
	public void removePair(JSONArray json, CallbackContext callbackContext) {
		Log.i(TAG, "removePair");
		String deviceID = Tools.getData(json, Tools.DEVICE_ID);
		JSONObject obj = new JSONObject();
		BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(deviceID);
		try {
			if (Tools.removeBond(device.getClass(), device)) {
				Tools.addProperty(obj, Tools.DEVICE_ID, device.getAddress());
				callbackContext.success(obj);
			}else {
				Tools.addProperty(obj, Tools.DEVICE_ID, device.getAddress());
				callbackContext.error(obj);
			}
		} catch (Exception e) {

		}
	}

	@Override
	public void writeValue(JSONArray json, CallbackContext callbackContext) {
		Log.i(TAG, "writeValue");
		String deviceID = Tools.getData(json, Tools.DEVICE_ID);
		if (connectedDevice.get(deviceID) == null) {
			Tools.sendErrorMsg(callbackContext);
			return;
		}
		int serviceIndex = Integer.parseInt(Tools.getData(json, Tools.SERVICE_INDEX));
		int characteristicIndex = Integer.parseInt(Tools.getData(json, Tools.CHARACTERISTIC_INDEX));
		String  descriptorIndex =Tools.getData(json, Tools.DESCRIPTOR_INDEX);
		String writeValue = Tools.getData(json, Tools.WRITE_VALUE);
		writeValueCC.put(deviceID, callbackContext);
		if (descriptorIndex.equals("")) {
			BluetoothGattCharacteristic characteristic = deviceServices.get(deviceID).get(serviceIndex)
					.getCharacteristics().get(characteristicIndex);
			characteristic.setValue(Tools.decodeBase64(writeValue));
			mBluetoothGatts.get(deviceID).writeCharacteristic(characteristic);
		}else {
			BluetoothGattDescriptor descriptor = deviceServices.get(deviceID).get(serviceIndex).getCharacteristics()
					.get(characteristicIndex).getDescriptors().get(Integer.parseInt(descriptorIndex));
			descriptor.setValue(Tools.decodeBase64(writeValue));
			mBluetoothGatts.get(deviceID).writeDescriptor(descriptor);
		}
	} 

	@Override
	public void readValue(JSONArray json, CallbackContext callbackContext) {
		Log.i(TAG, "readValue");
		String deviceID = Tools.getData(json, Tools.DEVICE_ID);
		if (connectedDevice.get(deviceID) == null ) {
			Tools.sendErrorMsg(callbackContext);
			return;
		}
		int serviceIndex = Integer.parseInt(Tools.getData(json, Tools.SERVICE_INDEX));
		int characteristicIndex = Integer.parseInt(Tools.getData(json, Tools.CHARACTERISTIC_INDEX));
		String  descriptorIndex =Tools.getData(json, Tools.DESCRIPTOR_INDEX);
		readValueCC.put(deviceID, callbackContext);
		if (descriptorIndex.equals("")) {
			mBluetoothGatts.get(deviceID).readCharacteristic(deviceServices.get(deviceID).get(serviceIndex)
					.getCharacteristics().get(characteristicIndex));
		}else {
			mBluetoothGatts.get(deviceID).readDescriptor(deviceServices.get(deviceID).get(serviceIndex)
					.getCharacteristics().get(characteristicIndex).getDescriptors().get(Integer.parseInt(descriptorIndex)));
		}
	}

	@Override
	public void setNotification(JSONArray json, CallbackContext callbackContext) {
		Log.i(TAG, "setNotification");
		String deviceID = Tools.getData(json, Tools.DEVICE_ID);
		if (connectedDevice.get(deviceID) == null ) {
			Tools.sendErrorMsg(callbackContext);
			return;
		}
		int serviceIndex = Integer.parseInt(Tools.getData(json, Tools.SERVICE_INDEX));
		int characteristicIndex = Integer.parseInt(Tools.getData(json, Tools.CHARACTERISTIC_INDEX));
		String enable = Tools.getData(json, Tools.ENABLE);
		BluetoothGattCharacteristic characteristic = deviceServices.get(deviceID).get(serviceIndex).getCharacteristics()
				.get(characteristicIndex);
		BluetoothGattDescriptor descriptor = characteristic.getDescriptor(Tools.NOTIFICATION_UUID);
		if (enable.equals("true")) {
			setNotificationCC.put(characteristic, callbackContext);
			descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
			mBluetoothGatts.get(deviceID).writeDescriptor(descriptor);
			mBluetoothGatts.get(deviceID).setCharacteristicNotification(characteristic, true);
			recordServiceIndex.put(deviceID, serviceIndex);
			recordCharacteristicIndex.put(deviceID, characteristicIndex);
		}else {
			descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
			mBluetoothGatts.get(deviceID).writeDescriptor(descriptor);
			mBluetoothGatts.get(deviceID).setCharacteristicNotification(characteristic, false);
			Tools.sendSuccessMsg(setNotificationCC.get(characteristic));
			setNotificationCC.remove(characteristic);
			recordServiceIndex.remove(deviceID);
			recordCharacteristicIndex.remove(deviceID);
		}
	}

	@Override
	public void getDeviceAllData(JSONArray json, CallbackContext callbackContext) {
		Log.i(TAG, "getDeviceAllData");
		String deviceID = Tools.getData(json, Tools.DEVICE_ID);
		if (connectedDevice.get(deviceID) == null) {<commit_msg>Update BluetoothG43plus.java<commit_after>/*
	Copyright 2013-2014, JUMA Technology

	Licensed under the Apache License, Version 2.0 (the "License");
	you may not use this file except in compliance with the License.
	You may obtain a copy of the License at

		http://www.apache.org/licenses/LICENSE-2.0

	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.
*/

package org.bcsphere.bluetooth;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.UUID;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONObject;

import org.bcsphere.bluetooth.tools.Tools;

import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothAdapter.LeScanCallback;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattServer;
import android.bluetooth.BluetoothGattServerCallback;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.util.Log;

@SuppressLint("NewApi")
public class BluetoothG43plus implements IBluetooth{
	private static final String TAG = "BluetoothG43plus";
	private BluetoothManager mBluetoothManager;
	private BluetoothAdapter mBluetoothAdapter;
	private BluetoothGattServer mBluetoothGattServer;
	private Context mContext;
	private boolean isScanning = false;
	private List<BluetoothDevice> deviceList = new ArrayList<BluetoothDevice>();;
	private JSONArray deviceInfoList = new JSONArray() ;
	private int scanSum = 0;
	private boolean isOpenGattServer = false;
	private int gattServerSum = 0;
	private HashMap<String, CallbackContext> connectCC = new HashMap<String, CallbackContext>();
	private HashMap<String, CallbackContext> disconnectCC = new HashMap<String, CallbackContext>();
	private HashMap<String, CallbackContext> getServicesCC = new HashMap<String, CallbackContext>();
	private HashMap<String, CallbackContext> writeValueCC = new HashMap<String, CallbackContext>();
	private HashMap<String, CallbackContext> readValueCC = new HashMap<String, CallbackContext>();
	private HashMap<BluetoothGattCharacteristic, CallbackContext> setNotificationCC = new HashMap<BluetoothGattCharacteristic, CallbackContext>();
	private HashMap<String, CallbackContext> getDeviceAllDataCC = new HashMap<String, CallbackContext>();
	private HashMap<String ,CallbackContext> getRSSICC = new HashMap<String, CallbackContext>();
	private HashMap<String, CallbackContext> addEventListenerCC = new HashMap<String, CallbackContext>();
	private CallbackContext addServiceCC;
	private HashMap<String, BluetoothGattService> localServices = new HashMap<String, BluetoothGattService>();
	private HashMap<String, Integer> recordServiceIndex = new HashMap<String, Integer>();
	private HashMap<String, Integer> recordCharacteristicIndex = new HashMap<String, Integer>();
	private HashMap< String ,Boolean> connectedDevice = new HashMap<String, Boolean>(); 
	private HashMap<String, BluetoothGatt> mBluetoothGatts = new HashMap<String, BluetoothGatt>();
	private HashMap<String, List<BluetoothGattService>> deviceServices = new HashMap<String, List<BluetoothGattService>>();
	@Override
	public void setContext(Context context) {
		Log.i(TAG, "setContext");
		this.mContext = context;
		mBluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
		mBluetoothAdapter = mBluetoothManager.getAdapter();
	}

	@Override
	public void startScan(JSONArray json, CallbackContext callbackContext) {
		Log.i(TAG, "startScan");
		if (isScanning) {
			Tools.sendSuccessMsg(callbackContext);
			scanSum = scanSum + 1;
			return;
		}
		if (deviceList != null) {
			deviceList = null;
			deviceList = new ArrayList<BluetoothDevice>();
		}
		if (deviceInfoList != null) {
			deviceInfoList = null;
			deviceInfoList = new JSONArray();
		}
		UUID[] uuids = Tools.getUUIDs(json);
		if (uuids == null || uuids.length < 1) {
			mBluetoothAdapter.startLeScan(mLeScanCallback);
			Tools.sendSuccessMsg(callbackContext);
			scanSum = scanSum + 1;
			isScanning = true;
		}else {
			mBluetoothAdapter.startLeScan(uuids, mLeScanCallback);
			Tools.sendSuccessMsg(callbackContext);
			scanSum = scanSum + 1;	
			isScanning = true;
		}
	}

	@Override
	public void getScanData(JSONArray json, CallbackContext callbackContext) {
		Log.i(TAG, "getScanData");
		if (!isScanning) {
			Tools.sendErrorMsg(callbackContext);
			return;
		}
		callbackContext.success(deviceInfoList);
	}

	@Override
	public void stopScan(JSONArray json, CallbackContext callbackContext) {
		Log.i(TAG, "stopScan");
		if (!isScanning) {
			Tools.sendSuccessMsg(callbackContext);
			return;
		}
		scanSum = scanSum - 1;
		if (scanSum == 0 ) {
			mBluetoothAdapter.stopLeScan(mLeScanCallback);
			isScanning = false;
			Tools.sendSuccessMsg(callbackContext);
		}else {
			Tools.sendSuccessMsg(callbackContext);
		}
	}

	@Override
	public void connect(JSONArray json, CallbackContext callbackContext) {
		Log.i(TAG, "connect");
		String deviceID = Tools.getData(json, Tools.DEVICE_ID);
		if (connectedDevice.get(deviceID) != null) {
			Tools.sendSuccessMsg(callbackContext);
			return;
		}
		connectCC.put(deviceID, callbackContext);
		BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(deviceID);
		mBluetoothGatts.put(device.getAddress(), device.connectGatt(mContext, false, mGattCallback));
	}

	@Override
	public void disconnect(JSONArray json, CallbackContext callbackContext) {
		Log.i(TAG, "disconnect");
		String deviceID = Tools.getData(json, Tools.DEVICE_ID);
		if (connectedDevice.get(deviceID) == null) {
			Tools.sendSuccessMsg(callbackContext);
			return;
		}
		disconnectCC.put(deviceID, callbackContext);
		mBluetoothGatts.get(deviceID).disconnect();
	}

	@Override
	public void getConnectedDevices(JSONArray json,
			CallbackContext callbackContext) {
		Log.i(TAG, "getConnectedDevices");
		JSONArray ary = new JSONArray();
		List<BluetoothDevice> devices = mBluetoothManager.getConnectedDevices(BluetoothProfile.GATT);
		for (int i = 0; i < devices.size(); i++) {
			JSONObject obj = new JSONObject();
			Tools.addProperty(obj, Tools.DEVICE_ID, devices.get(i).getAddress());
			Tools.addProperty(obj, Tools.DEVICE_NAME, devices.get(i).getName());
			ary.put(obj);
		}
		callbackContext.success(ary);
	}

	@Override
	public void getPairedDevices(JSONArray json, CallbackContext callbackContext) {
		Log.i(TAG, "getPairedDevices");
		JSONArray ary = new JSONArray();
		Set<BluetoothDevice> devices = mBluetoothAdapter.getBondedDevices();
		Iterator<BluetoothDevice> it = devices.iterator();
		while (it.hasNext()) {
			BluetoothDevice device = (BluetoothDevice) it.next();
			JSONObject obj = new JSONObject();
			Tools.addProperty(obj, Tools.DEVICE_ID, device.getAddress());
			Tools.addProperty(obj, Tools.DEVICE_NAME, device.getName());
			ary.put(obj);
		}
		callbackContext.success(ary);
	}

	@Override
	public void createPair(JSONArray json, CallbackContext callbackContext) {
		Log.i(TAG, "createPair");
		String deviceID = Tools.getData(json, Tools.DEVICE_ID);
		JSONObject obj = new JSONObject();
		BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(deviceID);
		try {
			if (Tools.creatBond(device.getClass(), device)) {
				Tools.addProperty(obj, Tools.DEVICE_ID, device.getAddress());
				callbackContext.success(obj);
			}else {
				Tools.addProperty(obj, Tools.DEVICE_ID, device.getAddress());
				callbackContext.error(obj);
			}
		} catch (Exception e) {

		}
	}

	@Override
	public void removePair(JSONArray json, CallbackContext callbackContext) {
		Log.i(TAG, "removePair");
		String deviceID = Tools.getData(json, Tools.DEVICE_ID);
		JSONObject obj = new JSONObject();
		BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(deviceID);
		try {
			if (Tools.removeBond(device.getClass(), device)) {
				Tools.addProperty(obj, Tools.DEVICE_ID, device.getAddress());
				callbackContext.success(obj);
			}else {
				Tools.addProperty(obj, Tools.DEVICE_ID, device.getAddress());
				callbackContext.error(obj);
			}
		} catch (Exception e) {

		}
	}

	@Override
	public void writeValue(JSONArray json, CallbackContext callbackContext) {
		Log.i(TAG, "writeValue");
		String deviceID = Tools.getData(json, Tools.DEVICE_ID);
		if (connectedDevice.get(deviceID) == null) {
			Tools.sendErrorMsg(callbackContext);
			return;
		}
		int serviceIndex = Integer.parseInt(Tools.getData(json, Tools.SERVICE_INDEX));
		int characteristicIndex = Integer.parseInt(Tools.getData(json, Tools.CHARACTERISTIC_INDEX));
		String  descriptorIndex =Tools.getData(json, Tools.DESCRIPTOR_INDEX);
		String writeValue = Tools.getData(json, Tools.WRITE_VALUE);
		writeValueCC.put(deviceID, callbackContext);
		if (descriptorIndex.equals("")) {
			BluetoothGattCharacteristic characteristic = deviceServices.get(deviceID).get(serviceIndex)
					.getCharacteristics().get(characteristicIndex);
			characteristic.setValue(Tools.decodeBase64(writeValue));
			mBluetoothGatts.get(deviceID).writeCharacteristic(characteristic);
		}else {
			BluetoothGattDescriptor descriptor = deviceServices.get(deviceID).get(serviceIndex).getCharacteristics()
					.get(characteristicIndex).getDescriptors().get(Integer.parseInt(descriptorIndex));
			descriptor.setValue(Tools.decodeBase64(writeValue));
			mBluetoothGatts.get(deviceID).writeDescriptor(descriptor);
		}
	} 

	@Override
	public void readValue(JSONArray json, CallbackContext callbackContext) {
		Log.i(TAG, "readValue");
		String deviceID = Tools.getData(json, Tools.DEVICE_ID);
		if (connectedDevice.get(deviceID) == null ) {
			Tools.sendErrorMsg(callbackContext);
			return;
		}
		int serviceIndex = Integer.parseInt(Tools.getData(json, Tools.SERVICE_INDEX));
		int characteristicIndex = Integer.parseInt(Tools.getData(json, Tools.CHARACTERISTIC_INDEX));
		String  descriptorIndex =Tools.getData(json, Tools.DESCRIPTOR_INDEX);
		readValueCC.put(deviceID, callbackContext);
		if (descriptorIndex.equals("")) {
			mBluetoothGatts.get(deviceID).readCharacteristic(deviceServices.get(deviceID).get(serviceIndex)
					.getCharacteristics().get(characteristicIndex));
		}else {
			mBluetoothGatts.get(deviceID).readDescriptor(deviceServices.get(deviceID).get(serviceIndex)
					.getCharacteristics().get(characteristicIndex).getDescriptors().get(Integer.parseInt(descriptorIndex)));
		}
	}

	@Override
	public void setNotification(JSONArray json, CallbackContext callbackContext) {
		Log.i(TAG, "setNotification");
		String deviceID = Tools.getData(json, Tools.DEVICE_ID);
		if (connectedDevice.get(deviceID) == null ) {
			Tools.sendErrorMsg(callbackContext);
			return;
		}
		int serviceIndex = Integer.parseInt(Tools.getData(json, Tools.SERVICE_INDEX));
		int characteristicIndex = Integer.parseInt(Tools.getData(json, Tools.CHARACTERISTIC_INDEX));
		String enable = Tools.getData(json, Tools.ENABLE);
		BluetoothGattCharacteristic characteristic = deviceServices.get(deviceID).get(serviceIndex).getCharacteristics()
				.get(characteristicIndex);
		BluetoothGattDescriptor descriptor = characteristic.getDescriptor(Tools.NOTIFICATION_UUID);
		if (enable.equals("true")) {
			setNotificationCC.put(characteristic, callbackContext);
			descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
			mBluetoothGatts.get(deviceID).writeDescriptor(descriptor);
			mBluetoothGatts.get(deviceID).setCharacteristicNotification(characteristic, true);
			recordServiceIndex.put(deviceID, serviceIndex);
			recordCharacteristicIndex.put(deviceID, characteristicIndex);
		}else {
			descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
			mBluetoothGatts.get(deviceID).writeDescriptor(descriptor);
			mBluetoothGatts.get(deviceID).setCharacteristicNotification(characteristic, false);
			Tools.sendSuccessMsg(callbackContext);
			setNotificationCC.remove(characteristic);
			recordServiceIndex.remove(deviceID);
			recordCharacteristicIndex.remove(deviceID);
		}
	}

	@Override
	public void getDeviceAllData(JSONArray json, CallbackContext callbackContext) {
		Log.i(TAG, "getDeviceAllData");
		String deviceID = Tools.getData(json, Tools.DEVICE_ID);
		if (connectedDevice.get(deviceID) == null) {
{'fraction_non_alphanumeric': 0.10820968562815644, 'fraction_numerical': 0.002348980151117723, 'mean_word_length': 6.111358574610245, 'pattern_counts': {'":': 0, '<': 83, '<?xml version=': 0, '>': 79, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2148329', 'n_tokens_mistral': 8127, 'n_tokens_neox': 7510, 'n_words': 1523}