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

336 lines
7.5 KiB

class Bluetooth {
constructor(options = {}) {
this.isOpenBle = false;
this.deviceId = "";
this.serviceId = "";
this.writeId = "";
this.notifyId = "";
this.num = 0;
this.serviceList = [];
if (options.autoOpen !== false) {
this.openBluetoothAdapter({
silent: true
}).catch(() => {});
}
}
showToast(title) {
uni.showToast({
title: title,
icon: 'none',
'duration': 2000
});
}
openBluetoothAdapter(options = {}) {
const silent = options.silent === true;
return new Promise((resolve, reject) => {
uni.openBluetoothAdapter({
success: res => {
this.isOpenBle = true;
// this.showToast("初始化蓝牙模块成功");
resolve(res);
},
fail: err => {
if (!silent) {
this.showToast('蓝牙状态读取失败,请检查是否打开蓝牙');
}
reject(err);
},
});
});
}
startBluetoothDevicesDiscovery() {
if (!this.isOpenBle) {
this.showToast(`初始化蓝牙模块失败`)
return;
}
let self = this;
uni.showLoading({
title: '蓝牙搜索中'
})
return new Promise((resolve, reject) => {
setTimeout(() => {
uni.startBluetoothDevicesDiscovery({
success: res => {
resolve(res)
},
fail: err => {
self.showToast(`搜索设备失败` + JSON.stringify(err));
reject(err);
}
})
}, 300);
});
}
stopBluetoothDevicesDiscovery() {
let self = this;
return new Promise((resolve, reject) => {
uni.stopBluetoothDevicesDiscovery({
success: e => {
uni.hideLoading();
},
fail: err => {
uni.hideLoading();
self.showToast(`停止搜索蓝牙设备失败` + JSON.stringify(err));
}
})
});
}
saveDevice(deviceId, deviceName = '') {
if (!deviceId) return;
uni.setStorageSync('bluetoothDeviceId', deviceId);
if (deviceName) {
uni.setStorageSync('bluetoothDeviceName', deviceName);
}
}
removeSavedDevice() {
uni.removeStorageSync('bluetoothDeviceId');
uni.removeStorageSync('bluetoothDeviceName');
uni.removeStorageSync('serviceId');
uni.removeStorageSync('notifyId');
uni.removeStorageSync('writeId');
}
resetConnectionInfo() {
this.serviceId = "";
this.writeId = "";
this.notifyId = "";
this.num = 0;
this.serviceList = [];
}
async connectDevice(deviceId, options = {}) {
if (!deviceId) {
return Promise.reject('设备ID不能为空');
}
await this.openBluetoothAdapter(options);
this.deviceId = deviceId;
this.resetConnectionInfo();
await this.createBLEConnection(deviceId, options);
this.serviceList = await this.getBLEDeviceServices(options);
await this.getBLEDeviceCharacteristics(options);
this.saveDevice(deviceId, options.deviceName);
return {
deviceId: this.deviceId,
serviceId: this.serviceId,
notifyId: this.notifyId,
writeId: this.writeId
};
}
connectSavedDevice(options = {}) {
const deviceId = uni.getStorageSync('bluetoothDeviceId');
if (!deviceId) {
return Promise.resolve(null);
}
return this.connectDevice(deviceId, {
...options,
deviceName: options.deviceName || uni.getStorageSync('bluetoothDeviceName')
});
}
createBLEConnection(deviceId, options = {}) {
//设备deviceId
let self = this;
const silent = options.silent === true;
if (!silent) {
uni.showLoading({
mask: true,
title: '设备连接中,请稍候...'
})
}
return new Promise((resolve, reject) => {
uni.createBLEConnection({
deviceId,
timeout: 5000,
success: (res) => {
resolve(res)
},
fail: err => {
if (err.errMsg == "createBLEConnection:fail already connect") {
resolve(err)
return true;
}
if (err.errCode == 10012) {
if (!silent) {
self.showToast(`蓝牙连接超时`);
}
} else if (!silent) {
self.showToast(`蓝牙连接失败` + JSON.stringify(err));
}
reject(err);
},
complete() {
if (!silent) {
uni.hideLoading();
}
}
})
});
}
//获取蓝牙设备所有服务(service)
getBLEDeviceServices(options = {}) {
let _serviceList = [];
let deviceId = this.deviceId;
let self = this;
const silent = options.silent === true;
return new Promise((resolve, reject) => {
setTimeout(() => {
uni.getBLEDeviceServices({
deviceId,
success: res => {
for (let service of res.services) {
if (service.isPrimary) {
_serviceList.push(service);
}
}
if (!silent) {
uni.hideLoading();
}
resolve(_serviceList)
},
fail: err => {
if (!silent) {
uni.hideLoading();
self.showToast(`获取设备Services` + JSON.stringify(err));
}
reject(err);
},
})
}, 500);
});
}
//获取蓝牙设备某个服务中所有特征值(characteristic)
getBLEDeviceCharacteristics(options = {}) {
let self = this;
let deviceId = self.deviceId;
let service = self.serviceList;
const silent = options.silent === true;
if (!service || !service[self.num]) {
return Promise.reject('找不到该读写的服务');
}
var uuid = service[self.num].uuid;
return new Promise((resolve, reject) => {
uni.getBLEDeviceCharacteristics({
deviceId: deviceId,
serviceId: uuid,
success: res => {
for (let _obj of res.characteristics) {
//获取notify
if (_obj.properties.notify) {
self.notifyId = _obj.uuid;
uni.setStorageSync('notifyId', self.notifyId);
}
//获取writeId
if (_obj.properties.write) {
self.writeId = _obj.uuid;
uni.setStorageSync('writeId', self.writeId);
}
}
if (!self.writeId || !self.notifyId) {
self.num++
if (self.num == service.length) {
reject('找不到该读写的特征值');
return false;
} else {
self.getBLEDeviceCharacteristics(options).then(resolve).catch(reject);
return;
}
} else {
self.serviceId = uuid;
uni.setStorageSync('serviceId', self.serviceId);
}
let result = {
'notifyId': self.notifyId,
'writeId': self.writeId
};
// self.showToast(`获取服务中所有特征值OK,${JSON.stringify(result)}`);
resolve(result)
},
fail: err => {
if (!silent) {
self.showToast(`getBLEDeviceCharacteristics` + JSON.stringify(err));
}
reject(err);
}
})
});
}
//断开联链接
closeBLEConnection(deviceId = this.deviceId) {
if (!deviceId) return;
uni.closeBLEConnection({
deviceId,
success(res) {
}
})
}
notifyBLECharacteristicValue() {
let deviceId = this.deviceId;
let serviceId = this.serviceId;
let characteristicId = this.notifyId;
uni.notifyBLECharacteristicValueChange({
state: true, // 启用 notify 功能
deviceId,
serviceId,
characteristicId,
success(res) {
uni.onBLECharacteristicValueChange(function(res) {
});
}
});
}
writeBLECharacteristicValue(buffer) {
let deviceId = this.deviceId;
let serviceId = this.serviceId;
let characteristicId = this.writeId;
return new Promise((resolve, reject) => {
uni.writeBLECharacteristicValue({
deviceId,
serviceId,
characteristicId,
value: buffer,
success(res) {
resolve(res);
},
fail(err) {
reject(err);
}
});
});
}
closeBluetoothAdapter() {
uni.closeBluetoothAdapter({
success: res => {
}
});
}
//若APP在之前已有搜索过某个蓝牙设备,并成功建立连接,可直接传入之前搜索获取的 deviceId 直接尝试连接该设备,无需进行搜索操作。
reconnect() {
return this.connectSavedDevice();
}
}
export default Bluetooth;