uniAPP实现安卓iOS逃不过与硬件打交道的状况,本文记录一下uniAPP蓝牙衔接相关状况
1.初始化蓝牙设备 | | 提示用户翻开蓝牙设备
//设置运用变量
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 办法中止查找。)
//敞开蓝牙查找
function startBluetoothDevicesDiscovery(callBack) {
uni.startBluetoothDevicesDiscovery({
allowDuplicatesKey: true,
success: res => {
console.log('敞开蓝牙查找 success', res);
onBluetoothDeviceFound(callBack);
},
fail: res => {
console.log('敞开蓝牙查找 err', res);
}
});
}
3.监听蓝牙设备列表
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.树立衔接并中止蓝牙查找
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.获取蓝牙设备服务
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.获取蓝牙特征值
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.超出信号强度外报警
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.暴露公共办法
//发送指令 蓝牙呼叫
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);
}