前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >微信小程序蓝牙开发,微信小程序 蓝牙通讯

微信小程序蓝牙开发,微信小程序 蓝牙通讯

原创
作者头像
高久峰
发布2023-07-02 17:15:30
3330
发布2023-07-02 17:15:30
举报

客户的需求如下:通过微信小程序控制蓝牙ble设备(电子面膜),通过不同指令控制面膜的亮度和时间。

01.首先看下客户的ble设备服务文档:(本部分需要有点蓝牙基础,在调试过程中可以用安卓软件nRF Connect软件来执行测试命令)

UUID

名称

特征属性

说明

FFF0

灯控服务

FFF1

灯控命令

Write

APP 发命令给设备

FFF2

灯状态

Notify

设备发状态给APP

FFF3

验证码通道

Write / Read

用户验证码

FFF4

电池状态

Notify

设备发电池状态给APP

FFF8

修改密码

Write/Read

FFF9

修改设备名称

Write/Read

0xFFF1灯控命令

命令格式:

字段

命令类型

命令数据

当前连接加密码

内容

0xFA

字节数

1

1

3

2

命令类型:

0x01 – 常规模式,命令数据第一个字节为模式(1-3表示模式1-3),第二个字节为开关状态(0为暂停,1为启动)。

0x02 – 个性模式,命令数据第一个数据为强度百分比(1-100),第二个字节是时间低位,第三个字节是时间高位(单位秒)。

FFF2 灯状态

4个字节,数据同灯控命令的(命令类型+命令数据)。

FFF3验证码算法

通道用户连接时加密验证,该通道具有read/write 两种属性。

以下是手机端连接上设备后的加密流程。

手机连接SKLight(记录MAC地址) => 使能SKLight FFF2通道完成 => 读取(read) FFF3 新生成的4个字节的随机数 => 随机数结合设备的MAC地址计算出验证码=> FFF3 将验证码写给 SKLight (建议发3次) 读取验证结果(建议500-1000ms后读取,这时只有0x01一个字节正确,0x00则为失败)=>完成(失败请APP断开连接)

计算验证码的 C 函数:

// mac 为设备MAC地址 , rand为读到的随机数

// auth_data 为计算得到的验证码,2个字节

void getAuthenticationData(uint8_t *mac, uint8_t *rand,uint8_t *auth_data)

{

auth_data [0] = mac[0]^ mac [1]^mac[2]^rand[0]^rand[1];

auth_data [1] = mac[3]^mac[4]^mac[5]^rand[2]^rand[3];

}

FFF4 电池状态

6个字节,字节1为电池电压高8位,字节2为电池电压低8位;字节3为电池电流高8位,字节4为电池电流低8位;字节5为电池电量(1-5),1表示低电量,5表示满电量;字节6为工作计时,为0时表示负载开路。

FFF8修改密码

验证成功后,可以通过该通道进行修改密码:

密码应为字符格式。

数据格式:共12字节:

旧密码

新密码

新密码(重复)

4Bytes

4Bytes

4Bytes

修改密码应该在 500~1000ms 以后读取该通道,读到0x01 说明密码修改成功,否则失败。

FFF9修改设备名称

验证成功后,可以通过该通道进行修改设备广播名称:

数据格式:1~20字节:

1~20

设备名称

修改密码应该在 500~1000ms 以后读取该通道,读到0x01 说明名称修改成功,否则失败。

名称修改完成后于断开连接时生效广播。

02.现在开始进行开发小程序端

    0201.蓝牙适配器开启

代码语言:javascript
复制
wx.openBluetoothAdapter({
  success: function (res) {
    //开启成功,继续搜索操作
  },
  fail:function(){
    //开启失败,后台监听状态处理,注意:在安卓系统中手动开启蓝牙可以监听,苹果在设置中开启监听不到,必须使用快捷图标开启(算是小程序蓝牙之坑)
    wx.onBluetoothAdapterStateChange(function (res) {
      if (res.available) {
          //后台监听到蓝牙适配器的状态变化,并且可用.
      }
    })       
  }
})

    0202.搜索设备

代码语言:javascript
复制
//单纯的去搜索设备,并不会返回搜索列表
wx.startBluetoothDevicesDiscovery({
  success: function (res) {
    //已经执行搜索,查看搜索到的设备列表
    wx.getBluetoothDevices({
      success: function (res) {
        //打印获取到的设备列表,此处可以获取到设备的广播消息
        //设备的deviceId字段要非常注意,安卓返回的硬件mac地址,苹果返回的是uuid
        //当然无论返回什么都不影响你使用小程序蓝牙api
        //但是如果你的服务uuid需要你提供硬件mac地址交互的话需要做兼容处理
        //例如你可以要求蓝牙方在广播数据中保存硬件mac地址.(第2坑)
        console.log(res)
      }
    })    
  }
})

    0203.连接ble设备

代码语言:javascript
复制
wx.createBLEConnection({
  //这里的deviceId就是上一步获取的设备列表的deviceId属性,不用关心这个字段的值,不关心是安卓还是苹果
  deviceId: deviceId,
  success: function (res) {
    console.log(res)
  }
})

    0204.获得验证码

代码语言:javascript
复制
//上面的文档指示我通过FFF3服务uuid读取1个4位数字的验证码
//然后结合设备硬件mac地址通过C算法生成验证码发送给设备

