微信小程序之蓝牙的链接


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 相关文章推荐
js 页面输出值
Nov 30 Javascript
jquery实现每个数字上都带进度条的幻灯片
Feb 20 Javascript
JavaScript调用客户端的可执行文件(示例代码)
Nov 28 Javascript
JS实现跟随鼠标立体翻转图片的方法
May 04 Javascript
jquery图片滚动放大代码分享(2)
Aug 28 Javascript
JavaScript基本语法学习教程
Jan 14 Javascript
基于AngularJS前端云组件最佳实践
Oct 20 Javascript
使用JavaScript判断用户输入的是否为正整数(两种方法)
Feb 05 Javascript
移动前端图片压缩上传的实例
Dec 06 Javascript
JavaScript树的深度优先遍历和广度优先遍历算法示例
Jul 30 Javascript
vue-test-utils初使用详解
May 23 Javascript
Element Breadcrumb 面包屑的使用方法
Jul 26 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程序
2006/10/09 PHP
PHP小教程之实现链表
2014/06/09 PHP
php中实现精确设置session过期时间的方法
2014/07/17 PHP
php打印输出棋盘的实现方法
2014/12/23 PHP
php 时间time与日期date之间的使用详解及区别
2016/11/07 PHP
javascript实现的鼠标链接提示效果生成器代码
2007/06/28 Javascript
ExtJs GridPanel简单的增删改实现代码
2010/08/26 Javascript
关于js中window.location.href,location.href,parent.location.href,top.location.href的用法与区别
2010/10/18 Javascript
让innerText在firefox火狐和IE浏览器都能用的写法
2011/05/14 Javascript
js中将URL中的参数提取出来作为对象的实现代码
2011/08/16 Javascript
js中parseFloat(参数1,参数2)定义和用法及注意事项
2013/01/27 Javascript
jQuery实现弹出窗口中切换登录与注册表单
2015/06/05 Javascript
浅谈json取值(对象和数组)
2016/06/24 Javascript
Bootstrap选项卡动态切换效果
2016/11/28 Javascript
Vue学习笔记进阶篇之单元素过度
2017/07/19 Javascript
关于echarts在节点显示动态数据及添加提示文本所遇到的问题
2018/04/20 Javascript
vue多层嵌套路由实例分析
2019/03/19 Javascript
基于jquery实现的tab选项卡功能示例【附源码下载】
2019/06/10 jQuery
mysql 之通过配置文件链接数据库
2017/08/12 Python
pybind11在Windows下的使用教程
2019/07/04 Python
Pytorch.nn.conv2d 过程验证方式(单,多通道卷积过程)
2020/01/03 Python
python发qq消息轰炸虐狗好友思路详解(完整代码)
2020/02/15 Python
Python批量处理csv并保存过程解析
2020/05/16 Python
Python Django form 组件动态从数据库取choices数据实例
2020/05/19 Python
python名片管理系统开发
2020/06/18 Python
pytorch掉坑记录:model.eval的作用说明
2020/06/23 Python
css3 clip实现圆环进度条的示例代码
2018/02/07 HTML / CSS
橄榄树药房:OLIVEDA
2019/09/01 全球购物
音乐节策划方案
2014/06/09 职场文书
领导班子对照检查材料
2014/09/22 职场文书
入党政审材料范文
2014/12/24 职场文书
考生诚信考试承诺书(2016版)
2016/03/25 职场文书
详解分布式系统中如何用python实现Paxos
2021/05/18 Python
Python机器学习之PCA降维算法详解
2021/05/19 Python
SQLServer 错误: 15404,无法获取有关 Windows NT 组/用户 WIN-8IVSNAQS8T7\Administrator 的信息
2021/06/30 SQL Server
如何使用注解方式实现 Redis 分布式锁
2022/07/23 Redis