Преглед на файлове

feature:更新蓝牙插件

zeng.chen преди 8 месеца
родител
ревизия
22d9957331
променени са 3 файла, в които са добавени 323 реда и са изтрити 166 реда
  1. 7 41
      app.js
  2. 260 110
      devices/ble_manager.js
  3. 56 15
      devices/bt_helper.js

+ 7 - 41
app.js

@@ -19,6 +19,9 @@ App({
     is_debug: 2, // 1 测试环境 // 2正式环境
     client: null,
     oneInitBluetooth: true,
+    isIOS: false,
+    isAndroid: false,
+    isHuaWei: false,
     // 设备列表,跟app同步字段
     classifyProducts: [],
     //MQTT连接的配置
@@ -189,7 +192,9 @@ App({
         _this.globalData.navBarHeight = res.statusBarHeight + custom.height + (custom.top - res.statusBarHeight) * 2;
         _this.globalData.MenuButtonheight = custom.height;
         _this.globalData.MenuButtonTop = custom.top;
-
+        const platform = res.platform;
+        _this.globalData.isIOS = platform == "ios";
+        _this.globalData.isAndroid = platform == "android";
       }
 
     })
@@ -197,45 +202,6 @@ App({
   // 获取蓝牙权限
   getBluetoothStatus() {
     const _this = this;
-    wx.getSetting({
-      success(res) {
-        if (res.authSetting["scope.bluetooth"]) {
-          _this.globalData.scopeBluetooth = true;
-        } else if (res.authSetting["scope.bluetooth"] === undefined) {
-          _this.globalData.scopeBluetooth = false;
-          wx.authorize({
-            scope: "scope.bluetooth",
-            complete() {
-              _this.getBluetoothStatus();
-            }
-          });
-        } else {
-          _this.globalData.scopeBluetooth = false;
-          wx.showModal({
-            title: '请打开系统蓝牙进行配网',
-            content: '如已打开蓝牙仍然弹框,请尝试重启小程序',
-            success(res) {
-              if (res.confirm) {
-                console.log('用户点击确定')
-                wx.openSetting({
-                  complete() {
-                    // _this.getBluetoothStatus();
-                  }
-                })
-              } else if (res.cancel) {
-                console.log('用户点击取消')
-              }
-            }
-          })
-        };
-        if (getCurrentPages()[getCurrentPages().length - 1].getBluetoothStatusCallck) {
-          getCurrentPages()[getCurrentPages().length - 1].getBluetoothStatusCallck(_this.globalData.scopeBluetooth);
-        }
-        // res.authSetting = {
-        //   "scope.userInfo": true,
-        //   "scope.userLocation": true
-        // }
-      }
-    })
+    
   },
 })

+ 260 - 110
devices/ble_manager.js

@@ -5,12 +5,8 @@ class bleManager {
     constructor() {
         this.hasPermission = false;
         this.isAvailable = false;
-        // this.devices = [];
-        this.connectedDeviceId = null;
-        // this.services = [];
-        this.serviceId = null;
-        this.deviceId = null;
-        this.characteristicId = null;
+        this.scanDevices = [];
+        this.device = null;
     }
 
     // 检查蓝牙权限
@@ -22,20 +18,26 @@ class bleManager {
                 success(res) {
                     if (res.authSetting["scope.bluetooth"]) {
                         _this.globalData.scopeBluetooth = true;
+                        this.hasPermission = true;
+                        // console.log('checkBluetoothPermission success, now is', res)
+
                         resolve(true);
 
                     } else if (res.authSetting["scope.bluetooth"] === undefined) {
                         _this.globalData.scopeBluetooth = false;
+                        this.hasPermission = false;
                         wx.authorize({
                             scope: "scope.bluetooth",
                             complete() {
-                                _this.getBluetoothStatus();
+
+                                resolve(_this.checkBluetoothPermission());
+
                             }
                         });
-                        resolve(false);
 
                     } else {
                         _this.globalData.scopeBluetooth = false;
+                        this.hasPermission = false;
 
                         wx.showModal({
                             title: '请打开系统蓝牙进行配网',
@@ -65,14 +67,24 @@ class bleManager {
 
     // 初始化蓝牙适配器
     initBluetoothAdapter() {
+        let _this = this;
+        wx.onBluetoothAdapterStateChange(function (res) {
+            console.log('adapterState changed, now is', res)
+            _this.isAvailable = res.available ?? false
+
+        })
         return new Promise((resolve, reject) => {
             wx.openBluetoothAdapter({
                 success: (res) => {
-                    this.isAvailable = true;
+                    _this.isAvailable = true;
+                    // console.log('adapterState success, now is', res)
+
                     resolve(true);
                 },
                 fail: (err) => {
-                    this.isAvailable = false;
+                    _this.isAvailable = false;
+                    // console.log('adapterState fail, now is', err)
+
                     reject(false);
                 }
             });
@@ -81,23 +93,56 @@ class bleManager {
 
     // 获取已连接的蓝牙设备
     getConnectedDevices() {
+        if (!this.isAvailable && !this.hasPermission) {
+            return false;
+        }
         return new Promise((resolve, reject) => {
             wx.getConnectedBluetoothDevices({
-                services: ["ffc0", "ab00", "ffe5"],
-                // services: ["0000ab00-0000-1000-8000-00805f9b34fb"
-                //     , "0000ffc0-0000-1000-8000-00805f9b34fb"
+                // services: ["FFC0", "ffc0", "FFC1", "FFC2", "ffc1", "ffc2", "AB00", "ab00", "AB01", "AB02", "FFF1", "fff1", "FFE2", "FFE5",],
+                services: ["ab00", "0000AB00-0000-1000-8000-00805F9B34FB", "ffe5", "1111"],
+                // services: [
+                //     "0000ab00-0000-1000-8000-00805f9b34fb",
+                //     "0000ffc0-0000-1000-8000-00805f9b34fb",
+                //     "0000FFF0-0000-1000-8000-00805F9B34FB",
+                //     "0000FFF1-0000-1000-8000-00805F9B34FB",
+                //     "0000FFE5-0000-1000-8000-00805F9B34FB",
                 // ],
                 success: (res) => {
                     // const connectedDevices = res.devices.map(device => ({
                     //     deviceId: device.deviceId,
                     //     name: device.name || device.localName
                     // }));
-                    console.log('已连接的蓝牙设备:', res.devices);
-                    resolve(res.devices);
+                    console.log('已连接的蓝牙设备:', res);
+                    resolve(res);
                 },
                 fail: (err) => {
                     console.error('获取已连接的蓝牙设备失败:', err);
-                    reject(new Error('获取已连接的蓝牙设备失败'));
+                    reject([]);
+                }
+            });
+        });
+    }
+
+    // 获取获取在蓝牙模块生效期间所有搜索到的蓝牙设备。包括已经和本机处于连接状态的设备。
+    getAllConnectedDevices() {
+        if (!this.isAvailable && !this.hasPermission) {
+            return [];
+        }
+        return new Promise((resolve, reject) => {
+            wx.getBluetoothDevices({
+                success: (res) => {
+                    // const connectedDevices = res.devices.map(device => ({
+                    //     deviceId: device.deviceId,
+                    //     name: device.name || device.localName
+                    // }));
+                    console.log('已扫描过的蓝牙设备:', res);
+                    let newDevices = this.fiterDevice(res)
+
+                    resolve(newDevices);
+                },
+                fail: (err) => {
+                    console.error('已扫描过的蓝牙设备失败:', err);
+                    reject([]);
                 }
             });
         });
@@ -131,9 +176,9 @@ class bleManager {
             }
 
             wx.writeBLECharacteristicValue({
-                deviceId: this.deviceId,
-                serviceId: this.serviceId,
-                characteristicId: this.characteristicId,
+                deviceId: this.device.deviceId,
+                serviceId: this.device.serviceId,
+                characteristicId: this.device.characteristicId,
                 value: buffer,
                 success: (res) => {
                     console.log('数据发送成功:', res);
@@ -147,47 +192,72 @@ class bleManager {
         });
     }
 
-    getSetting() {
+    async getSetting() {
         const _this = this;
-        wx.getSetting({
-            success(res) {
-                if (res.authSetting["scope.userFuzzyLocation"]) {
-                    // 成功
-                    _this.getBluetoothStatus();
+        return new Promise((resolve, reject) => {
 
-                } else if (res.authSetting["scope.userFuzzyLocation"] === undefined) {
+            wx.getSetting({
+                success(res) {
+                    if (res.authSetting["scope.userFuzzyLocation"]) {
+                        // 成功
+                        // _this.getBluetoothStatus();
+                        console.log("有定位权限")
+                        resolve(true);
+
+                    } else if (res.authSetting["scope.userFuzzyLocation"] === undefined) {
+
+                        wx.authorize({
+                            scope: "scope.userFuzzyLocation",
+                            success() {
+                                console.log("再次获取定位权限")
+                                resolve(_this.getSetting());
 
-                    wx.authorize({
-                        scope: "scope.userFuzzyLocation",
-                        success() {
-                            _this.getSetting();
-                        }
-                    });
-                } else {
-
-                    wx.showModal({
-                        title: '请打开系统位置获取',
-                        success(res) {
-                            if (res.confirm) {
-                                console.log('用户点击确定')
-                                wx.openSetting({
-                                    complete() {
-                                        // _this.getSetting();
-                                    }
-                                })
-                            } else if (res.cancel) {
-                                console.log('用户点击取消');
                             }
-                        }
-                    })
+                        });
+                    } else {
+
+                        wx.showModal({
+                            title: '请打开系统位置获取定位权限',
+                            success(res) {
+                                if (res.confirm) {
+                                    console.log('用户点击确定')
+                                    wx.openSetting({
+                                        complete() {
+                                            // _this.getSetting();
+                                            // resolve(_this.getSetting());
+
+                                        }
+                                    })
+                                } else if (res.cancel) {
+                                    console.log('用户点击取消');
+                                }
+                            }
+                        })
+                        console.log("没有有定位权限")
+                        reject(false);
+
+                    }
                 }
-            }
-        })
+            })
+
+        });
+
     }
     // 开始搜索蓝牙设备
-    startScan(success, fail) {
+    async startScan(success, fail) {
+
+        let open = await this.getSetting()
+        if (!open) {
+            if (fail) {
+                fail("需要先开启定位");
+            }
+            console.log('需要先开启定位');
+        }
+        if (!this.isAvailable && !this.hasPermission) {
+            return false;
+        }
         wx.startBluetoothDevicesDiscovery({
-            services: ["ffc0", "ab00", "ffe5"],
+            // services: ["ffc0", "ab00", "ffe5"],
             success: (res) => {
                 // this.onBluetoothDeviceFound();
                 console.log('蓝牙设备搜索已启动:', res);
@@ -199,6 +269,13 @@ class bleManager {
             },
             fail: (err) => {
                 if (fail) {
+                    if (err.errno == 1509008) {
+                        wx.showToast({
+                            title: '搜索蓝牙需要先开启定位权限',
+                            icon: 'none',
+                            duration: 2000
+                        })
+                    }
                     fail(err);
                 }
                 console.log('启动蓝牙设备搜索失败', err ?? "err is null");
@@ -206,49 +283,85 @@ class bleManager {
                 // reject(new Error('启动蓝牙设备搜索失败', err ?? "err is null"));
             }
         });
-        // return new Promise((resolve, reject) => {
-        //     wx.startBluetoothDevicesDiscovery({
-        //         services: ["ffc0", "ab00", "ffe5"],
-        //         success: (res) => {
-        //             // this.onBluetoothDeviceFound();
-        //             console.log('蓝牙设备搜索已启动:', res);
-        //             resolve(res);
-        //         },
-        //         fail: (err) => {
-        //             reject(new Error('启动蓝牙设备搜索失败', err ?? "err is null"));
-        //         }
-        //     });
-        // });
     }
 
     // 监听发现新设备的事件
     onBluetoothDeviceFound(callback) {
         wx.onBluetoothDeviceFound((res) => {
-            const devices = res.devices.map(device => ({
-                deviceId: device.deviceId,
-                name: device.name || device.localName
-            }));
+
+            let newDevices = this.fiterDevice(res)
             // this.devices.push(...devices);
-            console.log('发现设备:', this.devices);
+            if (newDevices.length > 0) {
+                // console.log('发现设备:', newDevices[0].deviceId, newDevices[0].uuid);
+            }
             if (callback) {
-                callback(devices);
+                callback(newDevices);
             }
         });
     }
+    ab2hex(buffer) {
+        var hexArr = Array.prototype.map.call(
+            new Uint8Array(buffer),
+            function (bit) {
+                return ('00' + bit.toString(16)).slice(-2)
+            }
+        )
+        return hexArr.join('');
+    }
+    fiterDevice(res) {
+        var devices = res.devices.filter(device => {
+            const name = device.name || '';
+            const localName = device.localName || '';
+            let isNot = this.isNotEmpty(name) || this.isNotEmpty(localName);
+            if (isNot) {
+                let mac = this.ab2hex(device.advertisData)
+                // console.log(mac)
+                device.mac = mac
+            }
+            return isNot
+        });
 
+        let newDevices = devices.map((device) => {
+            let uuid = device.advertisServiceUUIDs[0] ?? ""
+            return {
+                deviceId: device.deviceId,
+                name: device.name,
+                localName: device.localName,
+                uuid: uuid,
+                mac: device.mac
+            }
+        });
+        return newDevices
+    }
+    isNotEmpty(name) {
+        let isNot = (name !== ''
+            && (name.includes("猫王") ||
+                name.includes("MW_") ||
+                name.includes("妙播") ||
+                name.includes("AirSmart") ||
+                name === "le")
+        )
+        // if (!isNot && name !== '') {
+        //     console.log('不是猫王设备名称:', name)
+        // }
+        return isNot;
+    }
     // 连接到指定设备
-    connectToDevice(deviceId) {
+    connectToDevice(device) {
+        this.device = device
+
         return new Promise((resolve, reject) => {
+            console.log("开始连接蓝牙:", device.deviceId)
             wx.createBLEConnection({
-                deviceId: deviceId,
+                deviceId: device.deviceId,
                 success: (res) => {
-                    this.connectedDeviceId = deviceId;
                     console.log('连接成功:', res);
                     resolve(res);
                 },
                 fail: (err) => {
+                    this.device = null
                     console.error('连接失败:', err);
-                    reject(new Error('连接失败'));
+                    reject(false);
                 }
             });
         });
@@ -256,7 +369,9 @@ class bleManager {
 
     // 停止搜索
     stopScan() {
+
         return new Promise((resolve, reject) => {
+
             wx.stopBluetoothDevicesDiscovery({
                 success: (res) => {
                     console.log('停止搜索成功:', res);
@@ -267,20 +382,42 @@ class bleManager {
                     reject(new Error('停止搜索失败'));
                 }
             });
+
         });
     }
+    closeBle() {
+        wx.closeBluetoothAdapter({
+            success(res) {
+                console.log(res)
+            }
+        })
+    }
 
     // 发现服务
     discoverServices(deviceId) {
+        console.log('发现服务:', deviceId);
+
         return new Promise((resolve, reject) => {
             wx.getBLEDeviceServices({
                 deviceId: deviceId,
                 success: (res) => {
-                    this.services = res.services;
-                    console.log('发现服务:', this.services);
-                    resolve(res.services);
+                    this.device.services = res.services;
+                    console.log('发现服务:', res.services);
+                    let service_id = "";
+                    for (let i = 0; i < res.services.length; i++) {
+                        if (services[i].uuid.toUpperCase().indexOf("AB00") != -1
+                            || services[i].uuid.toUpperCase().indexOf("FFC0") != -1
+                        ) {
+                            service_id = services[i].uuid;
+                            break;
+                        }
+                    }
+                    this.device.serviceId = service_id;
+                    resolve(service_id);
                 },
                 fail: (err) => {
+                    this.device.serviceId = null;
+
                     console.error('发现服务失败:', err);
                     reject(new Error('发现服务失败'));
                 }
@@ -288,21 +425,29 @@ class bleManager {
         });
     }
 
-    // 发现特征值
+    // 发现特征值 read / write
     discoverCharacteristics(deviceId, serviceId) {
+        console.log('发现特征值:', deviceId, serviceId);
+
+        if (deviceId !== this.device.deviceId) {
+            console.log('设备id不匹配')
+            return false
+        }
         return new Promise((resolve, reject) => {
             wx.getBLEDeviceCharacteristics({
                 deviceId: deviceId,
                 serviceId: serviceId,
                 success: (res) => {
                     // this.characteristics[serviceId] = res.characteristics;
-                    this.characteristicId = res.characteristics;
-                    console.log('发现特征值:', this.characteristicId);
+                    console.log('发现特征值:', res.characteristics);
+                    this.device.characteristics = res.characteristics;
+
                     resolve(res.characteristics);
                 },
                 fail: (err) => {
+                    this.device.characteristics = null;
                     console.error('发现特征值失败:', err);
-                    reject(new Error('发现特征值失败'));
+                    reject("");
                 }
             });
         });
@@ -310,6 +455,11 @@ class bleManager {
 
     // 读取特征值
     readCharacteristicValue(deviceId, serviceId, characteristicId) {
+        if (deviceId !== this.device.deviceId) {
+            console.log('设备id不匹配2')
+            return ""
+        }
+        console.log('开始读取特征值', deviceId, serviceId, characteristicId)
         return new Promise((resolve, reject) => {
             wx.readBLECharacteristicValue({
                 deviceId: deviceId,
@@ -321,44 +471,44 @@ class bleManager {
                 },
                 fail: (err) => {
                     console.error('读取特征值失败:', err);
-                    reject(new Error('读取特征值失败'));
+                    reject("");
                 }
             });
         });
     }
 
     // 监听特征值变化
-    notifyCharacteristicValueChange(deviceId, serviceId, characteristicId, state, callback) {
-        // return new Promise((resolve, reject) => {
+    notifyCharacteristicValueChange(deviceId, serviceId, characteristicId, callback) {
         wx.notifyBLECharacteristicValueChange({
-            deviceId: deviceId,
-            serviceId: serviceId,
-            characteristicId: characteristicId,
-            state: state, // true 表示开启通知,false 表示关闭通知
-            success: (res) => {
-                console.log('通知特征值变化成功:', res);
-                // resolve(res);
-                if (callback) {
-                    callback(res)
-                }
-            },
-            fail: (err) => {
-                console.error('通知特征值变化失败:', err);
-                // reject(new Error('通知特征值变化失败'));
-            }
-        });
-        // });
-    }
+            deviceId: deviceId,  //设备mac   IOS和安卓系统不一样
+            serviceId: serviceId,     //服务通道,这里主要是notify
+            characteristicId: characteristicId,     //notify uuid
+            state: true,
+            success: function (res) {
+                console.log("开启notify 成功")
+                //TODO  onBLECharacteristicValueChange  监听特征值 设备的数据在这里获取到
+                wx.onBLECharacteristicValueChange(function (characteristic) {
+                    console.log('characteristic value comed:')
+                    let buffer = characteristic.value
+                    let dataView = new DataView(buffer)
+                    let dataResult = []
+                    console.log("dataView.byteLength", dataView.byteLength)
+                    for (let i = 0; i < dataView.byteLength; i++) {
+                        console.log("0x" + dataView.getUint8(i).toString(16))
+                        dataResult.push(dataView.getUint8(i).toString(16))
+                    }
+                    const result = dataResult
+                    console.log("拿到的数据:", result)
 
-    // 搜索蓝牙服务
-    searchServices(deviceId) {
-        return this.discoverServices(deviceId);
+                    if (callback) {
+                        callback(result)
+                    }
+                })
+            },
+            fail: function (res) { }
+        })
     }
 
-    // 搜索蓝牙特征值
-    searchCharacteristics(deviceId, serviceId) {
-        return this.discoverCharacteristics(deviceId, serviceId);
-    }
 }
 
 const ble = new bleManager();

+ 56 - 15
devices/bt_helper.js

@@ -67,7 +67,10 @@ class BtHelper {
 
     async search(mqttFilterList) {
         let res = await bleManager.startScan()
-        console.log(res);
+        setTimeout(() => {
+            bleManager.stopScan();
+        }, 10000);
+        // console.log(res);
         // return await this._helper.search();
     }
 
@@ -80,23 +83,60 @@ class BtHelper {
         bleManager.stopScan();
     }
 
-    async connect(data, onChanged, isClick = false) {
+    async connect(data, onChanged) {
         // await this._helper.connect({ data, onChanged, isClick });
         try {
-            await bleManager.connectToDevice(data.deviceId);
+            var res = await bleManager.connectToDevice(data);
             console.log('连接成功');
             // this.setData({ connectedDeviceId: deviceId });
-            const services = await bleManager.searchServices(deviceId);
+            if (res === false) {
+                console.log("连接失败")
+                return
+            }
+            const serviceId = await bleManager.discoverServices(data.deviceId);
+
             // this.setData({ services });
-            for (const service of services) {
-                const characteristics = await bleManager.searchCharacteristics(deviceId, service.uuid);
-                bleManager.readBLECharacteristicValue({
-                    deviceId: data.deviceId,
-                    serviceId: services.serviceId,
-                    characteristicId: characteristics,
-                })
-                // this.setData({ characteristics: { ...this.data.characteristics, [service.uuid]: characteristics } });
+            console.log("服务ID", serviceId)
+
+            var characteristics = await bleManager.discoverCharacteristics({
+                deviceId: data.deviceId,
+                serviceId: serviceId,
+            })
+
+            console.log('device特征值:', res.characteristics)
+            for (let i = 0; i < res.characteristics.length; i++) {
+                let charc = res.characteristics[i];
+                if (charc.properties.notify) {
+                    // 订阅的
+                    bleManager.notifyCharacteristicValueChange(data.deviceId, service.serviceId, characteristics, true, (res) => {
+                        // console.log(res)
+                    })
+                }
+                if (charc.properties.write || element.properties.writeWithoutResponse) {
+                    // 写入的
+                }
+                if (charc.properties.read) {
+                    console.log('读read_id:', that.data.read_id);
+                    var chara = await bleManager.readCharacteristicValue({
+                        deviceId: data.deviceId,
+                        serviceId: uuid,
+                        characteristicId: characteristics,
+                    })
+                }
+            }
+
+
+
+
+            console.log("查询特征值:", chara)
+
+
+
+            if (onChanged) {
+                onChanged(true)
             }
+            // this.setData({ characteristics: { ...this.data.characteristics, [service.uuid]: characteristics } });
+
         } catch (error) {
             console.error(error);
         }
@@ -125,7 +165,6 @@ class BtHelper {
             let res = await bleManager.initBluetoothAdapter();
             console.log(res)
 
-
             let per = await bleManager.checkBluetoothPermission();
             console.log(per)
         } catch (error) {
@@ -135,8 +174,10 @@ class BtHelper {
 
     async getConnectedDevices() {
         try {
-            const connectedDevices = await bleManager.getConnectedDevices();
-            return connectedDevices
+            // const connectedDevices = await bleManager.getConnectedDevices();
+            const allDevices = await bleManager.getAllConnectedDevices()
+            console.log("全部设备:", allDevices.length)
+            return allDevices
         } catch (error) {
             console.error(error);
         }