const util = require("../../utils/util"); const plugin = requirePlugin("sdkPlugin").AiLink; function inArray(arr, key, val) { for (let i = 0; i < arr.length; i++) { if (arr[i][key] === val) { return i; } } return -1; } // ArrayBuffer转16进度字符串示例 function ab2hex(buffer, split = ',') { var hexArr = Array.prototype.map.call( new Uint8Array(buffer), function (bit) { return ('00' + bit.toString(16)).slice(-2) } ) return hexArr.join(split); } Page({ data: { showWriteInput: false, devices: [ // { // deviceId: "02:03:04:05:06:07", // name: "elink", // localName: "elink", // mac: "02:03:04:05:06:07", // RSSI: -69, // advertisServiceUUIDs:[ // "FFE0","FFC0" // ], // analyzeDataText:"0102003241123413" // } ], connected: false, chs: [], }, onLoad: function () { }, // 初始化蓝牙模块 openBluetoothAdapter() { wx.openBluetoothAdapter({ success: (res) => { console.log('openBluetoothAdapter success', res) this.startBluetoothDevicesDiscovery() }, fail: (res) => { if (res.errCode === 10001) { wx.showToast({ title: '请打开蓝牙', icon: "none" }) wx.onBluetoothAdapterStateChange(function (res) { console.log('onBluetoothAdapterStateChange', res) if (res.available) { this.startBluetoothDevicesDiscovery() } }) } } }) }, // 获取本机蓝牙适配器状态 getBluetoothAdapterState() { wx.getBluetoothAdapterState({ success: (res) => { console.log('getBluetoothAdapterState', res) if (res.discovering) { this.onBluetoothDeviceFound() } else if (res.available) { this.startBluetoothDevicesDiscovery() } } }) }, // 开始搜寻附近的蓝牙外围设备 startBluetoothDevicesDiscovery() { if (this._discoveryStarted) { return } this._discoveryStarted = true wx.startBluetoothDevicesDiscovery({ allowDuplicatesKey: true, services: [ "FFE0", "F0A0", ], success: (res) => { console.log('startBluetoothDevicesDiscovery success', res) this.onBluetoothDeviceFound() }, }) }, // 停止搜寻附近的蓝牙外围设备 stopBluetoothDevicesDiscovery() { wx.stopBluetoothDevicesDiscovery() }, // 监听寻找到新设备的事件 onBluetoothDeviceFound() { wx.onBluetoothDeviceFound((res) => { res.devices.forEach(device => { if (!device.name && !device.localName) { return } const foundDevices = this.data.devices const idx = inArray(foundDevices, 'deviceId', device.deviceId) const data = {} // console.log(device) // console.log(ab2hex(device.advertisData)) // 此处判断是否BM30广播模块,如使用连接模块请删除此 if ,只保留 else 内容 if (device.advertisServiceUUIDs[0].indexOf("F0A0") !== -1) { let parseDataRes = plugin.parseBroadcastData(device.advertisData) console.log(parseDataRes) if (parseDataRes.status == 1) { let analyzeData = plugin.analyzeBroadcastScaleData(parseDataRes) console.log(analyzeData) device.analyzeDataText = analyzeData.text } } else { let buff = device.advertisData.slice(-6) device.mac = new Uint8Array(buff) // 保存广播数据中的mac地址,这是由于iOS不直接返回mac地址 } if (idx === -1) { data[`devices[${foundDevices.length}]`] = device } else { data[`devices[${idx}]`] = device } this.setData(data) }) }) }, // 连接低功耗蓝牙设备 createBLEConnection(e) { const ds = e.currentTarget.dataset const index = ds.index // 保存当前连接的设备,注意不能从wxml的dataset中直接返回该对象,因为ArrarBuffer类型的数据无法保留 this._device = this.data.devices[index] console.log(this._device) const deviceId = ds.deviceId const name = ds.name this.mac = ds.mac wx.createBLEConnection({ deviceId, success: (res) => { this.setData({ connected: true, name, deviceId, }) console.log("createBLEConnection:success") wx.stopBluetoothDevicesDiscovery() this.getBLEDeviceServices(deviceId) } }) // 连接上设备就可以停止蓝牙搜索,减少功耗。 this.stopBluetoothDevicesDiscovery() }, // 断开与低功耗蓝牙设备的连接 closeBLEConnection() { wx.closeBLEConnection({ deviceId: this._deviceId }) this.setData({ connected: false, chs: [], }) }, // 获取蓝牙设备的 serviceId getBLEDeviceServices(deviceId) { wx.getBLEDeviceServices({ deviceId, success: (res) => { for (let i = 0; i < res.services.length; i++) { if (res.services[i].isPrimary) { this.getBLEDeviceCharacteristics(deviceId, res.services[i].uuid) return } } } }) }, // 获取蓝牙设备某个服务中所有特征值(characteristic) getBLEDeviceCharacteristics(deviceId, serviceId) { this._deviceId = deviceId this._serviceId = serviceId this._device.serviceId = serviceId wx.getBLEDeviceCharacteristics({ deviceId, serviceId, success: (res) => { console.log('getBLEDeviceCharacteristics success', res.characteristics) // 这部分功能在插件的 initPlugin 中已实现,如需用到其中的 uuid 也可取消注释 // // 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, // }) // 初始化插件 plugin.initPlugin(res.characteristics, this._device) wx.onBLECharacteristicValueChange((characteristic) => { // 解析特征值,返回解密后的数据 let bleData = plugin.parseBleData(characteristic.value) if (bleData.status == 0) { console.log("握手成功") } else if (bleData.status == 1) { console.log(bleData) let payload = bleData.data //对应协议中的payload数据,可以自行解析该数据 console.log(ab2hex(payload, ' ')) console.log(ab2hex(bleData.completeData, ' ')) // 以体脂秤数据解析为例 let weight, adc; switch (payload[0]) { /* * 例如: A7 00 0E 05 01 00 01 F4 10 19 7A---------50.0kg * 其中 01 00 01 F4 10 为 payload * 具体指令请根据协议解析 */ case 0x01: case 0x02: let weightValue = (payload[1] << 16) | (payload[2] << 8) | payload[3] let decPoint = (payload[4] & 0xf0) >> 4 let unit = payload[4] & 0x0f // console.log("体重数值:" + weightValue) // console.log("小数点:" + decPoint) // console.log("单位:" + unit) if (unit == 1) { // 单位为斤 weight = weightValue / 2 } else { // ... 其他单位 } weight = weightValue / (decPoint * 10) // 除去小数点位数 break; // ... /* * 例如: A7 00 0E 03 07 02 30 4A 7A---------阻抗测量成功,阻抗 560Ω * 其中 07 02 30 为 payload * 具体指令请根据协议解析 */ case 0x07: adc = (payload[1] << 8) | payload[2] break; case 0x0A: //测量完成 let bodyData = plugin.getBodyData(1, 20, 170, weight, adc) // 体脂秤数据解析 console.log("解析后的体脂数据: ", bodyData) console.log(util.getWeightDisplay(170, weight)) break; } const idx = inArray(this.data.chs, 'uuid', characteristic.characteristicId) const data = {} if (idx === -1) { data[`chs[${this.data.chs.length}]`] = { uuid: characteristic.characteristicId, value: ab2hex(payload, ' ') } } else { data[`chs[${idx}]`] = { uuid: characteristic.characteristicId, value: ab2hex(payload, ' ') } } this.setData(data) } else { console.log(bleData) } }) }, fail(res) { console.error('getBLEDeviceCharacteristics', res) } }) }, writeBLECharacteristicValue(buffer, uuid, deviceId, serviceId) { // 向蓝牙设备发送一个二进制流数据 wx.writeBLECharacteristicValue({ deviceId, serviceId, characteristicId: uuid, value: buffer, success(res) { console.log('writeBLECharacteristicValue success', res) console.log(ab2hex(buffer)) } }) }, closeBluetoothAdapter() { wx.closeBluetoothAdapter() this._discoveryStarted = false }, // 打开指令输入框 showWriteInputView() { this.setData({ showWriteInput: true }) }, // 关闭指令输入框 hideWriteInputView() { this.setData({ showWriteInput: false }) }, // 指令输入 writingCmd(e) { this._cmd = e.detail.value }, // 指令下发 submitCmd() { if (!this._cmd) { return } let arr = [] if (this._cmd.indexOf(",") == -1) { arr = this._cmd.split(" ") } else { arr = this._cmd.split(",") } for (let i in arr) { arr[i] = parseInt(arr[i], 16) } // let arr = [ // 0xA6, // 0x01, // 0x28, // 0x29, // 0x6A, // //A6 01 28 29 6A // ] if (arr[0] == 0xA6) { let payload = arr.slice(2, -2) plugin.sendDataOfA6(payload) } else if (arr[0] == 0xA7) { let cid = [arr[1], arr[2]] // 001E let payload = arr.slice(4, -2) plugin.sendDataOfA7(payload) // this.writeBLECharacteristicValue(buff, this.uuid1, this._deviceId, this._serviceId) } return }, });