import errToString from "./error";
|
|
var util = require('../util');
|
|
const app =getApp()
|
|
|
|
let PRINT_SHOW = true //是否开启蓝牙调试
|
|
let SYSTEM_INFO = {}
|
|
let MTU_SIZE = 512
|
|
|
|
function toPlatformString(systemInfo, str) {
|
|
if (systemInfo.platform == 'android')
|
|
return str.toLowerCase();
|
|
else if (systemInfo.platform == 'ios')
|
|
return str.toUpperCase();
|
|
else
|
|
return str;
|
|
}
|
|
|
|
function _openAdapter() {
|
|
|
|
print(`准备初始化蓝牙适配器...`);
|
|
|
|
wx.getSystemInfo({
|
|
success: function (res) {
|
|
print(`model: ${res.model}`);
|
|
print(`pixelRatio: ${res.pixelRatio}`);
|
|
print(`windowWidth: ${res.windowWidth}`);
|
|
print(`windowHeight: ${res.windowHeight}`);
|
|
print(`language: ${res.language}`);
|
|
print(`version: ${res.version}`);
|
|
print(`platform: ${res.platform}`);
|
|
print(`environment: ${res.environment}`);
|
|
SYSTEM_INFO = res;
|
|
}
|
|
})
|
|
|
|
return wx.openBluetoothAdapter().then(
|
|
(res) => {
|
|
print(`✔ 适配器初始化成功!`);
|
|
return [null, res]
|
|
},
|
|
(err) => {
|
|
print(`✘ 初始化失败!${errToString(err)}`);
|
|
return [errToString(err), null]
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param {Array<string>} services
|
|
* @param { Int } interval
|
|
*/
|
|
function _startSearch() {
|
|
print(`准备搜寻附近的蓝牙外围设备...`);
|
|
return promisify(wx.startBluetoothDevicesDiscovery, {
|
|
services: [this.serviceId], //如果填写了此UUID,那么只会搜索出含有这个UUID的设备
|
|
allowDuplicatesKey: false,
|
|
interval: 1000
|
|
}).then(
|
|
(res) => {
|
|
print(`✔ 搜索成功!`);
|
|
return [null, res]
|
|
|
|
},
|
|
(err) => {
|
|
print(`✘ 搜索蓝牙设备失败!${errToString(err)}`);
|
|
return [errToString(err), null]
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
*@param {Array<string>} devices
|
|
*@deviceId 设备ID
|
|
*/
|
|
function _onBluetoothFound() {
|
|
print(`监听搜寻新设备事件...`);
|
|
return _onBluetoothFound_promise.call(this).then(res => { //_getBluetoothDevices_promise _onBluetoothFound_promise
|
|
print(`✔ 设备 ${this.blename} 查找成功!`);
|
|
return [null, res]
|
|
}, err => {
|
|
print(`✘ 设备 ${this.blename} 查找失败!`);
|
|
return [errToString(err), null]
|
|
|
|
})
|
|
}
|
|
|
|
/**
|
|
* @param {Array} devices 查找到设备数组
|
|
* @param {int} count 计数器-嗅探2次
|
|
*/
|
|
function _onBluetoothFound_promise() {
|
|
let devices = []
|
|
let count = 0
|
|
return new Promise((resolve, reject) => {
|
|
wx.onBluetoothDeviceFound(res => {
|
|
devices.push(...res.devices)
|
|
print(`已嗅探设备数:${devices.length}...`)
|
|
print(`已嗅探设备信息:${JSON.stringify(devices)}`)
|
|
count++
|
|
print(`已嗅探次数:${count}`)
|
|
//if (count > 1)
|
|
if (devices.length > 0) {
|
|
devices.forEach(element => {
|
|
if ((element.name && element.name == this.blename) || (element.localName && element.localName == this.blename)) {
|
|
this.deviceId = element.deviceId
|
|
|
|
print(`我的设备Mac:${this.deviceId} `)
|
|
print(`我的设备名:${element.name}, ${element.localName}`)
|
|
resolve(res)
|
|
}
|
|
});
|
|
|
|
} else {
|
|
reject('device not found')
|
|
}
|
|
|
|
|
|
}, err => {
|
|
// reject(err)
|
|
})
|
|
})
|
|
}
|
|
|
|
/**
|
|
*@param {Array<string>} devices
|
|
*@deviceId 设备ID
|
|
*/
|
|
function _getBluetoothDevices() {
|
|
print(`监听搜寻新设备事件...`);
|
|
let devices = []
|
|
return wx.getBluetoothDevices({
|
|
success: function (res) {
|
|
console.log(res)
|
|
devices.push(res.devices)
|
|
print(`已嗅探设备数:${res.devices.length}...`)
|
|
print(`已嗅探设备信息:${JSON.stringify(res.devices)}`)
|
|
if (devices.length > 0) {
|
|
devices.forEach(element => {
|
|
if ((element.name && element.name == this.blename) || (element.localName && element.localName == this.blename)) {
|
|
this.deviceId = element.deviceId
|
|
|
|
print(`我的设备Mac:${this.deviceId} `)
|
|
print(`我的设备名:${element.name}, ${element.localName}`)
|
|
|
|
print(`✔ 设备 ${this.blename} 查找成功!`);
|
|
return [null, res]
|
|
}
|
|
});
|
|
} else {
|
|
return [`暂时没有嗅探到设备 ${this.blename}, 继续嗅探...`, null]
|
|
}
|
|
},
|
|
fail: function (res) {
|
|
print(`✘ 设备 ${this.blename} 查找失败!`);
|
|
return [errToString(err), null]
|
|
}
|
|
})
|
|
}
|
|
|
|
|
|
function _getBluetoothDevices_1() {
|
|
print(`监听搜寻新设备事件...`);
|
|
return _getBluetoothDevices_promise.call(this).then(res => {
|
|
print(`✔ 设备 ${this.blename} 查找成功!`);
|
|
return [null, res]
|
|
}, err => {
|
|
print(`✘ 设备 ${this.blename} 查找失败!`);
|
|
return [errToString(err), null]
|
|
})
|
|
}
|
|
|
|
/**
|
|
* @param {Array} devices 查找到设备数组
|
|
* @param {int} count 计数器-嗅探2次
|
|
*/
|
|
function _getBluetoothDevices_promise() {
|
|
let devices = []
|
|
print(`1111`)
|
|
return new Promise((resolve, reject) => {
|
|
|
|
print(`2222`)
|
|
|
|
wx.getBluetoothDevices(res => {
|
|
|
|
print(`3333`)
|
|
devices.push(...res.devices)
|
|
print(`已嗅探设备数:${devices.length}...`)
|
|
print(`已嗅探设备信息:${JSON.stringify(devices)}`)
|
|
if (devices.length > 0) {
|
|
devices.forEach(element => {
|
|
if ((element.name && element.name == this.blename) || (element.localName && element.localName == this.blename)) {
|
|
this.deviceId = element.deviceId
|
|
|
|
print(`我的设备Mac:${this.deviceId} `)
|
|
print(`我的设备名:${element.name}, ${element.localName}`)
|
|
|
|
resolve(res)
|
|
}
|
|
});
|
|
|
|
}
|
|
reject('device not found')
|
|
|
|
}, err => {
|
|
|
|
print(`4444`)
|
|
|
|
reject(err)
|
|
})
|
|
})
|
|
}
|
|
|
|
|
|
|
|
function _stopSearchBluetooth() {
|
|
print(`停止查找新设备...`);
|
|
return wx.stopBluetoothDevicesDiscovery().then(
|
|
(res) => {
|
|
print(`✔ 停止查找设备成功!`);
|
|
return [null, res]
|
|
},
|
|
(err) => {
|
|
print(`✘ 停止查询设备失败!${errToString(err)}`);
|
|
return [errToString(err), null]
|
|
}
|
|
);
|
|
}
|
|
|
|
function _connectBlue() {
|
|
print(`准备连接设备...`);
|
|
return promisify(wx.createBLEConnection, {
|
|
deviceId: this.deviceId,
|
|
}).then(
|
|
(res) => {
|
|
print(`✔ 连接蓝牙成功!`);
|
|
return [null, res]
|
|
},
|
|
(err) => {
|
|
print(`✘ 连接蓝牙失败!${errToString(err)}`);
|
|
return [errToString(err), null]
|
|
}
|
|
);
|
|
}
|
|
|
|
function _setBLEMTU() {
|
|
|
|
if (SYSTEM_INFO.platform != 'android') {
|
|
print(`仅安卓手机需要设置MTU Size`);
|
|
return ["仅安卓手机需要设置MTU Size", null];
|
|
}
|
|
|
|
print(`准备设置 MTU Size...`);
|
|
|
|
return promisify(wx.setBLEMTU, {
|
|
deviceId: this.deviceId,
|
|
mtu: MTU_SIZE
|
|
}).then(
|
|
(res) => {
|
|
|
|
//console.log("setBLEMTU success >> " + JSON.stringify(res))
|
|
print(`✔ 设置MTU Size = ${MTU_SIZE} 成功!`);
|
|
return [null, res]
|
|
},
|
|
(err) => {
|
|
|
|
//console.log("setBLEMTU fail >> " + JSON.stringify(res))
|
|
print(`✘ 设置MTU Size 失败!`);
|
|
return [errToString(err), null]
|
|
}
|
|
);
|
|
}
|
|
|
|
function _closeBLEConnection() {
|
|
print(`断开蓝牙连接...`)
|
|
return promisify(wx.closeBLEConnection, {
|
|
deviceId: this.deviceId,
|
|
}).then(
|
|
(res) => {
|
|
print(`✔ 断开蓝牙成功!`);
|
|
return [null, res]
|
|
},
|
|
(err) => {
|
|
print(`✘ 断开蓝牙连接失败!${errToString(err)}`);
|
|
return [errToString(err), null]
|
|
}
|
|
);
|
|
}
|
|
|
|
function _closeBLEAdapter() {
|
|
print(`释放蓝牙适配器...`)
|
|
return wx.closeBluetoothAdapter().then(res => {
|
|
print(`✔ 释放适配器成功!`)
|
|
getApp().globalData.bleStatus = ''
|
|
return [null, res]
|
|
}, err => {
|
|
print(`✘ 释放适配器失败!${errToString(err)}`)
|
|
return [errToString(err), null]
|
|
})
|
|
}
|
|
|
|
function _getBLEServices() {
|
|
print(`获取蓝牙设备所有服务...`)
|
|
return promisify(wx.getBLEDeviceServices, {
|
|
deviceId: this.deviceId
|
|
}).then(res => {
|
|
print(`✔ 获取service成功!`)
|
|
console.log('services UUID:\n', JSON.stringify(res.services));
|
|
for (var i = 0; i < res.services.length; i++) {
|
|
console.log("第" + (i + 1) + "个UUID:" + res.services[i].uuid + "\n")
|
|
}
|
|
return [null, res]
|
|
}, err => {
|
|
print(`✘ 获取service失败!${errToString(err)}`)
|
|
return [errToString(err), null]
|
|
})
|
|
}
|
|
|
|
function _getCharacteristics() {
|
|
print(`开始获取特征值...`);
|
|
return promisify(wx.getBLEDeviceCharacteristics, {
|
|
deviceId: this.deviceId,
|
|
serviceId: toPlatformString(SYSTEM_INFO, this.serviceId), //具有写、通知属性的服务uuid
|
|
}).then(
|
|
(res) => {
|
|
print(`✔ 获取特征值成功!`);
|
|
for (let i = 0; i < res.characteristics.length; i++) {
|
|
let item = res.characteristics[i];
|
|
if (item.properties.read) {
|
|
this.readCharacteristicId = item.uuid;
|
|
print(`readCharacteristicId:${item.uuid}`)
|
|
}
|
|
if (item.properties.write && !item.properties.read) {
|
|
this.writeCharacteristicId = item.uuid;
|
|
print(`writeCharacteristicId:${item.uuid}`)
|
|
}
|
|
if (item.properties.notify || item.properties.indicate) {
|
|
this.notifyCharacteristicId = item.uuid;
|
|
print(`notifyCharacteristicId:${item.uuid}`)
|
|
}
|
|
}
|
|
return [null, res]
|
|
},
|
|
(err) => {
|
|
print(`✘ 获取特征值失败!${errToString(err)}`);
|
|
return [errToString(err), null]
|
|
}
|
|
);
|
|
}
|
|
|
|
// 订阅特征值
|
|
function _notifyBLECharacteristicValueChange() {
|
|
return promisify(wx.notifyBLECharacteristicValueChange, {
|
|
deviceId: this.deviceId,
|
|
serviceId: toPlatformString(SYSTEM_INFO, this.serviceId),
|
|
characteristicId: toPlatformString(SYSTEM_INFO, this.notifyCharacteristicId),
|
|
state: true
|
|
}).then(res => {
|
|
wx.hideLoading()
|
|
wx.showToast({
|
|
title: "连接成功",
|
|
duration: 2000,
|
|
icon: "none"
|
|
})
|
|
print(`✔ 订阅notify成功!`)
|
|
|
|
return [null, res]
|
|
}, err => {
|
|
wx.hideLoading()
|
|
wx.showToast({
|
|
title: `连接失败!${errToString(err)}`,
|
|
duration: 2000,
|
|
icon: "none"
|
|
})
|
|
print(`✘ 订阅notify失败!${errToString(err)}`)
|
|
return [errToString(err), null]
|
|
})
|
|
}
|
|
|
|
/**
|
|
* 指令封装
|
|
* @param {Array} data
|
|
*/
|
|
function _sentOrder(cmd, payload, timestamp1) {
|
|
print(`开始封装指令...`)
|
|
console.log(payload)
|
|
let data = payload
|
|
let payloadLength = data.length;
|
|
let length = 13 + payload.length
|
|
let b = new Uint8Array(length);
|
|
|
|
b[0] = 0x89;
|
|
b[1] = 0x89;
|
|
b[2] = cmd;
|
|
console.log(timestamp1)
|
|
// let timestamp = timestamp1 //new Date().getTime();
|
|
|
|
//let ts = timestamp.toString(16)
|
|
// let t = util.IntToBytesLittleEndian(timestamp, 6)
|
|
/*
|
|
b[4] = (byte)((timestamp >> 40) & 0x00000000000000ff);
|
|
b[5] = (byte)((timestamp >> 32) & 0x00000000000000ff);
|
|
b[6] = (byte)((timestamp >> 24) & 0x00000000000000ff);
|
|
b[7] = (byte)((timestamp >> 16) & 0x00000000000000ff);
|
|
b[8] = (byte)((timestamp >> 8) & 0x00000000000000ff);
|
|
b[9] = (byte)(timestamp & 0x00000000000000ff);
|
|
*/
|
|
let timestamp = timestamp1 //new Date().getTime();
|
|
let t = new Uint8Array(6);
|
|
for (let i = 0; i < 6; i++) {
|
|
t[5 - i] = timestamp & 255;
|
|
timestamp = timestamp >> 8;
|
|
}
|
|
console.log(t)
|
|
b.set(t, 4)
|
|
console.log(t)
|
|
|
|
// b.set(t, 4)
|
|
|
|
b[3] = b[9];
|
|
|
|
b[10] = (payloadLength >> 8) & 0xff;
|
|
b[11] = payloadLength & 0xff;
|
|
let key = b[3];
|
|
for (let i = 0; i < payloadLength; i++) {
|
|
data[i] -= (payloadLength - i) ^ key;
|
|
data[i] = (data[i] ^ (key ^ i));
|
|
}
|
|
|
|
b.set(data, 12)
|
|
|
|
let xor = b[0];
|
|
for (let i = 1; i < length - 1; i++)
|
|
xor ^= b[i];
|
|
|
|
b[length - 1] = xor;
|
|
|
|
print(`✔ 封装成功! ${b}`)
|
|
|
|
return b;
|
|
}
|
|
|
|
|
|
function _writeBLECharacteristicValue(data) {
|
|
return promisify(wx.writeBLECharacteristicValue, {
|
|
deviceId: this.deviceId,
|
|
serviceId: toPlatformString(SYSTEM_INFO, this.serviceId),
|
|
characteristicId: toPlatformString(SYSTEM_INFO, this.writeCharacteristicId),
|
|
value: data,
|
|
}).then(res => {
|
|
print(`✔ 写入数据成功!`)
|
|
return [null, res]
|
|
}, err => {
|
|
print(`✘ 写入数据失败!${errToString(err)}`)
|
|
return [errToString(err), null]
|
|
})
|
|
}
|
|
|
|
/**
|
|
* 对微信接口的promise封装
|
|
* @param {function} fn
|
|
* @param {object} args
|
|
*/
|
|
function promisify(fn, args) {
|
|
return new Promise((resolve, reject) => {
|
|
fn({
|
|
...(args || {}),
|
|
success: (res) => resolve(res),
|
|
fail: (err) => reject(err),
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 对微信接口回调函数的封装
|
|
* @param {function} fn
|
|
*/
|
|
function promisify_callback(fn) {
|
|
return new Promise((resolve, reject) => {
|
|
fn(
|
|
(res) => {
|
|
resolve(res);
|
|
},
|
|
(rej) => {
|
|
reject(rej);
|
|
}
|
|
);
|
|
});
|
|
}
|
|
|
|
function print(str) {
|
|
PRINT_SHOW ? console.log(str) : null;
|
|
}
|
|
|
|
export {
|
|
print,
|
|
_getCharacteristics,
|
|
_connectBlue,
|
|
_setBLEMTU,
|
|
_getBLEServices,
|
|
_closeBLEConnection,
|
|
_closeBLEAdapter,
|
|
_stopSearchBluetooth,
|
|
_notifyBLECharacteristicValueChange,
|
|
_onBluetoothFound,
|
|
_getBluetoothDevices,
|
|
_startSearch,
|
|
_openAdapter,
|
|
_sentOrder,
|
|
_writeBLECharacteristicValue,
|
|
promisify,
|
|
promisify_callback,
|
|
};
|