/**
* 蓝牙相关操作
*
import { blueMixin } from 'mixin/blueMixin';
export default {
mixins: [blueMixin],
};
onLoad里面
this.openBluetooth();
this.device_no = uni.getStorageSync('uni_bluetooth_deviceId');
*
*/
export const blueMixin = {
data() {
return {
dataToSend: "",
checkLette: '', // 蓝牙ID前缀
//checkLette: '', // 蓝牙ID前缀
devices: [], // 存储搜索到的设备
receivedData: null, // 保存接收到的数据
device_no: null, // 用localName
deviceId: null, // 当前连接的设备ID
serviceId: '', // 服务UUID
characteristicId: '', // 特征UUID
connectedDeviceName: '', //当前连接的设备
characteristicIdWrite: '',
connect_status: false, //连接状态
loop_blue: '',
};
},
onShow() {
this.initBlue()
},
methods: {
initBlue() {
this.device_no = uni.getStorageSync('uni_bluetooth_deviceId');
},
sendData() {
if (!this.dataToSend) {
console.warn('没有要发送的数据');
return;
}
console.log('sendData >> ', this.dataToSend);
// 将字符串转换为 HEX
let d = this.dataToSend
d = JSON.stringify(this.dataToSend)
const hexData = this.strToHex(d); // 转换为 HEX
console.log('hex', hexData);
// 将 HEX 转换为 ArrayBuffer
const buffer = this.hexToArrayBuffer(hexData); // 转换为 ArrayBuffer
console.log('ArrayBuffer', buffer);
uni.writeBLECharacteristicValue({
deviceId: this.deviceId,
serviceId: this.serviceId,
characteristicId: this.characteristicIdWrite,
value: buffer,
success: (res) => {
uni.showToast({
title: "发送成功,请在茶壶上操作",
icon: "none"
})
console.log('发送数据成功', res);
},
fail: (err) => {
uni.showToast({
title: "连接异常",
icon: "none"
})
console.error('发送数据失败', err);
}
});
},
openBluetooth() {
uni.openBluetoothAdapter({
success: (res) => {
console.log('蓝牙适配器已打开', res);
this.searchBluetooth();
if (this.loop_blue) {
clearInterval(this.loop_blue)
}
this.loop_blue = setInterval(() => {
this.searchBluetooth()
console.log("3 秒重连")
}, 3000)
},
fail: (err) => {
uni.showModal({
title: '提示',
content: '请打开蓝牙',
showCancel: false,
success: (res) => {
if (res.confirm) {
console.log('用户点击确定');
}
}
})
console.error('打开蓝牙适配器失败', err);
}
});
},
// 启动搜索设备
searchBluetooth() {
// 清空之前的设备列表
this.devices = [];
console.log('搜索蓝牙设备');
uni.startBluetoothDevicesDiscovery({
success: (res) => {
console.log('开始搜索设备', res);
},
fail: (err) => {
console.error('开始搜索设备失败', err);
}
});
// 监听设备发现
console.log("搜索设备No:" + this.device_no)
uni.onBluetoothDeviceFound((devices) => {
devices.devices.forEach(device => {
// 根据前缀过滤设备
if (device.name && (this.checkLette === '' || device.name.startsWith(this
.checkLette))) {
console.log('发现设备 deviceId' + device.deviceId)
console.log('发现设备 localName ' + device.localName)
console.log(device)
this.deviceId = device.deviceId
this.devices.push(device);
if (this.device_no && this.device_no == device.localName) {
this.connectToDevice(device);
}
}
});
// 去重处理
this.devices = [...new Map(this.devices.map(item => [item.deviceId, item])).values()];
});
// 可选:设置一个定时器停止搜索
setTimeout(() => {
uni.stopBluetoothDevicesDiscovery({
success: () => {
console.log('停止搜索设备');
},
fail: (err) => {
console.error('停止搜索设备失败', err);
}
});
}, 10 * 1000); // 停止搜索
},
// 连接到蓝牙设备
connectToDevice(device) {
console.log('连接设备')
console.log(device)
uni.setStorageSync('uni_bluetooth_deviceId', device.localName);
this.device_no = device.localName;
this.connectedDeviceName = device.name;
this.doConnectToDeviceId(device.deviceId);
},
//
doConnectToDeviceId(deviceId) {
console.log("connect DeviceId", deviceId);
var that = this
//这里连接有时失败
uni.createBLEConnection({
deviceId: deviceId,
success: (res) => {
this.connect_status = true;
if (this.loop_blue) {
clearInterval(this.loop_blue)
}
console.log('成功连接到设备', deviceId);
that.ajax(that.config.tea_bluetooth.device.bind, {
device_no: this.device_no,
data: {
}
}).then(res => {
console.log('bind')
console.log(res)
})
this.initBlue();
this.getDeviceServices(); // 连接成功后获取服务
},
fail: (err) => {
console.error('连接设备失败', err);
this.connect_status = false;
}
});
},
// 获取设备的服务
getDeviceServices() {
uni.getBLEDeviceServices({
deviceId: this.deviceId,
success: (res) => {
console.log('获取到设备服务:', res.services);
if (res.services.length > 0) {
// 假设我们取第一个服务
this.serviceId = res.services[0].uuid;
this.getDeviceCharacteristics(); // 获取特征值
}
},
fail: (err) => {
console.error('获取设备服务失败', err);
}
});
},
// 获取服务中的特征值
getDeviceCharacteristics() {
uni.getBLEDeviceCharacteristics({
deviceId: this.deviceId,
serviceId: this.serviceId,
success: (res) => {
console.log(res);
if (res.characteristics.length > 0) {
res.characteristics.forEach(characteristic => {
if (characteristic.properties.write) {
this.characteristicIdWrite = characteristic.uuid;
} else {
this.characteristicId = characteristic.uuid;
}
});
this.startListenData(); // 开始监听数据
}
},
fail: (err) => {
console.error('获取设备特征值失败', err);
}
});
},
writeLog(data) {
let obj = JSON.parse(data)
obj.device_no = this.device_no
console.log('写日志,对象值')
console.log(obj)
this.ajax(this.config.tea_bluetooth.log, {
data: obj
}).then(res => {
console.log('writeLog')
console.log(res)
})
},
// 开始监听蓝牙设备发来的数据
startListenData() {
console.log('startListenData')
console.log("device no:" + this.device_no);
console.log("deviceId:" + this.deviceId);
console.log("serviceId:" + this.serviceId);
console.log("characteristicId:" + this.characteristicId);
uni.notifyBLECharacteristicValueChange({
state: true,
deviceId: this.deviceId,
serviceId: this.serviceId,
characteristicId: this.characteristicId,
success: (res) => {
console.log('已设置通知', res);
// 监听特征值变化
uni.onBLECharacteristicValueChange((characteristic) => {
const {
value
} = characteristic;
this.receivedData = this.ab2str(value); // 将 ArrayBuffer 转换为字符串
console.log('接收到数据:', this.receivedData);
//写入日志
this.writeLog(this.receivedData);
});
},
fail: (err) => {
console.error('监听蓝牙数据失败', 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.reverse().join(':')
},
// ArrayBuffer 转字符串的工具方法
ab2str(buf) {
return String.fromCharCode.apply(null, new Uint8Array(buf));
},
str2ab(str) {
const buf = new ArrayBuffer(str.length);
const bufView = new Uint8Array(buf);
for (let i = 0; i < str.length; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
},
strToHex(str) {
return str.split('').map(char => {
const hex = char.charCodeAt(0).toString(16); // 获取字符的 Unicode 编码并转为 HEX
return hex.padStart(2, '0'); // 确保每个字节为两位
}).join('');
},
// 将 HEX 字符串转换为 ArrayBuffer
hexToArrayBuffer(hex) {
const len = hex.length;
const buffer = new Uint8Array(len / 2);
for (let i = 0; i < len; i += 2) {
buffer[i / 2] = parseInt(hex.substr(i, 2), 16);
}
return buffer.buffer;
},
}
};
搜索蓝牙设备
<template>
<view style="margin: 20px;">
<view class="device" v-for="(device, index) in devices">
<view @click="connectToDevice(device)"
:class="device.deviceId == device_no?'actived':'' ">
{{device.name}}
</view>
</view>
<view class="padding">
<view class="w-100">
<cl-button @click="save" type="primary">чбошод</cl-button>
</view>
</view>
</view>
</template>
<script>
import {
blueMixin
} from '@/mixin/blueMixin';
export default {
mixins: [blueMixin],
data() {
return {
};
},
onLoad() {
this.openBluetooth();
},
methods: {
save() {
this.back_data({
step: 2
})
}
}
};
</script>
<style scoped>
button {
margin: 5px;
}
.device {
margin-bottom: 20px;
padding:10px;
border: 1px solid #ccc;
border-radius: 5px;
background-color: #fff;
}
.space-between {
display: flex;
justify-content: space-between;
align-items: center;
}
.actived {
color: blue !important;
}
</style>