当前位置: 首页 > news >正文

微信小程序实现蓝牙开锁、开门、开关、指令发送成功,但蓝牙设备毫无反应、坑

文章目录

  • 开源
  • html
  • JavaScript


开源

wx联系本人获取源码(开源): MJ682517


html

<view><view class="p_l_36 p_r_36"><input class="w_100_ h_80 lh_80 ta_c b_2s_eee radius_20" value="{{instructVal}}" type="text" placeholder="请输入开门指令" bindinput="bindinput" /></view><view class="m_t_36 w_50_ h_90 lh_90 m_l_a m_r_a bc_409eff radius_10 color_fff ta_c" catchtap="openBluetoothAdapter">蓝牙开锁</view>
</view>

JavaScript

需要从下往上阅读,使用函数自调的方式解决API不能及时获取数据的问题,替换方案是使用定时器,但是个人觉得定时器不好,所以使用了函数自调的方式实现获取不到数据的问题。

getBluetoothDevices方法中获取deviceIdgetBLEDeviceServices方法中获取到serviceId,获取到的是数组,取数组中的uuid作为serviceId值,具体用哪个值,需要与蓝牙设备文档比对;getBLEDeviceCharacteristics方法中获取characteristicId,获取到的是数组,取数组中的uuid作为characteristicId值。

一般情况的对应的值如下
serviceId: 0000FFB0-0000-1000-8000-00805F9B34FB
notifyId: 0000FFB2-0000-1000-8000-00805F9B34FB
writeId: 0000FFB1-0000-1000-8000-00805F9B34FB
注意观察第一个横杠前面最后两位的值,不难发现规律。
写入的指令一般是以十六进制(EE03E30100)字符串的方式,最后转为二进制发送给蓝牙。

坑: 在不确定蓝牙文档是否正确的情况下,写入成功,但是蓝牙设备毫无反应,那么大概率就是写入的指令有问题,所以需要校对一下指令是否正确。

蓝牙文档需要与厂商获取。

获取蓝牙服务值方法getBLEDeviceServices
获取蓝牙特征值方法getBLEDeviceCharacteristics。特征值一般包括两个,一个代表写入值,一个代表读取值,意思是说写入的是需要把写入的特征值带上,读取的时候把读取的特征值带上。

notifyBLECharacteristicValueChange方法启用蓝牙低功耗设备特征值变化时的notify功能,订阅特征。此时传入的是读取的特征值。

