微信小程序之蓝牙的链接


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隐藏与显示回到顶部按钮及window.onscroll事件应用
Jan 25 Javascript
js onload处理html页面加载之后的事件
Oct 30 Javascript
ParseInt函数参数设置介绍
Jan 02 Javascript
js中浮点型运算BUG的解决方法说明
Jan 06 Javascript
jQuery控制Div拖拽效果完整实例分析
Apr 15 Javascript
js实现三张图(文)片一起切换的banner焦点图
Aug 25 Javascript
详解js跨域原理以及2种解决方案
Dec 09 Javascript
JavaScript实现鼠标点击导航栏变色特效
Feb 08 Javascript
canvas绘制环形进度条
Feb 23 Javascript
Angular4学习教程之DOM属性绑定详解
Jan 04 Javascript
opencv 识别微信登录验证滑动块位置
Aug 07 Javascript
详解swiper在vue中的应用(以3.0为例)
Sep 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
模板引擎正则表达式调试小技巧
2011/07/20 PHP
PHP中获取内网用户MAC地址(WINDOWS/linux)的实现代码
2011/08/11 PHP
PHP无法访问远程mysql的问题分析及解决
2013/05/16 PHP
解析关于java,php以及html的所有文件编码与乱码的处理方法汇总
2013/06/24 PHP
Symfony2在Nginx下的配置方法图文教程
2016/02/04 PHP
如何用PHP做到页面注册审核
2017/03/02 PHP
laravel实现批量更新多条记录的方法示例
2017/10/22 PHP
利用XMLHTTP传递参数在另一页面执行并刷新本页
2006/10/26 Javascript
在JavaScript中实现命名空间
2006/11/23 Javascript
jquery 插件 任意位置浮动固定层
2008/12/25 Javascript
JavaScript 变量命名规则
2009/09/23 Javascript
javascript 弹出窗口中是否显示地址栏的实现代码
2011/04/14 Javascript
事件绑定之小测试  onclick && addEventListener
2011/07/31 Javascript
JavaScript中的函数声明和函数表达式区别浅析
2015/03/27 Javascript
jquery验证邮箱格式并显示提交按钮
2015/11/07 Javascript
jQuery+Ajax实现限制查询间隔的方法
2016/06/07 Javascript
AngularJs expression详解及简单示例
2016/09/01 Javascript
jQuery实现立体式数字动态增加(animate方法)
2016/12/21 Javascript
几种响应式文字详解
2017/05/19 Javascript
小程序新版订阅消息模板消息
2019/12/31 Javascript
python3.4下django集成使用xadmin后台的方法
2017/08/15 Python
Python使用itertools模块实现排列组合功能示例
2018/07/02 Python
浅谈Python中的bs4基础
2018/10/21 Python
python实现得到当前登录用户信息的方法
2019/06/21 Python
python3中的eval和exec的区别与联系
2019/10/10 Python
Python直接赋值及深浅拷贝原理详解
2020/09/05 Python
python利用xlsxwriter模块 操作 Excel
2020/10/14 Python
使用HTML5 Canvas绘制直线或折线等线条的方法讲解
2016/03/14 HTML / CSS
详解HTML5中的拖放事件(Drag 和 drop)
2016/11/14 HTML / CSS
浅谈HTML5新增和废弃的标签
2019/04/28 HTML / CSS
小狗电器官方商城:中国高端吸尘器品牌
2017/03/29 全球购物
写出SQL四条最基本的数据操作语句(DML)
2012/12/12 面试题
工程力学专业毕业生求职信
2013/10/06 职场文书
工会2014法制宣传日活动总结
2014/11/01 职场文书
2016公司中秋节寄语
2015/12/07 职场文书
如何用Node.js编写内存效率高的应用程序
2021/04/30 Javascript