uniapp 调用蓝牙接收数据、发送指令后接收返回结果

2023-11-18

一、连接蓝牙设备

1.初始化蓝牙

先判断本机的蓝牙是否打开

           initBle() {
				console.log('--------------------初始化蓝牙----------------');
				this.bleDevs = [];
				uni.openBluetoothAdapter({
					success: (res) => { //已打开
						uni.getBluetoothAdapterState({ //蓝牙的匹配状态
							success: (row) => {
								console.log(row)
								// 开始搜索蓝牙设备
								this.startBluetoothDeviceDiscovery()
							},
							fail(error) {
								uni.showToast({
									icon: 'none',
									title: '查看手机蓝牙是否打开'
								});
							}
						});

					},
					fail: err => { //未打开 
						uni.showToast({
							icon: 'none',
							title: '查看手机蓝牙是否打开'
						});
					}
				})
			},

2.搜索蓝牙

// 开始搜索蓝牙设备
			startBluetoothDeviceDiscovery() {
				let _this = this
				uni.startBluetoothDevicesDiscovery({
					success: (res) => {
						console.log('搜索蓝牙外围设备完成', res)
						_this.timer1 = setTimeout(() => { //加个延迟、目的是为了设备搜索完毕再获取列表,不然获取为空列表
							// 获取设备列表
							_this.onBluetoothDeviceFound()

						}, 1000)

					},
					fail: (err)=> {
						console.log(err)
					}
				})
			},

3.获取设备列表

// 获取设备列表
			onBluetoothDeviceFound() {
				let that = this
				uni.getBluetoothDevices({
					success: function(res) {
						//过滤掉name为空的设备
						var bluetoothArr = res.devices.filter(function(obj) {
							return obj.name != ""
						})
						that.bleDevs = bluetoothArr
					},
					fail: function() {
						console.log("搜索蓝牙设备失败");
						uni.showToast({
							title: '搜索蓝牙设备失败或附件暂无开启的蓝牙设备',
							icon: 'none',
							duration: 2000
						})
					},
					complete: function() {
						console.log('搜索完成')
						//设备获取完成之后  停止搜索
						uni.stopBluetoothDevicesDiscovery({
							success(res) {
								console.log('停止搜索蓝牙', res)
							}
						})
					}
				})
			},

4.连接设备

//选择设备连接把deviceId传进来
			createBLEConnection(deviceId) {
				let that = this
				this.deviceId = deviceId
				this.pageLoading = true
				//连接蓝牙
				uni.createBLEConnection({
					// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
					deviceId: this.deviceId,
					success(res) {
					console.log("蓝牙连接成功", res)
						that.timer2 = setTimeout(() => {
							// 设置最大传输字节  这里根据情况自己设置
							uni.setBLEMTU({
								deviceId: that.deviceId,
								mtu: 500,//传输字节数
								success() {
									// 获取已连接设备列表
									that.getConnectedBluetoothDevices()
									// 连接成功之后  把已连接的设备从设备列表中删除
									let index = ''
									that.bleDevs.forEach((i, key) => {
										if (i.deviceId == that.deviceId) {
											index = key

										}
									})
									if (index !== '') {
										that.bleDevs.splice(index, 1)
									}
									
									that.pageLoading = false
									//获取服务 
									// that.getBLEDeviceServices()
								}
							})
						}, 1000)

					},
					fail(res) {
						console.log("蓝牙连接失败", res)
						uni.showToast({
							icon: 'none',
							title: '蓝牙连接失败'
						})
					}
				})
			},

二、接收数据

只有设备的特征值支持notify 才能接收数据

1. 获取设备服务列表

//获取蓝牙的所有服务
			getBLEDeviceServices(deviceId) {
				let that = this
				uni.getBLEDeviceServices({
					deviceId: deviceId,
					success: (res) => {
						console.log("获取服务成功",res)
						//这里会获取到好多个services  uuid  根据实际情况选择自己需要的服务
						console.log("services", res.services)
						if (res.services.length > 0) {
							let serviceId = res.services[2].uuid //根据我们的设备  使用的是第三个服务
							that.serviceId=res.services[2].uuid
							//获取服务特征
							this.getBLEDeviceCharacteristics(deviceId, serviceId)
						}

					},
					fail(res) {
						console.log("获取蓝牙失败", res)
					}
				})
			},

2. 获取蓝牙特征

如果 notify:true 或indicate :true 支持接收数据 write:true 支持发送数据 read:true 支持读取数据

