|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function inArray(arr, key, val) { |
|
|
function inArray(arr, key, val) { |
|
|
|
|
|
if (!arr || !arr.length || typeof arr != 'object' || !Array.isArray(arr)) { |
|
|
|
|
|
return -1 |
|
|
|
|
|
} |
|
|
for (let i = 0; i < arr.length; i++) { |
|
|
for (let i = 0; i < arr.length; i++) { |
|
|
if (arr[i][key] === val) { |
|
|
|
|
|
return i; |
|
|
|
|
|
|
|
|
if (!key) { |
|
|
|
|
|
if (arr[i] == val) { |
|
|
|
|
|
return i |
|
|
|
|
|
} |
|
|
|
|
|
} else if (arr[i][key] === val) { |
|
|
|
|
|
return i |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
return -1; |
|
|
return -1; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// ArrayBuffer转16进度字符串示例 |
|
|
// ArrayBuffer转16进度字符串示例 |
|
|
function ab2hex(buffer, split = ',') { |
|
|
|
|
|
|
|
|
function ab2hex(buffer, split) { |
|
|
var hexArr = Array.prototype.map.call( |
|
|
var hexArr = Array.prototype.map.call( |
|
|
new Uint8Array(buffer), |
|
|
new Uint8Array(buffer), |
|
|
function (bit) { |
|
|
function (bit) { |
|
|
|
|
|
|
|
|
], |
|
|
], |
|
|
connected: false, |
|
|
connected: false, |
|
|
chs: [], |
|
|
chs: [], |
|
|
|
|
|
cmd: '', |
|
|
|
|
|
name: '', |
|
|
|
|
|
deviceId: null, |
|
|
|
|
|
historyList: [], |
|
|
}, |
|
|
}, |
|
|
onLoad: function () { |
|
|
onLoad: function () { |
|
|
|
|
|
|
|
|
|
|
|
let historyList = [] |
|
|
|
|
|
historyList = wx.getStorageSync('historyList') |
|
|
|
|
|
this.setData({ |
|
|
|
|
|
historyList, |
|
|
|
|
|
}) |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
// 初始化蓝牙模块 |
|
|
// 初始化蓝牙模块 |
|
|
|
|
|
|
|
|
allowDuplicatesKey: true, |
|
|
allowDuplicatesKey: true, |
|
|
services: [ |
|
|
services: [ |
|
|
"FFE0", |
|
|
"FFE0", |
|
|
"F0A0", |
|
|
|
|
|
|
|
|
// "F0A0", // BM30广播模块需加上,如使用连接模块可忽略 |
|
|
], |
|
|
], |
|
|
success: (res) => { |
|
|
success: (res) => { |
|
|
console.log('startBluetoothDevicesDiscovery success', res) |
|
|
console.log('startBluetoothDevicesDiscovery success', res) |
|
|
|
|
|
|
|
|
} else { |
|
|
} else { |
|
|
let buff = device.advertisData.slice(-6) |
|
|
let buff = device.advertisData.slice(-6) |
|
|
device.mac = new Uint8Array(buff) // 保存广播数据中的mac地址,这是由于iOS不直接返回mac地址 |
|
|
device.mac = new Uint8Array(buff) // 保存广播数据中的mac地址,这是由于iOS不直接返回mac地址 |
|
|
|
|
|
let tempMac = Array.from(device.mac) |
|
|
|
|
|
tempMac.reverse() |
|
|
|
|
|
device.macAddr = ab2hex(tempMac, ':').toUpperCase() |
|
|
} |
|
|
} |
|
|
if (idx === -1) { |
|
|
if (idx === -1) { |
|
|
data[`devices[${foundDevices.length}]`] = device |
|
|
data[`devices[${foundDevices.length}]`] = device |
|
|
|
|
|
|
|
|
}, |
|
|
}, |
|
|
// 连接低功耗蓝牙设备 |
|
|
// 连接低功耗蓝牙设备 |
|
|
createBLEConnection(e) { |
|
|
createBLEConnection(e) { |
|
|
|
|
|
this._connLoading = true |
|
|
|
|
|
wx.showLoading({ |
|
|
|
|
|
title: '连接中', |
|
|
|
|
|
}) |
|
|
|
|
|
setTimeout(() => { |
|
|
|
|
|
if (this._connLoading) { |
|
|
|
|
|
this._connLoading = false |
|
|
|
|
|
wx.hideLoading() |
|
|
|
|
|
} |
|
|
|
|
|
}, 6000) |
|
|
const ds = e.currentTarget.dataset |
|
|
const ds = e.currentTarget.dataset |
|
|
const index = ds.index |
|
|
const index = ds.index |
|
|
// 保存当前连接的设备,注意不能从wxml的dataset中直接返回该对象,因为ArrarBuffer类型的数据无法保留 |
|
|
// 保存当前连接的设备,注意不能从wxml的dataset中直接返回该对象,因为ArrarBuffer类型的数据无法保留 |
|
|
|
|
|
|
|
|
}) |
|
|
}) |
|
|
console.log("createBLEConnection:success") |
|
|
console.log("createBLEConnection:success") |
|
|
wx.stopBluetoothDevicesDiscovery() |
|
|
wx.stopBluetoothDevicesDiscovery() |
|
|
|
|
|
this.onBLEConnectionStateChange() |
|
|
this.getBLEDeviceServices(deviceId) |
|
|
this.getBLEDeviceServices(deviceId) |
|
|
|
|
|
}, |
|
|
|
|
|
fail: res => { |
|
|
|
|
|
this._connLoading = false |
|
|
|
|
|
wx.hideLoading() |
|
|
|
|
|
wx.showToast({ |
|
|
|
|
|
title: '连接失败', |
|
|
|
|
|
icon: 'none' |
|
|
|
|
|
}) |
|
|
} |
|
|
} |
|
|
}) |
|
|
}) |
|
|
// 连接上设备就可以停止蓝牙搜索,减少功耗。 |
|
|
// 连接上设备就可以停止蓝牙搜索,减少功耗。 |
|
|
this.stopBluetoothDevicesDiscovery() |
|
|
this.stopBluetoothDevicesDiscovery() |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
onBLEConnectionStateChange() { |
|
|
|
|
|
wx.onBLEConnectionStateChange((res) => { |
|
|
|
|
|
console.log('wx.onBLEConnectionStateChange() ', res.deviceId, res.connected, res.errorCode, res.errorMsg) |
|
|
|
|
|
// 该方法回调中可以用于处理连接意外断开等异常情况 |
|
|
|
|
|
// console.log(`%c device ${res.deviceId} state has changed, connected: ${res.connected}`, 'color: #F26363') |
|
|
|
|
|
if (!res.connected) { |
|
|
|
|
|
wx.showToast({ |
|
|
|
|
|
title: '连接已断开', |
|
|
|
|
|
icon: 'none' |
|
|
|
|
|
}) |
|
|
|
|
|
this.setData({ |
|
|
|
|
|
connected: false, |
|
|
|
|
|
showWriteInput: false, |
|
|
|
|
|
}) |
|
|
|
|
|
} |
|
|
|
|
|
}) |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
// 断开与低功耗蓝牙设备的连接 |
|
|
// 断开与低功耗蓝牙设备的连接 |
|
|
closeBLEConnection() { |
|
|
closeBLEConnection() { |
|
|
wx.closeBLEConnection({ |
|
|
wx.closeBLEConnection({ |
|
|
|
|
|
|
|
|
this.setData({ |
|
|
this.setData({ |
|
|
connected: false, |
|
|
connected: false, |
|
|
chs: [], |
|
|
chs: [], |
|
|
|
|
|
showWriteInput: false, |
|
|
}) |
|
|
}) |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
wx.getBLEDeviceServices({ |
|
|
wx.getBLEDeviceServices({ |
|
|
deviceId, |
|
|
deviceId, |
|
|
success: (res) => { |
|
|
success: (res) => { |
|
|
console.log(res) |
|
|
|
|
|
for (let i = 0; i < res.services.length; i++) { |
|
|
for (let i = 0; i < res.services.length; i++) { |
|
|
if (res.services[i].isPrimary && res.services[i].uuid.indexOf("FFE0")>-1) { |
|
|
|
|
|
|
|
|
if (res.services[i].isPrimary && res.services[i].uuid.indexOf('FFE0') > -1) { |
|
|
this.getBLEDeviceCharacteristics(deviceId, res.services[i].uuid) |
|
|
this.getBLEDeviceCharacteristics(deviceId, res.services[i].uuid) |
|
|
return |
|
|
return |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 这部分功能在插件的 initPlugin 中已实现,如需用到其中的 uuid 也可取消注释 |
|
|
// 这部分功能在插件的 initPlugin 中已实现,如需用到其中的 uuid 也可取消注释 |
|
|
// // let uuid1, uuid2, uuid3; |
|
|
// // let uuid1, uuid2, uuid3; |
|
|
// for (let i = 0; i < res.characteristics.length; i++) { |
|
|
|
|
|
// let item = res.characteristics[i] |
|
|
|
|
|
// if (item.uuid.indexOf('0000FFE1') != -1) { |
|
|
|
|
|
// this.uuid1 = item.uuid //下发数据 |
|
|
|
|
|
// } else if (item.uuid.indexOf('0000FFE2') != -1) { |
|
|
|
|
|
// this.uuid2 = item.uuid //监听数据 |
|
|
|
|
|
// } else if (item.uuid.indexOf('0000FFE3') != -1) { |
|
|
|
|
|
// this.uuid3 = item.uuid //写入设置 |
|
|
|
|
|
// } |
|
|
|
|
|
// } |
|
|
|
|
|
// // 打开监听 |
|
|
|
|
|
// wx.notifyBLECharacteristicValueChange({ |
|
|
|
|
|
// deviceId, |
|
|
|
|
|
// serviceId, |
|
|
|
|
|
// characteristicId: this.uuid2, |
|
|
|
|
|
// state: true, |
|
|
|
|
|
// }) |
|
|
|
|
|
// wx.notifyBLECharacteristicValueChange({ |
|
|
|
|
|
// deviceId, |
|
|
|
|
|
// serviceId, |
|
|
|
|
|
// characteristicId: this.uuid3, |
|
|
|
|
|
// state: true, |
|
|
|
|
|
// }) |
|
|
|
|
|
|
|
|
for (let i = 0; i < res.characteristics.length; i++) { |
|
|
|
|
|
let item = res.characteristics[i] |
|
|
|
|
|
if (item.uuid.indexOf('0000FFE1') != -1) { |
|
|
|
|
|
this.uuid1 = item.uuid //下发数据 |
|
|
|
|
|
} else if (item.uuid.indexOf('0000FFE2') != -1) { |
|
|
|
|
|
this.uuid2 = item.uuid //监听数据 |
|
|
|
|
|
} else if (item.uuid.indexOf('0000FFE3') != -1) { |
|
|
|
|
|
this.uuid3 = item.uuid //写入设置 |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
// 打开监听 |
|
|
|
|
|
wx.notifyBLECharacteristicValueChange({ |
|
|
|
|
|
deviceId, |
|
|
|
|
|
serviceId, |
|
|
|
|
|
characteristicId: this.uuid2, |
|
|
|
|
|
state: true, |
|
|
|
|
|
}) |
|
|
|
|
|
wx.notifyBLECharacteristicValueChange({ |
|
|
|
|
|
deviceId, |
|
|
|
|
|
serviceId, |
|
|
|
|
|
characteristicId: this.uuid3, |
|
|
|
|
|
state: true, |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
// 初始化插件 |
|
|
// 初始化插件 |
|
|
plugin.initPlugin(res.characteristics, this._device) |
|
|
plugin.initPlugin(res.characteristics, this._device) |
|
|
|
|
|
|
|
|
wx.onBLECharacteristicValueChange((characteristic) => { |
|
|
wx.onBLECharacteristicValueChange((characteristic) => { |
|
|
// 解析特征值,返回解密后的数据 |
|
|
// 解析特征值,返回解密后的数据 |
|
|
console.log("===" + plugin.ab2hex(characteristic.value)) |
|
|
|
|
|
let bleData = plugin.parseBleData(characteristic.value) |
|
|
let bleData = plugin.parseBleData(characteristic.value) |
|
|
|
|
|
console.log(bleData) |
|
|
if (bleData.status == 0) { |
|
|
if (bleData.status == 0) { |
|
|
console.log("握手成功") |
|
|
console.log("握手成功") |
|
|
|
|
|
this._connLoading = false |
|
|
|
|
|
wx.hideLoading() |
|
|
|
|
|
wx.showToast({ |
|
|
|
|
|
title: '连接成功', |
|
|
|
|
|
}) |
|
|
} else if (bleData.status == 1) { |
|
|
} else if (bleData.status == 1) { |
|
|
console.log(bleData) |
|
|
|
|
|
let payload = bleData.data //对应协议中的payload数据,可以自行解析该数据 |
|
|
let payload = bleData.data //对应协议中的payload数据,可以自行解析该数据 |
|
|
console.log(ab2hex(payload, ' ')) |
|
|
|
|
|
console.log(ab2hex(bleData.completeData, ' ')) |
|
|
|
|
|
|
|
|
// console.log(ab2hex(payload, ' ')) |
|
|
|
|
|
// console.log(ab2hex(bleData.completeData, ' ')) |
|
|
|
|
|
|
|
|
// 以体脂秤数据解析为例 |
|
|
// 以体脂秤数据解析为例 |
|
|
let weight, adc; |
|
|
let weight, adc; |
|
|
|
|
|
|
|
|
if (idx === -1) { |
|
|
if (idx === -1) { |
|
|
data[`chs[${this.data.chs.length}]`] = { |
|
|
data[`chs[${this.data.chs.length}]`] = { |
|
|
uuid: characteristic.characteristicId, |
|
|
uuid: characteristic.characteristicId, |
|
|
value: ab2hex(payload, ' ') |
|
|
|
|
|
|
|
|
value: ab2hex(bleData.completeData, ' ') |
|
|
} |
|
|
} |
|
|
} else { |
|
|
} else { |
|
|
data[`chs[${idx}]`] = { |
|
|
data[`chs[${idx}]`] = { |
|
|
uuid: characteristic.characteristicId, |
|
|
uuid: characteristic.characteristicId, |
|
|
value: ab2hex(payload, ' ') |
|
|
|
|
|
|
|
|
value: ab2hex(bleData.completeData, ' ') |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
this.setData(data) |
|
|
this.setData(data) |
|
|
} else { |
|
|
} else { |
|
|
console.log(bleData) |
|
|
|
|
|
|
|
|
// console.log(bleData) |
|
|
} |
|
|
} |
|
|
}) |
|
|
}) |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
value: buffer, |
|
|
value: buffer, |
|
|
success(res) { |
|
|
success(res) { |
|
|
console.log('writeBLECharacteristicValue success', res) |
|
|
console.log('writeBLECharacteristicValue success', res) |
|
|
console.log(ab2hex(buffer)) |
|
|
|
|
|
|
|
|
console.log('下发指令==> ' + ab2hex(buffer)) |
|
|
} |
|
|
} |
|
|
}) |
|
|
}) |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
showWriteInput: false |
|
|
showWriteInput: false |
|
|
}) |
|
|
}) |
|
|
}, |
|
|
}, |
|
|
// 指令输入 |
|
|
|
|
|
writingCmd(e) { |
|
|
|
|
|
this._cmd = e.detail.value |
|
|
|
|
|
}, |
|
|
|
|
|
// 指令下发 |
|
|
// 指令下发 |
|
|
submitCmd() { |
|
|
|
|
|
if (!this._cmd) { |
|
|
|
|
|
|
|
|
submitCmd(e, cmd) { |
|
|
|
|
|
let arr = [] |
|
|
|
|
|
let temp = [] |
|
|
|
|
|
if (!cmd) { |
|
|
|
|
|
cmd = this.data.cmd |
|
|
|
|
|
} |
|
|
|
|
|
console.log(cmd) |
|
|
|
|
|
if(!cmd || !this.data.connected){ |
|
|
return |
|
|
return |
|
|
} |
|
|
} |
|
|
let arr = [] |
|
|
|
|
|
if (this._cmd.indexOf(",") == -1) { |
|
|
|
|
|
arr = this._cmd.split(" ") |
|
|
|
|
|
|
|
|
if(cmd.indexOf(",") == -1){ |
|
|
|
|
|
temp = cmd.split(" ") |
|
|
} else { |
|
|
} else { |
|
|
arr = this._cmd.split(",") |
|
|
|
|
|
|
|
|
temp = cmd.split(",") |
|
|
} |
|
|
} |
|
|
for (let i in arr) { |
|
|
|
|
|
arr[i] = parseInt(arr[i], 16) |
|
|
|
|
|
|
|
|
let tempCmd = temp.join(' ') |
|
|
|
|
|
for(let i = 0; i < temp.length; i++){ |
|
|
|
|
|
arr[i] = parseInt(temp[i],16) |
|
|
} |
|
|
} |
|
|
// let arr = [ |
|
|
// let arr = [ |
|
|
// 0xA6, |
|
|
// 0xA6, |
|
|
|
|
|
|
|
|
// 0x6A, |
|
|
// 0x6A, |
|
|
// //A6 01 28 29 6A |
|
|
// //A6 01 28 29 6A |
|
|
// ] |
|
|
// ] |
|
|
if (arr[0] == 0xA6) { |
|
|
|
|
|
let payload = arr.slice(2, -2) |
|
|
|
|
|
|
|
|
if(arr[0] == 0xA6){ |
|
|
|
|
|
let len = arr[1] |
|
|
|
|
|
let payload = arr.slice(2, 2 + len) |
|
|
plugin.sendDataOfA6(payload) |
|
|
plugin.sendDataOfA6(payload) |
|
|
} else if (arr[0] == 0xA7) { |
|
|
|
|
|
let cid = [arr[1], arr[2]] // 001E |
|
|
|
|
|
let payload = arr.slice(4, -2) |
|
|
|
|
|
|
|
|
// let buff = new Uint8Array(arr).buffer |
|
|
|
|
|
// this.writeBLECharacteristicValue(buff, this.uuid3, this._deviceId, this._serviceId) |
|
|
|
|
|
} else if(arr[0] == 0xA7) { |
|
|
|
|
|
let len = arr[3] |
|
|
|
|
|
let payload = arr.slice(4, 4 + len) |
|
|
plugin.sendDataOfA7(payload) |
|
|
plugin.sendDataOfA7(payload) |
|
|
// this.writeBLECharacteristicValue(buff, this.uuid1, this._deviceId, this._serviceId) |
|
|
|
|
|
} |
|
|
} |
|
|
return |
|
|
|
|
|
|
|
|
let historyList = wx.getStorageSync('historyList') || [] |
|
|
|
|
|
let idx = historyList.findIndex(item => item.cmd == tempCmd) |
|
|
|
|
|
if (idx < 0) { |
|
|
|
|
|
historyList.push({cmd: tempCmd}) |
|
|
|
|
|
} |
|
|
|
|
|
this.setData({ |
|
|
|
|
|
historyList |
|
|
|
|
|
}) |
|
|
|
|
|
wx.setStorage({ |
|
|
|
|
|
data: historyList, |
|
|
|
|
|
key: 'historyList', |
|
|
|
|
|
}) |
|
|
|
|
|
wx.showToast({ |
|
|
|
|
|
title: '已发送', |
|
|
|
|
|
icon: 'none' |
|
|
|
|
|
}) |
|
|
|
|
|
}, |
|
|
|
|
|
history_delete(e) { |
|
|
|
|
|
let index = e.currentTarget.dataset.index |
|
|
|
|
|
this.data.historyList.splice(index, 1) |
|
|
|
|
|
this.setData({ |
|
|
|
|
|
historyList: this.data.historyList |
|
|
|
|
|
}) |
|
|
|
|
|
wx.setStorage({ |
|
|
|
|
|
data: this.data.historyList, |
|
|
|
|
|
key: 'historyList', |
|
|
|
|
|
}) |
|
|
|
|
|
}, |
|
|
|
|
|
history_copy(e) { |
|
|
|
|
|
let index = e.currentTarget.dataset.index |
|
|
|
|
|
wx.setClipboardData({ |
|
|
|
|
|
data: this.data.historyList[index].cmd |
|
|
|
|
|
}) |
|
|
|
|
|
}, |
|
|
|
|
|
history_send(e) { |
|
|
|
|
|
let index = e.currentTarget.dataset.index |
|
|
|
|
|
let cmd = this.data.historyList[index].cmd |
|
|
|
|
|
this.submitCmd(null, cmd) |
|
|
}, |
|
|
}, |
|
|
}); |
|
|
}); |