微信小程序之蓝牙的链接


Posted in Javascript onSeptember 26, 2017

微信小程序之蓝牙的链接

微信小程序蓝牙连接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错误)。

如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

Javascript 相关文章推荐
jquery tab标签页的制作
May 10 Javascript
jquery入门—选择器实现隔行变色实例代码
Jan 04 Javascript
jQuery动画效果-slideUp slideDown上下滑动示例代码
Aug 28 Javascript
jquery获取元素值的方法(常见的表单元素)
Nov 15 Javascript
js将控件隐藏及display属性的使用介绍
Dec 30 Javascript
json+jQuery实现的无限级树形菜单效果代码
Aug 27 Javascript
微信小程序 WXML、WXSS 和JS介绍及详解
Oct 08 Javascript
JS 循环li添加点击事件 (闭包的应用)
Dec 10 Javascript
AngularJS使用ocLazyLoad实现js延迟加载
Jul 05 Javascript
基于vue.js组件实现分页效果
Dec 29 Javascript
js实现简单放大镜效果
Mar 07 Javascript
40行代码把Vue3的响应式集成进React做状态管理
May 20 Javascript
jQuery EasyUI Layout实现tabs标签的实例
Sep 26 #jQuery
jQuery EasyUI开发技巧总结
Sep 26 #jQuery
jQuery 开发之EasyUI 添加数据的实例
Sep 26 #jQuery
微信小程序中post方法与get方法的封装
Sep 26 #Javascript
javascript 产生随机数的几种方法总结
Sep 26 #Javascript
Three.js实现浏览器变动时进行自适应的方法
Sep 26 #Javascript
BootStrap点击保存后实现模态框自动关闭的思路(模态框)
Sep 26 #Javascript
You might like
PHP中的CMS的涵义
2007/03/11 PHP
PHP获取当前所在目录位置的方法
2014/11/26 PHP
php 删除一维数组中某一个值元素的操作方法
2018/02/01 PHP
ThinkPHP5 框架引入 Go AOP,PHP AOP编程项目详解
2020/05/12 PHP
IE event.srcElement和FF event.target 功能比较
2010/03/01 Javascript
动态标签 悬停效果 延迟加载示例代码
2013/11/21 Javascript
javascript读取xml实现javascript分页
2013/12/13 Javascript
jquery弹出层类代码分享
2013/12/27 Javascript
javascript 10进制和62进制的相互转换
2014/07/31 Javascript
jquery.uploadify插件在chrome浏览器频繁崩溃解决方法
2015/03/01 Javascript
JS实现适合于后台使用的动画折叠菜单效果
2015/09/21 Javascript
js生成随机数(指定范围)的实例代码
2016/07/10 Javascript
老生常谈javascript的类型转换
2016/10/12 Javascript
使用UrlConnection实现后台模拟http请求的简单实例
2017/01/04 Javascript
jQuery页面弹出框实现文件上传
2017/02/09 Javascript
jquery实现自定义图片裁剪功能【推荐】
2017/03/08 Javascript
微信小程序 setData使用方法及常用错误解决办法
2017/05/11 Javascript
JS模拟超市简易收银台小程序代码解析
2017/08/18 Javascript
详解vue中引入stylus及报错解决方法
2017/09/22 Javascript
JavaScript判断浏览器运行环境的详细方法
2019/06/30 Javascript
关于layui时间回显问题的解决方法
2019/09/24 Javascript
JQuery样式与属性设置方法分析
2019/12/07 jQuery
Ant Design的可编辑Tree的实现操作
2020/10/31 Javascript
[49:08]FNATIC vs Infamous 2019国际邀请赛小组赛 BO2 第二场 8.16
2019/08/18 DOTA
tornado框架blog模块分析与使用
2013/11/21 Python
使用Python进行AES加密和解密的示例代码
2018/02/02 Python
django 2.2和mysql使用的常见问题
2019/07/18 Python
pandas 对group进行聚合的例子
2019/12/27 Python
CSS3 display知识详解
2015/11/25 HTML / CSS
可爱的童装和鞋子:Fabkids
2019/08/16 全球购物
什么是典型的软件三层结构?软件设计为什么要分层?软件分层有什么好处?
2012/03/14 面试题
大学生期末自我鉴定
2014/02/01 职场文书
单位委托书怎么写
2014/08/02 职场文书
行政专员岗位职责说明书
2014/09/01 职场文书
教师理论学习心得体会
2016/01/21 职场文书
使用Redis实现分布式锁的方法
2022/06/16 Redis