// const plugin = requirePlugin("myPlugin").AiFresh; const {BM16His: plugin} = requirePlugin("sdkPlugin"); 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) { var hexArr = Array.prototype.map.call( new Uint8Array(buffer), function (bit) { return ('00' + bit.toString(16)).slice(-2) } ) return hexArr.join(','); } // var information = [] Page({ data: { devices: [], mac: "", connected: false, text: "", unitList_all: ['g', 'ml', 'lb:oz', 'oz', 'kg', '斤', '牛奶 ml', '水 ml', '牛奶 floz', '水 floz', 'lb'], unitList: ['g', 'ml', 'lb:oz', 'oz'], weight: 0, unit: 'g', unitIndex: 0, min: 0, second: 0, showWriteInput: false, connected: false, chs: [], cmd: '', name: '', deviceId: null, historyList: [], height:0, information:[], }, onLoad: function () { let screenHeight = wx.getSystemInfoSync().windowHeight; this.setData({ height: screenHeight - 344, }); }, clearDevices() { this.setData({ devices: [] }) this.closeBluetoothAdapter() wx.nextTick(()=>{ this.openBluetoothAdapter() }) }, // 初始化蓝牙模块 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", // BM30广播模块需加上,如使用连接模块可忽略 ], powerLevel: 'high', success: (res) => { console.log('startBluetoothDevicesDiscovery success', res) this.onBluetoothDeviceFound() }, }) }, // 停止搜寻附近的蓝牙外围设备 stopBluetoothDevicesDiscovery() { wx.stopBluetoothDevicesDiscovery() }, // 监听寻找到新设备的事件 onBluetoothDeviceFound() { wx.onBluetoothDeviceFound((res) => { console.log('res',res); res.devices.forEach(device => { if (!device.name && !device.localName) { return } const foundDevices = this.data.devices console.log('foundDevices',foundDevices); const idx = inArray(foundDevices, 'deviceId', device.deviceId) let advertisDatas = ab2hex(device.advertisData).split(',').toString() let index = advertisDatas.indexOf('6e,49') let cid = advertisDatas[index + 9] + advertisDatas[index + 10] const data = {} // console.log(device) // console.log(ab2hex(device.advertisData)) // 此处判断是否BM30广播模块,如使用连接模块请删除此 if ,只保留 else 内容 if (cid == 14 ||cid == '0e') { 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) device.analyzeDataText = analyzeData.text console.log(analyzeData.data.weight) } } else { let buff = device.advertisData.slice(8, 14) device.mac = new Uint8Array(buff) // 保存广播数据中的mac地址,这是由于iOS不直接返回mac地址 let tempMac = Array.from(device.mac) tempMac.reverse() device.macAddr = ab2hex(tempMac, ':').toUpperCase() } if (idx === -1) { data[`devices[${foundDevices.length}]`] = device } else { data[`devices[${idx}]`] = device } this.setData(data) } }) }) }, // 连接低功耗蓝牙设备 createBLEConnection(e) { this._connLoading = true wx.showLoading({ title: '连接中', }) setTimeout(() => { if (this._connLoading) { this._connLoading = false wx.hideLoading() } }, 6000) const ds = e.currentTarget.dataset const index = ds.index // 保存当前连接的设备,注意不能从wxml的dataset中直接返回该对象,因为ArrarBuffer类型的数据无法保留 const deviceId = ds.deviceId const name = ds.name this._device = this.data.devices[index] console.log(this._device) wx.createBLEConnection({ deviceId, success: (res) => { // console.log('this._device',this._device); let buff = this._device.advertisData.slice(-6) let arr = new Uint8Array(buff).reverse() let mac = ab2hex(arr).replace(/,/g,":") // console.log('mac',mac); this.setData({ connected: true, name, deviceId, mac }) console.log("createBLEConnection:success") this.log('蓝牙连接成功!') wx.stopBluetoothDevicesDiscovery() this.onBLEConnectionStateChange() this.getBLEDeviceServices(deviceId) }, fail: res => { this._connLoading = false wx.hideLoading() wx.showToast({ title: '连接失败', icon: 'none' }) } }) // 连接上设备就可以停止蓝牙搜索,减少功耗。 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.log(this.data.mac + '蓝牙已断开连接....') this.setData({ showWriteInput: false, }) } }) }, // 断开与低功耗蓝牙设备的连接 closeBLEConnection() { wx.closeBLEConnection({ deviceId: this._deviceId }) this.log(this.data.mac + '蓝牙已断开连接....') this.setData({ showWriteInput: false, }) }, quit(){ this.closeBLEConnection() this.setData({ connected: false, information:[] }) }, // 获取蓝牙设备的 serviceId getBLEDeviceServices(deviceId) { wx.getBLEDeviceServices({ deviceId, success: (res) => { for (let i = 0; i < res.services.length; i++) { if (res.services[i].isPrimary && res.services[i].uuid.indexOf('FFE0') > -1) { 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) console.log('plugin',plugin); // 初始化插件 plugin.initPlugin(res.characteristics, this._device) wx.onBLECharacteristicValueChange((characteristic) => { // 解析特征值,返回解密后的数据 let bleData = plugin.parseBleData(characteristic.value) console.log(bleData) if (bleData.status == 0) { console.log("握手成功") this._connLoading = false wx.hideLoading() wx.showToast({ title: '连接成功', }) } else if (bleData.status == 2) { let payload = bleData.data //对应协议中的payload数据,可以自行解析该数据 // console.log(ab2hex(payload, ' ')) // console.log(ab2hex(bleData.completeData, ' ')) switch (payload[0]) { case 0x1B: if (payload[1] == 0) { this.log('设置系统时间成功') }else if (payload[1] == 1) { this.log('设置系统时间失败') }else{ this.log('系统不支持时间设置') } break; case 0x1C: if (payload[1] == 1) { let {year,month,day,hour,min,second} = plugin.analyzeSystemTime(payload) this.log(`系统时间为:${year}/${month}/${day} ${hour}:${min}:${second}`) } else { this.log('系统时间无效') } break; case 0x2B: if (payload[1] == 0x05) { if (payload[2] == 0) { this.log('无用户历史记录') } else if(payload[2] == 1) { this.log('开始发送历史记录') }else{ this.log('结束发送历史记录') } } if (payload[1] == 0x06) { if (payload[2] == 0x01) { plugin.analyzeMCUBodyData(payload) } else if (payload[2] == 0x02){ plugin.analyzeMCUBodyData(payload) }else if (payload[2] == 0x03) { let { year,month,day,hour,min,second,id,userCharacteristics,sex,age,height,weight,metabolicBasisRate,bodyAge ,uint,symbol,impedance,compute,bodyFat,subcutaneousFat,visceralFat,musclesRate,boneMass,waterContent,proteinRate,heartRate } = plugin.analyzeMCUBodyData(payload) this.log(`时间为:${year}/${month}/${day} ${hour}:${min}:${second} id:${id} 用户特征:${userCharacteristics},性别:${sex},年龄:${age},身高:${height}, 体重:${weight},单前单位:${uint},重量数据精度:${symbol},阻抗:${impedance}, 心率数据:${heartRate},体脂:${bodyFat},皮下脂肪:${subcutaneousFat} ,内脏脂肪:${visceralFat},肌肉率:${musclesRate},基础代谢率:${metabolicBasisRate}, 骨量:${boneMass},水含量:${waterContent},蛋白率:${proteinRate},身体年龄:${bodyAge}`) } } if (payload[1] == 0x07) { if (payload[2] == 0x01) { plugin.analyzeAPPBodyData(payload) } else if (payload[2] == 0x02){ let { year,month,day,hour,min,second,id,userCharacteristics,sex,age,height,weight,uint,symbol,impedance,compute,heartRate } = plugin.analyzeAPPBodyData(payload) this.log(`时间为:${year}/${month}/${day} ${hour}:${min}:${second} id:${id} 用户特征:${userCharacteristics},性别:${sex},年龄:${age},身高:${height}, 体重:${weight},单前单位:${uint},重量数据精度:${symbol},阻抗:${impedance}, 算法标识:${compute},心率数据:${heartRate}`) } } if (payload[1] == 0x04) { if (payload[2] == 0) { this.log('更新列表成功') } else if(payload[2] == 1){ this.log('更新个人用户成功') }else if(payload[2] == 2){ this.log('更新列表失败') }else if(payload[2] == 3){ this.log('更新个人用户失败') }else{ this.log('未知指令') } } } } else if (bleData.status == 1){ } }) }, fail(res) { console.error('getBLEDeviceCharacteristics', res) } }) }, log(data){ let info = this.data.information info.unshift(data) this.setData({ information:info }) }, 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 }, setSystemTime(){ // console.log('设置时间'); plugin.setSystemTime() }, getSystemTime(){ // console.log('获取时间'); plugin.getSystemTime() }, updateUserList(){ // console.log('更新用户列表'); let userInfo = { identity:0,id:7,sex:1,age:21,height:176,weight:77.5,impedance:450} let userInfo1 = { identity:1,id:2,sex:0,age:29,height:162,weight:66.1,impedance:420 } let userInfo2 = { identity:0,id:1,sex:1,age:22,height:168,weight:71.1,impedance:430 } let userList = [] userList.push(userInfo) userList.push(userInfo1) userList.push(userInfo2) plugin.updateUserList(userList) }, updateUserInformation(){ //console.log('更新用户个人信息'); let userInfo ={ identity:0,id:7,sex:1,age:21,height:176,weight:77.5,impedance:450} plugin.updateUserInformation(userInfo) }, requestHis(){ plugin.requestHis() } });