From bff93587cd4ab7fd796d9c315795910e5597ea97 Mon Sep 17 00:00:00 2001 From: konewu <379301272@qq.com> Date: Mon, 8 Mar 2021 11:40:05 +0800 Subject: [PATCH] =?UTF-8?q?2021.03.08:=20=E4=BC=98=E5=8C=96bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/compiler.xml | 6 + .idea/gradle.xml | 15 +- .idea/jarRepositories.xml | 35 ++ .idea/misc.xml | 2 +- app/build.gradle | 16 +- .../sinovotec/sinovobledemo/MainActivity.java | 16 +- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- sinovoble/build.gradle | 18 +- sinovoble/src/main/AndroidManifest.xml | 6 + .../com/sinovotec/sinovoble/SinovoBle.java | 366 +++++++++++------- .../sinovoble/callback/BleConnCallBack.java | 309 +++++++-------- .../sinovoble/callback/BleScanCallBack.java | 85 ++-- .../sinovoble/callback/IConnectCallback.java | 5 +- .../sinovotec/sinovoble/common/BleData.java | 204 ++++++---- .../sinovoble/common/BleScanDevice.java | 4 - .../common/BluetoothListenerReceiver.java | 38 +- 17 files changed, 654 insertions(+), 475 deletions(-) create mode 100644 .idea/compiler.xml create mode 100644 .idea/jarRepositories.xml diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..61a9130 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml index d291b3d..9ea9b88 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -1,15 +1,22 @@ + diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 0000000..c67c793 --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index af0bbdd..3378229 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -5,7 +5,7 @@ - + diff --git a/app/build.gradle b/app/build.gradle index 0989593..268614f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -22,19 +22,25 @@ android { proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'androidx.appcompat:appcompat:1.2.0' - implementation 'androidx.constraintlayout:constraintlayout:2.0.1' - testImplementation 'junit:junit:4.12' + implementation 'androidx.constraintlayout:constraintlayout:2.0.2' + testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' + implementation project(path: ':sinovoble') - implementation 'com.alibaba:fastjson:1.1.72.android' //fastjson 解析库 + implementation 'com.alibaba:fastjson:1.2.40' //fastjson 解析库 - implementation('com.aliyun.alink.linksdk:iot-linkkit:1.7.2') - implementation('com.aliyun.alink.linksdk:public-channel-core:0.7.7.1') +// implementation('com.aliyun.alink.linksdk:iot-linkkit:1.7.2') +// implementation('com.aliyun.alink.linksdk:public-channel-core:0.7.7.1') } diff --git a/app/src/main/java/com/sinovotec/sinovobledemo/MainActivity.java b/app/src/main/java/com/sinovotec/sinovobledemo/MainActivity.java index 4b4fbdc..179415d 100644 --- a/app/src/main/java/com/sinovotec/sinovobledemo/MainActivity.java +++ b/app/src/main/java/com/sinovotec/sinovobledemo/MainActivity.java @@ -3,7 +3,6 @@ import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; -import android.os.Looper; import android.util.Log; import android.view.View; import android.widget.Button; @@ -11,7 +10,6 @@ import android.widget.TextView; import android.widget.Toast; -import com.alibaba.fastjson.JSONObject; import com.sinovotec.sinovoble.SinovoBle; import com.sinovotec.sinovoble.callback.IConnectCallback; import com.sinovotec.sinovoble.callback.IScanCallBack; @@ -25,7 +23,7 @@ public class MainActivity extends AppCompatActivity { /** * 扫描回调 */ - private IScanCallBack mBleScanCallBack = new IScanCallBack() { + private final IScanCallBack mBleScanCallBack = new IScanCallBack() { @Override public void onDeviceFound(String scanResult) { Log.w("xxx", "onDeviceFound:" + scanResult); @@ -42,7 +40,7 @@ public void onScanTimeout(String scanResult) { /** * 连接回调 */ - private IConnectCallback mConnCallBack = new IConnectCallback() { + private final IConnectCallback mConnCallBack = new IConnectCallback() { @Override public void onConnectSuccess(String macAddress) { @@ -66,8 +64,7 @@ public void onBluetoothOn() { } @Override - public void onDisconnect() { - Log.i("xxx","连接回调 IConnectCallback 连接断开"); + public void onDisconnect(String macaddress) { } @@ -143,6 +140,11 @@ public void onAuthorOther(String result) { } + @Override + public void onLockFrozen(String result) { + + } + @Override public void onReceiveDataFailed() { @@ -161,7 +163,7 @@ protected void onCreate(Bundle savedInstanceState) { Button chkp = findViewById(R.id.btn_chkpower); final EditText myet = findViewById(R.id.lockid_et); - final EditText usernameet = findViewById(R.id.username_et); + // final EditText usernameet = findViewById(R.id.username_et); reslut_tv = findViewById(R.id.result_tv); newbtn.setOnClickListener(new View.OnClickListener() { diff --git a/build.gradle b/build.gradle index 243cf0c..f75b2d8 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.5.4' + classpath 'com.android.tools.build:gradle:3.5.2' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 5537f82..9b2198e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,4 +1,4 @@ -#Thu Sep 10 15:52:33 CST 2020 +#Mon Mar 08 11:25:46 CST 2021 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/sinovoble/build.gradle b/sinovoble/build.gradle index 027f935..941efac 100644 --- a/sinovoble/build.gradle +++ b/sinovoble/build.gradle @@ -27,24 +27,34 @@ android { } } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + sourceSets { main{ jniLibs.srcDirs = ['jnilibs'] } } + repositories { + maven { + url "https://repo.eclipse.org/content/repositories/paho-snapshots/" + } + } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'androidx.appcompat:appcompat:1.2.0' - testImplementation 'junit:junit:4.12' + testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' - implementation 'com.alibaba:fastjson:1.1.72.android' //fastjson 解析库 + implementation 'com.alibaba:fastjson:1.2.40' //fastjson 解析库 原来 1.1.72 - implementation('com.aliyun.alink.linksdk:iot-linkkit:1.7.2') - implementation('com.aliyun.alink.linksdk:public-channel-core:0.7.7.1') + implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.0' //原来 1.1.0 + implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1' } diff --git a/sinovoble/src/main/AndroidManifest.xml b/sinovoble/src/main/AndroidManifest.xml index e92c4f3..89d343e 100644 --- a/sinovoble/src/main/AndroidManifest.xml +++ b/sinovoble/src/main/AndroidManifest.xml @@ -8,5 +8,11 @@ + + + + + + diff --git a/sinovoble/src/main/java/com/sinovotec/sinovoble/SinovoBle.java b/sinovoble/src/main/java/com/sinovotec/sinovoble/SinovoBle.java index ae42e32..a73000e 100644 --- a/sinovoble/src/main/java/com/sinovotec/sinovoble/SinovoBle.java +++ b/sinovoble/src/main/java/com/sinovotec/sinovoble/SinovoBle.java @@ -33,7 +33,7 @@ public class SinovoBle { - private String TAG = "SinovoBle"; + private final String TAG = "SinovoBle"; private String lockID ; //锁的ID,用户输入的,用于添加锁的 private String phoneIMEI; //手机的imei,作为手机id private String lockMAC; //当前连接锁的蓝牙mac地址 @@ -41,25 +41,34 @@ public class SinovoBle { private String lockName; //锁的名称 private String lockFirmVersion; private String lockType; + private String lockGWid = ""; //锁对应的网关id private String bleServiceUUID; //蓝牙服务的UUID private String blecharacteristUUID; //蓝牙特征字的UUID private boolean isBindMode = false; //是否为绑定模式 private boolean isScanAgain = false; //扫描停止后是否继续扫描 - private boolean isConnected = false; //是否已经连接成功 + private boolean isConnected = false; //是否已经连接成功, 已经可以发送命令了 + private boolean isLinked = false; //是否连接上了,第一步连接上与否, 下面还需要 发现服务,设置 读写属性才能发送命令 + private boolean isConnectting = false; //是否正在连接 + private boolean isAddingLock = false; //是否正在添加锁,主要是解决,在扫描绑定锁之后,添加到服务器端,避免反复在提交数据,等待基本数据同步完成再添加到服务器端 + private String connectTime = ""; //记录下连接的时间 + private String connectingMac = ""; //当前正在连接的设备mac地址 + + private int connType = 0; //指定连接方式,为0 表示用蓝牙连接,为1表示通过网关连接 private Context context; //上下文 private BluetoothManager bluetoothManager; //蓝牙管理 private BluetoothAdapter bluetoothAdapter; //蓝牙适配器 - private Handler scanBleHandler = new Handler(Looper.getMainLooper()); //设置定时任务的handler,扫描5s后 定时调用 停止扫描的函数 - private Handler bindTimeoutHandler = new Handler(Looper.getMainLooper()); //设置定时任务的handler,绑定2分钟后,超时失败 + private final Handler scanBleHandler = new Handler(Looper.getMainLooper()); //设置定时任务的handler,扫描5s后 定时调用 停止扫描的函数 + private final Handler bindTimeoutHandler = new Handler(Looper.getMainLooper()); //设置定时任务的handler,绑定2分钟后,超时失败 + private final Handler autoConnetHandler = new Handler(Looper.getMainLooper()); //设置自动连接的handler,一般情况下,自动连接超时为30s ,但偶尔有异常,连接失败了回调通知 - private ArrayList scanLockList ; //保存扫描的结果 - private ArrayList bondBleMacList; //保存在绑定时,已经尝试连接过的锁 ,避免已经尝试过绑定不合适的锁,还会重复绑定 - private ArrayList autoConnectList; //自动连接的设备列表,内容为mac地址 + private final ArrayList scanLockList ; //保存扫描的结果 + private final ArrayList bondBleMacList; //保存在绑定时,已经尝试连接过的锁 ,避免已经尝试过绑定不合适的锁,还会重复绑定 + private ArrayList toConnectLockList; //自动连接的设备列表,内容为mac地址,sno @SuppressLint("StaticFieldLeak") private static SinovoBle instance; //入口操作管理 @@ -90,7 +99,7 @@ public static SinovoBle getInstance() { private SinovoBle() { scanLockList = new ArrayList<>(); bondBleMacList = new ArrayList<>(); - autoConnectList = new ArrayList<>(); + toConnectLockList = new ArrayList<>(); } public String getLockID() { @@ -101,10 +110,6 @@ public boolean isBindMode() { return isBindMode; } - public boolean isConnectting() { - return isConnectting; - } - public String getPhoneIMEI() { return phoneIMEI; } @@ -121,7 +126,11 @@ public String getBleServiceUUID() { return bleServiceUUID; } - public boolean isConnected() { +// public boolean isConnected() { +// return isConnected; +// } + + public boolean isBleConnected() { return isConnected; } @@ -129,6 +138,10 @@ public Handler getBindTimeoutHandler() { return bindTimeoutHandler; } + public Handler getAutoConnetHandler() { + return autoConnetHandler; + } + public String getBlecharacteristUUID() { return blecharacteristUUID; } @@ -165,8 +178,8 @@ public ArrayList getScanLockList() { return scanLockList; } - public ArrayList getAutoConnectList() { - return autoConnectList; + public ArrayList getToConnectLockList() { + return toConnectLockList; } public Context getContext() { @@ -201,10 +214,6 @@ public void setBindMode(boolean bindMode) { isBindMode = bindMode; } - public void setConnectting(boolean connectting) { - isConnectting = connectting; - } - public void setConnected(boolean connected) { Log.d(TAG,"设置连接状态:" + connected); isConnected = connected; @@ -247,8 +256,8 @@ public void setmConnCallBack(IConnectCallback mConnCallBack) { this.mConnCallBack = mConnCallBack; } - public void setAutoConnectList(ArrayList autoConnectList) { - this.autoConnectList = autoConnectList; + public void setToConnectLockList(ArrayList toConnectLockList) { + this.toConnectLockList = toConnectLockList; } public void setLockType(String lockType) { @@ -260,9 +269,33 @@ public String getLockFirmVersion() { } public LoadLibJni getMyJniLib() { + if (myJniLib == null){ + if (LoadLibJni.LoadLib()){ + Log.d(TAG, "加载 so库,初始化 成功"); + myJniLib = new LoadLibJni(); + }else { + Log.e(TAG, "加载 so库,初始化 失败"); + } + } return myJniLib; } + public int getConnType() { + return connType; + } + + public void setConnType(int connType) { + this.connType = connType; + } + + public boolean isAddingLock() { + return isAddingLock; + } + + public void setAddingLock(boolean addingLock) { + isAddingLock = addingLock; + } + /** * 初始化 * @@ -281,13 +314,12 @@ public void init(Context context, IScanCallBack iScanCallBack, IConnectCallback context.registerReceiver(receiver,makeFilter()); //加载 so库,初始化 - if (LoadLibJni.LoadLib()){ - Log.d(TAG, "加载 so库,初始化 成功"); - myJniLib = new LoadLibJni(); - }else { - Log.e(TAG, "加载 so库,初始化 失败"); - } - +// if (LoadLibJni.LoadLib()){ +// Log.d(TAG, "加载 so库,初始化 成功"); +// myJniLib = new LoadLibJni(); +// }else { +// Log.e(TAG, "加载 so库,初始化 失败"); +// } } } private IntentFilter makeFilter() { @@ -296,19 +328,18 @@ private IntentFilter makeFilter() { return filter; } - private void startBleScan(){ + public void startBleScan(){ + if (SinovoBle.getInstance().isConnectting()){ + Log.e(TAG,"当前正在连接,不能进行扫描"); + return; + } Log.d(TAG, "调用startBleScan 来扫描"); - getBondBleMacList().clear(); //clean the bondBleMacList before starting scan + getBondBleMacList().clear(); //clean the bondBleMacList before starting scan setScanAgain(true); //绑定模式下,设置绑定超时检测 if (isBindMode()) { - bindTimeoutHandler.postDelayed(new Runnable() { - @Override - public void run() { - checkScanResult(); - } - }, 60*1000); + bindTimeoutHandler.postDelayed(this::checkScanResult, 60*1000); } bleScan(getmBleScanCallBack()); @@ -317,7 +348,7 @@ public void run() { //绑定超时检测 private void checkScanResult(){ Log.e(TAG,"绑定超时检测,超时为1分钟"); - if (!isConnected()){ + if (!isBleConnected()){ Log.d(TAG,"绑定超时检测,需要告知回调"); LinkedHashMap map = new LinkedHashMap<>(); map.put("scanResult", "0"); @@ -336,45 +367,70 @@ public void addLock(String lockqrID, String phoneID){ //每次准备绑定之前,先取消上次的绑定超时检测 if (SinovoBle.getInstance().getBindTimeoutHandler() != null) { - Log.w(TAG,"取消 绑定超时检测"); + // Log.w(TAG,"取消 绑定超时检测"); SinovoBle.getInstance().getBindTimeoutHandler().removeCallbacksAndMessages(null); } - Log.d(TAG,"调用 addLock"); + // Log.d(TAG,"调用 addLock"); setScanAgain(true); setBindMode(true); - setConnectting(false); setLockID(lockqrID); setPhoneIMEI(phoneID); - startBleScan(); //开始绑定,需要清空自动连接列表 - autoConnectList.clear(); + toConnectLockList.clear(); + disconnBle(); + startBleScan(); } /** * 非绑定模式下,自动连接指定的锁,可以指定多把,蓝牙先扫描到哪一把就连哪一把 * @param autoConnectList 需要自动连接的锁列表 + * @connectViaScan 为 true的时候,表示需要先扫描,扫描到 列表中的锁再连接,为false 则表示直接连接,不需要经过扫描 */ - public void autoConnectLock(ArrayList autoConnectList){ - + public void autoConnectLock(final ArrayList autoConnectList, Boolean connectViaScan){ if (mBleScanCallBack == null || mConnCallBack ==null){ Log.e(TAG,"ScanCallBack or mConnCallBack is null"); + + //出错了,需要提示客户 return; } - Log.w(TAG, "autoConnectLock 开始进行自动连接。。。。"); - setScanAgain(true); - setBindMode(false); - setConnectting(false); - setAutoConnectList(autoConnectList); - startBleScan(); - } + //保存用户指定的 自动连接锁列表 + setToConnectLockList(autoConnectList); - public int checkEnvir(){ - if (!isConnected()){ - Log.e(TAG,"Bluetooth not connected"); - return 1; + setBindMode(false); + if (connectViaScan) { + Log.d(TAG,"Scan first according to setup needs"); + SinovoBle.getInstance().startBleScan(); + }else { + //准备 自动连接之前,先停止扫描; 这样连接效率很高一些 + Log.d(TAG,"No scanning is required according to the Settings"); + + //只连接队列中的第一把锁,连接的时候 先停止蓝牙扫描,这样连接效率高一些,同时连接速度也快一些 + if (!autoConnectList.isEmpty()){ + setScanAgain(false); + BleScanCallBack.getInstance(mBleScanCallBack).stopScan(); + BleConnectLock bleConnectLock = autoConnectList.get(0); + + //add 20210128 + autoConnectList.clear(); + autoConnectList.add(bleConnectLock); + + Log.w(TAG, "autoConnectLock :connect to "+ bleConnectLock.getLockMac() + ",there are "+autoConnectList.size()+" locks in autoConnectLock's list"); + BluetoothDevice device = bluetoothAdapter.getRemoteDevice(bleConnectLock.getLockMac()); + + //延迟 300ms 再去连接 + SinovoBle.getInstance().setScanAgain(false); + connectBle(device); + + //目前测试来看,最长超时返回为 31s,绝对部分是 30s + autoConnetHandler.postDelayed(() -> { + BleConnCallBack.getInstance().disConectBle(); + }, 33*1000); + } } + } + private int checkEnvir(){ if (SinovoBle.getInstance().getLockSNO() == null){ Log.e(TAG,"SNO error"); return -1; @@ -533,7 +589,7 @@ public int resetPassword(String userNid, String codeType, String codeID, String * 具有查看日志权限时,值为08,09,10,11,12,13,14,15 * @param data s */ - public int setLock(String dataType, String data){ + public int setLockInfo(String dataType, String data){ int result = checkEnvir(); if (result !=0){ return result; @@ -562,12 +618,12 @@ public int setLock(String dataType, String data){ if (dataType.equals("03")){ String sixteen = ""; if (!data.isEmpty()){ - if(Integer.valueOf(data) <0 || Integer.valueOf(data)>240){ + if(Integer.parseInt(data) <0 || Integer.parseInt(data)>240){ Log.e(TAG,"Parameter error"); return 2; } - sixteen = Integer.toHexString(Integer.valueOf(data)); + sixteen = Integer.toHexString(Integer.parseInt(data)); if (sixteen.length() <2){ sixteen = "0"+sixteen; } @@ -582,7 +638,7 @@ public int setLock(String dataType, String data){ if (data.isEmpty()){ data = "02"; } - if (Integer.valueOf(data)<0 || Integer.valueOf(data)>2){ + if (Integer.parseInt(data)<0 || Integer.parseInt(data)>2){ Log.e(TAG,"Parameter error"); return 2; } @@ -614,27 +670,13 @@ public int setLock(String dataType, String data){ */ public int requestLockInfo(String dataType){ int result = checkEnvir(); - if (result !=0){ - return result; - } - - String data = SinovoBle.getInstance().getLockSNO() ; - if (dataType.equals("01")){ - BleData.getInstance().exeCommand("12", data, false); - } - - if (dataType.equals("02")){ - BleData.getInstance().exeCommand("0e", data, false); - } - - if (dataType.equals("03")){ - BleData.getInstance().exeCommand("0f", data, false); - } - - if (dataType.equals("04")){ - BleData.getInstance().exeCommand("1a", data, false); - } + if (result !=0){ return result; } + String data = SinovoBle.getInstance().getLockSNO(); + if (dataType.equals("01")){ BleData.getInstance().exeCommand("12", data, false); } + if (dataType.equals("02")){ BleData.getInstance().exeCommand("0e", data, false); } + if (dataType.equals("03")){ BleData.getInstance().exeCommand("0f", data, false); } + if (dataType.equals("04")){ BleData.getInstance().exeCommand("1a", data, false); } return 0; } @@ -765,6 +807,19 @@ public int verifyPassword(String password){ return 0; } + /** + * 通知锁端断开蓝牙连接 + */ + public int toDisconnBle(){ + int result = checkEnvir(); + if (result !=0){ + return result; + } + + String data = SinovoBle.getInstance().getLockSNO(); + BleData.getInstance().exeCommand("1e", data, true); + return 0; + } /** * 开关门操作 @@ -817,32 +872,6 @@ public int cleanData(String datakType){ return 0; } - /** - * 用户授权 - * @param codeType 密码类型 - * @param code 密码 - * @param username 准备生成的用户名称 - */ - public int authorOther(String codeType, String code, String username){ - if (codeType.isEmpty() || code.isEmpty() || username.isEmpty()){ - Log.e(TAG,"Parameter error"); - return 2; - } - - int result = checkEnvir(); - if (result !=0){ - return result; - } - - //username 转换为 ascii码 - String username_ascii = ComTool.stringToAscii(username); - - Log.d(TAG,"字符串:"+username + ", ascii:"+ username_ascii); - String data = SinovoBle.getInstance().getLockSNO() + codeType + code + username_ascii; - BleData.getInstance().exeCommand("26", data, true); - return 0; - } - //用户取消了绑定 public void cancelAddLock(){ @@ -882,13 +911,13 @@ public int bleScan(final IScanCallBack iScanCallBack){ return -2; } - if (autoConnectList.isEmpty() && !isBindMode()){ + if (toConnectLockList.isEmpty() && !isBindMode()){ setScanAgain(false); return 1; } if (BleScanCallBack.getInstance(iScanCallBack).isScanning()){ - Log.e(TAG, "Bluetooth scanning is already underway"); + Log.e(TAG, "It's scanning. Ignore this scan request"); return 1; } @@ -902,15 +931,9 @@ public int bleScan(final IScanCallBack iScanCallBack){ filters.add(filter2); Log.d(TAG, "Start scanning"); - scanBleHandler.postDelayed(new Runnable() { - @Override - public void run() { - BleScanCallBack.getInstance(iScanCallBack).stopScan(); - } - }, getScanRepeatInterval()); + scanBleHandler.postDelayed(() -> BleScanCallBack.getInstance(iScanCallBack).stopScan(), getScanRepeatInterval()); BleScanCallBack.getInstance(iScanCallBack).setScanning(true); - ScanSettings bleScanSettings = new ScanSettings.Builder() .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) .setReportDelay(0) //扫描到结果,立马报告 @@ -922,64 +945,62 @@ public void run() { //取消蓝牙扫描的定时任务 public void removeScanHandlerMsg(){ - if (scanBleHandler !=null) { - scanBleHandler.removeCallbacksAndMessages(null); //取消定时任务 - } + scanBleHandler.removeCallbacksAndMessages(null); //取消定时任务 } - /** - * 对外提供连接锁的接口函数 - */ - public void connectLock(final BleScanDevice bleScanLock){ - if (!getScanLockList().isEmpty() && !SinovoBle.getInstance().isConnectting() && !SinovoBle.getInstance().isConnected()){ - new Handler(Looper.getMainLooper()).postDelayed(new Runnable() { - @Override - public void run() { - SinovoBle.getInstance().connectBle(bleScanLock.GetDevice()); - } - }, 100); - } - } - - /** * 连接蓝牙设备 * @param bluetoothDevice 待连接的设备 * @return //是否连接成功 */ - private boolean connectBle(final BluetoothDevice bluetoothDevice) { + public boolean connectBle(final BluetoothDevice bluetoothDevice) { if (SinovoBle.getInstance().getBluetoothAdapter() == null || bluetoothDevice == null) { + SinovoBle.getInstance().setConnectting(false); Log.e(TAG, "Bluetooth Adapter is null"); return false; } if (!SinovoBle.getInstance().getBluetoothAdapter().isEnabled()) { + SinovoBle.getInstance().setConnectting(false); Log.e(TAG, "Bluetooth not enabled"); return false; } - if (SinovoBle.getInstance().isConnectting()){ -// Log.d(TAG, "当前正在连接中,忽略本次的连接请求:"+ bluetoothDevice.getAddress()); + if (SinovoBle.getInstance().isLinked() || SinovoBle.getInstance().isBleConnected()){ + SinovoBle.getInstance().setConnectting(false); + Log.e(TAG, "It's connected. Ignore this connection request"); return false; } - //防止连接出现133错误, 不能发现Services -// if (BleConnCallBack.getInstance().getmBluetoothGatt() != null ) { -// Log.w(TAG, "connectDevice: closeGatt"); -// BleConnCallBack.getInstance().releaseBle(); -// return false; -// } + if (SinovoBle.getInstance().isConnectting()){ + String nowtime = ComTool.getNowTime(); + if (getConnectTime()!=null && ComTool.calTimeDiff(getConnectTime(), nowtime) <20) { + Log.e(TAG, "It's connecting. Ignore this connection request"); + return false; + } + } - SinovoBle.getInstance().setConnectting(true); //标记 已经在开始进行连接 - BleConnCallBack.getInstance().setConnectingMAC(bluetoothDevice.getAddress()); //标记 当前准备连接的地址,以便后面断开进行重连 + setConnectTime(ComTool.getNowTime()); + SinovoBle.getInstance().setConnectting(true); + SinovoBle.getInstance().setConnectingMac(bluetoothDevice.getAddress()); + // Log.e(TAG, "设置正在进行连接,设置连接时间为:" + getConnectTime() + ",准备连接的mac:"+ bluetoothDevice.getAddress()); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - BleConnCallBack.getInstance().setmBluetoothGatt(bluetoothDevice.connectGatt(getContext(), false, BleConnCallBack.getInstance(), BluetoothDevice.TRANSPORT_LE)); - } else { - BleConnCallBack.getInstance().setmBluetoothGatt(bluetoothDevice.connectGatt(getContext(), false, BleConnCallBack.getInstance())); - } + Handler mHandler = new Handler(getContext().getMainLooper()); + mHandler.post(() -> { + if (BleConnCallBack.getInstance().getmBluetoothGatt() !=null) { + BleConnCallBack.getInstance().getmBluetoothGatt().close(); + } - Log.d(TAG, "connectGatt to:"+BleConnCallBack.getInstance().getConnectingMAC()); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + BleConnCallBack.getInstance().setmBluetoothGatt(bluetoothDevice.connectGatt(getContext(), + false, BleConnCallBack.getInstance(), BluetoothDevice.TRANSPORT_LE)); + } else { + BleConnCallBack.getInstance().setmBluetoothGatt(bluetoothDevice.connectGatt(getContext(), + false, BleConnCallBack.getInstance())); + } + }); + + Log.d(TAG, "connectGatt to:" + bluetoothDevice.getAddress()); return true; } @@ -988,4 +1009,51 @@ public void disconnBle(){ BleConnCallBack.getInstance().disConectBle(); } + //对外提供断开连接 close 释放资源 + public void releaseBle(){ + BleConnCallBack.getInstance().releaseBle(); + } + + public String getLockGWid() { + return lockGWid; + } + + public void setLockGWid(String lockGWid) { + this.lockGWid = lockGWid; + } + + public boolean isLinked() { + return isLinked; + } + + public void setLinked(boolean linked) { + isLinked = linked; + } + + public void setConnectting(boolean connectting) { + isConnectting = connectting; + } + + public boolean isConnectting() { + return isConnectting; + } + + public void setConnectTime(String connectTime) { + this.connectTime = connectTime; + } + + public String getConnectTime() { + return connectTime; + } + + public String getConnectingMac() { + return connectingMac; + } + + public void setConnectingMac(String connectingMac) { + this.connectingMac = connectingMac; + } + + public void autoConnectLock(ArrayList mylist) { + } } diff --git a/sinovoble/src/main/java/com/sinovotec/sinovoble/callback/BleConnCallBack.java b/sinovoble/src/main/java/com/sinovotec/sinovoble/callback/BleConnCallBack.java index 5e4fb5c..70818b5 100644 --- a/sinovoble/src/main/java/com/sinovotec/sinovoble/callback/BleConnCallBack.java +++ b/sinovoble/src/main/java/com/sinovotec/sinovoble/callback/BleConnCallBack.java @@ -27,10 +27,8 @@ public class BleConnCallBack extends BluetoothGattCallback { private static BleConnCallBack instance; //入口操作管理 - private static String TAG = "SinovoBle"; + private static final String TAG = "SinovoBle"; - private String connectingMAC; //记录当前正在连接的锁的mac地址 ,用于在连接断开之后进行重连判断; - private int reconnectCount = 0; //记录某一把锁的重连次数 private int exeCmdMaxCount = 0; //命令发送失败后重试的次数,3次都发送失败,则要断开连接进行重连 private BluetoothGatt mBluetoothGatt; private BluetoothGattService mBleGattService; @@ -44,14 +42,6 @@ public class BleConnCallBack extends BluetoothGattCallback { } } - /** - * 获取当前正在连接的锁的mac地址 - * @return s - */ - public String getConnectingMAC() { - return connectingMAC; - } - /** * 获取连接用的 BluetoothGatt * @return s @@ -68,32 +58,12 @@ public void setmBluetoothGatt(BluetoothGatt mBluetoothGatt) { this.mBluetoothGatt = mBluetoothGatt; } - private int getReconnectCount() { - return reconnectCount; - } - - private void setReconnectCount(int reconnectCount) { - this.reconnectCount = reconnectCount; - } - - - /** - * 设置当前正在连接的锁的mac地址 - * - * @param connectingMAC s - */ - public void setConnectingMAC(String connectingMAC) { - this.connectingMAC = connectingMAC; - } - - /** * 单例方式获取蓝牙通信入口 * * @return 返回BleConnCallBack */ public static BleConnCallBack getInstance() { - if (instance == null) { synchronized (BleConnCallBack.class) { if (instance == null) { @@ -103,31 +73,58 @@ public static BleConnCallBack getInstance() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { super.onConnectionStateChange(gatt, status, newState); - Log.d(TAG,"BleConnCallBack:GATT:"+gatt.getDevice().getAddress() + " status:"+status + " newstate:"+newState); + if (SinovoBle.getInstance().getAutoConnetHandler() != null) { + // Log.w(TAG,"取消 自动连接超时检测"); + SinovoBle.getInstance().getAutoConnetHandler().removeCallbacksAndMessages(null); + } + SinovoBle.getInstance().setConnectting(false); if(status == BluetoothGatt.GATT_SUCCESS) { if (newState == BluetoothProfile.STATE_CONNECTED) { - Log.i(TAG, "Connected to GATT server."); - afterConnected(); + Log.i(TAG, "Connected to GATT server. try discover Services"); + + if (!SinovoBle.getInstance().isLinked()){ + afterConnected(); + String locksno = ""; + for ( BleConnectLock bleConnectLock : SinovoBle.getInstance().getToConnectLockList()){ + if (bleConnectLock.getLockMac().equals(gatt.getDevice().getAddress())){ + locksno = bleConnectLock.getLockSno(); + break; + } + } + SinovoBle.getInstance().getToConnectLockList().clear(); + SinovoBle.getInstance().getToConnectLockList().add(new BleConnectLock(gatt.getDevice().getAddress(),locksno)); + } } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { Log.i(TAG, "Disconnected from GATT server."); - if (!SinovoBle.getInstance().isBindMode()) { - SinovoBle.getInstance().getmConnCallBack().onDisconnect(); - } afterDisconnected(gatt.getDevice().getAddress()); } else if (newState == BluetoothProfile.STATE_CONNECTING) { + SinovoBle.getInstance().setLinked(false); Log.i(TAG, "connecting from GATT server."); } else { + SinovoBle.getInstance().setLinked(false); Log.i(TAG, "Disconnecting from GATT server."); } }else { - Log.i(TAG, "连接状态出错,关闭gatt资源,重连尝试, 正在连接的:"+ getConnectingMAC()+", 连接错误的:"+ gatt.getDevice().getAddress()); - if (!gatt.getDevice().getAddress().equals(getConnectingMAC())){ - Log.w(TAG, "连接丢失的mac地址是:"+gatt.getDevice().getAddress() + ",当前正在连接的mac地址是:"+getConnectingMAC() + ",不一致,不处理"); - }else{ - Log.i(TAG, "连接状态出错,关闭gatt资源,断开连接"); - BleConnCallBack.getInstance().disConectBle(); + if (!SinovoBle.getInstance().getToConnectLockList().isEmpty()){ + if (SinovoBle.getInstance().getConnectingMac().equals(gatt.getDevice().getAddress())){ + Log.i(TAG, "连接状态出错,关闭gatt资源,断开连接"); + afterDisconnected(gatt.getDevice().getAddress()); + }else { + Log.w(TAG, "连接丢失的mac地址是:"+gatt.getDevice().getAddress() + ",当前正在连接的mac地址是:"+ + SinovoBle.getInstance().getConnectingMac() + ",不一致,不处理"); + } + }else { + if (SinovoBle.getInstance().isBindMode()){ + if (SinovoBle.getInstance().getScanLockList().size() >0) { + if (gatt.getDevice().getAddress().equals(SinovoBle.getInstance().getConnectingMac())){ + Log.w(TAG, "绑定模式下。连接丢失后重连。mac:"+ SinovoBle.getInstance().getConnectingMac()); + afterDisconnected(gatt.getDevice().getAddress()); + } + } + } } + SinovoBle.getInstance().setLinked(false); } } @@ -142,7 +139,7 @@ public void onServicesDiscovered(BluetoothGatt gatt, int status) { Log.e(TAG, " Discovered Services Failed, errcode:" + status); //错误码中返回 129 ,需要关闭蓝牙,在重新打开 if (status == 129) { - Log.e(TAG, "----/错误码中返回 129 ,重新初始化蓝牙"); + Log.e(TAG, "Error code:129 ,it's need to init bluetooth again"); SinovoBle.getInstance().init(SinovoBle.getInstance().getContext(), SinovoBle.getInstance().getmBleScanCallBack(), SinovoBle.getInstance().getmConnCallBack()); } } @@ -179,31 +176,27 @@ public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic //数据返回的回调(此处接收BLE设备返回数据) @Override + @SuppressWarnings("unchecked") public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { super.onCharacteristicChanged(gatt, characteristic); byte[] recvData = characteristic.getValue(); String recvStr = byte2hex(recvData); -// Log.d(TAG, "回调 onCharacteristicChanged 表示已经收到锁端("+gatt.getDevice().getAddress()+")发来的数据:"+recvStr); - if (sendDataHandler != null && !recvStr.substring(2,4).equals("27")){ -// Log.d(TAG, "已经收到锁端回复,且不是27的功能码,取消掉 2秒定时检测 是否有 恢复的任务"); + if (sendDataHandler != null && !recvStr.startsWith("27", 2)){ sendDataHandler.removeCallbacksAndMessages(null); //取消定时任务 } - LinkedHashMap resultmap = BleData.getInstance().getDataFromBle(recvStr); - Log.d(TAG, "数据处理后的结果:" + JSON.toJSONString(resultmap)); + LinkedHashMap resultmap = BleData.getInstance().getDataFromBle(recvStr, SinovoBle.getInstance().getLockMAC().replace(":","")); + // Log.d(TAG, ":" + JSON.toJSONString(resultmap)); - JSONObject jsonObject =new JSONObject(resultmap); - afterReceiveData(jsonObject); + if(resultmap !=null) { + afterReceiveData(new JSONObject(resultmap)); + } } //写操作的回调 @Override public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { super.onCharacteristicWrite(gatt, characteristic, status); - -// if (status != BluetoothGatt.GATT_SUCCESS) { -// Log.d(TAG, "写入失败 ,onCharacteristicWrite,status=" + status); -// } } /** @@ -218,7 +211,7 @@ public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descri String macaddress = gatt.getDevice().getAddress(); if (status == BluetoothGatt.GATT_SUCCESS) { - Log.d(TAG, "onDescriptorWrite 回调成功, 真正连接成功,可以发送命令了"); + Log.d(TAG, "onDescriptorWrite successful, it can send commands"); SinovoBle.getInstance().setLockMAC(macaddress); BleData.getInstance().getCommandList().clear(); @@ -238,9 +231,8 @@ public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descri Log.d(TAG, "非绑定模式下,进行连接,直接发送相关命令,mac:"+ bleMac); boolean isExist = false; - for (int i = 0; i< SinovoBle.getInstance().getAutoConnectList().size(); i++){ - BleConnectLock tmpConnectLock = SinovoBle.getInstance().getAutoConnectList().get(i); - Log.d(TAG, "遍历出AutoConnectList 中的锁的,mac:"+ bleMac); + for (BleConnectLock tmpConnectLock : SinovoBle.getInstance().getToConnectLockList()){ + Log.d(TAG, "遍历出AutoConnectList 中的锁的,mac:"+ tmpConnectLock.getLockMac()); if (tmpConnectLock.getLockMac().equals(gatt.getDevice().getAddress())){ bleSno = tmpConnectLock.getLockSno(); isExist = true; @@ -255,17 +247,16 @@ public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descri SinovoBle.getInstance().setLockSNO(bleSno); //清空自动连接的列表,或许断开只能重连它,不能连接其他设备,除非手动切换 - SinovoBle.getInstance().getAutoConnectList().clear(); + SinovoBle.getInstance().getToConnectLockList().clear(); BleConnectLock myAutoConnectLock = new BleConnectLock(bleMac, bleSno); - SinovoBle.getInstance().getAutoConnectList().add(myAutoConnectLock); + SinovoBle.getInstance().getToConnectLockList().add(myAutoConnectLock); //通知回调,连接成功 final String bleSNO = bleSno; final String bleMAC = bleMac; - new Handler(Looper.getMainLooper()).postDelayed(new Runnable() { - @Override - public void run() { - SinovoBle.getInstance().getmConnCallBack().onConnectSuccess(bleMAC); + new Handler(Looper.getMainLooper()).postDelayed(() -> { + SinovoBle.getInstance().getmConnCallBack().onConnectSuccess(bleMAC); + if (bleSNO.length() == 6) { BleData.getInstance().exeCommand("1f", bleSNO, false); //查询基准时间 } }, 800); @@ -285,23 +276,19 @@ public void run() { * 连接成功的处理, 需要去发现服务 */ void afterConnected(){ - if (SinovoBle.getInstance().isConnected()){ - Log.d(TAG, "已经连接成功了,又收到了 连接成功的回调,不处理"); + SinovoBle.getInstance().setLinked(true); + if (SinovoBle.getInstance().isBleConnected()){ + Log.d(TAG, "it's connected,Ignore repeated notifications of successful connection"); return; } BleData.getInstance().setExeCmding(false); - //非绑定模式下,直接更新状态 - if (!SinovoBle.getInstance().isBindMode()){ - SinovoBle.getInstance().setConnectting(false); - } - //连接成功之后,需要去发现服务 if (getmBluetoothGatt() != null){ getmBluetoothGatt().discoverServices(); }else { - Log.w(TAG, "异常了,连接成功,但mBluetoothGatt 为null,重新初始化ble"); + Log.e(TAG, "error! it's connected,but BluetoothGatt is null, need to init ble again"); SinovoBle.getInstance().disconnBle(); } } @@ -310,51 +297,38 @@ void afterConnected(){ * 连接断开的处理 */ void afterDisconnected(String disconn_mac){ - Log.e(TAG, "连接断开,当前断开的设备的mac是:"+ disconn_mac); + Log.e(TAG, "It's disconneced, lock's mac:"+ disconn_mac); - SinovoBle.getInstance().setConnectting(false); + SinovoBle.getInstance().setLinked(false); SinovoBle.getInstance().setConnected(false); + SinovoBle.getInstance().setConnectting(false); BleData.getInstance().setExeCmding(false); + sendDataHandler.removeCallbacksAndMessages(null); //取消发送数据定时检测的任务 if (!SinovoBle.getInstance().getBluetoothAdapter().isEnabled()){ - Log.e(TAG, "蓝牙已经关闭,无需重连处理"); + Log.e(TAG, "Bluetooth is off, ignore"); return; } - releaseBle(); //20201023 - if (!SinovoBle.getInstance().getScanLockList().isEmpty()) { - String scanDeviceMac0 = SinovoBle.getInstance().getScanLockList().get(0).GetDevice().getAddress(); - if (disconn_mac.equals(scanDeviceMac0)) { - Log.e(TAG, "丢失的连接是扫描列表中的第一个设备,需要进行重连:"+ disconn_mac); - setReconnectCount(getReconnectCount() + 1); - - if (getReconnectCount() >2 && !SinovoBle.getInstance().getScanLockList().isEmpty()){ - Log.e(TAG, "重连超过2次,不在重连它:"+ disconn_mac); - SinovoBle.getInstance().getBondBleMacList().add(SinovoBle.getInstance().getLockMAC()); - SinovoBle.getInstance().getScanLockList().remove(0); //删除对首的设备 - - //非绑定模式下,如果连接不成功,则要告知用户 - if (!SinovoBle.getInstance().isBindMode() && SinovoBle.getInstance().getScanLockList().isEmpty()){ - SinovoBle.getInstance().getmConnCallBack().onDisconnect(); - } - } - } - } - if (SinovoBle.getInstance().isBindMode()){ - Log.e(TAG, "绑定模式下,丢失的连接,延迟200ms再去连接"); + Log.e(TAG, "绑定模式下,丢失的连接,延迟300ms再去连接"); if (SinovoBle.getInstance().getScanLockList().size() >0) { Log.w(TAG, "绑定模式下。连接丢失后重连。mac:"+ SinovoBle.getInstance().getScanLockList().get(0).GetDevice().getAddress()); - SinovoBle.getInstance().connectLock(SinovoBle.getInstance().getScanLockList().get(0)); + + //延迟 300ms 再去连接 + Handler delayToConnect = new Handler(Looper.getMainLooper()); + delayToConnect.postDelayed(() -> SinovoBle.getInstance().connectBle(SinovoBle.getInstance().getScanLockList().get(0).GetDevice()), 300); } }else { Log.e(TAG, "非绑定模式下,丢失的连接是:"+ disconn_mac); - if (!disconn_mac.equals(getConnectingMAC())){ - Log.w(TAG, "连接丢失的mac地址是:"+disconn_mac + ",当前正在连接的mac地址是:"+getConnectingMAC() + ",不一致,不处理"); - return; + if (!SinovoBle.getInstance().getToConnectLockList().isEmpty()){ + if (SinovoBle.getInstance().getConnectingMac().equals(disconn_mac)){ + SinovoBle.getInstance().getmConnCallBack().onDisconnect(disconn_mac); + }else { + Log.w(TAG, "连接丢失的mac地址是:"+disconn_mac + ",当前正在连接的mac地址是:"+SinovoBle.getInstance().getConnectingMac() + ",不一致,不处理"); + } } - SinovoBle.getInstance().getmConnCallBack().onDisconnect(); } } @@ -364,7 +338,7 @@ void afterDisconnected(String disconn_mac){ */ void afterDiscoverService(BluetoothGatt gatt){ if (getmBluetoothGatt() == null){ - Log.e(TAG, "服务发现失败,mBluetoothGatt 为空,断开重连"); + Log.e(TAG, "Failed to discover services,mBluetoothGatt is null, try to reconnect"); disConectBle(); return; } @@ -378,7 +352,7 @@ void afterDiscoverService(BluetoothGatt gatt){ if (serUUID.equals(BleConstant.SERVICE_UUID_FM67)) { sUUID = BleConstant.SERVICE_UUID_FM67; characteristUUID = BleConstant.CHARACTERISTIC_UUID_FM67; - Log.d(TAG, "根据过滤出来的服务UUID,检测到当前连接的是FM67"); +// Log.d(TAG, "根据过滤出来的服务UUID,检测到当前连接的是FM67"); break; } } @@ -387,55 +361,52 @@ void afterDiscoverService(BluetoothGatt gatt){ SinovoBle.getInstance().setBlecharacteristUUID(characteristUUID); //延迟500ms 再去设置 读写 描述符 - new Handler(Looper.getMainLooper()).postDelayed(new Runnable() { - @Override - public void run() { - Log.d(TAG, "延迟500ms再去设置 读写描述符"); - if (mBluetoothGatt == null){ - Log.e(TAG, "mBluetoothGatt is null ,cann't get services"); - return; - } + new Handler(Looper.getMainLooper()).postDelayed(() -> { + Log.d(TAG, "Delay setting BleGattCharacteristic for 500 milliseconds"); + if (mBluetoothGatt == null){ + Log.e(TAG, "mBluetoothGatt is null ,cann't get services"); + return; + } - if (!SinovoBle.getInstance().getBluetoothAdapter().isEnabled()){ - Log.e(TAG, "Bluetooth not enabled"); - return; - } + if (!SinovoBle.getInstance().getBluetoothAdapter().isEnabled()){ + Log.e(TAG, "Bluetooth not enabled"); + return; + } - mBleGattService = mBluetoothGatt.getService(UUID.fromString(SinovoBle.getInstance().getBleServiceUUID())); - if (mBleGattService == null){ - Log.e(TAG, "failed to get services"); - disConectBle(); - return; - } + mBleGattService = mBluetoothGatt.getService(UUID.fromString(SinovoBle.getInstance().getBleServiceUUID())); + if (mBleGattService == null){ + Log.e(TAG, "failed to get services"); + disConectBle(); + return; + } - mBleGattCharacteristic = mBleGattService.getCharacteristic(UUID.fromString(SinovoBle.getInstance().getBlecharacteristUUID())); - if (mBleGattCharacteristic == null){ - Log.e(TAG, "Characteristic is null"); - disConectBle(); - return; - } + mBleGattCharacteristic = mBleGattService.getCharacteristic(UUID.fromString(SinovoBle.getInstance().getBlecharacteristUUID())); + if (mBleGattCharacteristic == null){ + Log.e(TAG, "Characteristic is null"); + disConectBle(); + return; + } - //设置特征能够进行通知,设置写 描述符 - mBluetoothGatt.setCharacteristicNotification(mBleGattCharacteristic, true); - BluetoothGattDescriptor write_descriptor = mBleGattCharacteristic.getDescriptor(UUID.fromString(BleConstant.CLIENT_CHARACTERISTIC_CONFIG)); + //设置特征能够进行通知,设置写 描述符 + mBluetoothGatt.setCharacteristicNotification(mBleGattCharacteristic, true); + BluetoothGattDescriptor write_descriptor = mBleGattCharacteristic.getDescriptor(UUID.fromString(BleConstant.CLIENT_CHARACTERISTIC_CONFIG)); - if (write_descriptor == null) { - Log.e(TAG, "write_descriptor is null"); - disConectBle(); - return; - } - write_descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); - mBluetoothGatt.writeDescriptor(write_descriptor); + if (write_descriptor == null) { + Log.e(TAG, "write_descriptor is null"); + disConectBle(); + return; + } + write_descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); + mBluetoothGatt.writeDescriptor(write_descriptor); - //设置读描述符 - BluetoothGattDescriptor read_descriptor = mBleGattCharacteristic.getDescriptor(UUID.fromString(BleConstant.CLIENT_CHARACTERISTIC_CONFIG)); - if (read_descriptor == null){ - Log.e(TAG, "read_descriptor is null"); - disConectBle(); - return; - } - mBluetoothGatt.readDescriptor(read_descriptor); + //设置读描述符 + BluetoothGattDescriptor read_descriptor = mBleGattCharacteristic.getDescriptor(UUID.fromString(BleConstant.CLIENT_CHARACTERISTIC_CONFIG)); + if (read_descriptor == null){ + Log.e(TAG, "read_descriptor is null"); + disConectBle(); + return; } + mBluetoothGatt.readDescriptor(read_descriptor); }, 500); } @@ -455,7 +426,6 @@ void afterReceiveData(JSONObject jsonObject){ }else { disConectBle(); SinovoBle.getInstance().setConnected(false); - SinovoBle.getInstance().setConnectting(false); //二维码是正确的,但用户没有去按set进行确认,导致超时 if (Objects.equals(errCode, "04")){ @@ -544,6 +514,10 @@ void afterReceiveData(JSONObject jsonObject){ SinovoBle.getInstance().getmConnCallBack().onAuthorOther(JSON.toJSONString(jsonObject)); } + //锁冻结的推送 + if (Objects.equals(funCode, "2b")){ + SinovoBle.getInstance().getmConnCallBack().onLockFrozen(JSON.toJSONString(jsonObject)); + } } public void writeCharacteristic(final byte[] value, final UUID serivceUUID, final UUID characterUUID){ @@ -568,27 +542,19 @@ public void writeCharacteristic(final byte[] value, final UUID serivceUUID, fina Log.w(TAG, "Cmd:"+ BleData.getInstance().getCommandList().getFirst()+" send ok"); //延迟1.5秒后再检测 是否已经收到锁端的恢复 - sendDataHandler.postDelayed(new Runnable() { - @Override - public void run() { - BleData.getInstance().checkDataReceive(); - } - }, 2000); - Log.d(TAG, "指令:"+ BleData.getInstance().getCommandList().getFirst()+" 发送出去了,1.5秒后检测是否收到回复"); + sendDataHandler.postDelayed(() -> BleData.getInstance().checkDataReceive(), 2000); + //Log.d(TAG, "指令:"+ BleData.getInstance().getCommandList().getFirst()+" 发送出去了,2秒后检测是否收到回复"); }else { exeCmdMaxCount ++; Log.e(TAG, "Cmd:"+ BleData.getInstance().getCommandList().getFirst()+" send failed, exeCmdMaxCount:"+exeCmdMaxCount); if (exeCmdMaxCount >2){ - Log.d(TAG,"连续3次都发送失败,需要断开连接 进行重连"); + Log.d(TAG,"Failed to send the command 3 times in a row, try to reconnect"); disConectBle(); }else { - new Handler(Looper.getMainLooper()).postDelayed(new Runnable() { - @Override - public void run() { - Log.d(TAG,"延迟200ms再次发送"); - BleConnCallBack.getInstance().writeCharacteristic(value, serivceUUID, serivceUUID); - } + new Handler(Looper.getMainLooper()).postDelayed(() -> { + Log.d(TAG,"Delay sending command for 200 milliseconds"); + BleConnCallBack.getInstance().writeCharacteristic(value, serivceUUID, serivceUUID); }, 200); } } @@ -599,9 +565,10 @@ public void run() { // 断开连接 public void disConectBle() { - Log.d(TAG, "关闭蓝牙连接 disConectBle() 清空缓存"); + Log.d(TAG, "diconnect blutooth and clear cache"); SinovoBle.getInstance().setConnectting(false); + SinovoBle.getInstance().setLinked(false); SinovoBle.getInstance().setConnected(false); BleData.getInstance().getCommandList().clear(); @@ -610,8 +577,8 @@ public void disConectBle() { //非绑定模式下,连接断开才通知回调 if (!SinovoBle.getInstance().isBindMode()) { - Log.w(TAG,"非绑定模式,连接断开,通知上层 回调"); - SinovoBle.getInstance().getmConnCallBack().onDisconnect(); + //Log.w(TAG,"非绑定模式,连接断开,通知上层 回调"); + SinovoBle.getInstance().getmConnCallBack().onDisconnect(SinovoBle.getInstance().getLockMAC()); } } @@ -619,11 +586,15 @@ public void disConectBle() { * 释放ble资源 */ public void releaseBle(){ - if (mBluetoothGatt!=null) { - Objects.requireNonNull(mBluetoothGatt).disconnect(); - Objects.requireNonNull(mBluetoothGatt).close(); - mBluetoothGatt = null; - } + Handler handler = new Handler(Looper.getMainLooper()); + handler.post(() -> { + if (mBluetoothGatt!=null) { + refreshDeviceCache(mBluetoothGatt); + Objects.requireNonNull(mBluetoothGatt).disconnect(); + Objects.requireNonNull(mBluetoothGatt).close(); + mBluetoothGatt = null; + } + }); } diff --git a/sinovoble/src/main/java/com/sinovotec/sinovoble/callback/BleScanCallBack.java b/sinovoble/src/main/java/com/sinovotec/sinovoble/callback/BleScanCallBack.java index 9ecfd20..ca709f7 100644 --- a/sinovoble/src/main/java/com/sinovotec/sinovoble/callback/BleScanCallBack.java +++ b/sinovoble/src/main/java/com/sinovotec/sinovoble/callback/BleScanCallBack.java @@ -20,7 +20,7 @@ public class BleScanCallBack extends ScanCallback { private static BleScanCallBack instance; //入口操作管理 - private static String TAG = "SinovoBle"; + private static final String TAG = "SinovoBle"; private boolean isScanning = false; //是否正在扫描 IScanCallBack iScanCallBack; //扫描结果回调 @@ -39,12 +39,10 @@ public void setScanning(boolean scanning) { isScanning = scanning; } - /** * 单例方式获取蓝牙通信入口 */ public static BleScanCallBack getInstance(IScanCallBack scanCallBack) { - if (instance != null){ return instance; } @@ -67,20 +65,28 @@ public void onScanResult(int callbackType, ScanResult result) { //尝试进行自动连接 if (SinovoBle.getInstance().isBindMode()) { -// Log.w(TAG, "绑定模式下,自动进行连接:"+bleScanDevice.GetDevice().getAddress()); - SinovoBle.getInstance().connectLock(bleScanDevice); + Log.w(TAG, "绑定模式下,自动进行连接:"+bleScanDevice.GetDevice().getAddress()); + Log.w(TAG, "开始连接之前,先停止扫描"); + SinovoBle.getInstance().setScanAgain(false); + BleScanCallBack.getInstance(iScanCallBack).stopScan(); + SinovoBle.getInstance().connectBle(bleScanDevice.GetDevice()); }else { - for (int j=0; j 14){ - String advtype = advData.substring(0, 2); - if (advtype.equals("01")) { //01,第二批出的锁,广播的是 锁id - String adLockid = advData.substring(2, 14); - if (!adLockid.equals(SinovoBle.getInstance().getLockID())) { - deviceIn = false; - Log.w(TAG, "Adv_data's lockID:" + adLockid + " is different from the lockID(" + SinovoBle.getInstance().getLockID() + ") entered by user,ignore"); - } - }else if (advtype.equals("02")){ //兼容第二批, 02 表示是广播的日志 - deviceIn = true; + if (advData.length() >= 12){ + String adLockid = advData.substring(0, 12); + if (adLockid.equals(SinovoBle.getInstance().getLockID())) { + Log.w(TAG, "Adv_data's lockID:" + adLockid + " is matches the lockID(" + SinovoBle.getInstance().getLockID() + ") entered by user,connect and stop scan"); + SinovoBle.getInstance().setScanAgain(false); + BleScanCallBack.getInstance(iScanCallBack).stopScan(); }else { - String adLockid = advData.substring(0, 12); - if (!adLockid.equals(SinovoBle.getInstance().getLockID())) { + String advtype = advData.substring(0, 2); + + if (advtype.equals("02")){ //兼容第二批, 02 表示是广播的日志 + Log.w(TAG, "兼容第二批就锁,广播包为02开头,运行加入" + advData ); + }else if (advtype.equals("01")) { + if (advData.length() >= 14){ + adLockid = advData.substring(2, 14); + if (adLockid.equals(SinovoBle.getInstance().getLockID())) { + Log.w(TAG, "Adv_data's lockID:" + adLockid + " is matches the lockID(" + SinovoBle.getInstance().getLockID() + ") entered by user,connect and stop scan"); + SinovoBle.getInstance().setScanAgain(false); + BleScanCallBack.getInstance(iScanCallBack).stopScan(); + }else { + deviceIn = false; + Log.w(TAG, "Adv_data's lockID:" + adLockid + " is different from the lockID(" + SinovoBle.getInstance().getLockID() + ") entered by user,ignore"); + } + }else { + deviceIn = false; + Log.w(TAG, "Adv_data's lockID:" + adLockid + " is different from the lockID(" + SinovoBle.getInstance().getLockID() + ") entered by user,ignore"); + } + }else { deviceIn = false; Log.w(TAG, "Adv_data's lockID:" + adLockid + " is different from the lockID(" + SinovoBle.getInstance().getLockID() + ") entered by user,ignore"); } } + }else { + Log.i(TAG, "锁" +scanLockMac +" 存在广播包,但长度小于14,不合法,不连接他"); + deviceIn = false; } } }else { //非绑定模式下,对比mac地址即可 deviceIn = false; //默认不符合加入 - for (int i = 0; i< SinovoBle.getInstance().getAutoConnectList().size(); i++){ - BleConnectLock myConnectLock = SinovoBle.getInstance().getAutoConnectList().get(i); + for (int i = 0; i< SinovoBle.getInstance().getToConnectLockList().size(); i++){ + BleConnectLock myConnectLock = SinovoBle.getInstance().getToConnectLockList().get(i); if (myConnectLock.getLockMac().equals(scanLockMac)){ Log.d(TAG,"该设备是需要自动连接的设备:"+ scanLockMac); deviceIn = true; @@ -201,7 +224,6 @@ BleScanDevice analyzeScanResult(ScanResult result) { //停止蓝牙扫描 //参数 ,是否立即停止(自动扫描的话,停止之后会判断 是否还需要重新扫描) public void stopScan() { -// Log.d(TAG, "stopscanBle 函数,停止扫描 stopScan"); setScanning(false); SinovoBle.getInstance().removeScanHandlerMsg(); @@ -217,12 +239,9 @@ public void stopScan() { SinovoBle.getInstance().getBluetoothAdapter().getBluetoothLeScanner().stopScan(instance); if (SinovoBle.getInstance().isScanAgain()) { - SinovoBle.getInstance().getScanBleHandler().postDelayed(new Runnable() { - @Override - public void run() { - Log.d(TAG, "start to scan again after 1s"); - SinovoBle.getInstance().bleScan(iScanCallBack); - } + SinovoBle.getInstance().getScanBleHandler().postDelayed(() -> { + Log.d(TAG, "start to scan again after 1s"); + SinovoBle.getInstance().bleScan(iScanCallBack); }, 1000); } } diff --git a/sinovoble/src/main/java/com/sinovotec/sinovoble/callback/IConnectCallback.java b/sinovoble/src/main/java/com/sinovotec/sinovoble/callback/IConnectCallback.java index cae2429..7a92fd7 100644 --- a/sinovoble/src/main/java/com/sinovotec/sinovoble/callback/IConnectCallback.java +++ b/sinovoble/src/main/java/com/sinovotec/sinovoble/callback/IConnectCallback.java @@ -17,7 +17,7 @@ public interface IConnectCallback { void onBluetoothOn(); //连接断开 - void onDisconnect(); + void onDisconnect(String macaddress); //添加锁 void onAddLock(String result); @@ -61,6 +61,9 @@ public interface IConnectCallback { //授权新用户的返回结果 void onAuthorOther(String result); + //锁锁死的返回 + void onLockFrozen(String result); + //发送数据没有回应 void onReceiveDataFailed(); diff --git a/sinovoble/src/main/java/com/sinovotec/sinovoble/common/BleData.java b/sinovoble/src/main/java/com/sinovotec/sinovoble/common/BleData.java index 4b64149..5267d01 100644 --- a/sinovoble/src/main/java/com/sinovotec/sinovoble/common/BleData.java +++ b/sinovoble/src/main/java/com/sinovotec/sinovoble/common/BleData.java @@ -10,15 +10,17 @@ import com.sinovotec.sinovoble.SinovoBle; import com.sinovotec.sinovoble.callback.BleConnCallBack; +//import static com.sinovotec.sinovoble.common.Aes128.decryptData; +//import static com.sinovotec.sinovoble.common.Aes128.encryptData; import static com.sinovotec.sinovoble.common.ComTool.asciiToString; import static com.sinovotec.sinovoble.common.ComTool.toByte; public class BleData { - private LinkedList commandList = new LinkedList<>(); //所有需要执行的命令 都放入到list中排队 ,等待执行 - private static BleData instance; //入口操作管理 + private final LinkedList commandList = new LinkedList<>(); //所有需要执行的命令 都放入到list中排队 ,等待执行 + private static BleData instance; //入口操作管理 private boolean isExeCmding = false; //是否正在执行命令 - private static String TAG = "SinovoBle"; + private static final String TAG = "SinovoBle"; public static BleData getInstance() { if (instance == null) { @@ -60,14 +62,13 @@ public void setExeCmding(boolean exeCmding) { * @param data 待计算的命令 * @return 计算出来的checksum值, 需要注意,计算出来的结果 需要取最后两位数字 */ - private static String checkSum(String data){ + public String checkSum(String data){ int checksum = 0; //计算校验和 String returnStr = ""; for (int i=0; i< data.length(); ){ if (i+2 > data.length()){ -// Log.d(TAG, "要进行计算的子字符串超过了 数组的大小,异常了, i+2:"+(i+2) + "字符串大小:"+data.length()); return ""; //计算错误, } String sub_str = data.substring(i, i + 2); @@ -117,22 +118,14 @@ private boolean checkSumIsOK(String data){ * 返回 errCode 为 -5 ,解密数据异常 * 返回 errCode 为 -6 ,有效数据长度超过16个字节 */ - public LinkedHashMap getDataFromBle(String data){ - Log.d(TAG, "getDataFromBle 接收的数据:"+data); + public LinkedHashMap getDataFromBle(String data, String mac){ + Log.d(TAG, "receive data from ble:"+data + ",lock's address:" + mac); LinkedHashMap map = new LinkedHashMap<>(); map.put("getData", "0"); - //非20字节的数据不处理 - if (data.length() !=40){ -// Log.d(TAG, "数据长度不为40,不是20字节,不处理"); - map.put("errCode", "-1"); - return map; - } - //1、先检验checksum 是否ok if (!checkSumIsOK(data)){ -// Log.d(TAG, "checksum 校验失败,直接退出"); map.put("errCode", "-2"); return map; } @@ -140,14 +133,12 @@ public LinkedHashMap getDataFromBle(String data){ //2、检测是否为fe开头的数据,非fe、fc开头则先不处理 String headCode = data.substring(0,2); if (!(headCode.equals("fe") || headCode.equals("fc"))){ -// Log.d(TAG, "ble发送过来数据包头部不是fe、fc,非法数据不处理");/ map.put("errCode", "-3"); return map; } String funcodebt = data.substring(2,4); if (funcodebt.equals("27")){ -// Log.d(TAG, "锁端发送功能码为27的推送数据,暂时无需处理此数据"); map.put("errCode", "-4"); return map; } @@ -164,18 +155,24 @@ public LinkedHashMap getDataFromBle(String data){ setExeCmding(false); Log.d(TAG, "正在同步,需要同步完成才能执行下一个命令"); }else { - if (funcodebt.equals(funcodelist) || (funcodebt.equals("14") && funcodelist.equals("13")) || funcodebt.equals("18") && funcodelist.equals("17")) { - Log.d(TAG, "确认过眼神,就是你了,现在可删除"); + if (funcodebt.equals(funcodelist) || (funcodebt.equals("14") && funcodelist.equals("13")) + || funcodebt.equals("18") && funcodelist.equals("17")) { + // Log.d(TAG, "确认过眼神,就是你了,现在可删除"); getCommandList().removeFirst(); setExeCmding(false); - sendDataToBle(); + + if (SinovoBle.getInstance().isBleConnected()) { + // Log.d(TAG, "蓝牙连接,通过蓝牙发送数据"); + sendDataToBle(); + } }else { Log.e(TAG,"命令对不上:锁端发过来的:"+funcodebt + ",本地命令队列中的:"+ funcodelist + ",可以处理此数据,但不自动执行下一条命令,也不删除队列的命令"); } } - } + Log.d(TAG, "准备进行解密 接收到的密文:" + data + ",解密的mac:" + mac.toUpperCase()); + //3、获取出来功能码 , 并进行解密处理 String funCode = data.substring(2,4); String dataEncrypt = data.substring(6,data.length()-2); @@ -183,13 +180,13 @@ public LinkedHashMap getDataFromBle(String data){ //非绑定功能的数据,需要解密 if (!funCode.equals("00")){ - // dataDecode = Aes128.decryptData(dataEncrypt, SinovoBle.getInstance().getLockMAC()); - String mac = SinovoBle.getInstance().getLockMAC().replace(":",""); - dataDecode = SinovoBle.getInstance().getMyJniLib().decryptAes(dataEncrypt, mac); + dataDecode = SinovoBle.getInstance().getMyJniLib().decryptAes(dataEncrypt, mac.toUpperCase()); }else { dataDecode = dataEncrypt; } + Log.d(TAG, "解密后的内容:" +dataDecode); + //异常情况,解密为空 if (dataDecode.isEmpty()){ map.put("errCode", "-5"); @@ -299,6 +296,9 @@ public LinkedHashMap getDataFromBle(String data){ //授权新用户 if (funCode.equals("26")) {return authorOther(datavalue);} + + //查询锁是否被冻结,锁死了(连续5次开门失败) + if (funCode.equals("2b")) {return lockIsFrozen(datavalue);} return map; } @@ -316,17 +316,25 @@ public void exeCommand(String funcode, String data, boolean toTop){ int byteLen = data.length() /2; byteLen += data.length() %2; + if (byteLen <3){ + Log.d(TAG, "数据包的内容异常,至少有3个字节才可以"); + return; + } + //如果data 不够16字节,则在后面补ff for (int i=32;i> data.length(); i--) { data_send.append("f"); } - Log.d(TAG, "需要发送的数据,在补f之后:"+data_send + ",长度:"+data_send.length()); + Log.d(TAG, "exeCommand 需要发送的数据,在补f之后:"+data_send + ",长度:"+data_send.length()); //加密处理 - if (!funcode.equals("00")){ - String mac = SinovoBle.getInstance().getLockMAC().replace(":",""); - data_send = new StringBuilder(SinovoBle.getInstance().getMyJniLib().encryptAes(data_send.toString(), mac)); - //data_send = encryptData(data_send, SinovoBle.getInstance().getLockMAC()); + if (!funcode.equals("00") && SinovoBle.getInstance().getLockMAC() !=null){ + String lockmac = SinovoBle.getInstance().getLockMAC().replace(":",""); + Log.d(TAG, "准备加密的mac:"+lockmac); + data_send = new StringBuilder(SinovoBle.getInstance().getMyJniLib().encryptAes(data_send.toString(), lockmac)); +// Log.d(TAG, "加密的结果so:"+data_send); + // data_send2 = new StringBuilder(encryptData(data_send.toString(), lockmac)); +// Log.d(TAG, "加密的结果2:"+encryptData(data_send.toString(), lockmac.toLowerCase())); } Log.d(TAG, "需要发送的数据,加密后:"+data_send); @@ -338,10 +346,6 @@ public void exeCommand(String funcode, String data, boolean toTop){ data_result = data_result + Integer.toHexString(byteLen) + data_send; } -// data_result = data_result + data_result+ data_result+ data_result+ data_result+data_result + data_result+ data_result+ data_result+ data_result +data_result + data_result+ data_result+ data_result; -// data_result = "fe1203453d3534921c6acd0461c06b8685fe1203453d3534921c6acd0461c06b0ebf8685fe1203453d3534921c6acd0461c06b0ebf8685fe1203453d3534921c6acd0461c06b0ebf8685fe1203453d3534921c6acd0461c06b0ebf8685fe1203453d3534921c6acd0461c06b0ebf8685fe1203453d3534921c6acd04634532"; -// Log.d(TAG,"加大内容试试:" + data_result); - data_result = data_result +checkSum(data_result); //先判断 此命令是否已经存在队列中,如果已经存在,则不再加入 @@ -362,9 +366,13 @@ public void exeCommand(String funcode, String data, boolean toTop){ //如果当前没有正在执行命令 if (!isExeCmding()){ - if (SinovoBle.getInstance().isBindMode() || (!SinovoBle.getInstance().isBindMode() && SinovoBle.getInstance().isConnected())){ - Log.d(TAG, "连接成功,且状态为非正在发送命令的状态,可以发送命令"); - sendDataToBle(); + if (SinovoBle.getInstance().getConnType() == 0 || SinovoBle.getInstance().isBleConnected() || SinovoBle.getInstance().isBindMode()) { + if (SinovoBle.getInstance().isBindMode() || (!SinovoBle.getInstance().isBindMode() && SinovoBle.getInstance().isBleConnected())) { + Log.d(TAG, "连接成功,且状态为非正在发送命令的状态,可以发送命令"); + sendDataToBle(); + } + }else { + Log.d(TAG, "采用wifi连接,通过mqtt 发送命令"); } }else { Log.e(TAG, "当前正在执行命令。忽略,不执行"); @@ -387,22 +395,14 @@ private void sendDataToBle(){ return; } - Log.d(TAG,"bledata 发送指令:"+getCommandList().getFirst()); - + Log.d(TAG,"bledata 发送指令:"+getCommandList().getFirst() + ", 发送方式:"+ SinovoBle.getInstance().getConnType()); setExeCmding(true); final byte[] write_msg_byte = toByte(getCommandList().getFirst()); + if (SinovoBle.getInstance().getBleServiceUUID() != null && SinovoBle.getInstance().getBlecharacteristUUID() != null ){ + final UUID uuid_service = UUID.fromString(SinovoBle.getInstance().getBleServiceUUID()); + final UUID uuid_characterics = UUID.fromString(SinovoBle.getInstance().getBlecharacteristUUID()); - SinovoBle sinovoBle = SinovoBle.getInstance(); - if (sinovoBle.getBleServiceUUID() != null && sinovoBle.getBlecharacteristUUID() != null ){ - final UUID uuid_service = UUID.fromString(sinovoBle.getBleServiceUUID()); - final UUID uuid_characterics = UUID.fromString(sinovoBle.getBlecharacteristUUID()); - - new Handler(Looper.getMainLooper()).postDelayed(new Runnable() { - @Override - public void run() { - BleConnCallBack.getInstance().writeCharacteristic(write_msg_byte, uuid_service, uuid_characterics); - } - }, 200); + new Handler(Looper.getMainLooper()).postDelayed(() -> BleConnCallBack.getInstance().writeCharacteristic(write_msg_byte, uuid_service, uuid_characterics), 200); }else { Log.d(TAG,"UUID 为空,异常了,断开连接"); @@ -442,7 +442,6 @@ private LinkedHashMap bindPhone(String datavalue){ } String errCode = datavalue.substring(len-2, len); map.put("errCode", errCode); -// Log.d(TAG,"手机绑定的错误码:"+errCode); //绑定成功 if (errCode.equals("00") || errCode.equals("0b")){ @@ -460,15 +459,13 @@ private LinkedHashMap bindPhone(String datavalue){ //绑定成功后,取消绑定超时检测 SinovoBle.getInstance().getBindTimeoutHandler().removeCallbacksAndMessages(null); - String bleMac = datavalue.substring(0,12); + String bleMac = datavalue.substring(0,12).toUpperCase(); String bleSno = datavalue.substring(12,18); SinovoBle.getInstance().setConnected(true); SinovoBle.getInstance().setLockMAC(bleMac); SinovoBle.getInstance().setLockSNO(bleSno); - //清空自动连接的列表,或许断开只能重连它,不能连接其他设备,除非手动切换 - SinovoBle.getInstance().getAutoConnectList().clear(); StringBuilder lockMac = new StringBuilder(); for (int j=0;j map = new LinkedHashMap<>(); + map.put("funCode", "2b"); + + Log.d(TAG, "返回的内容:"+ datavalue); + if (len<2){ + map.put("errCode", "01"); //数据长度有误 + return map; + } + + String errCode = "00"; + if (len > 2){ + errCode = datavalue.substring(len-2, len); + } + map.put("errCode", errCode); //数据长度有误 + map.put("lockMac", SinovoBle.getInstance().getLockMAC()); + + if (errCode.equals("00")) { + String enable = datavalue.substring(0, 2); + map.put("enable", enable); + } + + return map; + } + /** * 转换mac地址,将 00A051F4DC4C转换为00:A0:51:F4:DC:4C @@ -1585,4 +1588,39 @@ private String macWithColon(String macAddress){ return lockMac.toString().toUpperCase(); } + + /** + * 将指令进行加密 + * @param funcode + * @param data + */ + public String getDataToEnctrypt(String funcode, String data, String mac){ + StringBuilder data_send = new StringBuilder(data); + int byteLen = data.length() /2; + byteLen += data.length() %2; + + //如果data 不够16字节,则在后面补ff + for (int i=32;i> data.length(); i--) { + data_send.append("f"); + } + Log.d(TAG, "getDataToEnctrypt 需要发送的数据,在补f之后:"+data_send + ",长度:"+data_send.length()); + + Log.d(TAG, "准备加密的mac:"+mac); + data_send = new StringBuilder(SinovoBle.getInstance().getMyJniLib().encryptAes(data_send.toString(), mac)); +// data_send = new StringBuilder(encryptData(data_send.toString(), mac)); + + Log.d(TAG, "需要发送的数据,加密后:"+data_send); + + String data_result = "fe" +funcode ; + if (byteLen<16){ + data_result = data_result + "0"+ Integer.toHexString(byteLen) + data_send; + }else { + data_result = data_result + Integer.toHexString(byteLen) + data_send; + } + + data_result = data_result +checkSum(data_result); + + return data_result; + } + } diff --git a/sinovoble/src/main/java/com/sinovotec/sinovoble/common/BleScanDevice.java b/sinovoble/src/main/java/com/sinovotec/sinovoble/common/BleScanDevice.java index b4fb7f0..c757cd8 100644 --- a/sinovoble/src/main/java/com/sinovotec/sinovoble/common/BleScanDevice.java +++ b/sinovoble/src/main/java/com/sinovotec/sinovoble/common/BleScanDevice.java @@ -37,8 +37,4 @@ public String getJoinTime() { return joinTime; } -// public void setJoinTime(String joinTime) { -// this.joinTime = joinTime; -// } - } diff --git a/sinovoble/src/main/java/com/sinovotec/sinovoble/common/BluetoothListenerReceiver.java b/sinovoble/src/main/java/com/sinovotec/sinovoble/common/BluetoothListenerReceiver.java index 8975aec..12c3080 100644 --- a/sinovoble/src/main/java/com/sinovotec/sinovoble/common/BluetoothListenerReceiver.java +++ b/sinovoble/src/main/java/com/sinovotec/sinovoble/common/BluetoothListenerReceiver.java @@ -5,12 +5,14 @@ import android.content.Context; import android.content.Intent; import android.util.Log; - import com.sinovotec.sinovoble.SinovoBle; import com.sinovotec.sinovoble.callback.BleConnCallBack; - import java.util.Objects; +/** + * 用于监听手机的蓝牙开启与关闭的 + */ + public class BluetoothListenerReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { @@ -20,28 +22,38 @@ public void onReceive(Context context, Intent intent) { switch (blueState) { case BluetoothAdapter.STATE_TURNING_ON: Log.e(TAG, "onReceive---------Bluetooth is turning on"); - break; case BluetoothAdapter.STATE_ON: Log.e(TAG, "onReceive---------Bluetooth is on"); - if (SinovoBle.getInstance().getmConnCallBack()!= null) { - SinovoBle.getInstance().setConnected(false); - SinovoBle.getInstance().setConnectting(false); - SinovoBle.getInstance().getmConnCallBack().onBluetoothOn(); + if (SinovoBle.getInstance().getLockGWid().isEmpty()) { + Log.e(TAG, "Gateway's id is null. it's connect via bluetooth"); + BleConnCallBack.getInstance().setmBluetoothGatt(null); + if (SinovoBle.getInstance().getmConnCallBack() != null) { + SinovoBle.getInstance().setConnected(false); + SinovoBle.getInstance().setLinked(false); + SinovoBle.getInstance().getmConnCallBack().onBluetoothOn(); + } + }else { + Log.e(TAG, "Gateway's id is not null. it's connect via gateway"); } break; case BluetoothAdapter.STATE_TURNING_OFF: Log.e(TAG, "onReceive---------Bluetooth is turning off"); - BleConnCallBack.getInstance().releaseBle(); - - if (SinovoBle.getInstance().getmConnCallBack()!= null) { - SinovoBle.getInstance().setConnected(false); - SinovoBle.getInstance().setConnectting(false); - SinovoBle.getInstance().getmConnCallBack().onBluetoothOff(); + if (SinovoBle.getInstance().isBleConnected()){ + BleConnCallBack.getInstance().releaseBle(); + if (SinovoBle.getInstance().getmConnCallBack()!= null) { + SinovoBle.getInstance().setConnected(false); + SinovoBle.getInstance().setLinked(false); + SinovoBle.getInstance().getmConnCallBack().onBluetoothOff(); + } +// }else { +// Log.e(TAG, "蓝牙未连接,关闭蓝牙不受影响"); } + break; case BluetoothAdapter.STATE_OFF: Log.e(TAG, "onReceive---------Bluetooth is off"); + BleConnCallBack.getInstance().releaseBle(); break; } }