//获取蓝牙特征
			getBLEDeviceCharacteristics(deviceId, serviceId) {
				console.log("------------------进入特征------------------");
				let that = this
				uni.getBLEDeviceCharacteristics({
					deviceId: deviceId,
					serviceId: serviceId,
					success: (res) => {
						console.log("res.characteristics.", res.characteristics)
						that.characteristics = res.characteristics
						// 这里哪个特征支持notify或indicate  就选择哪个
						that.characteristicId = res.characteristics[0].uuid // 接收数据的特征uuid
						that.characteristicId2 = res.characteristics[1].uuid  //发送数据的特征uuid
						that.notifyBLECharacteristicValueChange(deviceId,serviceId,that.characteristicId)
					},
					fail: (res) => {
						console.log(res)
					}
				})
			},

3. 接收设备数据

// 启用 notify 功能
			notifyBLECharacteristicValueChange(deviceId,serviceId,characteristicId) {
				let that = this
				uni.notifyBLECharacteristicValueChange({
					state: true, // 启用 notify 功能
					deviceId: deviceId,
					serviceId: serviceId,
					characteristicId: characteristicId,
					success: (res) => {
						//监听设备发送数据
						uni.onBLECharacteristicValueChange((res) => {
							console.log("监听成功", res.value)
							// ArrayBuffer
							//res.value是ArrayBuffer类型的,转换成需要的格式,我们再进行操作
							//这是转换成ASCII码
							let str =that.ab2ascii(res.value)
							//转换后的数据
							that.data = str
						})
					},
					fail: (res) => {
						console.log('启用 notify 功能失败', res)
						uni.showToast({
							icon:'none',
							title:'设备暂不支持接收数据',
							duration:3000
						})
					}
				})
			},
			// 二进制流转ascii
			ab2ascii(buffer) {
				var str = Array.prototype.map.call(
					new Uint8Array(buffer),
					function(bit) {
						return String.fromCharCode(bit);
					}
				)
				return str.join('');
			},
			

三、向设备发送数据,并接收返回数据

发送数据和接收数据的操作类似 先获取服务和支持write的蓝牙特征,支持write的特征写入数据 、支持notify 接收数据

// 向蓝牙写入数据
			BleWrite(instruction) {
				//instruction  写入的数据
				let _this = this
				let serviceId = _this.serviceId
				//characteristicId2  是支持write 特征uuid
				let characteristicId = _this.characteristicId2

				let deviceId = _this.deviceId
				//转换数据格式
				const buffer = _this.asciiToArrayBuffer(instruction);
				uni.writeBLECharacteristicValue({
					deviceId, // 蓝牙设备 deviceId
					serviceId, // 蓝牙服务uuid,即第二个uuid
					characteristicId, // 蓝牙特征值的 (即 writeId)
					value: buffer, // 这里的value是ArrayBuffer类型
					writeType: 'write',
					success(res) {
						console.log('指令下发成功==', res)
						//写入成功之后  如需接收数据   在上面的接收数据处获取返回的结果
					},
					fail(err) {
						console.log('指令发送失败', err)
						uni.showToast({
							icon: "none",
							title: "指令发送失败",
							duration: 3000
						})
					}
				})
			},
			// ascii  转  二进制流
			asciiToArrayBuffer(str) {
				if (!str) {
					return new ArrayBuffer(0);
				}
				var buffer = new ArrayBuffer(str.length);
				// let dataView = new DataView(buffer)
				var bufView = new Uint8Array(buffer);
				for (var i = 0, strLen = str.length; i < strLen; i++) {
					bufView[i] = str.charCodeAt(i);
				}
				return buffer;
			},
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