// index.js
let timeout = undefined;Page({data: {devices: [],deviceId: '',services: [],serviceId: '',characteristics: [],characteristicId: '',instructVal: 'EE03E30100'},// 指令输入bindinput({detail: {value}}) {this.setData({instructVal: value});},// 失败时的统一提示failShowToast(title = '开锁失败') {clearTimeout(timeout);timeout = undefined;wx.hideLoading();wx.showToast({icon: 'none',title});},/*** 根据不同方法名调用方法,统一定时器的触发判断,* 当定时器触发时,无法确定当前调用的方法是哪个* @param {String} fnName */methodExecution(fnName = '') {if (timeout) this[fnName]();},// 关闭蓝牙模块closeBluetoothAdapter() {let that = this;// 关闭蓝牙模块wx.closeBluetoothAdapter({success() {},fail() {that.methodExecution('closeBluetoothAdapter');}});},// 断开与蓝牙低功耗设备的连接closeBLEConnection() {let that = this;// 断开与蓝牙低功耗设备的连接wx.closeBLEConnection({deviceId: that.data.deviceId,success() {that.closeBluetoothAdapter();},fail() {that.methodExecution('closeBLEConnection');}});},// 向蓝牙低功耗设备特征值中写入二进制数据writeBLECharacteristicValue() {let that = this;let str = that.data.instructVal;if (!str) return wx.showToast({title: '请输入指令',icon: 'none'});/* 将数值转为ArrayBuffer类型数据 */let typedArray = new Uint8Array(str.match(/[\da-f]{2}/gi).map((h) => parseInt(h, 16))),buffer = typedArray.buffer;// 向蓝牙低功耗设备特征值中写入二进制数据wx.writeBLECharacteristicValue({deviceId: that.data.deviceId,serviceId: that.data.serviceId,characteristicId: '0000FFB1-0000-1000-8000-00805F9B34FB',value: buffer,success() {clearTimeout(timeout);timeout = undefined;wx.hideLoading();wx.showToast({icon: 'none',title: '开锁成功'});// that.closeBLEConnection();},fail() {that.methodExecution('writeBLECharacteristicValue');}});},// 监听蓝牙低功耗设备的特征值变化事件onBLECharacteristicValueChange() {let that = this;// 监听蓝牙低功耗设备的特征值变化事件wx.onBLECharacteristicValueChange((res) => {if (res.value) {that.writeBLECharacteristicValue();} else {that.methodExecution('onBLECharacteristicValueChange');}});},// 启用蓝牙低功耗设备特征值变化时的 notify 功能,订阅特征notifyBLECharacteristicValueChange() {let that = this;// 启用蓝牙低功耗设备特征值变化时的 notify 功能,订阅特征wx.notifyBLECharacteristicValueChange({state: true,deviceId: that.data.deviceId,serviceId: that.data.serviceId,characteristicId: that.data.characteristicId,success() {that.onBLECharacteristicValueChange();},fail() {that.methodExecution('notifyBLECharacteristicValueChange');}});},// 获取蓝牙低功耗设备某个服务中所有特征 (characteristic)getBLEDeviceCharacteristics() {let that = this;// 获取蓝牙低功耗设备某个服务中所有特征 (characteristic)wx.getBLEDeviceCharacteristics({deviceId: that.data.deviceId,serviceId: that.data.serviceId,success({characteristics}) {that.setData({characteristics,characteristicId: '0000FFB2-0000-1000-8000-00805F9B34FB'}, () => that.notifyBLECharacteristicValueChange());},fail() {that.methodExecution('getBLEDeviceCharacteristics');}});},// 获取蓝牙低功耗设备所有服务 (service)getBLEDeviceServices() {let that = this;// 获取蓝牙低功耗设备所有服务 (service)wx.getBLEDeviceServices({deviceId: that.data.deviceId,success({services}) {that.setData({services,serviceId: '0000FFB0-0000-1000-8000-00805F9B34FB'}, () => that.getBLEDeviceCharacteristics());},fail() {that.methodExecution('getBLEDeviceServices');}});},// 停止搜寻附近的蓝牙外围设备stopBluetoothDevicesDiscovery() {let that = this;// 停止搜寻附近的蓝牙外围设备wx.stopBluetoothDevicesDiscovery({success() {that.getBLEDeviceServices();},fail() {that.methodExecution('stopBluetoothDevicesDiscovery');}});},// 连接蓝牙低功耗设备createBLEConnection() {let that = this;// 连接蓝牙低功耗设备wx.createBLEConnection({deviceId: that.data.deviceId,success() {that.stopBluetoothDevicesDiscovery();},fail() {that.methodExecution('createBLEConnection');}});},// 获取在蓝牙模块生效期间所有搜索到的蓝牙设备getBluetoothDevices() {let that = this;// 获取在蓝牙模块生效期间所有搜索到的蓝牙设备wx.getBluetoothDevices({success({devices}) {for (let i = 0; i < devices.length; i++) {const item = devices[i];if (item.name === 'YX_0A45320C78C6') {item.ASUUID = item.advertisServiceUUIDs[0];that.setData({devices: item,deviceId: item.deviceId}, () => that.createBLEConnection());break;}}that.methodExecution('getBluetoothDevices');},fail() {that.methodExecution('getBluetoothDevices');}});},// 开始搜寻附近的蓝牙外围设备startBluetoothDevicesDiscovery() {let that = this;// 开始搜寻附近的蓝牙外围设备wx.startBluetoothDevicesDiscovery({// 此字段会导致startBluetoothDevicesDiscovery不执行// services: ['YX'],success() {that.getBluetoothDevices();},fail() {that.methodExecution('startBluetoothDevicesDiscovery');}});},// 蓝牙开锁openBluetoothAdapter() {let that = this,thatData = that.data;if (!that.data.instructVal) return wx.showToast({title: '请输入指令',icon: 'none'});if (timeout) return wx.showToast({title: '加载中',icon: 'none'});wx.showLoading({title: '加载中',mask: true});timeout = setTimeout(() => {that.failShowToast('开锁失败');}, 1000 * 26);if (thatData.deviceId && thatData.serviceId && thatData.characteristicId) return that.writeBLECharacteristicValue();// 初始化蓝牙模块wx.openBluetoothAdapter({success() {that.setData({devices: [],deviceId: '',services: [],serviceId: '',characteristics: [],characteristicId: ''}, () => that.startBluetoothDevicesDiscovery());},fail() {that.failShowToast('查看手机蓝牙是否打开');}});},onLoad() {}
})

相关文章:

微信小程序实现蓝牙开锁、开门、开关、指令发送成功,但蓝牙设备毫无反应、坑

文章目录 开源htmlJavaScript 开源 wx联系本人获取源码(开源): MJ682517 html <view><view class"p_l_36 p_r_36"><input class"w_100_ h_80 lh_80 ta_c b_2s_eee radius_20" value"{{instructVal}}" type"text" plac…...

微信小程序中使用echarts方法

