微信小程序:BLE蓝牙开发

一、添加蓝牙权限:

1.添加蓝牙权限(工程/app.json):

{
  ...,
  "permission": {
    "scope.bluetooth": {"desc": "BLE蓝牙开发"},
    "scope.userLocation": {"desc": "BLE蓝牙开发定位"},
    "scope.userLocationBackground": {"desc": "BLE蓝牙开发后台定位"}
  }
}

二、实现扫描/连接/接收BLE设备数据:

1.实现BLE蓝牙设备扫描:

const TIMEOUT = 10000;
var isInit = false
var isScanning = false
var timer = null
var mTimeout = TIMEOUT;
//开始扫描
function startScan({
  timeout = TIMEOUT,
  onFindCallback,
  onStopCallback
}) {
  if (isScanning) return
  console.log('0.开始初始化蓝牙 >>>>>>')
  mTimeout = timeout
  listenerScanResult(onFindCallback) //监听扫描结果
  wx.openBluetoothAdapter({ // 初始化蓝牙
    mode: 'central', //小程序作为中央设备
    success: (res) => { //初始化蓝牙成功
      isScanning = true
      console.log('1.开始扫描设备 >>>>>>')
      wx.startBluetoothDevicesDiscovery({
        allowDuplicatesKey: false
      }) //开始搜索蓝牙设备
      startTimer(onStopCallback)
    },
    fail: (res) => { //初始化蓝牙失败
      if (res.errCode !== 10001) return
      wx.onBluetoothAdapterStateChange((res) => {
        if (!res.available) return
        isScanning = true
        console.log('1.开始扫描设备 >>>>>>')
        wx.startBluetoothDevicesDiscovery({
          allowDuplicatesKey: false
        }) //开始搜索蓝牙设备
        startTimer(onStopCallback)
      })
    }
  })
}

function startTimer(onStopCallback) {
  cancelTimer()
  timer = setTimeout(function () {
    stopScan()
    if (onStopCallback != null && typeof onStopCallback === 'function') {
      onStopCallback() //停止扫描回调外部
    }
  }, mTimeout) //默认10秒后停止扫描
}

function cancelTimer() {
  if (timer != null) {
    clearTimeout(timer)
    timer = null
  }
}
//监听并处理扫描结果
function listenerScanResult(onFindCallback) {
  if (isInit) return
  isInit = true
  wx.onBluetoothDeviceFound((res) => { //监听扫描结果
    res.devices.forEach((device) => {
      if (!device.name.startsWith('T')) return //过滤非本公司蓝牙设备
      console.log('扫到设备, deviceName: ', device.name)
      if (onFindCallback != null && typeof onFindCallback === 'function') {
        onFindCallback(device) //找到设备回调外部
      }
    })
  })
}
//是否扫描中
function isScan() {
  return isScanning
}
//停止扫描
function stopScan() {
  console.log('停止扫描设备 >>>>>>')
  cancelTimer()
  if (!isScanning) return;
  isScanning = false;
  wx.stopBluetoothDevicesDiscovery() //停止扫描
}

module.exports = {
  startScan,
  isScan,
  stopScan
}

2.实现连接设备/接收数据:

var Scan = require('../ble/scan/Scan')
const SET_MODE_SERVICE_UUID = "0000180f-0000-1000-8000-00805f9b34fb" //设置模式-服务UUID
const SET_MODE_CHARACTERISTIC_UUID = "00002a19-0000-1000-8000-00805f9b34fb" //设置模式-特征值UUID
const SET_MODE_DESCRIPTOR_UUID = "00002902-0000-1000-8000-00805f9b34fb" //设置模式-特征值描述UUID(固定不变)
const WRITE_DATA_SERVICE_UUID = "01ff0100-ba5e-f4ee-5ca1-eb1e5e4b1ce1" //写数据-服务UUID
const WRITE_DATA_CHARACTERISTIC_UUID = "01ff0101-ba5e-f4ee-5ca1-eb1e5e4b1ce1" //写数据-特征值UUID
const ENABLE_NOTIFICATION_VALUE = [0x01, 0x00]; //启用Notification模式
const DISABLE_NOTIFICATION_VALUE = [0x00, 0x00]; //停用Notification模式
const ENABLE_INDICATION_VALUE = [0x02, 0x00]; //启用Indication模式
const TIMEOUT = 10000;
var timer = null
var onConnected = null
var onDisconnect = null
var onRead = null
var writeService = null
var writeCharacteristic = null
var isConnecting = false
var isConnected = false
var mDevice = null

