美文网首页小程序合集小程序微信小程序
熊晨沣蓝牙实战--小程序蓝牙连接2.0

熊晨沣蓝牙实战--小程序蓝牙连接2.0

作者: 极乐叔 | 来源:发表于2017-09-26 11:34 被阅读140次

    微信小程序蓝牙连接2.0说明:

    1、本版本区分了ANDROID和IOS系统下蓝牙连接的不同方式。
    2、兼容了更多情况下的链接包括:

    (1)未开启设备蓝牙,当监听到开启了蓝牙后自动开始连接。
    (2)初始化蓝牙失败后每3000ms自动重新初始化蓝牙适配器。
    (3)安卓端开启蓝牙适配器扫描失败,每3000ms自动重新开启。
    (4)IOS端获取已连接蓝牙设备为空,每3000ms自动重新获取。
    (5)安卓端蓝牙开始链接后中断扫描,连接失败了,重新开始扫描。
    (6)IOS端开始连接设备后,停止获取已连接设备,连接失败自动重新开启获取。
    (7)连接成功后,关闭系统蓝牙,蓝牙适配器重置。
    (8)连接成功后,关闭系统蓝牙,再次打开蓝牙,自动重新开始连接。
    (9)连接成功后,关闭目标蓝牙设备,自动重新开始扫描(获取)。
    (10)连接成功后,最小化小程序(连接未中断),打开小程序显示已连接。
    (11)连接成功后,杀掉小程序进程,连接关闭,自动重新开始扫描(获取)。

    3、想起来了再来更新....。
    4、流程图,明天或后天或...谁有空帮我画一下也行。

    我的连接是在App.js中做的。
    在App.js中的onLaunch触发是调用 init()方法。

    init代码:

    init: function (n) {
        this.list = [];
        this.serviceId = "6E400001-B5A3-F393-E0A9-E50E24DCCA9E";
        this.serviceId_2 = "00001803-0000-1000-8000-00805F9B34FB";
        this.serviceId_3 = "00001814-0000-1000-8000-00805F9B34FB";
        this.serviceId_4 = "00001802-0000-1000-8000-00805F9B34FB";
        this.serviceId_5 = "00001804-0000-1000-8000-00805F9B34FB";
        this.serviceId_6 = "00001535-1212-EFDE-1523-785FEABCD123";
        this.characterId_write = "6E400042-B5A3-F393-E0A9-E50E24DCCA9E";
        this.characterId_read = "6E400012-B5A3-F393-E0A9-E50E24DCCA9E";
        this.connectDeviceIndex = 0;
        this.isGettingConnected = false;
        this.isDiscovering = false;
        this.isConnecting = false;
        this.connectedDevice = {};
        console.log('init state', this.connectedDevice.state);
        if (!this.connectedDevice.state || n == 200) {
          this.connectedDevice.state = false;
          this.connectedDevice.deviceId = '';
          this.adapterHasInit = false
        }
        this.startConnect();
      }
    

    说明:

    1、 serviceId_2~6 是我已知的想要连接的蓝牙设备的serviceId可以只写一个。
    2、characterId_write 是我已知的想要连接的蓝牙设备写入数据的特征值。
    3、characterId_read是我已知的想要连接的蓝牙设备读取数据的特征值。
    (以上3个都是为了做比对,真实的操作按照获取到的sericeid, characterid为准)。
    4、connectedDevice 是已连接了的设备信息对象。

    init完成后开始调用连接 startConnect();

    startConnect代码:

    startConnect: function () {
        var that = this;
        if (that.connectedDevice.state) return;
        that.connectedDevice.deviceId = "";
        that.connectedDevice.state = false;
        // 如果适配器已经初始化不在调用初始化(重复初始化会报错)
        if (this.adapterHasInit == undefined || this.adapterHasInit) return;
        wx.showLoading({
          title: '初始化蓝牙',
          duration: 2000
        });
        // 开启蓝牙适配器状态监听
        this.listenAdapterStateChange();
        // 初始化蓝牙适配器状态(必须步骤,否则无法进行后续的任何操作)
        wx.openBluetoothAdapter({
          success: function (res) {
            console.log("初始化蓝牙适配器成功");
            that.getBluetoothAdapterState();
            that.adapterHasInit = true;
          },
          fail: function (err) {
            console.log(err);
            wx.showLoading({
              title: '请开蓝牙',
              icon: 'loading',
              duration: 2000
            })
          }
        });
      }
    

    说明:这段有注释,就不多说了,比较简单。

    在初始化蓝牙适配器状态成功后调用getBluetoothAdapterState()方法。

    getBluetoothAdapterState代码:

    getBluetoothAdapterState: function () {
        var that = this;
        wx.getBluetoothAdapterState({
          success: function (res) {
            console.log(res);
            var available = res.available;
            that.isDiscovering = res.discovering;
            if (!available) {
              wx.showLoading({
                title: '请开蓝牙',
                icon: 'loading',
                duration: 2000
              })
            } else {
              if (!that.connectedDevice['state']) {
                that.judegIfDiscovering(res.discovering);
              }
            }
          },
          fail: function (err) {
            console.log(err);
          }
        })
      }
    

    说明:此方法是用来获取当前蓝牙状态。

    当检测到蓝牙可用时调用judegIfDiscovering方法。

    judegIfDiscovering代码:

    judegIfDiscovering: function (discovering) {
        var that = this;
        if (this.isConnectinng) return;
        wx.getConnectedBluetoothDevices({
          services: [that.serviceId],
          success: function (res) {
            console.log("获取处于连接状态的设备", res);
            var devices = res['devices'];
            if (devices[0]) {
              if (that.isAndroidPlatform) {
                wx.showToast({
                  title: '蓝牙连接成功',
                  icon: 'success',
                  duration: 2000
                });
              } else {
                that.getConnectedBluetoothDevices(256);
              }
            } else {
              if (discovering) {
                wx.showLoading({
                  title: '蓝牙搜索中'
                })
              } else {
                if (that.isAndroidPlatform) {
                  that.startBluetoothDevicesDiscovery();
                } else {
                  that.getConnectedBluetoothDevices(267);
                }
              }
            }
          },
          fail: function (err) {
            console.log('getConnectedBluetoothDevices err 264', err);
            if (that.isAndroidPlatform) {
              that.startBluetoothDevicesDiscovery();
            } else {
              that.getConnectedBluetoothDevices(277);
            }
          }
        });
      }
    

    说明:
    1、此方法是用来判断是否正在扫描。
    2、isAndroidPlatform 是通过小程序的getSystemInfo获取到的判断是安卓设备还是IOS设备。

    如果是安卓设备调用startBluetoothDevicesDiscovery()开启扫描,如果是IOS设备调用getConnectedBluetoothDevices() 开启获取已配对的蓝牙设备。

    startBluetoothDevicesDiscovery代码:

    startBluetoothDevicesDiscovery: function () {
        var that = this;
        if (!this.isAndroidPlatform) return;
        if (!this.connectedDevice['state']) {
          wx.getBluetoothAdapterState({
            success: function (res) {
              console.log(res);
              var available = res.available;
              that.isDiscovering = res.discovering;
              if (!available) {
                wx.showLoading({
                  title: '请开蓝牙',
                  icon: 'loading',
                  duration: 2000
                })
              } else {
                if (res.discovering) {
                  wx.showLoading({
                    title: '蓝牙搜索中'
                  })
                } else {
                  wx.startBluetoothDevicesDiscovery({
                    services: [],
                    allowDuplicatesKey: true,
                    success: function (res) {
                      that.onBluetoothDeviceFound();
                      wx.showLoading({
                        title: '蓝牙搜索中'
                      })
                    },
                    fail: function (err) {
                      if (err.isDiscovering) {
                        wx.showLoading({
                          title: '蓝牙搜索中'
                        })
                      } else {
                        that.startDiscoveryTimer = setTimeout(function () {
                          if (!that.connectedDevice.state) {
                            that.startBluetoothDevicesDiscovery();
                          }
                        }, 5000)
                      }
                    }
                  });
                }
              }
            },
            fail: function (err) {
              console.log(err);
            }
          })
        }
    

    说明:

    1、仅在安卓端设备上开启扫描附近蓝牙设备。

    2、在开启成功的回调中开启发现新蓝牙设备的事件监听onBluetoothDeviceFound()。

    onBluetoothDeviceFound代码:

    [mw_shl_code=javascript,true]onBluetoothDeviceFound: function () {
        var that = this;
        wx.onBluetoothDeviceFound(function (res) {
          console.log('new device list has founded');
          if (res.devices[0]) {
            var name = res.devices[0]['name'];
            if (name.indexOf('FeiZhi') != -1) {
              var deviceId = res.devices[0]['deviceId'];
              console.log(deviceId);
              that.deviceId = deviceId;
              if (!that.isConnecting) {
                that.startConnectDevices();
              }
            }
          }
        })
      }
    

    说明:
    1、此处对已发现的蓝牙设备根据name属性进行了过滤。
    2、当筛选出含有需要连接的设备的name属性的设备是获取到deviceId,开始连接调用startConnectDevices()方法。

    startConnectDevices代码:

    startConnectDevices: function (ltype, array) {
        var that = this;
        clearTimeout(this.getConnectedTimer);
        clearTimeout(this.startDiscoveryTimer);
        this.getConnectedTimer = null;
        this.startDiscoveryTimer = null;
        this.isConnectinng = true;
        wx.showLoading({
          title: '正在连接'
        });
        that.stopBluetoothDevicesDiscovery();
        wx.createBLEConnection({
          deviceId: that.deviceId,
          success: function (res) {
            console.log('连接成功', res);
            wx.showLoading({
              title: '正在连接'
            });
            that.connectedDevice.state = true;
            that.connectedDevice.deviceId = that.deviceId;
            if (res.errCode == 0) {
              setTimeout(function () {
                that.getService(that.deviceId);
              }, 5000)
            }
            wx.onBLEConnectionStateChange(function (res) {
              console.log('连接变化', res);
              that.connectedDevice.state = res.connected;
              that.connectedDevice.deviceId = res.deviceId;
              if (!res.connected) {
                that.init('200');
              }
            });
          },
          fail: function (err) {
            console.log('连接失败:', err);
            wx.hideLoading();
            if (ltype == 'loop') {
              array = array.splice(0, 1);
              console.log(array);
              that.loopConnect(array);
            } else {
              if (that.isAndroidPlatform) {
                that.startBluetoothDevicesDiscovery();
              } else {
                that.getConnectedBluetoothDevices(488);
              }
            }
          },
          complete: function () {
            that.isConnectinng = false;
          }
        });
      }
    

    说明:
    1、开启连接后终止扫描(获取已配对)方法。
    2、根据deviceId创建低功耗蓝牙连接。如果连接成功,就继续做后续读写操作。
    3、如果连接失败根据设备系统分别调用startBluetoothDevicesDiscovery() 或 getConnectedBluetoothDevices();

    getConnectedBluetoothDevices代码:

    getConnectedBluetoothDevices: function (n) {
        var that = this;
        that.isGettingConnected = true;
        wx.showLoading({
          title: '蓝牙搜索中'
        });
        wx.getConnectedBluetoothDevices({
          services: [that.serviceId],
          success: function (res) {
            console.log("获取处于连接状态的设备", res);
            var devices = res['devices'],
              flag = false,
              index = 0,
              conDevList = [];
            devices.forEach(function (value, index, array) {
              if (value['name'].indexOf('FeiZhi') != -1) {
                // 如果存在包含FeiZhi字段的设备
                flag = true;
                index += 1;
                conDevList.push(value['deviceId']);
                that.deviceId = value['deviceId'];
              }
            });
            if (flag) {
              that.connectDeviceIndex = 0;
              that.loopConnect(conDevList);
            } else {
              that.failToGetConnected();
            }
          },
          fail: function (err) {
            that.failToGetConnected();
          },
          complete: function () {
            that.isGettingConnected = false;
          }
        });
      }
    

    说明:如果获取蓝牙已配对的蓝牙设备失败了,或获取到的列表为空调用failToGetConnected();

    failToGetConnected代码:

    failToGetConnected: function () {
        var that = this;
        if (!that.getConnectedTimer) {
          clearTimeout(that.getConnectedTimer);
          that.getConnectedTimer = null;
        }
        that.getConnectedTimer = setTimeout(function () {
          wx.getBluetoothAdapterState({
            success: function (res) {
              console.log(res);
              var available = res.available;
              if (!available) {
                wx.showLoading({
                  title: '请开蓝牙',
                  icon: 'loading',
                  duration: 2000
                })
              } else {
                if (!that.connectedDevice['state']) {
                  that.getConnectedBluetoothDevices();
                }
              }
            },
            fail: function (err) {
              console.log(err);
            }
          })
        }, 5000);
      }
    

    说明:
    1、该方法调用成功后返回的devices是一个数组包含多个已经系统配对的蓝牙设备。
    2、如果devices列表获取到调用loopConnect()方法开始递归调用连接蓝牙设备。

    loopConnect代码:

    loopConnect: function (array) {
        var that = this;
        var listLen = array.length;
        if (array[0]) {
          that.deviceId = array[0];
          if (!that.isConnecting) {
            that.startConnectDevices('loop', array);
          }
        } else {
          console.log('已配对的设备小程序蓝牙连接失败');
          if (!that.isAndroidPlatform) {
            that.getConnectedBluetoothDevices(431);
          }
        }
      }
    

    说明:looConnect在创建连接的方法连接失败后会操作删除数组的第一个值,然后继续调用该方法,直到其中所有的设备都连接过。
    差点漏了:在app.js的onShow里调用init()方法。

    特别说明:

    1、安卓和IOS的蓝牙连接在当前版本中推荐采用不同方式。安卓设备直接使用小程序的蓝牙连接,取消系统配对。IOS设备先系统配对在打开小程序可以时效秒连接成功。
    2、此版本的连接仍然有待完善,连接不会自动终止(需要的可以自己加),会无限扫描重连,直到成功。
    3、链接成功后的操作如果写入数据和开启notify需要同时进行,建议先写入,后开启notify。(原因未知,否则必然出现10008错误)。

    本文由 博主熊晨沣 原创发布于小程序社区(www.wxapp-union.com/portal.php)
    转载请注明出处

    相关文章

      网友评论

      本文标题:熊晨沣蓝牙实战--小程序蓝牙连接2.0

      本文链接:https://www.haomeiwen.com/subject/zgksextx.html