package com.sirius.botasky.cyberble.ble;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.util.Log;
import com.sirius.botasky.cyberble.callback.DeviceConnectStateCallback;
import com.sirius.botasky.cyberble.callback.DeviceOperationCallback;
import com.sirius.botasky.cyberble.callback.ScanCallback;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/**
* Bluetooth的总类,ble设备管理,扫描.
* Created by botasky on 13/04/2017.
*/
public class BleAdmin implements BluetoothAdapter.LeScanCallback {
private static final String TAG = BleAdmin.class.getSimpleName();
private Context mContext;
private BluetoothAdapter mBluetoothAdapter;
private BluetoothManager mBluetoothManager;
private int mDeviceCount;//搜索到的蓝牙设备的数量
private ScanCallback mScanCallBack;
private List<BluetoothDevice> mScanDevices;
private Map<String, BleDeviceOperator> mConnectedDevice;
private Map<String, BleDeviceOperator> mConnectingDevice;
private DeviceConnectStateCallback mDeviceCallback;
private DeviceOperationCallback mDeviceOperationCallback;
private boolean isScanning = false;
/**
* @param mContext
* @param deviceConnectCallback
* @param mDeviceOperationCallback
*/
public BleAdmin(Context mContext, DeviceConnectStateCallback deviceConnectCallback, DeviceOperationCallback mDeviceOperationCallback) {
this.mContext = mContext;
this.mDeviceCallback = deviceConnectCallback;
this.mDeviceOperationCallback = mDeviceOperationCallback;
initialize();
}
/**
* @param mContext
*/
public BleAdmin(Context mContext) {
this.mContext = mContext;
initialize();
}
/**
* 蓝牙操作回调
*
* @param mDeviceOperationCallback
*/
public void setCallbacks(DeviceOperationCallback mDeviceOperationCallback, DeviceConnectStateCallback deviceConnectStateCallback) {
this.mDeviceOperationCallback = mDeviceOperationCallback;
this.mDeviceCallback = deviceConnectStateCallback;
}
/**
* 初始化蓝牙一些操作
*/
private void initialize() {
mBluetoothManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = mBluetoothManager.getAdapter();
mConnectedDevice = new HashMap<>();
if (mBluetoothAdapter == null) {
throw new IllegalArgumentException("Your device is not support ble");
}
}
/**
* 判断蓝牙是否打开
*
* @return
*/
private boolean isBleEnable() {
return mBluetoothAdapter.isEnabled();
}
/**
* open ble
*/
public void openBle() {
if (!isBleEnable()) {
mBluetoothAdapter.enable();
}
}
/**
* disable ble
*/
public void disableBle() {
if (isBleEnable()) {
mBluetoothAdapter.disable();
}
}
/**
* 查找指定的UUID的设备
*
* @param specifyUUID
*/
public void startScanWithSpecifyDevice(String specifyUUID, ScanCallback mScanCallBack) {
this.mScanCallBack = mScanCallBack;
UUID[] sp = {UUID.fromString(specifyUUID)};
startScan(sp);
}
public void startScanAllDevice(ScanCallback mScanCallBack) {
this.mScanCallBack = mScanCallBack;
startScan(null);
}
private void startScan(UUID[] specify) {
if (isScanning){
return;
}
isScanning = true;
//初始化mScanDevices
mDeviceCount = 0;
if (mScanDevices == null) {
mScanDevices = new ArrayList<>();
}
mScanDevices.clear();
if (specify == null) {
mBluetoothAdapter.startLeScan(this);
} else {
mBluetoothAdapter.startLeScan(specify, this);
}
}
/**
* 取消查找
*/
public void stopScan() {
if (!isScanning){
return;
}
isScanning = false;
mBluetoothAdapter.stopLeScan(this);
}
@Override
public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
Log.e(TAG, " found" + mScanDevices.size());
if (!mScanDevices.contains(device)) {
mScanDevices.add(device);
}
if (mScanDevices.size() > mDeviceCount) {
mScanCallBack.onDeviceFound(mScanDevices);
mDeviceCount++;
}
}
/**
* 通过地址直接连接设备
*
* @param deviceAddress
*/
public void connectDevice(String deviceAddress) {
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(deviceAddress);
connectDevice(device);
}
/**
* 通过设备直接连接
*
* @param device
*/
public synchronized void connectDevice(final BluetoothDevice device) {
BleDeviceOperator deviceOperator = new BleDeviceOperator(device, mContext, mBluetoothCattCallback);
deviceOperator.connectDevice();
if (mConnectingDevice == null) {
mConnectingDevice = new HashMap<>();
}
if (!mConnectingDevice.containsKey(device.getAddress())) {
mConnectingDevice.put(device.getAddress(), deviceOperator);
}
}
/**
* 断开已连接或者取消连接中的设备
* @param address
*/
public void disconnectDevice(String address) {
if (mConnectedDevice != null && mConnectedDevice.containsKey(address)) {
mConnectedDevice.get(address).disconnectDevice();
mConnectedDevice.remove(address);
}
if (mConnectedDevice != null && mConnectingDevice.containsKey(address)){
mConnectingDevice.get(address).disconnectDevice();
mConnectingDevice.remove(address);
}
}
public void disconnectDevice(BluetoothDevice device) {
disconnectDevice(device.getAddress());
}
/**
* 发现服务
*
* @param address
*/
public void discoverDeviceServices(String address) {
if (mConnectedDevice != null && mConnectedDevice.containsKey(address)) {
mConnectedDevice.get(address).discoverDeviceServices();
}
}
/**
* 蓝牙操作服务,
*
* @param service
*/
public void processDeviceService(BleDeviceService service) {
if (mConnectedDevice != null && mConnectedDevice.containsKey(service.getmDeviceAddress())) {
mConnectedDevice.get(service.getmDeviceAddress()).processService(service);
}
}
/**
* 基础回调
*/
//蓝牙连接状态
public static final int STATE_CONNECTED = BluetoothProfile.STATE_CONNECTED;
public static final int STATE_DISCONNECTED = BluetoothProfile.STATE_DISCONNECTED;
public static final int STATE_CONNECTING = BluetoothProfile.STATE_CONNECTING;
private BluetoothGattCallback mBluetoothCattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
String address = gatt.getDevice().getAddress();
if (newState == STATE_CONNECTED) {
Log.e(TAG, " connect state is " + newState);
if (!mConnectedDevice.containsKey(address)) {
mConnectedDevice.put(address, mConnectingDevice.get(address));
mConnectingDevice.remove(address);
}
mDeviceCallback.onDeviceConnected(address);
} else if (newState == STATE_DISCONNECTED) {
Log.e(TAG, " connect state is fail");
if (mConnectedDevice.containsKey(address)) {
mConnectedDevice.remove(address);
}
if (mConnectingDevice.containsKey(address)) {
mConnectingDevice.remove(address);
}
mDeviceCallback.onDeviceDisconnected(address);
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
String address = gatt.getDevice().getAddress();
if (status == BluetoothGatt.GATT_SUCCESS) {
mConnectedDevice.get(address).setSerivce();
mDeviceOperationCallback.onDeviceServiceDiscover(true, address, gatt.getServices());
} else {
mDeviceOperationCallback.onDeviceServiceDiscover(false, address, null);
}
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
mConnectedDevice.get(gatt.getDevice().getAddress()).deleteService(characteristic);
mDeviceOperationCallback.onDeviceCharacteristicRead(true, gatt.getDevice().getAddress(), characteristic);
} else {
mDeviceOperationCallback.onDeviceCharacteristicRead(false, gatt.getDevice().getAddress(), characteristic);
}
}
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicWrite(gatt, characteristic, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
Log.e(TAG, " write success");
mDeviceOperationCallback.onDeviceCharacteristicWrite(true, gatt.getDevice().getAddress(), characteristic);
} else {
mDeviceOperationCallback.onDeviceCharacteristicWrite(false, gatt.getDevice().getAddress(), characteristic);
Log.e(TAG, " write failure");
}
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
String address = gatt.getDevice().getAddress();
mDeviceOperationCallback.onDeviceCharacteristicNotify(address, characteristic);
}
};
}