uniapp实现读取蓝牙连接蓝牙等操作(vue2+js)直接一把梭版
参考博客地址:https://juejin.cn/post/7093171532318375950
界面demo如下
代码部分
<template>
<view>
<view class="BuuetoothServiceList">
<text>蓝牙设备列表</text>
</view>
<scroll-view scroll-y class="box">
<view class="item" v-for="item in blueDeviceList" @click="connect(item)">
<view>
<text>id: {{ item.deviceId }}</text>
</view>
<view>
<text>RSSI:{{item.RSSI}}</text>
</view>
<view>
<text>name: {{ item.name }}</text>
</view>
</view>
</scroll-view>
<button @click="initBluetooth()"
style="width: 9rem;height: 3rem;background-color: rgb(138, 145, 159);">①蓝牙连接</button>
<view class="BuuetoothServiceList">
<text>蓝牙服务列表</text>
</view>
<scroll-view scroll-y class="box">
<view class="item" v-for="item in sevicesList">
<view>
<text user-select="true">uuid: {{ item.uuid }}</text>
</view>
</view>
</scroll-view>
<view class="BuuetoothServiceList">
<text>蓝牙特征值列表</text>
</view>
<scroll-view scroll-y class="box">
<view class="item" v-for="item in eigenvalueList">
<view>
<text user-select="true">uuid: {{ item.uuid }}</text>
</view>
</view>
</scroll-view>
<!-- <uni-easyinput type="text" v-model="formData.name" placeholder="请输入姓名" /> -->
<view class="btnBox"><input type="text"
style="width: 75%;height: 3rem;background-color: rgb(246, 244, 241);margin-left: 5%;border-radius: 20rpx;box-shadow:0 0 8rpx #000;margin-top: 20rpx;"
placeholder="请输入蓝牙服务表中的uuid" v-model="serviceUuid" />
<view class="clearInput">
<icon type="clear" @click="clearIptA()"></icon>
</view>
</view>
<view class="btnBox">
<!-- <button @click="discovery()"
style="width: 12rem;height: 3rem;margin-top: 1rem;background-color: rgb(138, 145, 159);">②搜索附近蓝牙设备</button>
<button @click="getServices()"
style="width: 10rem;height: 3rem;margin-top: 1rem;background-color: rgb(138, 145, 159);">③获取蓝牙服务</button> -->
<button @click="getCharacteristics()"
style="width: 10rem;height: 3rem;margin-top: 1rem;background-color:rgb(138, 145, 159);">②获取特征值</button>
<!-- <button @click="notify()"
style="width: 10rem;height: 3rem;margin-top: 1rem;background-color:rgb(138, 145, 159);">③开启消息监听</button> -->
</view>
<view class="btnBox">
<input type="text"
style="box-shadow:0 0 8rpx #000;width: 75%;height: 3rem;background-color: rgb(246, 244, 241);margin-left: 5%;border-radius: 20rpx;margin-top: 20rpx;"
placeholder="开始监听之前,请输入需要监听的特征值" v-model="eigenvalue" />
<view class="clearInput">
<icon type="clear" @click="clearIptB()"></icon>
</view>
</view>
<view class="btnBox">
<button @click="notify()"
style="width: 10rem;height: 3rem;margin-top: 1rem;background-color:rgb(138, 145, 159);">③开启消息监听</button>
<input type="text"
style="width: 75%;height: 3rem;background-color: rgb(246, 244, 241);margin-left: 5%;border-radius: 20rpx;box-shadow:0 0 8rpx #000;margin-top: 20rpx;"
placeholder="请填写需要发送的内容" v-model="sendMessage" />
<!-- <uni-icons type="icon-youxi" size="30"></uni-icons> -->
<view class="clearInput">
<icon type="clear" @click="clearIptC()"></icon>
</view>
<!-- <text style="background-color: aqua;height: 3rem;line-height: 3rem;margin-left: 2.5%;"></text> -->
<button @click="send()"
style="width: 10rem;height: 3rem;margin-top: 1rem;background-color:rgb(138, 145, 159);">④发送数据</button>
<button @click="read()"
style="width: 10rem;height: 3rem;margin-top: 1rem;background-color:rgb(138, 145, 159);">⑤读取数据</button>
</view>
<view class="msg_x" style="background-color: rgb(246, 244, 241);">
<view class="msg_txt">
监听到的内容:{{ message }}
</view>
<view class="msg_hex">
监听到的内容(十六进制):{{ messageHex }}
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
blueDeviceList: [],
deviceId: null,
sevicesList: [],
serviceUuid: null,
eigenvalueList: [],
eigenvalue: null,
message: "",
messageHex: "",
sendMessage: ""
}
},
methods: {
initBluetooth() {
let that = this
uni.openBluetoothAdapter({
success(res) {
console.log('初始化蓝牙成功')
console.log(res)
//开始搜索蓝牙设备
that.discovery()
//获取蓝牙服务
console.log('调用服务预备');
that.getServices()
},
fail(err) {
console.log('初始化蓝牙失败')
console.error(err)
}
})
},
// 开始搜索蓝牙设备
discovery() {
let that = this
uni.startBluetoothDevicesDiscovery({
//services:['FFE0'],
success(res) {
console.log('开始搜索')
// 开启监听回调
//uni.onBluetoothDeviceFound(that.found(res))
uni.onBluetoothDeviceFound(function(res) {
console.log(res, '---')
if (res.devices[0].name == "iCore Server") {
that.blueDeviceList.push(res.devices[0])
}
})
},
fail(err) {
console.log('搜索失败')
console.error(err)
}
})
},
//连接蓝牙设备
connect(data) {
console.log(data, '---+++___')
this.deviceId = data.deviceId
let that = this
uni.createBLEConnection({
deviceId: this.deviceId,
success(res) {
uni.showToast({
icon: 'success',
title: '蓝牙连接成功'
})
console.log('连接成功')
console.log(res)
that.stopDiscovery()
//获取蓝牙服务
that.getServices()
},
fail(err) {
uni.showToast({
icon: 'error',
title: '蓝牙连接失败'
})
console.log('连接失败')
console.log(err)
}
})
},
//停止搜索
stopDiscovery() {
uni.stopBluetoothDevicesDiscovery({
success(res) {
console.log('停止成功')
console.log(res)
},
fail(err) {
console.log('停止失败')
console.error(err)
}
})
},
//获取蓝牙服务
getServices() {
console.log('开始获取蓝牙服务');
let that = this;
uni.getBLEDeviceServices({
deviceId: that.deviceId, // 设备ID,在上一步【4】里获取
success(res) {
that.sevicesList = res.services
console.log(that.sevicesList, '=================')
},
fail(err) {
console.error(err)
}
})
},
//获取特征值
getCharacteristics() {
if (this.serviceUuid == null) {
console.log('----')
uni.showToast({
icon: 'error',
title: '请在上面输入框中输入uuid'
})
}
let that = this
//console.log(this.serviceUuid, 'serviceUuid')
uni.getBLEDeviceCharacteristics({
deviceId: that.deviceId, // 设备ID,在【4】里获取到
serviceId: that.serviceUuid, // 服务UUID,在【6】里能获取到
success(res) {
that.eigenvalueList = res.characteristics
console.log(res)
},
fail(err) {
console.error(err)
}
})
},
notify() {
let that = this
uni.notifyBLECharacteristicValueChange({
state: true, // 启用 notify 功能
deviceId: that.deviceId, // 设备ID,在【4】里获取到
serviceId: that.serviceUuid, // 服务UUID,在【6】里能获取到
characteristicId: that.eigenvalue, // 特征值,在【7】里能获取到
success(res) {
console.log(res)
// 接受消息的方法
that.listenValueChange()
},
fail(err) {
console.log(err)
}
})
},
// ArrayBuffer转16进度字符串示例
ab2hex(buffer) {
const hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function(bit) {
return ('00' + bit.toString(16)).slice(-2)
}
)
return hexArr.join('')
},
// 将16进制的内容转成我们看得懂的字符串内容
hexCharCodeToStr(hexCharCodeStr) {
var trimedStr = hexCharCodeStr.trim();
var rawStr = trimedStr.substr(0, 2).toLowerCase() === "0x" ? trimedStr.substr(2) : trimedStr;
var len = rawStr.length;
if (len % 2 !== 0) {
alert("存在非法字符!");
return "";
}
var curCharCode;
var resultStr = [];
for (var i = 0; i < len; i = i + 2) {
curCharCode = parseInt(rawStr.substr(i, 2), 16);
resultStr.push(String.fromCharCode(curCharCode));
}
return resultStr.join("");
},
listenValueChange() {
let that = this
uni.onBLECharacteristicValueChange(res => {
// 结果
console.log(res, '这是监听成功的回调');
// 结果里有个value值,该值为 ArrayBuffer 类型,所以在控制台无法用肉眼观察到,必须将该值转换为16进制
let resHex = that.ab2hex(res.value)
//console.log(resHex);
that.messageHex = resHex
// 最后将16进制转换为ascii码,就能看到对应的结果
let result = that.hexCharCodeToStr(resHex);
that.message = String(result)
console.log(String(result),'000000')
})
},
//发送数据
send() {
// 向蓝牙设备发送一个0x00的16进制数据
let msg = this.sendMessage
console.log(msg,'$$$$$$$$$$$$$$$$$$$$$$$$$$');
if (this.sendMessage == "") {
uni.showToast({
icon: 'error',
title: '需要发送的内容不能为空'
})
return
}
const buffer = new ArrayBuffer(msg.length)
const dataView = new DataView(buffer)
// dataView.setUint8(0, 0)
for (var i = 0; i < msg.length; i++) {
dataView.setUint8(i, msg.charAt(i).charCodeAt())
}
let that = this
uni.writeBLECharacteristicValue({
deviceId: that.deviceId,
serviceId: that.serviceUuid,
characteristicId: that.eigenvalue,
value: buffer,
success(res) {
console.log('writeBLECharacteristicValue success', res.errMsg)
uni.showToast({
title: 'write指令发送成功'
})
},
fail(err) {
console.error(err,"写入指令发送失败")
uni.showToast({
title: 'write指令发送失败',
icon: 'error'
})
}
})
},
//读取数据
read() {
let that = this
uni.readBLECharacteristicValue({
deviceId: that.deviceId,
serviceId: that.serviceUuid,
characteristicId: that.eigenvalue,
success(res) {
console.log(res,"数据读取成功")
uni.showToast({
title: 'read指令发送成功'
})
},
fail(err) {
console.error(err)
uni.showToast({
title: 'read指令发送失败',
icon: 'error'
})
}
})
},
//清除输入框中数据
//清除蓝牙表中的uuid
clearIptA() {
this.serviceUuid = ""
},
//清除监听特定值的
clearIptB() {
this.eigenvalue = ""
},
//发送内容的输入框
clearIptC() {
this.sendMessage = ""
}
},
onLoad() {
}
}
</script>
<style>
.box {
width: 100%;
height: 500rpx;
box-sizing: border-box;
margin-bottom: 8rpx;
border: 1px solid rgb(138, 145, 159);
}
.item {
box-sizing: border-box;
padding: 10rpx;
border-bottom: 1px solid gray;
}
/* button {
margin-bottom: 20rpx;
} */
.btnBox {
display: flex;
display: flex;
align-items: flex-end;
flex-wrap: wrap;
}
.BuuetoothServiceList {
width: 100%;
height: 2rem;
margin-bottom: 8rpx;
line-height: 2rem;
text-align: center;
font-weight: 700;
}
.msg_x {
border: 2px solid seagreen;
width: 98%;
margin: 10rpx auto;
box-sizing: border-box;
padding: 20rpx;
}
/* .msg_txt {
margin-bottom: 20rpx;
} */
.clearInput {
width: 5%;
height: 3rem;
line-height: 3rem;
float: left;
margin-left: 2%;
}
</style>
总结如下:
参考uniapp官方文档api
初始化:打开蓝牙模块
搜寻:检测附近存在的设备
连接:找到目标设备进行
监听:开启监听功能,接收其他设备传过来的数据
发送指令:不管发送数据还是读取数据,都可以理解为向外发送指令