uniapp 调用蓝牙接收数据、发送指令后接收返回结果 的相关文章

  • Redux 状态在 mapStateToProps 中未定义

    我目前正在关注this http teropa info blog 2015 09 10 full stack redux tutorial html教程 我遇到了一些障碍mapStateToProps在下面的代码中 import Reac
  • 主干关系事件未触发?

    class TheModel extends Backbone RelationalModel relations type Backbone HasMany key subModels relatedModel SubModel coll
  • 在 Web 浏览器中查找触发 then 事件的 jQuery 代码

    我加入了一个团队来从事一个项目 现在他们使用 jQuery 并且很多 javascript 文件都是外部文件而不是嵌入的 当我点击一个按钮时 它看起来就像 a class button cancel Cancel a 它触发一个在一个 ja
  • ReferenceError:找不到变量:需要

    我在加载时遇到问题node modules到我的网页之一 我已经安装了 npm node js 并且我想使用require 函数在我的网站上初始化 Firebase 我不知道为什么 但它抛出引用错误 ReferenceError 找不到变量
  • HTMLImageElement 作为 React Child 无效

    我正在尝试异步加载图像 并且仅在加载图像后才将其显示在 React 应用程序中 componentDidMount const img new Image img onload gt this setState originalImage
  • 如何向 jQuery Tokeninput 添加占位符?

    如何将占位符添加到 jQuery Tokeninput 字段 一个正常的placeholder属性在这里不起作用 对于这样的输入
  • 使用 Javascript 在 Imacros 中循环

    我如何使用 javascript 循环 imm imacros 脚本 我搜索了一下 发现了这个 for i 0 i lt n i iimPlay marconame iim 但当我使用它时 我的浏览器 Firefox 18 挂起 for i
  • 为什么 jQuery 点击事件会多次触发

    我这里有这个示例代码http jsfiddle net DBBUL 10 http jsfiddle net DBBUL 10 document ready function creategene click function confir
  • 计算Javascript中两次点击之间的时间

    我想用 javascript 计算属性的两次点击之间的时间 但我不知道如何 例如 a href click here a 如果用户单击多次 假设 5 秒内 我想显示警报 如果有帮助的话我正在使用 jQuery 我对 javascript 不
  • 将音频与视频流合并 Node.js

    我正在创建 YouTube 视频下载器并且正在使用ytdl core库 它无法下载带有音频的高质量视频 因为 youtube 将其放在另一个文件中 但我需要将其全部下载到一个文件中 我已经这样做了 app get download asyn
  • 如何记录返回的事件发射器

    如何记录所发出的事件stream返回于MyFunc 与 JSDoc MyFunc description param Object opts description return Stream description function My
  • 使react-leaflet能够离线使用

    我一直在使用反应传单 https github com PaulLeCam react leaflet图书馆 到目前为止运作良好 现在我希望网站预加载尽可能多的图块 以便网络应用程序 也是 PWA 可以在没有互联网的情况下使用 我找到了一些
  • 用数组反向查找对象

    假设我有一个这样的对象 resourceMap a 0 1 2 3 4 5 6 7 8 9 10 b 11 12 c 21 23 d 54 55 56 57 510 确定是否的最佳方法是什么resourceId 21将会 c 我们不知道钥匙
  • 如何滚动到div内的元素?

    我有一个滚动的div我想在点击它时发生一个事件 它会强制执行此操作div滚动以查看内部元素 我写的JavasCript是这样的 document getElementById chr scrollIntoView true 但这会在滚动时滚
  • 如何访问另一个 mobx 商店中的 mobx 商店?

    假设以下结构 stores RouterStore js UserStore js index js each of Store jsfiles 是一个 mobx 存储类 包含 observable and action index js只
  • WebRTC:通道、轨道和流与 RTP SSRC 和 RTP 会话之间的关系

    来自 Mozilla 网站 https developer mozilla org en US docs Web API Media Streams API https developer mozilla org en US docs We
  • ES6 模板文字的延迟执行

    我正在玩新的ES6 模板文字 http tc39wiki calculist org es6 template strings 我首先想到的是String format对于 JavaScript 所以我开始实现一个原型 String pro
  • 您如何看待引导模式触发器的相应回调?

    On 引导模态 http getbootstrap com javascript modals 我们知道我们可以为触发器绑定事件 例如show or hide using show shown hide hidden 但此事件绑定仅适用于一
  • 当选择下拉列表中的某些值时,取消选中复选框

    当我从下拉列表中选择某个值或用户未从下拉列表中选择任何值时 我需要取消选中复选框 我现在正在使用 Jquery 这是我现在使用的代码 但它不起作用 Script
  • 如何在 SVG 元素上使用箭头标记?

    我需要在 d3 js 中创建一个箭头 但我找到的只是带有节点图的示例 我需要的是简单地制作一个从 A 点到 B 点的箭头 我尝试实现以下示例中的部分代码 http bl ocks org 1153292 http bl ocks org 1

