微信小程序 蓝牙通讯

news2024/9/30 5:44:38

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

01.首先看下客户的ble设备服务文档:(本部分需要有点蓝牙基础,在调试过程中可以用安卓软件nRF Connect软件来执行测试命令)
在这里插入图片描述
0xFFF1灯控命令
命令格式:

在这里插入图片描述
命令类型:

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字节:
在这里插入图片描述
修改密码应该在 500~1000ms 以后读取该通道,读到0x01 说明密码修改成功,否则失败。

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

数据格式:1~20字节:
修改密码应该在 500~1000ms 以后读取该通道,读到0x01 说明名称修改成功,否则失败。

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

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

0201.蓝牙适配器开启

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

0202.搜索设备

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

0203.连接ble设备

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

0204.获得验证码

//上面的文档指示我通过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.发送验证码

  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启动

//指令构造要注意高位和低位的处理
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)
}
})

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2178808.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PCL 法线空间采样

目录 一、概述 1.1原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 2.1.1 法线计算 2.1.2 基于法线进行采样 2.1.3 可视化原始点云和采样后的点云 2.2完整代码 三、实现效果 PCL点云算法汇总及实战案例汇总的目录地址链接&#xff1a; PCL点云算法与项目实…

英伟达的AI一键生成数字人物理运动动画框架:统一控制模式,提升交互性和沉浸感

在虚拟现实(VR)、增强现实(AR)和3D内容创作领域,创建具有真实感和动态性的虚拟角色一直是技术上的挑战。最近,英伟达推出了一种新的框架,通过将物理驱动的角色控制视为运动修复问题,实现了跨场景的虚拟角色控制。这一创新方法不仅支持多种控制模式,还能够生成连贯且自…

container_of 函数的分析

这个函数的目的是&#xff0c; 通过结构体里面的内容 找到 大结构体的 基地址。 函数的原型是&#xff1a;  &#xff30;&#xff34;&#xff32;是指针 &#xff54;&#xff59;&#xff50;&#xff45; &#xff0c; &#xff4d;&#xff45;&#xff4d;&#xff…

PCL 快速均匀下采样

目录 一、概述 1.1原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 2.1.1 快速均匀下采样 2.1.2 可视化原始点云和下采样后的点云 2.2完整代码 三、实现效果 PCL点云算法汇总及实战案例汇总的目录地址链接&#xff1a; PCL点云算法与项目实战案例汇总&#…

恋爱辅助应用小程序app开发之广告策略

恋爱话术小程序带流量主广告开启&#xff0c;是一个有效的盈利模式&#xff0c;可以增加小程序的收入来源。以下是对此的详细分析 一、流量主广告的定义与优势 流量主广告是指在小程序中嵌入广告位&#xff0c;通过展示广告内容来获取广告主的付费。对于恋爱话术小程序而言&am…

图解C#高级教程(一):委托

什么是委托 可以认为委托是持有一个或多个方法的对象。但它与对象不同&#xff0c;因为委托可以被执行。当执行委托时&#xff0c;委托会执行它所“持有”的方法。先看一个完整的使用示例。 // See https://aka.ms/new-console-template for more informationdelegate void M…

无人机避障—— 激光雷达定高北醒TF03-UART(二)

无人机避障过程&#xff0c;光靠大疆飞控内部的气压计不准&#xff0c;很容易在高度较低的时候受到地面植被等障碍物影响&#xff0c;使得掉高严重&#xff0c;因此采用激光雷达定高模块进行定高。 硬件&#xff1a; 北醒TF03-UART、Xavier-NX 软件代码&#xff1a; 北醒官…

关于没有启用root问题,分区表挂载错误,导致系统无法启动

方法一、root没有登陆过&#xff0c;改root密码 1、为啥这样设置&#xff0c;root 2、密码破解也无效 2.1、开机启动&#xff0c;按 e 进入启动文件界面 2.2、把ro修改为rw&#xff0c;注意r和o之间包了个反斜杠 2.3、ctrl x退出当前模式 2.4、rw initsysroot/bin/sh 2.5、c…

HarmonyOs 查看官方文档使用弹窗

1. 学会查看官方文档 HarmonyOS跟上网上的视频学习一段时间后&#xff0c;基本也就入门了&#xff0c;但是有一些操作网上没有找到合适教学的视频&#xff0c;这时&#xff0c;大家就需要养成参考官方文档的习惯了&#xff0c;因为官方的开发文档是我们学习深度任何一门语言或…