小程序中使用echarts echarts是一个基于JS的数据可视化图标库&#xff0c;它提供了直观&#xff0c;生动&#xff0c;可交互&#xff0c;可个性定制的数据可视化图表。一般在vue中会使用到&#xff0c;并且官网也详细的说明了如何在vue中使用&#xff0c;但是今天我想来探讨的…...

【面试题】前端中 JS 发起的请求可以暂停吗?

这个问题非常有意思&#xff0c;我一看到就想了很多可以回复的答案&#xff0c;但是评论区太窄&#xff0c;就直接开一篇文章来写了。 审题 JS 发起的请求可以暂停吗&#xff1f;这一句话当中有两个概念需要明确&#xff0c;一是什么样的状态才能称之为 暂停&#xff1f;二是…...

通过社区参与解锁早期增长:Maven 远程医疗平台概览

Maven通过用户导向的渐进式验证&#xff0c;找到了一个被忽视的巨大女性医疗服务市场&#xff0c;作为女性医疗保健的先行者&#xff0c;已服务超过1500万用户&#xff0c;目前估值已达$14亿。本文将深入探索Maven实现产品市场匹配的三个阶段&#xff0c;从如何验证初始的市场机…...

Vue中使用echarts

1 安装 npm install -g cnpm --registryhttps://registry.npm.taobao.org cnpm install echarts -S 2 main.js引入 3 引入成功...

边缘计算对现代交通的重要作用

边缘计算之所以重要&#xff0c;是在于即使在5G真正商用之时&#xff0c;可以实现超大带宽&#xff08;eMBB&#xff09;的应用场景&#xff0c;但庞大数据量的涌现也就意味着需要在云和端传输过程中找到一个承接点&#xff0c;对数据进行预处理再选择是否上云。 边缘计算应用演…...

Python桥接模式介绍、使用

一、Python桥接模式介绍 概念&#xff1a; Python桥接模式&#xff08;Bridge Pattern&#xff09;是一种软件设计模式&#xff0c;用于将抽象部分与其实现部分分离&#xff0c;使它们可以独立地变化。 它可以通过使用桥接接口来创建一个桥接对象来连接抽象和实现部分。 功能…...

ChatGPT在知识图谱的构建和更新中的应用如何?

ChatGPT在知识图谱的构建和更新中具有重要的应用潜力。知识图谱是一种用于表示和存储结构化知识的图形化数据模型&#xff0c;通常由实体、属性和关系组成。知识图谱的构建和更新是一个复杂而关键的过程&#xff0c;涉及知识的收集、组织、链接和推理。ChatGPT作为一种预训练语…...

JS正则表达式:常用正则手册/RegExp/正则积累

一、正则基础语法 JavaScript 正则表达式 | 菜鸟教程 JS正则表达式语法大全&#xff08;非常详细&#xff09; 二、使用场景 2.1、校验中国大陆手机号的正则表达式 正则 /^1[3456789]\d{9}$/解释 序号正则解释1^1以数字 1 开头2[3456789]第二位可以是 3、4、5、6、7、8、…...

自动化测试框架unittest与pytest的区别!

引言 前面文章已经介绍了python单元测试框架&#xff0c;大家平时经常使用的是unittest&#xff0c;因为它比较基础&#xff0c;并且可以进行二次开发&#xff0c;如果你的开发水平很高&#xff0c;集成开发自动化测试平台也是可以的。而这篇文章主要讲unittest与pytest的区别&…...

【Git】

学习来自于&#xff1a; 女朋友乱用Git&#xff0c;差点把我代码删了。。。 一些常用的Git 知识点整理 关于Git这一篇就够了 Git基本命令大全 30分钟精通Git&#xff0c;学不会来找我 Git 版本管理 | 莫烦PYTHON Git 代码版本管理教程 文章目录 【前言】集中式与分布式的…...

[论文笔记] CLRerNet: Improving Confidence of Lane Detection with LaneIoU

Honda, Hiroto, and Yusuke Uchida. “CLRerNet: Improving Confidence of Lane Detection with LaneIoU.” arXiv preprint arXiv:2305.08366 (2023). 2023.05 出的一篇车道线检测的文章, 效果在CULane, CurveLanes SOTA 文章目录 简介LaneIoULineIoU存在问题为什么使用LaneIo…...

LeetCode|backtracking|review:40. 131. 93. 47. 332. | 37. Sudoku Solver

复习&#xff1a; 40. Combination Sum II [1,1,2,3]中&#xff0c;答案里有[1,1,2], 但是不能有两个[1,2,3] 131. Palindrome Partitioning 每个for都是在给定的start之后找一个palindrome。当start 93. Restore IP Addresses forloop每次loop都是在给定的start的后三个数…...

被泼冷水后,谁能超越微服务?