随机推荐

  • JVM面试FAQ分析

    JVM面试FAQ分析 1 入门部分 1 1为什么要学习JVM 1 2 你了解哪些JVM产品 1 3 JVM的构成有哪几部分 2 类加载部分 2 1 你知道哪些类加载器 2 2 什么是双亲委派类加载模型 2 3 双亲委派方式加载类有什么优势
  • AdaBoost算法

    参考 https www bilibili com video BV1ix411i7yp p 26 机器学习技法 之 聚合模型 Aggregation Model 士杰的博客 CSDN博客 聚合模型
  • Java当中解析ini文件对应到JavaBean当中

    目录 1 ini文件简介 2 ini文件 3 ini解析工具类 4 示例运行结果 1 ini文件简介 ini 文件是Initialization File的缩写 即初始化文件 是windows的系统配置文件所采用的存储格式 统管window
  • 使用Nginx做反向代理超时的问题

    使用Nginx做反向代理时 当被代理服务器没有在指定时间内创建连接 接受请求或返回响应时 Nginx就会断开连接 并返回给客户端 504 Gateway Time out 错误 关于Nginx做反向代理超时 可以通过proxy connec
  • java判断是否为金额

    金额验证 public static boolean isNumber String str java util regex Pattern pattern java util regex Pattern compile 1 9 1 d 0
  • VsCode 常用好用插件/配置+开发Vue 必装的插件

    一 VsCode 常用好用插件 1 实时刷新网页的插件 LiveServer 2 open in browser 支持快捷键与鼠标右键快速在浏览器中打开html文件 支持自定义打开指定的浏览器 包括 Firefox Chrome Opera
  • vue3+tsx+element-plus封装组件总结

    最近在做vue3 plan tsx element plus的项目 tsx在我这里是用来做组件的 以往的开发方式是sfc 就是vue页面的写法
  • java socket 阻塞模式_关于socket的Accept阻塞模式的退出方法分析

    众所周知 socket的Accept会阻塞当前线程 如果子程序 或者类在被回收时 没有正确的中止socket 则会引发一些异常 我说下常用的一些处理方法 1 强行中断线程 这种方法我觉得是最差的 因为强行中断正在执行的线程 可能会引发一些意
  • 基于51单片机实现8位数码管显示表白数字(Proteus仿真)

    wechat 嵌入式工程师成长日记 具体功能实现 8位数码管从左往右显示 5201314 并且不闪烁 使用器件 若干电阻 4只LED红灯 8位数码管 总线 排阻 NPN三极管 AT89C51芯片 Proteus仿真原理图 WeChat 愿随
  • Unity 将图片做成预制体

    Unity 将图片做成预制体 刚导入Assets的图片是无法直接拖入场景中的 若我们想要将图片变成预制体 需要做一点转化 方法如下 选中想要转成预制体的图片 更改如下图 然后就可以将图片拖入场景中 进而拖进Assets里面制成预制体啦
  • 【如何卸载Alitum Designer10】

    我由于装了AD20 所以想要卸载掉AD10 但是无论是用电脑管家还是电脑的控制面板里面都无法卸载AD10 百度了下 亲测方法可行 故在此分享一下 找到D Program Files x86 Altium AD 10 System Insta
  • interview2-框架篇

    一 Spring篇 1 Spring 1 Bean线程安全问题 不是线程安全的 Spring框架中有一个 Scope注解 默认的值就是singleton 单例的 因为一般在spring的bean的中都是注入无状态的对象 没有线程安全问题 如
  • PCL alpha shapes平面点云边界特征提取(C++详细过程版)

    边界提取 一 概述 二 代码实现 三 结果展示 一 概述 AlphaShape边界提取算法在PCL里有现成的调用函数 具体算法原理和实现代码见 PCL alpha shapes平面点云边界特征提取 为充分了解AlphaShape算法实现的每
  • MySQL性能调优的10个方法

    1 选择合适的存储引擎 InnoDB 除非你的数据表使用来做只读或者全文检索 相信现在提到全文检索 没人会用 MYSQL 了 你应该默认选择 InnoDB 你自己在测试的时候可能会发现 MyISAM 比 InnoDB 速度快 这是因为 My
  • java 实现邮箱发送邮件功能(端口:465、587)

    使用465端口对邮件进行ssl加密传输 package com example alysslEmail import java security Security import java util Date import java util
  • 解决Eclipse里的注释中文错位问题

    2018年6月之后的eclipse版本 会出现中文注释字体不一 且缩进不一致的问题 如下 解决Eclipse里的注释中文错位问题如下 强迫症请收藏 1 Window gt Preference 2 输入formatter 选择如下 然后Ed
  • 计算机网络之物联网的特点及其主要应用领域

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 目录 前言 一 物联网的概念及其特点 1 1 物联网的概念 1 2 物联网的特点 二 物联网的分类及其主要应用领域 总结 前言 物联网是新一代信息技术的重要组成部分 也是信息
  • openGL之API学习(一九九)纹理单元和纹理对象的关系

    glGenTextures产生的是纹理对象 简称纹理 纹理单元数量在GPU上确定的 不需要创建 glBindTexture将纹理对象绑定到当前纹理单元的的目标类型上 一个纹理单元可以有多个类型1D 2D等 一个纹理对象能够绑定到多个目标类型
  • 不需要带手机直接选择刷脸支付

    刷脸成为了现实 各地实行刷脸的试点都取得成功 刷脸也就这样的走进我们的生活 不需要带手机 钱包 直接选择刷脸 当然 方便的还是无须等待排队 原本一个收银台需要配备一名收银员 所以考虑人力成本收银柜台数量是有限的 刷脸支付需要经历的步骤 不到
  • uniapp 调用蓝牙接收数据、发送指令后接收返回结果

    uniapp 调用蓝牙接收数据 向设备发送指令后接收返回结果 一 连接蓝牙设备 1 初始化蓝牙 2 搜索蓝牙 3 获取设备列表 4 连接设备 二 接收数据 1 获取设备服务列表 2 获取蓝牙特征 3 接收设备数据 三 向设备发送数据 并接收