You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

445 lines
11 KiB
JavaScript

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*!
* Create by Winford
*/
// var HEX = require('./HEX.min.js');
// 初始化蓝牙
const _openBluetoothAdapter = () => {
return new Promise(function(resolve, reject) {
uni.closeBluetoothAdapter({
fail: reject,
success () {
// 初始化蓝牙
console.log('初始化蓝牙')
uni.openBluetoothAdapter({
success: resolve,
fail: reject
})
}
})
});
}
// 蓝牙建立连接
const _createBLEConnection = (deviceId) => {
// 连接BLE
return new Promise(function(resolve, reject) {
uni.createBLEConnection({
deviceId,
success: resolve,
fail: reject
})
});
}
const _getBLEDeviceServices = (deviceId) => {
// 获取服务
return new Promise(function(resolve, reject) {
uni.getBLEDeviceServices({
deviceId,
success: (res) => {
for (let i = 0; i < res.services.length; i++) {
let service = res.services[i];
if (service.uuid.startsWith('0000FF00')) {
resolve(service);
return;
}
}
resolve();
//resolve(await _getBLEDeviceServices(deviceId))
},
fail: reject
// fail: function(e) {
// console.log(e);
// }
})
});
}
const _getBLEDeviceCharacteristics = (deviceId, serviceId) => {
// 获取读写特征值
return new Promise(function(resolve, reject) {
uni.getBLEDeviceCharacteristics({
deviceId,
serviceId,
success: (res) => {
let characteristics = {};
for (let i = 0; i < res.characteristics.length; i++) {
let item = res.characteristics[i];
// console.log(item);
if (item.properties.notify) {
characteristics.notify = characteristics.notify || item;
}
if (item.properties.write) {
characteristics.write = characteristics.write || item;
}
if (item.uuid.startsWith('0000FF03')) {
characteristics.dataFC = characteristics.dataFC || item;
}
}
resolve(characteristics);
},
fail: reject
});
});
}
// 写数据
const _wxWriteBLECharacteristicValue = ({
deviceId,
serviceId,
characteristicId,
value
}) => {
return new Promise(function(resolve, reject) {
uni.writeBLECharacteristicValue({
deviceId,
serviceId,
characteristicId,
value,
writeType: 'writeNoResponse',
//writeType: 'write',
success: function() {
resolve(true);
},
fail: function(e) {
console.log(e);
if (e.code == 10007) {
// uniapp bug, retry.
resolve(false);
} else {
reject(e)
}
}
});
});
}
const sleep = (time) => new Promise((resolve, reject) => setTimeout(resolve, time));
// 写数据
const _writeBLECharacteristicValue = async (deviceId, serviceId, characteristicId, value, mtu = 20) => {
const total = value.byteLength;
console.log("================mtu=" + mtu, new Date())
let num = 0;
let count = 0;
while (count < total) {
const element = value.slice(count, count + mtu); // 取出MTU个数据
if (element.byteLength === 0) break; // 表示已经发送完毕
// #ifdef APP-PLUS
// await sleep(50);
let writeResult = await _wxWriteBLECharacteristicValue({
deviceId,
serviceId,
characteristicId,
value: element
});
if (writeResult) {
count = count + element.byteLength;
num++;
}
// #endif
// #ifdef MP-WEIXIN
// num % 100 == 0 && await sleep(100);
_wxWriteBLECharacteristicValue({
deviceId,
serviceId,
characteristicId,
value: element
});
count = count + element.byteLength;
num++;
// #endif
// console.log("================count=" + count)
// console.log("================num=" + num)
}
console.log("================num=" + num, new Date())
}
// 写数据
const _writeBLECharacteristicValueWithDataFC = async (device, value) => {
// const data = value.slice(); // copy一份浅拷贝
const total = value.byteLength;
console.log('total--->', total);
let num = 0;
let count = 0;
const dataFC = device.dataFC;
while (count < total) {
if (dataFC.mtu > 0 && dataFC.credit > 0) {
const subData = value.slice(count, count + dataFC.mtu - 3); // 取出MTU-3个数据
if (subData.byteLength === 0) break; // 表示已经发送完毕
count = count + subData.byteLength;
dataFC.credit--;
// #ifdef APP-PLUS
while (!(await _wxWriteBLECharacteristicValue({
deviceId: device.deviceId,
serviceId: device.serviceId,
characteristicId: device.writeCharacteristicId,
value: subData,
}))) {
await sleep(100); // I don't know why, but uni-app is shit, okay
console.log('写入失败,正在重新写入。。。');
}
// #endif
// #ifndef APP-PLUS
_wxWriteBLECharacteristicValue({
deviceId: device.deviceId,
serviceId: device.serviceId,
characteristicId: device.writeCharacteristicId,
value: subData,
});
// #endif
num++;
} else {
// 令牌用尽,等待令牌
await sleep(0);
// console.log('令牌用尽,等待令牌');
}
}
console.log('num--->', num);
}
// 发现设备
const find = (onBluetoothDeviceFound) => {
_openBluetoothAdapter().then(function(res) {
// 添加监听
uni.onBluetoothDeviceFound(function(res) {
if (onBluetoothDeviceFound) {
onBluetoothDeviceFound(res);
}
});
uni.startBluetoothDevicesDiscovery({
interval: 1000
});
}).catch(function(res) {
uni.showToast({
title: '请打开蓝牙',
icon: 'none'
})
});
}
// 停止发现设备
const stopFind = () => {
uni.stopBluetoothDevicesDiscovery();
}
// 连接
const connect = async ({
deviceId,
onBLEConnectionStateChange,
onBLECharacteristicValueChange,
onDataFCValueChange,
fail,
}) => {
let device = {
connected: false,
deviceId: deviceId,
serviceId: '',
notifyCharacteristicId: '',
writeCharacteristicId: '',
dataFCCharacteristicId: '',
onBLEConnectionStateChange,
onBLECharacteristicValueChange,
onDataFCValueChange,
dataFC: {
mtu: 0,
credit: 0,
},
};
// 请求蓝牙权限
await _openBluetoothAdapter().then(function(res) {
return new Promise((resolve, reject) => {
// 添加监听
uni.onBLEConnectionStateChange(function(res) {
// 该方法回调中可以用于处理连接意外断开等异常情况
device.connected = res.connected;
if (device.onBLEConnectionStateChange) {
device.onBLEConnectionStateChange(res);
}
if (res.connected) {
resolve(res);
} else {
reject(res);
}
});
// 连接BLE
_createBLEConnection(deviceId);
});
// 添加监听
// uni.onBLEConnectionStateChange(function(res) {
// // 该方法回调中可以用于处理连接意外断开等异常情况
// device.connected = res.connected;
// if (device.onBLEConnectionStateChange) {
// device.onBLEConnectionStateChange(res);
// }
// });
// // 连接BLE
// return _createBLEConnection(deviceId);
})
.then(async function(res) {
// 获取服务
await sleep(1000);
let service = await _getBLEDeviceServices(deviceId);
if (!service) {
// 有时候获取不到,尝试重新获取
await sleep(2000);
service = await _getBLEDeviceServices(deviceId);
}
if (!service) {
Promise.reject('获取service失败');
} else {
return service;
}
})
.then(function(service) {
// 获取读写特征值
console.log('获取读写特征值')
device.serviceId = service.uuid;
return _getBLEDeviceCharacteristics(device.deviceId, device.serviceId);
})
.then(function(characteristics) {
// 读
device.notifyCharacteristicId = characteristics.notify ? characteristics.notify.uuid : '';
// 写
device.writeCharacteristicId = characteristics.write ? characteristics.write.uuid : '';
// 流控
device.dataFCCharacteristicId = characteristics.dataFC ? characteristics.dataFC.uuid : '';
})
.catch(function(err) {
console.log(err);
fail(err)
});
device.mtu = 20;
if (uni.getSystemInfoSync().platform === 'android') {
await new Promise(function(resolve, reject) {
uni.setBLEMTU({
deviceId: deviceId,
mtu: 512,
success(res) {
//device.mtu = res.mtu;
console.log('setBLEMTU success', res);
resolve(res);
},
fail(res) {
console.log('setBLEMTU fail', res);
reject(res);
},
});
});
// #ifdef APP-PLUS
await sleep(500); // I don't know why, but uni-app is shit, okay
// #endif
}
console.log('onBLECharacteristicValueChange')
// 监听
uni.onBLECharacteristicValueChange(function(res) {
// 读监听
if (res.characteristicId === device.notifyCharacteristicId) {
device.onBLECharacteristicValueChange && device.onBLECharacteristicValueChange(res);
}
// 流控监听
if (res.characteristicId === device.dataFCCharacteristicId) {
const data = new Uint8Array(res.value);
const flag = data[0];
if (flag === 1) {
device.dataFC.credit += data[1];
// console.log('===流控更新credit', data[1]);
} else if (flag === 2) {
device.dataFC.mtu = (data[2] << 8) + data[1]; // 低位在前,高位在后
// console.log('===流控更新mtu', device.dataFC.mtu);
}
device.onDataFCValueChange && device.onDataFCValueChange(res);
}
});
// 读监听
if (device.notifyCharacteristicId) {
console.log('notifyBLECharacteristicValueChange: ' + device.notifyCharacteristicId)
await new Promise(function(resolve, reject) {
uni.notifyBLECharacteristicValueChange({
state: true, // 启用 notify 功能
// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
deviceId: device.deviceId,
// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
serviceId: device.serviceId,
// 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
characteristicId: device.notifyCharacteristicId,
success: resolve,
fail: reject
});
});
}
// 流控监听
if (device.dataFCCharacteristicId) {
// #ifdef APP-PLUS
await sleep(500); // I don't know why, but uni-app is shit, okay
// #endif
console.log('notifyBLECharacteristicValueChange: ' + device.dataFCCharacteristicId)
await new Promise(function(resolve, reject) {
uni.notifyBLECharacteristicValueChange({
state: true, // 启用 notify 功能
// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
deviceId: device.deviceId,
// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
serviceId: device.serviceId,
// 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
characteristicId: device.dataFCCharacteristicId,
success: resolve,
fail: reject
});
});
}
// 写方法
// device.write = async (value, {
// mtu = 20
// }) => {
// // console.log(device.deviceId, 'write', HEX.ab2hex(value));
// if (device.writeCharacteristicId) {
// await _writeBLECharacteristicValue(device.deviceId, device.serviceId, device
// .writeCharacteristicId, value, mtu);
// }
// };
// 流控写方法(传输速度提升6倍)
device.write = async (value) => {
// console.log(device.deviceId, 'writeWithDataFC', HEX.ab2hex(value));
if (device.writeCharacteristicId && device.dataFCCharacteristicId) {
await _writeBLECharacteristicValueWithDataFC(device, value);
}
};
// 断开连接
device.close = () => {
return new Promise((resolve, reject) => {
uni.closeBLEConnection({
deviceId: device.deviceId,
success: resolve,
fail: reject
})
})
};
console.log(device);
return device;
}
export default {
find,
stopFind,
connect
}