function startTimeoutCheck() {
  cancelTimeoutCheck()
  timer = setTimeout(function () {
    close() //超时后关闭蓝牙连接
  }, TIMEOUT) //10秒后超时
}

function cancelTimeoutCheck() {
  if (timer != null) {
    clearTimeout(timer)
    timer = null
  }
}
//1.扫描
function start({
  deviceName,
  timeout = 10000,
  onDeviceNotFindCallback,
  onConnectedCallback,
  onDisconnectCallback,
  onReadCallback
}) { //开始扫描
  if (isConnecting || isConnected) return
  onConnected = onConnectedCallback
  onDisconnect = onDisconnectCallback
  onRead = onReadCallback
  Scan.startScan({
    timeout: timeout,
    onFindCallback: function (device) { //找到设备回调函数
      if (device.name == deviceName) {
        mDevice = device
        Scan.stopScan() //停止扫描
        connect(device) //转 - 2.连接
      }
    },
    onStopCallback: function () { //停止扫描回调函数
      if (mDevice == null) {
        console.log("没找到设备 >>>>>>")
        onDeviceNotFindCallback() //没扫描到设备时, 回调外部
      }
    }
  })
}
//2.连接
function connect(device) { //开始连接
  console.log("2.开始连接 >>>>>>deviceName: " + device.name)
  isConnecting = true
  startTimeoutCheck()
  wx.createBLEConnection({
    deviceId: device.deviceId, //设备的 deviceId
    success: () => { // 连接成功
      console.log("连接成功 >>>>>>deviceName: " + device.name)
      cancelTimeoutCheck()
      if (onConnected != null && typeof onConnected === 'function') {
        onConnected() //连接成功回调外部
      }
      requestMtu(device); //设置MTU
      discoverServices(device) //开始扫描服务
    },
    fail: (res) => { //连接失败
      console.log("连接失败 >>>>>>deviceName: " + device.name)
      cancelTimeoutCheck()
      close() //连接失败关闭蓝牙连接
      if (onDisconnect != null && typeof onDisconnect === 'function') {
        onDisconnect() //关闭连接回调外部
      }
    }
  })
}
//2.1.设置MTU
function requestMtu(device) {
  console.log("2.1.请求设置mtu为512 >>>>>>name: " + device.name)
  wx.setBLEMTU({
    deviceId: device.deviceId,
    mtu: 200, //最大传输字节
    success: (res) => { // mtu设置成功
      console.log("mtu设置成功 >>>>>>deviceName: " + device.name + " 当前mtu: " + res.mtu)
    },
    fail: () => { // mtu设置失败
      console.log("mtu设置失败 >>>>>>deviceName: " + device.name)
    }
  })
}
//3.发现服务
function discoverServices(device) {
  console.log("3.开始发现服务 >>>>>>deviceName: " + device.name)
  startTimeoutCheck()
  wx.getBLEDeviceServices({
    deviceId: device.deviceId, //设备的 deviceId
    success: (res) => {
      console.log("发现服务成功 >>>>>>deviceName: " + device.name)
      cancelTimeoutCheck()
      isConnecting = false
      isConnected = true
      var len = res.services.length
      for (let i = 0; i < len; i++) {
        var serviceItem = res.services[i]
        var serviceUuid = serviceItem.uuid;
        if (serviceUuid.toUpperCase() == SET_MODE_SERVICE_UUID.toUpperCase()) { //找到设置模式的服务
          console.log("3.1.找到设置模式的服务 >>>>>>deviceName: " + device.name + "  serviceUuid: " + SET_MODE_SERVICE_UUID)
          readCharacteristics(device, serviceItem); //读取特征值
        } else if (serviceUuid.toUpperCase() == WRITE_DATA_SERVICE_UUID.toUpperCase()) { //找到写数据的服务
          console.log("3.2.找到写数据的服务 >>>>>>deviceName: " + device.name + "  serviceUuid: " + WRITE_DATA_SERVICE_UUID)
          writeService = serviceItem;
          readCharacteristics(device, serviceItem); //读取特征值
        }
      }
    }
  })
}
//4.读取特征值(读出设置模式与写数据的特征值)
function readCharacteristics(device, serviceItem) {
  wx.getBLEDeviceCharacteristics({
    deviceId: device.deviceId, //设备的 deviceId
    serviceId: serviceItem.uuid, // 上一步中找到的某个服务id
    success: (res) => {
      var len = res.characteristics.length
      for (let i = 0; i < len; i++) {
        var characteristicItem = res.characteristics[i]
        var characteristicUuid = characteristicItem.uuid;
        if (characteristicUuid.toUpperCase() == SET_MODE_CHARACTERISTIC_UUID.toUpperCase()) { //找到设置模式的特征值
          console.log("4.1.找到设置模式的特征值 >>>>>>deviceName: " + device.name + "  characteristicUUID: " + SET_MODE_CHARACTERISTIC_UUID);
          setNotificationMode(device, serviceItem, characteristicItem); //设置为Notification模式(设备主动给手机发数据)
        } else if (characteristicUuid.toUpperCase() == WRITE_DATA_CHARACTERISTIC_UUID.toUpperCase()) { //找到写数据的特征值
          console.log("4.2.找到写数据的特征值 >>>>>>deviceName: " + device.name + "  characteristicUUID: " + WRITE_DATA_CHARACTERISTIC_UUID);
          writeCharacteristic = characteristicItem; //保存写数据的征值
        }
      }
    }
  })
}
//4.1.设置为Notification模式(设备主动给手机发数据),Indication模式需要手机读设备的数据
function setNotificationMode(device, serviceItem, characteristicItem) {
  console.log("4.1.设置为通知模式 >>>>>>name: " + device.name)
  wx.onBLECharacteristicValueChange((data) => { //监听设备数据
    if (data == null) return;
    console.log("接收数据 >>>>>>name: " + device.name + "  data: " + data);
    onRead(data); //回调外部,返回设备发送的数据
  })
  wx.notifyBLECharacteristicValueChange({
    deviceId: device.deviceId,
    serviceId: serviceItem.uuid,
    characteristicId: characteristicItem.uuid,
    state: true,
  }) //为指定特征的值设置通知
  if (characteristicItem.properties.write) { // 该特征值可写(即设置模式的descriptor)
    console.log("发送Notification模式给设备 >>>>>>name: " + device.name);
    let buffer = new ArrayBuffer(2)
    let bufSet = new DataView(buffer)
    bufSet.setInt16(0, ENABLE_NOTIFICATION_VALUE[0])
    bufSet.setInt16(1, ENABLE_NOTIFICATION_VALUE[1])
    wx.writeBLECharacteristicValue({
      deviceId: device.deviceId,
      serviceId: serviceItem.serviceId,
      characteristicId: characteristicItem.uuid,
      value: buffer,
    }) //发送Notification模式给设备
  }
}
//发送指令到设备
function writeCommand(data) {
  console.log("发送指令给设备 >>>>>>deviceName: " + device.name + "  data: " + data);
  var len = data.length;
  let buffer = new ArrayBuffer(len)
  let bufSet = new DataView(buffer)
  for (let i = 0; i < len; i++) {
    bufSet.setUint8(i, data[i])
  }
  wx.writeBLECharacteristicValue({
    deviceId: device.deviceId,
    serviceId: writeService.serviceId,
    characteristicId: writeCharacteristic.uuid,
    value: buffer,
  }) //发送指令给设备
}
//断开连接
function close(device) {
  console.log("断开连接 >>>>>>deviceName: " + device.name);
  isConnecting = false
  isConnected = false
  wx.closeBLEConnection({
    deviceId: device.deviceId,
  }) //断开连接
  wx.closeBluetoothAdapter({}) //关闭蓝牙
}

module.exports = {
  start,
  close
}

3.调用例子:

var ConnectManager = require('../../utils/ble/ConnectManager')
...//省略其他
ConnectManager.start({
  deviceName: "T11302002020169", //待连接设备的名称
  onDeviceNotFindCallback: function () { //没找到设备
  },
  onConnectedCallback: function () { //连接成功回调
  },
  onDisconnectCallback: function () { //连接关闭回调
  },
  onReadCallback: function (data) {   //设备发过来的数据
  },
})

  • 5
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值