package com.tech.idealled.ble;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
import android.support.annotation.RequiresApi;
import android.text.TextUtils;
import android.util.Log;
import com.example.lightstrip.entity.BleData;
import com.example.lightstrip.exposed.SendCallBack;
import com.example.lightstrip.exposed.WriteCallBack;
import com.example.lightstrip.ui.connect.DeviceCallback;
import com.tech.idealled.App;
import com.tech.idealled.core.data.Agreement;
import com.tech.idealled.core.db.bean.Device;
import com.tech.idealled.core.db.dao.DeviceDao;
import com.tech.idealled.ui.home.MainActivity;
import com.tech.idealled.util.LogUtil;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
;
/**
* @author xiaotie
* 2022、2、17
* lightStrip 专用类
*/
import cn.com.heaton.blelibrary.ble.L;
import cn.com.heaton.blelibrary.ble.model.BleDevice;
import cn.com.heaton.blelibrary.ble.utils.ByteUtils;
@SuppressLint("MissingPermission")
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class LightStripBleManager {
public static final HashMap<String,BleData> devices = new HashMap<>();
public static final HashMap<String,Runnable> runnableCallback = new HashMap<>();
private static final LightStripBleManager instance = new LightStripBleManager();
private final BleListenerImpl bleListener;
private final DeviceDao deviceDao;
private BleManager bleManager = BleManager.getInstance();
private DeviceCallback deviceCallback;
private BluetoothManager bluetoothManager;
private BluetoothAdapter bluetoothAdapter;
private static final UUID SERVICE = UUID.fromString("0000fff0-0000-1000-8000-00805f9b34fb");
private static final UUID Write1 = UUID.fromString("d44bc439-abfd-45a2-b575-925416129600");
private static final UUID Write2 = UUID.fromString("d44bc439-abfd-45a2-b575-92541612960a");
private static final UUID Write3 = UUID.fromString("d44bc439-abfd-45a2-b575-92541612960b");
private static final UUID Notify = UUID.fromString("d44bc439-abfd-45a2-b575-925416129601");
private final BluetoothGattCallback bluetoothGattCallback;
private final Handler handler = new Handler();
private final int timeOut = 5000;
private List<HashMap<String,List<byte[]>>> cache= new ArrayList<>();
private List<WriteCallBack> callBacks = new ArrayList<>();
private SendCallBack sendCallBack;
private Runnable sendTimeOut = new Runnable() {
@Override
public void run() {
if(sendCallBack!=null && cache.size()>0 && cache.get(cache.size()-1)!=null){
for (String address:cache.get(cache.size()-1).keySet()) {
sendCallBack.timeOut(devices.get(address));
};
}
}
};
private double curTime;
private LightStripBleManager(){
bleListener = new BleListenerImpl();
bleManager.registerBleListener(bleListener);
deviceDao = App.getDaoSession().getDeviceDao();
bluetoothGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
BleData bleData = devices.get(gatt.getDevice().getAddress());
//操作成功
if(status == BluetoothGatt.GATT_SUCCESS){
if(bleData == null){
LogUtil.e( "device cache miss.");
return;
}
if(newState == BluetoothProfile.STATE_DISCONNECTED){
bleData.setConnectionState(newState);
if(deviceCallback != null){
deviceCallback.onBleData(bleData,false);
}
gatt.close();
devices.remove(gatt.getDevice().getAddress());
LogUtil.d("connectOrDis + 断开连接"+bleData.getBleAddress()+"---"+bleData.getBleName());
}else if(newState == BluetoothProfile.STATE_CONNECTED){
LogUtil.d("connectOrDis + 获取服务"+gatt.getDevice().getAddress()+"---"+gatt.getDevice().getName());
boolean b = bleData.getBluetoothGatt().discoverServices();
if(!b){
LogUtil.d("connectOrDis + GATT Service acquisition failed");
devices.remove(bleData.getBleAddress());
gatt.disconnect();
return;
}else {
runnableCallback.put(bleData.getBleAddress(), () -> {
LogUtil.d("connectOrDis + GATT Service No reaction");
devices.remove(bleData.getBleAddress());
gatt.disconnect();
});
handler.postDelayed(runnableCallback.get(bleData.getBleAddress()), timeOut);
}
}
}
if(status == 133){
LogUtil.d("connectOrDis + status 133");
devices.remove(bleData.getBleAddress());
gatt.disconnect();
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
handler.removeCallbacks(runnableCallback.get(gatt.getDevice().getAddress()));
LogUtil.d("connectOrDis + 设置mtu"+gatt.getDevice().getAddress()+"---"+gatt.getDevice().getName());
gatt.requestMtu(512);
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
}
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicWrite(gatt, characteristic, status);
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
byte[] dataEd = Agreement.getDecodeData(characteristic.getValue());
String address = gatt.getDevice().getAddress();
for (WriteCallBack callBack :callBacks) {
callBack.onCharacteristicChanged(devices.get(address),dataEd);
}
for (int i = 0; i < cache.size(); i++) {
HashMap<String,List<byte[]>> item = cache.get(i);
if(item.containsKey(address)){
List<byte[]> bytes = item.get(address);
String arrays = Arrays.toString(bytes.get(0));
String censor = arrays.substring(1, arrays.length()-1);
if(Arrays.toString(dataEd).contains(censor)){
boolean result = true;
if(bytes.get(1)!=null && bytes.size()<3 && bytes.get(1).length != 0){
result= write(gatt, bytes.get(1), Write1);
}else if(bytes.get(1)!=null) {
result = write(gatt, bytes.get(1), Write2);
}
if(!result && sendCallBack!=null){
sendCallBack.fail(devices.get(address));
}
bytes.remove(1);
if(bytes.size()<2 || bytes.get(1).length==0){
item.remove(address);
if(result){
for (HashMap<String,List<byte[]>> it: cache) {
result = it.get(address)==null;
}
if(result){
sendCallBack.success(devices.get(address));
}
}
}else {
item.put(address,bytes);
}
if(cache.get(i).size() ==0){
cache.remove(i);
}
if(cache.size() ==0 && sendCallBack!=null){
sendCallBack.successAll();
}
return;
}
}
}
}
@Override
public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
super.onDescriptorRead(gatt, descriptor, status);
}
@Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
super.onDescriptorWrite(gatt, descriptor, status);
}
@Override
public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
super.onMtuChanged(gatt, mtu, status);
BleData bleData = devices.get(gatt.getDevice().getAddress());
if(bleData == null){
LogUtil.d( "connectOrDis + device cache miss.");
return;
}
LogUtil.d("connectOrDis + 设置mtu成功"+bleData.getBleAddress()+"---"+bleData.getBleName());
BluetoothGatt bluetoothGatt = bleData.getBluetoothGatt();
BluetoothGattService gattService = bluetoothGatt.getService(SERVICE);
if(gattService != null){
BluetoothGattCharacteristic characteristic = gattService.getCharacteristic(Notify);
if(characteristic != null){
enableNotification(bluetoothGatt,true, characteristic);
LogUtil.d("connectOrDis + 更新设备"+bleData.getBleAddress()+"---"+bleData.getBleName());
bleData.setConnectionState(BluetoothProfile.STATE_CONNECTED);
if(deviceCallback != null){
deviceCallback.onBleData(bleData,false);
}
devices.put(bleData.getBleAddress(),bleData);
}else {
LogUtil.d("connectOrDis + Characteristic null "+bleData.getBleAddress()+"---"+bleData.getBleName());
gatt.disconnect();
devices.remove(bleData.getBleAddress());
}
}else {
LogUtil.d("connectOrDis + GATT Service null "+bleData.getBleAddress()+"---"+bleData.getBleName());
gatt.disconnect();
devices.remove(bleData.getBleAddress());
}
}
};
}
public void registerCallback(WriteCallBack writeCallBack){
callBacks.add(writeCallBack);
}
public void unregisterCallback(WriteCallBack writeCallBack){
callBacks.remove(writeCallBack);
}
/**
*
* @param bluetoothGatt Gatt
* @param enable 注册(true)/注销(false)
* @param characteristic 通知特征ID
*/
public void enableNotification(BluetoothGatt bluetoothGatt, boolean enable, BluetoothGattCharacteristic characteristic) {
if (bluetoothGatt == null || characteristic == null) {
return;
}
if (!bluetoothGatt.setCharacteristicNotification(characteristic, enable)) {
return;
}
//获取到Notify当中的Descriptor通道 然后再进行注册
List<BluetoothGattDescriptor> clientConfigs = characteristic.getDescriptors();
if (clientConfigs == null || clientConfigs.size() ==0) {
return;
}
if (enable) {
for (BluetoothGattDescriptor clientConfig: clientConfigs) {
clientConfig.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
boolean b = bluetoothGatt.writeDescriptor(clientConfig);
LogUtil.d("connectOrDis + 注册通知"+b);
}
} else {
for (BluetoothGattDescriptor clientConfig: clientConfigs) {
clientConfig.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
boolean b = bluetoothGatt.writeDescriptor(clientConfig);
LogUtil.d("connectOrDis + 注销通知"+b);
}
}
}
public static LightStripBleManager getInstance(){
return instance;
}
@SuppressLint("MissingPermission")
public void disconnectAll(){
for (BleData bleData:devices.values()) {
bleData.getBluetoothGatt().disconnect();
}
}
public void setCallBack(DeviceCallback deviceCallback){
this.deviceCallback = deviceCallback;
}
public List<BleData> getDevices() {
return new ArrayList<>(devices.values());
}
private boolean write (BluetoothGatt gatt, byte[] data,UUID write) {
BluetoothGattService gattService = gatt.getService(SERVICE);
if(gattService==null){
LogUtil.d("Write + GATT 服务丢失");
return false;
}
BluetoothGattCharacteristic characteristic = gattService.getCharacteristic(write);
if(characteristic==null){
LogUtil.d("Write + Characteristic 特征丢失");
return false;
}
characteristic.setValue(data);
return gatt.writeCharacteristic(characteristic);
}
public boolean write1(byte[] data) {
boolean result = false;
for (BleData bleData :devices.values()) {
if(bleData.getConnectionState() == BluetoothProfile.STATE_CONNECTED){
result = write(bleData.getBluetoothGatt(),data,Write1);
}
}
return result;
}
/**
* @param data 发送的数据
* @param sendCallBack {@link SendCallBack}
* @param list 后续要发的东西 格式:
* byte[0] 触动发送的条件 例:new byte[]{'X', 'I', 'A', 'Y', 'I', 'B','U'}
* byte[1] byte[last-1] 发送的东西(write2) 例:new byte[]{'S', J', 'Y', 'I'}
* byte[last] 发送结束的通知(write1) 例:new byte[]{'O', 'K'}, 不需要时可以为new byte[0]
* @return
*/
@SafeVarargs
public final boolean write1(byte[] data, SendCallBack sendCallBack, List<byte[]>... list) {
this.sendCallBack = sendCallBack;
cache.clear();
handler.removeCallbacks(sendTimeOut);
handler.postDelayed(sendTimeOut,10*1000);
boolean result = false;
if(devices.size() ==0 ){
if(sendCallBack!=null){
sendCallBack.fail(null);
}
return false;
}
HashMap<String, List<byte[]>> stringHash;
for (List<byte[]> item : list) {
stringHash = new HashMap<>();
for (BleData bleData : devices.values()){
stringHash.put(bleData.getBleAddress(), new ArrayList<>(item));
}
cache.add(stringHash);
}
for (BleData bleData : devices.values()) {
if (bleData.getConnectionState() == BluetoothProfile.STATE_CONNECTED) {
result = write(bleData.getBluetoothGatt(), data, Write1);
if(!result && sendCallBack!=null){
sendCallBack.fail(bleData);
}
}
}
return result;
}
public boolean write3(byte[] data) {
boolean result = false;
for (BleData bleData :devices.values()) {
if(bleData.getConnectionState() == BluetoothProfile.STATE_CONNECTED){
result = write(bleData.getBluetoothGatt(),data,Write3);
}
}
return result;
}
public boolean write1(BluetoothGatt gatt, byte[] dataEd) {
return write(gatt,dataEd,Write1);
}
class BleListenerImpl extends BleListener{
@Override
public boolean filterDevice(BleDevice device, int rssi, byte[] scanRecord) {
if(!LightStripBleConfig.matchProduct(scanRecord)) {return true;}
BleData bleData = new BleData();
bleData.setBluetoothDevice(device.getBluetoothDevice());
bleData.setScanRecord(scanRecord);
bleData.setConnectionState(BluetoothProfile.STATE_DISCONNECTED);
bleData.setBleAddress(device.getBleAddress());
bleData.setBleName(device.getBleName());
bleData.setOtaVersion("");
if(deviceCallback != null){
deviceCallback.onBleData(bleData,true);
}
if(isReConnect(bleData.getBleAddress())){
if (System.currentTimeMillis() - curTime > 1500) {
connectOrDis(bleData);
curTime = System.currentTimeMillis();
}
}
return super.filterDevice(device, rssi, scanRecord);
}
@Override
public void onStart() {
super.onStart();
}
@Override
public void onStop() {
super.onStop();
}
@Override
public void onChanged(BleDevice device, byte[] data) {
}
}
/**
* 保存 是否可以重连地址
*
* @param bleName 设备名称
* @param bleAddress 设备地址
* @param isReConnect 是否可以重连
*/
public void saveDevice(String bleName, String bleAddress, boolean isReConnect) {
try {
Device device = deviceDao.queryBuilder().where(DeviceDao.Properties.Mac.eq(bleAddress)).unique();
if (device != null && !TextUtils.isEmpty(device.getMac())) {
device.setDeviceName(bleName);
device.setIsReConnect(isReConnect);
device.setMac(bleAddress);
deviceDao.update(device);
} else {
Device device1 = new Device();
device1.setDeviceName(bleName);
device1.setIsReConnect(isReConnect);
device1.setMac(bleAddress);
deviceDao.save(device1);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 连接、断开设备
*
*/
@SuppressLint("MissingPermission")
public void connectOrDis(BleData bleData){
if(devices.get(bleData.getBleAddress()) == null ||
(devices.get(bleData.getBleAddress()).getConnectionState() == bleData.getConnectionState() &&
devices.get(bleData.getBleAddress()).getConnectionState() != BluetoothProfile.STATE_CONNECTING &&
devices.get(bleData.getBleAddress()).getConnectionState() != BluetoothProfile.STATE_DISCONNECTING)
){}else {return;}
LogUtil.d("connectOrDis + 操作中"+bleData.getBleAddress()+"---"+bleData.getBleName()+"---"+bleData.getConnectionState());
//检查蓝牙地址
if(!BluetoothAdapter.checkBluetoothAddress(bleData.getBleAddress())){
LogUtil.e( "checkBluetoothAddress False");
return;
}
//断开设备
if(bleData.getConnectionState() == BluetoothProfile.STATE_CONNECTED){
LogUtil.d("connectOrDis + 断开设备"+bleData.getBleAddress()+"---"+bleData.getBleName());
bleData.getBluetoothGatt().disconnect();
bleData.setConnectionState(BluetoothProfile.STATE_DISCONNECTING);
runnableCallback.put(bleData.getBleAddress(), () -> {
LogUtil.d("connectOrDis + GATT Service No reaction");
devices.remove(bleData.getBleAddress());
});
devices.put(bleData.getBleAddress(),bleData);
return;
}
//连接设备
if (bluetoothManager == null) {
bluetoothManager = (BluetoothManager) App.getContext().getSystemService(Context.BLUETOOTH_SERVICE);
if (bluetoothManager == null) {
LogUtil.e( "Unable to initBLE BluetoothManager.");
return;
}
}
if (bluetoothAdapter == null) {
bluetoothAdapter = bluetoothManager.getAdapter();
if (bluetoothAdapter == null) {
LogUtil.e( "Unable to obtain a BluetoothAdapter.");
return;
}
}
LogUtil.d("connectOrDis + 获取设备"+bleData.getBleAddress()+"---"+bleData.getBleName());
BluetoothDevice device = bluetoothAdapter.getRemoteDevice(bleData.getBleAddress());
LogUtil.d("connectOrDis + 保存设备"+bleData.getBleAddress()+"---"+bleData.getBleName());
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// //GATT连接到远程双模设备优先BLE
// bleData.setBluetoothGatt(device.connectGatt(App.getContext(), false, bluetoothGattCallback, BluetoothDevice.TRANSPORT_LE));
// }else {
bleData.setBluetoothGatt(device.connectGatt(App.getContext(), false, bluetoothGattCallback));
// }
bleData.setConnectionState(BluetoothProfile.STATE_CONNECTING);
devices.put(bleData.getBleAddress(),bleData);
}
/**
* 是否可以重连
*
* @param bleAddress 设备地址
* @return 是否可以重连
*/
private boolean isReConnect(String bleAddress) {
try {
if (!TextUtils.isEmpty(bleAddress)) {
Device device = deviceDao.queryBuilder().where(DeviceDao.Properties.Mac.eq(bleAddress)).unique();
if (device != null) {
return device.getIsReConnect();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
}
Android 蓝牙连接类
最新推荐文章于 2024-05-16 20:42:16 发布