uniapp连接蓝牙操作(蓝牙设备地锁)

 介绍:

本文采用uni-app框架来创建一个简单的用户界面,用于搜索、连接和发送命令给蓝牙设备。

1.打开蓝牙适配器 

function openBluetooth() {uni.openBluetoothAdapter({success() {uni.offBluetoothDeviceFound();// 监听新设备发现事件uni.onBluetoothDeviceFound((res) => {res.devices.forEach(device => {if (device.name && device.name.startsWith('one-parking')) {const existingDevice = devicesInfo.value.find(d => d.deviceId === device.deviceId);if (!existingDevice) {devicesInfo.value.push(device);}}});});// 开始搜索蓝牙设备uni.startBluetoothDevicesDiscovery({success() {console.log('开始搜索蓝牙设备...');// 设置一个定时器,在一定时间后停止搜索setTimeout(stopDiscovery, 10000);},fail(err) {console.error('开始搜索失败', err);}});},fail() {uni.showToast({title: '请打开蓝牙',icon: 'none'});}});}

2.连接蓝牙

function connectBluetooth( data : any ) {bluetoothInfo.value = data;bluetoothInfo.value.deviceId = data.deviceId;uni.createBLEConnection({deviceId : data.deviceId,success() {// 判断连接的状态和断开重新连接checkSttusOrReconnect(data);// 获取蓝牙的服务ServiceIDuni.getBLEDeviceServices({deviceId : data.deviceId,success(servicesRes : any) {if(servicesRes.services.length > 0) {bluetoothInfo.value.serviceId = servicesRes.services[0].uuid;// 获取蓝牙的特征值characteristicIduni.getBLEDeviceCharacteristics({deviceId : data.deviceId,serviceId : servicesRes.services[0].uuid,success(resCharacter) {if(resCharacter.characteristics.length > 0) {bluetoothInfo.value.characteristics = resCharacter.characteristics;// 接受通知notify();let macAddress = data.name.split('-')[1];let password = calculatePassword(macAddress);let bondCommand = `phbond${password}`;sendMsg(bondCommand);}}})}}});}})}

提示:这里根据蓝牙的设备id连接后,一起获取了服务和特征id,用于方便后面蓝牙进行通信,其中的特征值是一个重点,不同的特征值id会对应不同的操作,不然就会操作不了其他的api,比如uni.notifyBLECharacteristicValueChange(OBJECT)这个就需要notify 或者 indicate 才可以成功调用

3.监听蓝牙的通知

    // 接收蓝牙端发送的通知function notify() {uni.notifyBLECharacteristicValueChange({state: true,// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接deviceId : bluetoothInfo.value.deviceId,serviceId: bluetoothInfo.value.serviceId,characteristicId : bluetoothInfo.value.characteristics.find(item => item.properties.notify).uuid,success() {monitorMsg();},fail(res) {console.log('不支持这个notify' + JSON.stringify(res))}})}function monitorMsg() {uni.onBLECharacteristicValueChange((res : any) => {console.log("发送过来的数据---------", res);let resHex = ab2ascii(res.value)console.log("转换后的简易数据----------",resHex);});}

 提示: 刚刚在上面说到的点就是特征值id有多个,需要有对应的特征权限

 4.发送数据

    // 向蓝牙写数据function sendMsg( msg : string ) {uni.writeBLECharacteristicValue({deviceId : bluetoothInfo.value.deviceId,serviceId: bluetoothInfo.value.serviceId,characteristicId : bluetoothInfo.value.characteristics.find(item => item.properties.write).uuid,value: asciiToArrayBuffer(msg) as any,writeType: 'write',success(res) {console.log('消息发送成功', res)},fail(res) {console.log('消息发送失败', res)}});}

注意:其中写数据需要向设备写的是二进制,所以需要转换一下

    // 二进制转化工具function ab2ascii(buffer : ArrayBuffer) {var str = Array.prototype.map.call(new Uint8Array(buffer),function(bit : any) {return String.fromCharCode(bit);})return str.join('');}function asciiToArrayBuffer(str : string) {if (!str) {return new ArrayBuffer(0);}var buffer = new ArrayBuffer(str.length);var bufView = new Uint8Array(buffer);for (var i = 0, strLen = str.length; i < strLen; i++) {bufView[i] = str.charCodeAt(i);}return buffer;}

5.监听蓝牙的状态并发现断开重连

function checkSttusOrReconnect( data : any ) {uni.onBLEConnectionStateChange(function (state) {if (!state.connected) {console.warn('与设备' + data.name + '的连接已断开');if(breakCount.value < 2) {reconnectionTimer = setTimeout(()=>{connectBluetooth(bluetoothInfo.value);},3000);}breakCount.value += 1;} else {console.log('与设备 ' + data.name + ' 的连接已建立');if(reconnectionTimer) { clearTimeout(reconnectionTimer) }breakCount.value = 0;}});
}

6.完整的demo代码(设备是车辆地锁)

<template><view class="pageBox"><view style="font-size: 22px;text-align: center;margin-top: 32px;">蓝牙测试用例</view><view style="margin: 12px;display: flex;flex-direction: column;"><radio-group style="margin: 12px;gap: 26px;display: flex;flex-wrap: wrap;padding: 6px;"><radio value="phup" @click="cmdText = 'phup'">phup(升)</radio><radio value="phdown" @click="cmdText = 'phdown'">phdown(降)</radio><radio value="phstatus" @click=" cmdText = 'phstatus'">phstatus(状态)</radio></radio-group><button @click="sendControllCmd()" style="background-color: #564DD6;color: #fff;border-radius: 26px;margin: 12px;">发送指令</button></view><view style="margin: 22px;font-size: 18px;font-weight: bold;color: royalblue;">蓝牙设置信息:</view><view v-for="devices in devicesInfo"><view style="justify-content: space-between;border-radius: 8px;display: flex;margin: 12px;margin:12px 22px;background-color: #fff;border: 2px dashed #564DD6;padding: 12px;"><view style="display: flex;flex-direction: column;gap: 6px;"><view>设备名称:{{devices.name}}</view><view>ID: {{devices.deviceId}}</view></view><view><button style="margin: 6px;border-radius: 6px;background-color: #9A2CD7;color: #fff;" size="mini" @click="connectBluetooth(devices)">连接</button></view></view></view></view>
</template><script setup lang="ts">import { onReady } from "@dcloudio/uni-app";import { ref } from "vue";onReady(()=>{openBluetooth();});let devicesInfo = ref([]);let reconnectionTimer : any;let breakCount = ref<number>(0);function openBluetooth() {uni.openBluetoothAdapter({success() {uni.offBluetoothDeviceFound();// 监听新设备发现事件uni.onBluetoothDeviceFound((res) => {res.devices.forEach(device => {if (device.name && device.name.startsWith('one-parking')) {const existingDevice = devicesInfo.value.find(d => d.deviceId === device.deviceId);if (!existingDevice) {devicesInfo.value.push(device);}}});});// 开始搜索蓝牙设备uni.startBluetoothDevicesDiscovery({success() {console.log('开始搜索蓝牙设备...');// 设置一个定时器,在一定时间后停止搜索setTimeout(stopDiscovery, 10000);},fail(err) {console.error('开始搜索失败', err);}});},fail() {uni.showToast({title: '请打开蓝牙',icon: 'none'});}});}function stopDiscovery() {uni.stopBluetoothDevicesDiscovery({success() {console.log('停止蓝牙嗅探成功');},fail(err) {console.error('停止蓝牙嗅探失败', err);}});}// 地锁密码获取: 提取MAC地址的最后6位转换为十进制 , 加上520168 , 取结果的最后六位function calculatePassword(mac : string) {let lastSixHex = mac.slice(-6);let hexToInt = parseInt(lastSixHex, 16);let sum = hexToInt + 520168;let finalPassword = ('000000' + sum).slice(-6);return finalPassword;}let bluetoothInfo = ref({deviceId: '',serviceId: '',characteristics: [],devicesInfo: {} // 连接的蓝牙设备});function connectBluetooth( data : any ) {bluetoothInfo.value = data;bluetoothInfo.value.deviceId = data.deviceId;uni.createBLEConnection({deviceId : data.deviceId,success() {// 判断连接的状态和断开重新连接checkSttusOrReconnect(data);// 获取蓝牙的服务ServiceIDuni.getBLEDeviceServices({deviceId : data.deviceId,success(servicesRes : any) {if(servicesRes.services.length > 0) {bluetoothInfo.value.serviceId = servicesRes.services[0].uuid;// 获取蓝牙的特征值characteristicIduni.getBLEDeviceCharacteristics({deviceId : data.deviceId,serviceId : servicesRes.services[0].uuid,success(resCharacter) {if(resCharacter.characteristics.length > 0) {bluetoothInfo.value.characteristics = resCharacter.characteristics;// 接受通知notify();let macAddress = data.name.split('-')[1];let password = calculatePassword(macAddress);let bondCommand = `phbond${password}`;sendMsg(bondCommand);}}})}}});}})}// 检查设备并重连function checkSttusOrReconnect( data : any ) {uni.onBLEConnectionStateChange(function (state) {if (!state.connected) {console.warn('与设备' + data.name + '的连接已断开');if(breakCount.value < 2) {reconnectionTimer = setTimeout(()=>{connectBluetooth(bluetoothInfo.value);},3000);}breakCount.value += 1;} else {console.log('与设备 ' + data.name + ' 的连接已建立');if(reconnectionTimer) { clearTimeout(reconnectionTimer) }breakCount.value = 0;}});}// 接收蓝牙端发送的通知function notify() {uni.notifyBLECharacteristicValueChange({state: true,// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接deviceId : bluetoothInfo.value.deviceId,serviceId: bluetoothInfo.value.serviceId,characteristicId : bluetoothInfo.value.characteristics.find(item => item.properties.notify).uuid,success() {monitorMsg();},fail(res) {console.log('不支持这个notify' + JSON.stringify(res))}})}function monitorMsg() {uni.onBLECharacteristicValueChange((res : any) => {console.log("发送过来的数据---------", res);let resHex = ab2ascii(res.value)console.log("转换后的简易数据----------",resHex);});}let cmdText = ref('');function sendControllCmd() {console.log('发送的指令:' + cmdText.value);sendMsg(cmdText.value);}// 向蓝牙写数据function sendMsg( msg : string ) {uni.writeBLECharacteristicValue({deviceId : bluetoothInfo.value.deviceId,serviceId: bluetoothInfo.value.serviceId,characteristicId : bluetoothInfo.value.characteristics.find(item => item.properties.write).uuid,value: asciiToArrayBuffer(msg) as any,writeType: 'write',success(res) {console.log('消息发送成功', res)},fail(res) {console.log('消息发送失败', res)}});}// 二进制转化工具function ab2ascii(buffer : ArrayBuffer) {var str = Array.prototype.map.call(new Uint8Array(buffer),function(bit : any) {return String.fromCharCode(bit);})return str.join('');}function asciiToArrayBuffer(str : string) {if (!str) {return new ArrayBuffer(0);}var buffer = new ArrayBuffer(str.length);var bufView = new Uint8Array(buffer);for (var i = 0, strLen = str.length; i < strLen; i++) {bufView[i] = str.charCodeAt(i);}return buffer;}</script> <style scoped lang="scss">.pageBox {height: 100%;width: 100%;position: fixed;}
</style>
ui界面
UI操作界面

操作台连接和蓝牙通知日志

最后官方文档地址:
Uniapp蓝牙连接文档icon-default.png?t=O83Ahttps://uniapp.dcloud.net.cn/api/system/bluetooth.html

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

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

相关文章

web:pc端企业微信登录-vue版

官方文档&#xff1a;developer.work.weixin.qq.com/document/pa… 不需要调用ww.register&#xff0c;直接调用ww.createWWLoginPanel即可创建企业微信登录面板 - 文档 - 企业微信开发者中心 (qq.com) 引入 //通过 npm 引入 npm install wecom/jssdk import * as ww from we…

外观模式的理解和实践

外观模式&#xff08;Facade Pattern&#xff09;是一种常用的软件设计模式&#xff0c;它提供了一个统一的接口&#xff0c;用来访问子系统中的一群接口。该模式定义了一个高层的接口&#xff0c;使得子系统更容易使用。简单来说&#xff0c;外观模式就是通过引入一个外观角色…

《应用导航设计:裂变式路由风暴来袭》——HarmonyOS开发项目时的Navigation路由奇妙使用

文章目录 应用导航设计引言概述场景示例基本实现推荐方案路由管理模块的实现页面跳转实现 业务实现中的关键点动态加载路由栈管理 应用导航设计 引言 在大型应用开发中&#xff0c;如何高效地设计应用导航&#xff0c;处理多模块间的路由跳转与解耦&#xff0c;始终是一个关键…

【腾讯云】AI驱动TDSQL-C Serveress 数据库技术实战营-如何是从0到1体验电商可视化分析小助手得统计功能,一句话就能输出目标统计图

欢迎来到《小5讲堂》 这是《腾讯云》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解。 温馨提示&#xff1a;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01; 目录 背景效果图流程图创建数据库基本信息数据库配置设置密码控制台开启…

win服务器的架设、windows server 2012 R2 系统的下载与安装使用

文章目录 windows server 2012 R2 系统的下载与安装使用1 windows server 2012 的下载2 打开 VMware 虚拟机软件&#xff08;1&#xff09;新建虚拟机&#xff08;2&#xff09;设置虚拟机&#xff08;3&#xff09;打开虚拟机 windows server 2012&#xff08;4&#xff09;进…

如何在谷歌浏览器中开启安全浏览

在数字化时代&#xff0c;网络安全变得愈发重要。作为全球最受欢迎的网络浏览器之一&#xff0c;谷歌浏览器提供了多种功能来保护用户的在线安全。本文将详细介绍如何在谷歌浏览器中开启安全浏览&#xff0c;并额外提供一些有用的页面滚动设置、地址栏快捷搜索和跟踪防护的相关…

djiango DRF的使用

djiango DRF的使用 一 、初始 DRF序列化环境安装环境配置数据模型定义定义DRF序列化模型对象 二 、DRF请求和响应请求对象&#xff08;Request objects&#xff09;响应对象&#xff08;Response objects&#xff09;状态码&#xff08;Status codes&#xff09;包装&#xff0…

计算机网络-HTTP协议

HTTP HTTP是一种不保存状态&#xff0c;即无状态的协议。HTTP协议自身不对请求和响应之间的通信进行保存。为了保存状态因此后面也有一些技术产生比如Cookies技术。 HTTP是通过URI定位网上的资源&#xff0c;理论上将URI可以访问互联网上的任意资源。 如果不是访问特定的资源…

CTFHub 命令注入-综合练习(学习记录)

综合过滤练习 命令分隔符的绕过姿势 ; %0a %0d & 那我们使用%0a试试&#xff0c;发现ls命令被成功执行 /?ip127.0.0.1%0als 发现一个名为flag_is_here的文件夹和index.php的文件&#xff0c;那么我们还是使用cd命令进入到文件夹下 http://challenge-438c1c1fb670566b.sa…

【AI知识】逻辑回归介绍+ 做二分类任务的实例(代码可视化)

1. 分类的基本概念 在机器学习的有监督学习中&#xff0c;分类一种常见任务&#xff0c;它的目标是将输入数据分类到预定的类别中。具体来说&#xff1a; 分类任务的常见应用&#xff1a; 垃圾邮件分类&#xff1a;判断一封电子邮件是否是垃圾邮件 。 医学诊断&#xff1a;…

为SSH2协议服务器的用户设置密钥

目录 私钥的创建1. 在服务器上直接生成2. 如果需要配置免密登录3. 查看生成的密钥 导出私钥至SSH用户获取sudo权限 新的一台服务器类型是SSH2&#xff1a;这表示服务器支持SSH&#xff08;Secure Shell&#xff09;协议的第二个版本。SSH是一个网络协议&#xff0c;用于加密方式…

level2逐笔委托查询接口

沪深逐笔委托队列查询 前置步骤 分配数据库服务器 查询模板 以下是沪深委托队列查询的请求模板&#xff1a; http://<数据库服务器>/sql?modeorder_book&code<股票代码>&offset<offset>&token<token>查询参数说明 参数名类型说明mo…

文献研读|基于像素语义层面图像重建的AI生成图像检测

前言&#xff1a;本篇文章主要对基于重建的AI生成图像检测的四篇相关工作进行介绍&#xff0c;分别为基于像素层面重建的检测方法 DIRE 和 Aeroblade&#xff0c;以及基于语义层面重建的检测方法 SimGIR 和 Zerofake&#xff1b;并对相应方法进行比较。 相关文章&#xff1a;论…

VScode MAC按任意键关闭终端 想要访问桌面文件

说明 最近配置MAC上CPP的运行环境&#xff0c;在安装必要的CPP插件后&#xff0c;配置launch和task等json文件后&#xff0c;点击运行三角形&#xff0c;每次都会跳出main想要访问桌面上的文件。并且输出也是在调试控制台&#xff0c;非常逆天。 尝试 尝试1:尽管我尝试将ta…

Linux Shell 脚本编程基础知识篇

ℹ️大家好&#xff0c;我是练小杰&#xff0c;从本文是Linux shell脚本编程的基础知识内容&#xff0c;后续我会不断补充~~ 更多Linux 相关内容请点击&#x1f449;“Linux专栏”~ 假面驾驭&#xff0c;时王&#xff0c;假面骑士时王~~ 文章目录 什么是 Linux Shell主要功能…

QT绘制同心扇形

void ChartForm::paintEvent(QPaintEvent *) {QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing);// 设置抗锯齿painter.save();// 设置无边框&#xff08;不需要设置QPen&#xff0c;因为默认是不绘制边框的&#xff09;QPen pen(Qt::NoPen);// QPen pen…

TL3568/TL3562更改主机名,在Kernel用menuconfig失效

前言 最近在玩RK3562开发板&#xff0c;想改串口调试时看到的主机名&#xff0c;开发板的主机名默认是RK3562-Tronlong&#xff0c;如图&#xff1a; 按照之前玩T113开发版&#xff0c;在Kernel通过make menuconfig&#xff0c;可以改。但是在这个RK3562&#xff0c;改了后&…

【PLL】ISSCC 2024 Tutorial: Calibration Techniques in PLLs

1. 数字辅助模拟电路 为什么要辅助&#xff0c;或替换模拟电路&#xff1f; 利用CMOS管子尺寸缩小&#xff0c;降低功耗 和 减小面积校正模拟电路的 非线性行为 和 失配 数字辅助的好处&#xff1a; 简化模拟电路设计提高能源效率&#xff0c;提高准确度 2. 锁相环基础 2.1 概…

STM32-笔记5-按键点灯(中断方法)

1、复制03-流水灯项目&#xff0c;重命名06-按键点灯&#xff08;中断法&#xff09; 在\Drivers\BSP目录下创建一个文件夹exti&#xff0c;在该文件夹下&#xff0c;创建两个文件exti.c和exti.h文件&#xff0c;并且把这两个文件加载到项目中&#xff0c;打开项目工程文件 加载…

Mvc、Springmvc框架

一.Mvc&#xff1a; 1.概念&#xff1a; MVC它是一种设计理念。把程序按照指定的结构来划分: Model模型 、View视图 、Controller控制层&#xff1b; 结构图&#xff1a; 二.Springmvc: 1.概念&#xff1a; springmvc框架它是spring框架的一个分支。它是按照mvc架构思想设计…