uniAPP实现安卓iOS逃不过与硬件打交道的情况,本文记录一下uniAPP蓝牙连接相关情况
1.初始化蓝牙设备 | | 提醒用户打开蓝牙设备
ini
//设置使用变量
let discoveryStarted = false;
let deviceId = '';
let deviceName = '';
let characteristicId = ''; //uuid
let serviceId = '';
let rssiTimer = '';
let rssi = 3; //蓝牙信号强度 1级:近身大于-60,2级:近距离-70~-60, 三级:远距离低于-70
//打开蓝牙适配器
function openBluetoothAdapter(callBack) {
uni.openBluetoothAdapter({
success: res => {
console.log('打开蓝牙适配器 success', res);
startBluetoothDevicesDiscovery(callBack);
},
fail: res => {
console.log('打开蓝牙适配错误', res);
if (res.code == 10001) {
uni.showToast({
title: '请先打开手机蓝牙',
icon: 'none'
});
uni.onBluetoothAdapterStateChange(res => {
if (res.available){
startBluetoothDevicesDiscovery(callBack);
}
});
}
}
});
}
2.搜索周边设备(此操作比较耗费系统资源,请在搜索并连接到设备后调用 uni.stopBluetoothDevicesDiscovery 方法停止搜索。)
javascript
//开启蓝牙搜索
function startBluetoothDevicesDiscovery(callBack) {
uni.startBluetoothDevicesDiscovery({
allowDuplicatesKey: true,
success: res => {
console.log('开启蓝牙搜索 success', res);
onBluetoothDeviceFound(callBack);
},
fail: res => {
console.log('开启蓝牙搜索 err', res);
}
});
}
3.监听蓝牙设备列表
ini
function onBluetoothDeviceFound(callBack) {
uni.onBluetoothDeviceFound(res => {
console.log('监听蓝牙设备列表',res.devices)
res.devices.forEach(device => {
if (device.name.indexOf(deviceName) == -1) {
return;
}
createBLEConnection(device, callBack);
});
});
}
4.建立连接并停止蓝牙搜索
ini
function createBLEConnection(device, callBack) {
deviceId = device.deviceId;
uni.createBLEConnection({
deviceId,
success: res => {
console.log('建立连接成功', res)
//获取蓝牙设备服务
getBLEDeviceServices(deviceId, callBack);
}
});
stopBluetoothDevicesDiscovery();
}
//停止蓝牙搜索
function stopBluetoothDevicesDiscovery() {
uni.stopBluetoothDevicesDiscovery();
discoveryStarted = false;
}
5.获取蓝牙设备服务
ini
function getBLEDeviceServices(deviceId, callBack) {
//反复获取,知道获取到为止
let timer = setInterval(() => {
uni.getBLEDeviceServices({
deviceId,
success: res => {
if (res.services.length > 0) {
clearInterval(timer);
for (let i = 0; i < res.services.length; i++) {
if (res.services[i].isPrimary) {
getBLEDeviceCharacteristics(deviceId, res.services[i].uuid, callBack);
serviceId = res.services[i].uuid;
return;
}
}
} else {
getBLEDeviceServices(deviceId, callBack);
}
}
});
}, 1000)
}
6.获取蓝牙特征值
scss
function getBLEDeviceCharacteristics(deviceId, serviceId, callBack) {
uni.getBLEDeviceCharacteristics({
deviceId,
serviceId,
success: res => {
console.log('getBLEDeviceCharacteristics success', res.characteristics);
for (let i = 0; i < res.characteristics.length; i++) {
let item = res.characteristics[i];
// console.log(item.properties)
if (item.properties.read) {
uni.readBLECharacteristicValue({
deviceId,
serviceId,
characteristicId: item.uuid
});
}
if (item.properties.write) {
characteristicId = item.uuid;
console.log('读写数据', deviceId, serviceId, characteristicId)
}
if (item.properties.notify || item.properties.indicate) {
uni.notifyBLECharacteristicValueChange({
deviceId,
serviceId,
characteristicId: item.uuid,
state: true
});
}
}
},
fail(res) {
console.error('getBLEDeviceCharacteristics err', res);
}
});
uni.onBLECharacteristicValueChange(characteristic => {
//自己的操作
let value = ab2hex(characteristic.value);
// console.log('自己的操作', value)
//监听设备信号强度
listenRSSI();
//连接成回调函数
if (callBack) {
callBack();
}
});
uni.onBLEConnectionStateChange(res => {
// 该方法回调中可以用于处理连接意外断开等异常情况
console.log(`device ${res.deviceId} 设备状态改变, connected: ${res.connected}`);
if (!res.connected) {
openBluetoothAdapter(callBack);
}
});
uni.getBluetoothDevices({
success: res => {
console.log('获取蓝牙设备成功:', res);
let devices = res.devices;
}
})
}
// ArrayBuffer转16进度字符串示例
function ab2hex(buffer) {
const hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function(bit) {
return ('00' + bit.toString(16)).slice(-2)
}
)
return hexArr.join('')
}
// ascii 转 二进制流
function 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;
}
//超出信号强度外报警
function outcallDo() {
let userInfo = uni.getStorageSync('userInfo');
if (userInfo.nearremind != '1') {
if (rssiTimer) {
clearInterval(rssiTimer)
}
uni.showToast({
icon: 'none',
title: '超出范围已发起报警'
})
writeBLECharacteristicValue();
let time = 10;
let timercall = setInterval(() => {
time--;
if (time == 0 || time < 0) {
clearInterval(timercall);
listenRSSI();
}
}, 1000)
}
}
function listenRSSI() {
// 监听设备信号强度
if (rssiTimer) {
clearInterval(rssiTimer)
}
rssiTimer = setInterval(() => {
uni.getBLEDeviceRSSI({
deviceId: deviceId,
success: (res) => {
console.log('设备信号强度', res)
uni.showToast({
icon: 'none',
title: '信号强度:' + res.RSSI
})
let saveRssi = uni.getStorageSync('saveRssi');
console.log('saveRssi', saveRssi)
saveRssi ? rssi = saveRssi : '';
if (rssi == 1) {
if (res.RSSI < -60) {
//报警
outcallDo();
}
} else if (rssi == 2) {
if (res.RSSI < -70) {
//报警
outcallDo();
}
} else if (rssi == 3) {
if (res.RSSI < -76) {
//报警
outcallDo();
}
}
}
})
}, 1000)
}
7.超出信号强度外报警
scss
function outcallDo() {
let userInfo = uni.getStorageSync('userInfo');
if (userInfo.nearremind != '1') {
if (rssiTimer) {
clearInterval(rssiTimer)
}
uni.showToast({
icon: 'none',
title: '超出范围已发起报警'
})
writeBLECharacteristicValue();
let time = 10;
let timercall = setInterval(() => {
time--;
if (time == 0 || time < 0) {
clearInterval(timercall);
listenRSSI();
}
}, 1000)
}
}
function listenRSSI() {
// 监听设备信号强度
if (rssiTimer) {
clearInterval(rssiTimer)
}
rssiTimer = setInterval(() => {
uni.getBLEDeviceRSSI({
deviceId: deviceId,
success: (res) => {
console.log('设备信号强度', res)
uni.showToast({
icon: 'none',
title: '信号强度:' + res.RSSI
})
let saveRssi = uni.getStorageSync('saveRssi');
console.log('saveRssi', saveRssi)
saveRssi ? rssi = saveRssi : '';
if (rssi == 1) {
if (res.RSSI < -60) {
//报警
outcallDo();
}
} else if (rssi == 2) {
if (res.RSSI < -70) {
//报警
outcallDo();
}
} else if (rssi == 3) {
if (res.RSSI < -76) {
//报警
outcallDo();
}
}
}
})
}, 1000)
}
8.暴露公共方法
javascript
//发送指令 蓝牙呼叫
export function writeBLECharacteristicValue(callBack) {
console.log('deviceId:' + deviceId)
console.log('serviceId:' + serviceId)
console.log('characteristicId:' + characteristicId)
// 向蓝牙设备发送一个0x00的16进制数据
const buffer = asciiToArrayBuffer(JSON.stringify({
'fn': '3'
}));
uni.writeBLECharacteristicValue({
deviceId: deviceId, // 这里的 deviceId 需要在 getBluetoothDevices 或 onBluetoothDeviceFound 接口中获取
serviceId: serviceId, // 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
characteristicId: characteristicId, // 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
value: buffer, // 这里的value是ArrayBuffer类型
success(res) {
uni.showToast({
icon: 'none',
title: '已发起呼叫'
});
if (callBack) {
callBack(0);
}
},
fail(res) {
console.log('writeBLECharacteristicValue fail', res);
//连接成回调函数
if (callBack) {
callBack(1);
}
}
});
}
/*
@eptName 设备名称
@callBack() 回调函数
*/
export function blueToothLink(eptName, callBack) {
deviceName = eptName;
openBluetoothAdapter(callBack);
}