//002.读取后我拿来计算
wx.onBLECharacteristicValueChange(function (characteristic) {

    var macstring = deviceId;//设备mac地址,我处理过.不能直接用搜索列表的deviceId
    var randstring = ab2hex(characteristic.value);//设备给我的4位数字
    var verifycode = getAuthenticationData(macstring, randstring);//需要将C语言的算法转javascript

})
//001.我来读取4位数字
wx.readBLECharacteristicValue({
  deviceId: deviceId,
  serviceId: '0000FFF0-0000-1000-8000-00805F9B34FB',
  characteristicId: '0000FFF3-0000-1000-8000-00805F9B34FB',
  success: function (res) {
  }
})

//003.C语法转换的javascript
function getAuthenticationData(macstring, randstring) {
  var auth_data = new Array();
  //Mac
  var Tempmac = macstring.split(':');
  for (var i = 0; i < Tempmac.length; i++) {
    Tempmac[i] = '0x' + Tempmac[i];
  }
  var mac = new Uint8Array(Tempmac);
  //Mac-End
  //Rand
  var Temprand = new Array();
  var temprandj = 0;
  for (var i = 0; i < randstring.length; i++) {
    Temprand[temprandj] = '0x' + randstring.slice(i, i + 2);
    i++;
    temprandj++;
  }
  var rand = new Uint8Array(Temprand);
  //Rand-End
  auth_data[0] = mac[0] ^ mac[1] ^ mac[2] ^ rand[0] ^ rand[1];
  auth_data[1] = mac[3] ^ mac[4] ^ mac[5] ^ rand[2] ^ rand[3];
  auth_data[0] = auth_data[0].toString(16);
  auth_data[1] = auth_data[1].toString(16);
  return auth_data;
}

    0205.发送验证码

代码语言:javascript
复制
  sendverify(verifycode);

  //发送验证码。文档建议发送3次然后再读取值,如果值是1那么验证通过,其他的uuid指令也通过验证
  sendverify: function (verifycode) {
    var self = this;
    var deviceId =app.globalData.deviceId;
   
    for (var i = 0; i < 3; i++) {
      var hex =verifycode[0] + verifycode[1];
      var typedArray = new Uint8Array(hex.match(/[\da-f]{2}/gi).map(function (h) {
        return parseInt(h, 16)
      }))
      //console.log('本次执行命令:' + hex);
      var buffer = typedArray.buffer
      wx.writeBLECharacteristicValue({
        deviceId: deviceId,
        serviceId: '0000FFF0-0000-1000-8000-00805F9B34FB',
        characteristicId: '0000FFF3-0000-1000-8000-00805F9B34FB',
        value: buffer,
        success: function (res) {
          //console.log('writeBLECharacteristicValue success', res.errMsg)
        }
      })
    }

    //文档建议1000MS后读取验证码
    setTimeout(function () {
      wx.onBLECharacteristicValueChange(function (characteristic) {
        var rescode = parseInt(ab2hex(characteristic.value),10);
        if (rescode ==1) {
          //console.log('通过验证');
          wx.notifyBLECharacteristicValueChange({
            state: true, 
            deviceId: deviceId,
            serviceId: '0000FFF0-0000-1000-8000-00805F9B34FB',
            characteristicId: '0000FFF4-0000-1000-8000-00805F9B34FB',
            success: function (res) {
                //读取电量信息
                wx.onBLECharacteristicValueChange(function (res) {
                  var charge = ab2hex(res.value);
                  console.log('原始数据:'+charge);
                  app.globalData.bettery=parseInt('0x' + charge[8] + charge[9], 16);
                  app.globalData.blecurrent = parseInt('' + charge[4] + charge[5] + charge[6] + charge[7]+'', 16)
                  var dianya = parseInt('' + charge[0] + charge[1] + charge[2] + charge[3] + '', 16)
                  console.log('电压:' + dianya);
                  console.log('电量:' + app.globalData.bettery);
                  console.log('电流:' + app.globalData.blecurrent);                  
                })
              //读取电量信息
            }
          })   
          return;                  
        }
        else {
          //验证码验证失败
          self.setData({
            ishow:0,
            showstatus: { text: 'Err,请尝试重新连接!', status: 1 }
          }); 
          wx.closeBLEConnection({
            deviceId: deviceId
          })                            
        }
      })
      wx.readBLECharacteristicValue({
        deviceId: deviceId,
        serviceId: '0000FFF0-0000-1000-8000-00805F9B34FB',
        characteristicId: '0000FFF3-0000-1000-8000-00805F9B34FB',
        success: function (res) {
        }
      })

    }, 1000)

  },

    0206.灯控测试,常规模式3启动

代码语言:javascript
复制
//指令构造要注意高位和低位的处理
var hex = 'fa010301000c22'

var typedArray = new Uint8Array(hex.match(/[\da-f]{2}/gi).map(function (h) {
return parseInt(h, 16)
}))
var buffer = typedArray.buffer
//指令构造
wx.writeBLECharacteristicValue({
deviceId: deviceId,
serviceId: '0000FFF0-0000-1000-8000-00805F9B34FB',
characteristicId: '0000FFF1-0000-1000-8000-00805F9B34FB',
value: buffer,
success: function (res) {
//console.log('writeBLECharacteristicValue success', res.errMsg)
}
})

附上小程序蓝牙项目地址,可正常运行.star谢谢

gitup地址:我是飞机票

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 0xFFF1灯控命令
    • FFF2 灯状态
    • FFF3验证码算法
      • FFF4 电池状态
      • FFF8修改密码
      • FFF9修改设备名称
      相关产品与服务
      验证码
      腾讯云新一代行为验证码(Captcha),基于十道安全栅栏, 为网页、App、小程序开发者打造立体、全面的人机验证。最大程度保护注册登录、活动秒杀、点赞发帖、数据保护等各大场景下业务安全的同时,提供更精细化的用户体验。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档