历史总会重演。一切刚过去的&#xff0c;又会被重新提起。开源项目Codename One的联合创始人Shai&#xff0c;曾是Sun Microsystems开源LWUIT项目的共同作者&#xff0c;参与了无数开源项目。作为最早一批Java开发者&#xff0c;最近感慨道&#xff1a;单体&#xff0c;又回来了…...

多线程(JavaEE初阶系列5)

目录 前言&#xff1a; 1.什么是定时器 2.标准库中的定时器及使用 3.实现定时器 结束语&#xff1a; 前言&#xff1a; 在上一节中小编给大家介绍了多线程中的两个设计模式&#xff0c;单例模式和阻塞式队列模式&#xff0c;在单例模式中又有两种实现方式一种是懒汉模式&a…...

Minimum Snap闭式求解相关公式推导

文章目录 1 M i n i m u m Minimum Minimum S n a p Snap Snap闭式求解的推导1.1 二次规划等式约束构建1.2 求 d d d1.3 转成无约束优化问题 1 M i n i m u m Minimum Minimum S n a p Snap Snap闭式求解的推导 可以看看我的这几篇Blog1&#xff0c;Blog2&#xff0c;Blog…...

Spring源码(五)— 解析XML配置文件(一) bean标签解析流程

前面几章的内容已经介绍了BeanFactory创建前的准备工作&#xff0c;以及加载XML配置文件前的准备的步骤。本章会着重介绍解析XML的步骤。 registerBeanDefinitions 前几个方法不做过多的赘述&#xff0c;着重看registerBeanDefinitions方法中解析XML的步骤。 public int regi…...

隐私政策声明

http://lxfamn.cn/tools 我们注重对您个人隐私的保护。有时候我们需要某些信息才能为您提供您请求的服务&#xff0c;本隐私声明解释了这些情况下的数据收集和使用情况。本隐私声明适用于本网站的所有相关服务。如果您访问本网站、使用本网站的任何服务&#xff0c;那么您便接受…...

Flutter 最佳实践和编码准则

Flutter 最佳实践和编码准则 视频 前言 最佳实践是一套既定的准则&#xff0c;可以提高代码质量、可读性和可靠性。它们确保遵循行业标准&#xff0c;鼓励一致性&#xff0c;并促进开发人员之间的合作。通过遵循最佳实践&#xff0c;代码变得更容易理解、修改和调试&#xff…...

LangChain Agents深入剖析及源码解密上(一)

LangChain Agents深入剖析及源码解密上(一) LangChain Agents深入剖析及源码解密上 Agent工作原理详解 本节会结合AutoGPT的案例,讲解LangChain代理(Agent)为核心的内容。我们前面已经谈了代理本身的很多内容,也看了绝大部分的源代码,例如:ReAct的源代码,还有mrkl的源代…...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

无法与IP建立连接,未能下载VSCode服务器

如题&#xff0c;在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈&#xff0c;发现是VSCode版本自动更新惹的祸&#xff01;&#xff01;&#xff01; 在VSCode的帮助->关于这里发现前几天VSCode自动更新了&#xff0c;我的版本号变成了1.100.3 才导致了远程连接出…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

质量体系的重要

质量体系是为确保产品、服务或过程质量满足规定要求&#xff0c;由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面&#xff1a; &#x1f3db;️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限&#xff0c;形成层级清晰的管理网络&#xf…...

Rapidio门铃消息FIFO溢出机制

关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系&#xff0c;以下是深入解析&#xff1a; 门铃FIFO溢出的本质 在RapidIO系统中&#xff0c;门铃消息FIFO是硬件控制器内部的缓冲区&#xff0c;用于临时存储接收到的门铃消息&#xff08;Doorbell Message&#xff09;。…...

Angular微前端架构:Module Federation + ngx-build-plus (Webpack)

以下是一个完整的 Angular 微前端示例&#xff0c;其中使用的是 Module Federation 和 npx-build-plus 实现了主应用&#xff08;Shell&#xff09;与子应用&#xff08;Remote&#xff09;的集成。 &#x1f6e0;️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...

MySQL 知识小结(一)

一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库&#xff0c;分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷&#xff0c;但是文件存放起来数据比较冗余&#xff0c;用二进制能够更好管理咱们M…...

JS手写代码篇----使用Promise封装AJAX请求

15、使用Promise封装AJAX请求 promise就有reject和resolve了&#xff0c;就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...

MinIO Docker 部署:仅开放一个端口

MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...

《Docker》架构

文章目录 架构模式单机架构应用数据分离架构应用服务器集群架构读写分离/主从分离架构冷热分离架构垂直分库架构微服务架构容器编排架构什么是容器&#xff0c;docker&#xff0c;镜像&#xff0c;k8s 架构模式 单机架构 单机架构其实就是应用服务器和单机服务器都部署在同一…...