http请求过程 part-2

http请求过程 http应用层 实体 实体分为实体首部和实体主体&#xff0c;实体首部是用来描述主体的 实体部分是可选的&#xff0c;它被用来运送请求或者响应的数据 传输层-TCP HTTP连接是建立在TCP连接的基础上 以流形式通过一条已经打开的TCP连接&#xff0c;按顺序进行…

Django Web开发接口定义

Django Web 介绍 Django Web是一个Pyhton高级 Web 框架,实际上 Django 也可以做到前后端分离,即主要作为后端框架使用,不用模板渲染也是可行的。 Django Web 应用的运行流程,如下图所示: 此外,Django Web 在开发环境可以通过自带的服务器进行本地调试。但是该服务器不适…

LeetCode从入门到超凡(五)深入浅出---位运算

引言 大家好&#xff0c;我是GISer Liu&#x1f601;&#xff0c;一名热爱AI技术的GIS开发者。本系列文章是我跟随DataWhale 2024年9月学习赛的LeetCode学习总结文档&#xff1b;本文主要讲解 位运算算法。&#x1f495;&#x1f495;&#x1f60a; 一、 位运算简介 1.什么是位…

【腾讯元宝-免费论文精读】

【腾讯元宝-免费论文精读】 1. 腾讯混元大模型2. 论文精读过程3. 总结&#xff1a; 1. 腾讯混元大模型 由腾讯研发的大语言模型&#xff0c;具备强大的中文创作能力&#xff0c; 复杂语境下的逻辑推理能力&#xff0c;以及可靠的任务执行能力 腾讯元宝&#xff1a;轻松工作&am…

Django对接支付宝沙箱环境(2024年9月新测有效)

1、申请沙箱环境 #需要填一些个人信息 https://opendocs.alipay.com/ 2、使用支付宝登入&#xff0c;并进入控制台&#xff0c;进入开发者工具推荐-->沙箱 3、获取基本信息 主要是APPID,和支付宝网关地址 4、生成应用私钥和应用公钥和支付宝公钥 上面的接口加签方式选择…

【Linux 22】生产者消费者模型

文章目录 &#x1f308; 一、生产者消费者模型⭐ 1. 生产者消费者模型的概念⭐ 2. 生产者消费者模型的特点⭐ 3. 生产者消费者模型的优点 &#x1f308; 二、基于阻塞队列的生产消费模型⭐ 1. 阻塞队列概念⭐ 2. 模拟实现基于阻塞队列的生产消费模型 &#x1f308; 三、POSIX 信…

Kubernetes云原生存储解决方案之 Rook Ceph实践探究

Kubernetes云原生存储解决方案之 Rook Ceph实践探究 除了手动部署独立的 Ceph 集群并配置与Kubernetes进行对接外&#xff0c;Rook Ceph 支持直接在 Kubernetes 集群上部署 Ceph 集群。 通过Rook Ceph云原生存储编排平台&#xff0c;使得 Kubernetes 集群中启用高可用的 Ceph…

PHP 基础语法详解

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

【有啥问啥】多目标跟踪SORT算法原理详解

多目标跟踪SORT算法原理详解 引言 多目标跟踪&#xff08;Multiple Object Tracking, MOT&#xff09;是计算机视觉领域的一个重要研究方向&#xff0c;广泛应用于视频监控、自动驾驶、人机交互等多个领域。其核心任务是在视频序列中持续、准确地识别和定位多个目标。SORT&am…

爬虫入门之爬虫原理以及请求响应

爬虫入门之爬虫原理以及请求响应 爬虫需要用到的库, 叫requests. 在导入requests库之前, 需要安装它, 打开cmd: 输入pip install 库名 pip install requests后面出现successful或requirement already就说明已经下载成功了!!! 下载出现的问题: 1.有报错或者是下载慢 修改镜像…

计算机的错误计算(一百零八)

摘要 回复网友来信&#xff0c;接前一节本节再谈多项式的错误计算。 例1. 计算 若在Visual Studio 2010中用C#编程计算&#xff1a; using System; using System.Collections.Generic; using System.Linq; class Program { static void Main(){ long part1 946495 * (…