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} 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} 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} 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, };