From 4af6b033d15a4cfbdd13388ccd9b66e0f500bdfa Mon Sep 17 00:00:00 2001 From: qiaocl <3189782663@qq.com> Date: Thu, 24 Nov 2022 15:49:31 +0800 Subject: [PATCH] =?UTF-8?q?=E8=93=9D=E7=89=99=E8=BF=9E=E6=8E=A5demo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bluetooth_demo.rar | Bin 0 -> 5903 bytes bluetooth_demo_F01.zip | Bin 0 -> 7537 bytes bluetooth_demo_F01/README.md | 8 + bluetooth_demo_F01/app.js | 5 + bluetooth_demo_F01/app.json | 20 ++ bluetooth_demo_F01/app.wxss | 55 ++++ bluetooth_demo_F01/pages/index/index.js | 322 ++++++++++++++++++++++ bluetooth_demo_F01/pages/index/index.json | 4 + bluetooth_demo_F01/pages/index/index.wxml | 37 +++ bluetooth_demo_F01/project.config.json | 52 ++++ bluetooth_demo_F01/sitemap.json | 7 + bluetooth_demo_F01/utils/util.js | 30 ++ bluetooth_demo_H01.zip | Bin 0 -> 7041 bytes bluetooth_demo_H01/README.md | 8 + bluetooth_demo_H01/app.js | 5 + bluetooth_demo_H01/app.json | 20 ++ bluetooth_demo_H01/app.wxss | 55 ++++ bluetooth_demo_H01/pages/index/index.js | 275 ++++++++++++++++++ bluetooth_demo_H01/pages/index/index.json | 4 + bluetooth_demo_H01/pages/index/index.wxml | 37 +++ bluetooth_demo_H01/project.config.json | 52 ++++ bluetooth_demo_H01/sitemap.json | 7 + bluetooth_demo_H01/utils/util.js | 30 ++ bluetooth_demo_L01.zip | Bin 0 -> 6370 bytes bluetooth_demo_L01/README.md | 10 + bluetooth_demo_L01/app.js | 5 + bluetooth_demo_L01/app.json | 20 ++ bluetooth_demo_L01/app.wxss | 55 ++++ bluetooth_demo_L01/pages/index/index.js | 164 +++++++++++ bluetooth_demo_L01/pages/index/index.json | 4 + bluetooth_demo_L01/pages/index/index.wxml | 42 +++ bluetooth_demo_L01/project.config.json | 56 ++++ bluetooth_demo_L01/sitemap.json | 7 + bluetooth_demo_L01/utils/util.js | 30 ++ bluetooth_demo_L10.zip | Bin 0 -> 37932 bytes bluetooth_demo_L11/app.js | 5 + bluetooth_demo_L11/app.json | 14 + bluetooth_demo_L11/app.wxss | 55 ++++ bluetooth_demo_L11/pages/index/index.js | 155 +++++++++++ bluetooth_demo_L11/pages/index/index.json | 4 + bluetooth_demo_L11/pages/index/index.wxml | 35 +++ bluetooth_demo_L11/project.config.json | 46 ++++ bluetooth_demo_L11/sitemap.json | 7 + bluetooth_demo_L11/utils/util.js | 30 ++ 44 files changed, 1777 insertions(+) create mode 100644 bluetooth_demo.rar create mode 100644 bluetooth_demo_F01.zip create mode 100644 bluetooth_demo_F01/README.md create mode 100644 bluetooth_demo_F01/app.js create mode 100644 bluetooth_demo_F01/app.json create mode 100644 bluetooth_demo_F01/app.wxss create mode 100644 bluetooth_demo_F01/pages/index/index.js create mode 100644 bluetooth_demo_F01/pages/index/index.json create mode 100644 bluetooth_demo_F01/pages/index/index.wxml create mode 100644 bluetooth_demo_F01/project.config.json create mode 100644 bluetooth_demo_F01/sitemap.json create mode 100644 bluetooth_demo_F01/utils/util.js create mode 100644 bluetooth_demo_H01.zip create mode 100644 bluetooth_demo_H01/README.md create mode 100644 bluetooth_demo_H01/app.js create mode 100644 bluetooth_demo_H01/app.json create mode 100644 bluetooth_demo_H01/app.wxss create mode 100644 bluetooth_demo_H01/pages/index/index.js create mode 100644 bluetooth_demo_H01/pages/index/index.json create mode 100644 bluetooth_demo_H01/pages/index/index.wxml create mode 100644 bluetooth_demo_H01/project.config.json create mode 100644 bluetooth_demo_H01/sitemap.json create mode 100644 bluetooth_demo_H01/utils/util.js create mode 100644 bluetooth_demo_L01.zip create mode 100644 bluetooth_demo_L01/README.md create mode 100644 bluetooth_demo_L01/app.js create mode 100644 bluetooth_demo_L01/app.json create mode 100644 bluetooth_demo_L01/app.wxss create mode 100644 bluetooth_demo_L01/pages/index/index.js create mode 100644 bluetooth_demo_L01/pages/index/index.json create mode 100644 bluetooth_demo_L01/pages/index/index.wxml create mode 100644 bluetooth_demo_L01/project.config.json create mode 100644 bluetooth_demo_L01/sitemap.json create mode 100644 bluetooth_demo_L01/utils/util.js create mode 100644 bluetooth_demo_L10.zip create mode 100644 bluetooth_demo_L11/app.js create mode 100644 bluetooth_demo_L11/app.json create mode 100644 bluetooth_demo_L11/app.wxss create mode 100644 bluetooth_demo_L11/pages/index/index.js create mode 100644 bluetooth_demo_L11/pages/index/index.json create mode 100644 bluetooth_demo_L11/pages/index/index.wxml create mode 100644 bluetooth_demo_L11/project.config.json create mode 100644 bluetooth_demo_L11/sitemap.json create mode 100644 bluetooth_demo_L11/utils/util.js diff --git a/bluetooth_demo.rar b/bluetooth_demo.rar new file mode 100644 index 0000000000000000000000000000000000000000..1fa601a365e016e4f9ef3a37773a7ebd5d50fdcf GIT binary patch literal 5903 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 I;(-AF1@t+;^#A|> literal 0 HcmV?d00001 diff --git a/bluetooth_demo_F01.zip b/bluetooth_demo_F01.zip new file mode 100644 index 0000000000000000000000000000000000000000..bd242e496f7182d76545c00815d06f23e26214b8 GIT binary patch literal 7537 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 literal 0 HcmV?d00001 diff --git a/bluetooth_demo_F01/README.md b/bluetooth_demo_F01/README.md new file mode 100644 index 0000000..badfeb4 --- /dev/null +++ b/bluetooth_demo_F01/README.md @@ -0,0 +1,8 @@ +# #参考使用设备类型 +``` +F01PRO + +``` + +## + diff --git a/bluetooth_demo_F01/app.js b/bluetooth_demo_F01/app.js new file mode 100644 index 0000000..ff15a95 --- /dev/null +++ b/bluetooth_demo_F01/app.js @@ -0,0 +1,5 @@ +//app.js +App({ + onLaunch: function () { + } +}) \ No newline at end of file diff --git a/bluetooth_demo_F01/app.json b/bluetooth_demo_F01/app.json new file mode 100644 index 0000000..36fa20f --- /dev/null +++ b/bluetooth_demo_F01/app.json @@ -0,0 +1,20 @@ +{ + "pages": [ + "pages/index/index" + ], + "window": { + "navigationBarBackgroundColor": "#0082FE", + "navigationBarTextStyle": "white", + "navigationBarTitleText": "蓝牙连接Demo", + "backgroundColor": "#eeeeee", + "backgroundTextStyle": "light" + }, + "plugins": { + "sdkPlugin": { + "version": "2.1.0", + "provider": "wx17e93aad47cdae1a" + } + }, + "style": "v2", + "sitemapLocation": "sitemap.json" +} diff --git a/bluetooth_demo_F01/app.wxss b/bluetooth_demo_F01/app.wxss new file mode 100644 index 0000000..bee9f30 --- /dev/null +++ b/bluetooth_demo_F01/app.wxss @@ -0,0 +1,55 @@ +/**app.wxss**/ +view, +cover-view, +scroll-view, +swiper, +swiper-item, +movable-area, +movable-view, +button, +input, +textarea, +label, +navigator { + box-sizing: border-box; +} + +page { + --safe-bottom: env(safe-area-inset-bottom); +} + +.container { + position: relative; + display: flex; + flex-direction: column; + align-items: center; + width: 100vw; + height: 100vh; + padding-bottom: var(--safe-bottom); +} + +.header { + width: 100%; +} + +.header button { + font-size: 16px; + line-height: 40px; + width: 100% !important; + border-bottom: 1px solid #dfdfdf; +} + +.device_item { + padding: 15px; + border-bottom: 1px solid #dfdfdf; +} + +.weight { + width: 100%; + margin: 15px; + padding-bottom: 15px; + text-align: center; + font-size: 18px; + font-weight: 700; + border-bottom: 1px solid #dfdfdf; +} diff --git a/bluetooth_demo_F01/pages/index/index.js b/bluetooth_demo_F01/pages/index/index.js new file mode 100644 index 0000000..304a2f5 --- /dev/null +++ b/bluetooth_demo_F01/pages/index/index.js @@ -0,0 +1,322 @@ +const util = require("../../utils/util"); +const { + inArray, + ab2hex +} = util +const plugin = requirePlugin("sdkPlugin").AiLink; +Page({ + data: { + devices: [], + connected: false, + cmd: '', + name: '', + weight: "", + height: "", + text: "", + imp: "", + uuid1: "", + uuid2: "", + uuid3: "", + deviceId: null, + }, + onLoad: function() {}, + // 初始化蓝牙模块 + openBluetoothAdapter() { + wx.openBluetoothAdapter({ + success: (res) => { + console.log('openBluetoothAdapter success', res) + wx.showToast({ + title: '蓝牙连接中', + icon: "none" + }) + this.startBluetoothDevicesDiscovery() + }, + fail: (res) => { + if (res.errCode === 10001) { + wx.showToast({ + title: '请打开蓝牙', + icon: "none" + }) + // 监听本机蓝牙状态变化的事件 + wx.onBluetoothAdapterStateChange((res) => { + console.log('onBluetoothAdapterStateChange', res) + if (res.available) { + this.startBluetoothDevicesDiscovery() + } + }) + } + } + }) + }, + + // 开始搜寻附近的蓝牙外围设备 + startBluetoothDevicesDiscovery() { + if (this._discoveryStarted) { + return + } + this._discoveryStarted = true + wx.startBluetoothDevicesDiscovery({ + allowDuplicatesKey: true, + interval: 1000, //上报设备的间隔 + services: [ + "FFE0", + ], + 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 + } + if (device.name.indexOf('AiLink_') != -1) { + wx.stopBluetoothDevicesDiscovery() //搜索到名称为“AiLink_”的蓝牙后,停止搜寻附近的蓝牙 + const foundDevices = this.data.devices + const idx = inArray(foundDevices, 'deviceId', device.deviceId) + const data = {} + let buff = device.advertisData.slice(-6) + 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) { + wx.showLoading({ + title: '连接中', + }) + const ds = e.currentTarget.dataset + const index = ds.index + this._device = this.data.devices[index] + 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") + this.onBLEConnectionStateChange() + this.getBLEDeviceServices(deviceId) + }, + fail: res => { + wx.hideLoading() + wx.showToast({ + title: '连接失败', + icon: 'none' + }) + } + }) + }, + //监听蓝牙连接状态 + onBLEConnectionStateChange() { + wx.onBLEConnectionStateChange((res) => { + if (!res.connected) { + setTimeout(() => { + wx.showToast({ + title: '连接已断开', + icon: 'none' + }) + }, 500) + this.setData({ + connected: false, + devices: [], + weight: "", + height: "", + text: "", + imp: "" + }) + } + }) + }, + + // 获取蓝牙设备的 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) { + wx.showLoading({ + title: '获取设备的UUID成功', + }) + this.getBLEDeviceCharacteristics(deviceId, res.services[i].uuid) + return + } + } + } + }) + }, + + // 获取蓝牙设备某个服务中所有特征值(characteristic) + /** + * read: true读,write: true写,notify: true广播 + */ + getBLEDeviceCharacteristics(deviceId, serviceId) { + let that = this + that._deviceId = deviceId + that._serviceId = serviceId + that._device.serviceId = serviceId + wx.hideLoading() + wx.getBLEDeviceCharacteristics({ + deviceId, + serviceId, + success: (res) => { + console.log('getBLEDeviceCharacteristics success', res.characteristics) + for (let i = 0; i < res.characteristics.length; i++) { + let item = res.characteristics[i]; + if (item.uuid.indexOf('0000FFE1') != -1) { + that.data.uuid1 = item.uuid //下发数据 + } else if (item.uuid.indexOf('0000FFE2') != -1) { + that.data.uuid2 = item.uuid //监听数据 + } else if (item.uuid.indexOf('0000FFE3') != -1) { + that.data.uuid3 = item.uuid //写入设置 + } + } + + // 打开监听 + wx.notifyBLECharacteristicValueChange({ + deviceId, + serviceId, + characteristicId: that.data.uuid2, + state: true, + }) + wx.notifyBLECharacteristicValueChange({ + deviceId, + serviceId, + characteristicId: that.data.uuid3, + state: true, + }) + // 初始化插件 + plugin.initPlugin(res.characteristics, that._device) + + wx.onBLECharacteristicValueChange((characteristic) => { + let bleData = plugin.parseBleData(characteristic.value) + let dw1 = "kg" + if (bleData.status == 0) { + // 发送 男,22岁,185 + let A = 22 + let H = 185 + let sex = "0x01" + let age = "0x" + A.toString(16) + let height = "0x" + H.toString(16) + let arr = [0x01, parseInt(sex), parseInt(age), parseInt(height),0x00] + plugin.sendDataOfA7(arr) + console.log("握手成功", arr) + } else if (bleData.status == 1) { + let payload = ab2hex(bleData.data, '') + let type = payload.substring(0, 2) + let typeInfo = payload.substring(4, 6) + console.log("payload", payload) + if (type == "10" || type == "40") { //体脂模式 + let data = parseInt(payload.substring(6, 12), 16) + let num = payload.substring(12, 13) + let dw = payload.substring(13, 14) + if (dw == "1") { + dw1 = "斤" + } + if (num == "1") { + data = data / 10 + } + if (num == "2") { + data = data / 100 + } + if (num == "3") { + data = data / 1000 + } + if (typeInfo == "01") { + that.setData({ + weight: "实时体重是:" + data + dw1 + }) + } + if (typeInfo == "02") { + that.setData({ + weight: "稳定体重是:" + data + dw1 + }) + } + } + if (type == "14" || type == "41") { //身高模式 + let height = parseInt(payload.substring(4, 8), 16) + that.setData({ + height: "身高是:" + height + }) + } + if (type == "11") { //阻抗模式 + if (typeInfo == "03" || typeInfo == "04") { + let imp = parseInt(payload.substring(8, 12), 16) + console.log("imp", payload, imp) + that.setData({ + imp: "阻抗值:" + imp + }) + } + } + } + }) + }, + fail(res) { + console.error('getBLEDeviceCharacteristics', res) + } + }) + }, + + /** + * 断开蓝牙模块 + */ + closeBluetoothAdapter() { + wx.closeBluetoothAdapter() + this._discoveryStarted = false + wx.showToast({ + title: '断开蓝牙模块', + icon: 'none' + }) + this.setData({ + devices: [], + weight: "", + height: "", + text: "", + imp: "" + }) + }, + // 断开与低功耗蓝牙设备的连接 + closeBLEConnection() { + wx.closeBLEConnection({ + deviceId: this._deviceId + }) + wx.showToast({ + title: '断开蓝牙连接', + icon: 'none' + }) + this.setData({ + connected: false, + devices: [], + text: "", + height: "", + weight: "", + imp: "" + }) + }, + +}); diff --git a/bluetooth_demo_F01/pages/index/index.json b/bluetooth_demo_F01/pages/index/index.json new file mode 100644 index 0000000..b55b5a2 --- /dev/null +++ b/bluetooth_demo_F01/pages/index/index.json @@ -0,0 +1,4 @@ +{ + "usingComponents": { + } +} \ No newline at end of file diff --git a/bluetooth_demo_F01/pages/index/index.wxml b/bluetooth_demo_F01/pages/index/index.wxml new file mode 100644 index 0000000..105d823 --- /dev/null +++ b/bluetooth_demo_F01/pages/index/index.wxml @@ -0,0 +1,37 @@ + + module.exports.max = function(n1, n2) { + return Math.max(n1, n2) + } + module.exports.len = function(arr) { + arr = arr || [] + return arr.length + } + + + + + + + + + + {{weight}} + {{height}} + {{imp}} + {{text}} + + 已发现 {{devices.length}} 个外围设备: + + + + {{item.name}} + (信号强度: {{item.RSSI}}dBm) + + mac地址: {{item.macAddr || item.deviceId}} + + + + + diff --git a/bluetooth_demo_F01/project.config.json b/bluetooth_demo_F01/project.config.json new file mode 100644 index 0000000..85164c5 --- /dev/null +++ b/bluetooth_demo_F01/project.config.json @@ -0,0 +1,52 @@ +{ + "description": "项目配置文件,详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html", + "setting": { + "urlCheck": true, + "es6": false, + "enhance": true, + "postcss": true, + "preloadBackgroundData": false, + "minified": true, + "newFeature": false, + "coverView": true, + "nodeModules": false, + "autoAudits": false, + "showShadowRootInWxmlPanel": true, + "scopeDataCheck": false, + "uglifyFileName": false, + "checkInvalidKey": true, + "checkSiteMap": true, + "uploadWithSourceMap": true, + "compileHotReLoad": false, + "lazyloadPlaceholderEnable": false, + "useMultiFrameRuntime": true, + "useApiHook": true, + "useApiHostProcess": true, + "babelSetting": { + "ignore": [], + "disablePlugins": [], + "outputPath": "" + }, + "useIsolateContext": true, + "userConfirmedBundleSwitch": false, + "packNpmManually": false, + "packNpmRelationList": [], + "minifyWXSS": true, + "disableUseStrict": false, + "minifyWXML": true, + "showES6CompileOption": false, + "useCompilerPlugins": false, + "ignoreUploadUnusedFiles": true + }, + "compileType": "miniprogram", + "simulatorType": "wechat", + "simulatorPluginLibVersion": {}, + "projectname": "bluetooth_demo_F01", + "libVersion": "2.23.2", + "appid": "wx39cf431caa22b5c8", + "editorSetting": { + "tabIndent": "insertSpaces", + "tabSize": 2 + }, + "condition": {} +} \ No newline at end of file diff --git a/bluetooth_demo_F01/sitemap.json b/bluetooth_demo_F01/sitemap.json new file mode 100644 index 0000000..ca02add --- /dev/null +++ b/bluetooth_demo_F01/sitemap.json @@ -0,0 +1,7 @@ +{ + "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html", + "rules": [{ + "action": "allow", + "page": "*" + }] +} \ No newline at end of file diff --git a/bluetooth_demo_F01/utils/util.js b/bluetooth_demo_F01/utils/util.js new file mode 100644 index 0000000..7aafdf3 --- /dev/null +++ b/bluetooth_demo_F01/utils/util.js @@ -0,0 +1,30 @@ +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++) { + if (!key) { + if (arr[i] == val) { + return i + } + } else 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); +} +module.exports = { + inArray, + ab2hex, +} diff --git a/bluetooth_demo_H01.zip b/bluetooth_demo_H01.zip new file mode 100644 index 0000000000000000000000000000000000000000..53fd0a3006799205de4bcbdc444b216a9a6d4c93 GIT binary patch literal 7041 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 literal 0 HcmV?d00001 diff --git a/bluetooth_demo_H01/README.md b/bluetooth_demo_H01/README.md new file mode 100644 index 0000000..a31eb28 --- /dev/null +++ b/bluetooth_demo_H01/README.md @@ -0,0 +1,8 @@ +# #参考使用设备类型 +``` +H01PRO + +``` + +## + diff --git a/bluetooth_demo_H01/app.js b/bluetooth_demo_H01/app.js new file mode 100644 index 0000000..ff15a95 --- /dev/null +++ b/bluetooth_demo_H01/app.js @@ -0,0 +1,5 @@ +//app.js +App({ + onLaunch: function () { + } +}) \ No newline at end of file diff --git a/bluetooth_demo_H01/app.json b/bluetooth_demo_H01/app.json new file mode 100644 index 0000000..36fa20f --- /dev/null +++ b/bluetooth_demo_H01/app.json @@ -0,0 +1,20 @@ +{ + "pages": [ + "pages/index/index" + ], + "window": { + "navigationBarBackgroundColor": "#0082FE", + "navigationBarTextStyle": "white", + "navigationBarTitleText": "蓝牙连接Demo", + "backgroundColor": "#eeeeee", + "backgroundTextStyle": "light" + }, + "plugins": { + "sdkPlugin": { + "version": "2.1.0", + "provider": "wx17e93aad47cdae1a" + } + }, + "style": "v2", + "sitemapLocation": "sitemap.json" +} diff --git a/bluetooth_demo_H01/app.wxss b/bluetooth_demo_H01/app.wxss new file mode 100644 index 0000000..bee9f30 --- /dev/null +++ b/bluetooth_demo_H01/app.wxss @@ -0,0 +1,55 @@ +/**app.wxss**/ +view, +cover-view, +scroll-view, +swiper, +swiper-item, +movable-area, +movable-view, +button, +input, +textarea, +label, +navigator { + box-sizing: border-box; +} + +page { + --safe-bottom: env(safe-area-inset-bottom); +} + +.container { + position: relative; + display: flex; + flex-direction: column; + align-items: center; + width: 100vw; + height: 100vh; + padding-bottom: var(--safe-bottom); +} + +.header { + width: 100%; +} + +.header button { + font-size: 16px; + line-height: 40px; + width: 100% !important; + border-bottom: 1px solid #dfdfdf; +} + +.device_item { + padding: 15px; + border-bottom: 1px solid #dfdfdf; +} + +.weight { + width: 100%; + margin: 15px; + padding-bottom: 15px; + text-align: center; + font-size: 18px; + font-weight: 700; + border-bottom: 1px solid #dfdfdf; +} diff --git a/bluetooth_demo_H01/pages/index/index.js b/bluetooth_demo_H01/pages/index/index.js new file mode 100644 index 0000000..fd3c3ed --- /dev/null +++ b/bluetooth_demo_H01/pages/index/index.js @@ -0,0 +1,275 @@ +const util = require("../../utils/util"); +const { + inArray, + ab2hex +} = util +Page({ + data: { + devices: [], + connected: false, + text: '', + name: '', + weight: "", + height: "", + imp: "", + readId: "", + writeId: "", + notifyId: "", + deviceId: null, + }, + onLoad: function() {}, + // 初始化蓝牙模块 + openBluetoothAdapter() { + wx.openBluetoothAdapter({ + success: (res) => { + console.log('openBluetoothAdapter success', res) + wx.showToast({ + title: '蓝牙连接中', + icon: "none" + }) + this.startBluetoothDevicesDiscovery() + }, + fail: (res) => { + if (res.errCode === 10001) { + wx.showToast({ + title: '请打开蓝牙', + icon: "none" + }) + // 监听本机蓝牙状态变化的事件 + wx.onBluetoothAdapterStateChange((res) => { + console.log('onBluetoothAdapterStateChange', res) + if (res.available) { + this.startBluetoothDevicesDiscovery() + } + }) + } + } + }) + }, + + // 开始搜寻附近的蓝牙外围设备 + startBluetoothDevicesDiscovery() { + if (this._discoveryStarted) { + return + } + this._discoveryStarted = true + wx.startBluetoothDevicesDiscovery({ + allowDuplicatesKey: true, + interval: 500, //上报设备的间隔 + 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 + } + if (device.name.indexOf('My') != -1) { + wx.stopBluetoothDevicesDiscovery() //搜索到名称为“AiLink_”的蓝牙后,停止搜寻附近的蓝牙 + const foundDevices = this.data.devices + const idx = inArray(foundDevices, 'deviceId', device.deviceId) + const data = {} + let buff = device.advertisData.slice(-6) + device.mac = new Uint8Array(buff) // 保存广播数据中的mac地址,这是由于iOS不直接返回mac地址 + let tempMac = Array.from(device.mac) + device.macAddr = ab2hex(tempMac, ':').toUpperCase() + if (idx === -1) { + data[`devices[${foundDevices.length}]`] = device + } else { + data[`devices[${idx}]`] = device + } + this.setData(data) + } + }) + }) + }, + // 连接低功耗蓝牙设备 + createBLEConnection(e) { + wx.showLoading({ + title: '连接中', + }) + const ds = e.currentTarget.dataset + const index = ds.index + this._device = this.data.devices[index] + 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") + this.onBLEConnectionStateChange() + this.getBLEDeviceServices(deviceId) + }, + fail: res => { + wx.hideLoading() + wx.showToast({ + title: '连接失败', + icon: 'none' + }) + } + }) + }, + //监听蓝牙连接状态 + onBLEConnectionStateChange() { + wx.onBLEConnectionStateChange((res) => { + if (!res.connected) { + setTimeout(() => { + wx.showToast({ + title: '连接已断开', + icon: 'none' + }) + }, 500) + this.setData({ + connected: false, + devices: [], + weight: "", + height: "", + text: "", + imp: "" + }) + } + }) + }, + + // 获取蓝牙设备的 serviceId + getBLEDeviceServices(deviceId) { + wx.getBLEDeviceServices({ + deviceId, + success: (res) => { + for (let i = 0; i < res.services.length; i++) { + if (res.services[i].uuid.indexOf('FFE0') > -1) { + wx.showLoading({ + title: '获取设备的UUID成功', + }) + this.getBLEDeviceCharacteristics(deviceId, res.services[i].uuid) + return + } + } + } + }) + }, + + // 获取蓝牙设备某个服务中所有特征值(characteristic) + /** + * read: true读,write: true写,notify: true广播 + */ + getBLEDeviceCharacteristics(deviceId, serviceId) { + let that = this + that._deviceId = deviceId + that._serviceId = serviceId + that._device.serviceId = serviceId + wx.hideLoading() + wx.getBLEDeviceCharacteristics({ + deviceId, + serviceId, + success: (res) => { + console.log('getBLEDeviceCharacteristics success', res.characteristics) + that.setData({ + text: "请站在秤上,开始测量" + }) + for (let i = 0; i < res.characteristics.length; i++) { + let item = res.characteristics[i]; + if (item.uuid.indexOf("FFE1") != -1) { + if (item.properties.notify == true) { + that.data.notifyId = item.uuid + } + if (item.properties.read) { + that.data.readId = item.uuid + } + if (item.properties.write == true) { + that.data.writeId = item.uuid + } + } + } + + // 打开监听 + wx.notifyBLECharacteristicValueChange({ + deviceId, + serviceId, + characteristicId: that.data.notifyId, + state: true, + }) + wx.notifyBLECharacteristicValueChange({ + deviceId, + serviceId, + characteristicId: that.data.writeId, + state: true, + }) + + wx.onBLECharacteristicValueChange((res) => { + let value = ab2hex(res.value, ''); + let weight = parseInt(value.substring(4, 8), 16) / 100 + let height = parseInt(value.substring(30, 34), 16) / 10 + let imp0 = value.substring(28, 30) + value.substring(34, 36) + that.setData({ + weight: "您的体重是:" + weight + 'kg' + }) + that.setData({ + height: "您的身高是:" + height + 'kg' + }) + that.setData({ + imp: "阻抗:" + parseInt(imp0, 16) + }) + that.setData({ + text: "测量结束" + }) + }) + }, + fail(res) { + console.error('getBLEDeviceCharacteristics', res) + } + }) + }, + + /** + * 断开蓝牙模块 + */ + closeBluetoothAdapter() { + wx.closeBluetoothAdapter() + this._discoveryStarted = false + wx.showToast({ + title: '断开蓝牙模块', + icon: 'none' + }) + this.setData({ + devices: [], + weight: "", + height: "", + imp: "" + }) + }, + // 断开与低功耗蓝牙设备的连接 + closeBLEConnection() { + wx.closeBLEConnection({ + deviceId: this._deviceId + }) + wx.showToast({ + title: '断开蓝牙连接', + icon: 'none' + }) + this.setData({ + connected: false, + devices: [], + height: "", + weight: "", + imp: "" + }) + }, + +}); diff --git a/bluetooth_demo_H01/pages/index/index.json b/bluetooth_demo_H01/pages/index/index.json new file mode 100644 index 0000000..b55b5a2 --- /dev/null +++ b/bluetooth_demo_H01/pages/index/index.json @@ -0,0 +1,4 @@ +{ + "usingComponents": { + } +} \ No newline at end of file diff --git a/bluetooth_demo_H01/pages/index/index.wxml b/bluetooth_demo_H01/pages/index/index.wxml new file mode 100644 index 0000000..105d823 --- /dev/null +++ b/bluetooth_demo_H01/pages/index/index.wxml @@ -0,0 +1,37 @@ + + module.exports.max = function(n1, n2) { + return Math.max(n1, n2) + } + module.exports.len = function(arr) { + arr = arr || [] + return arr.length + } + + + + + + + + + + {{weight}} + {{height}} + {{imp}} + {{text}} + + 已发现 {{devices.length}} 个外围设备: + + + + {{item.name}} + (信号强度: {{item.RSSI}}dBm) + + mac地址: {{item.macAddr || item.deviceId}} + + + + + diff --git a/bluetooth_demo_H01/project.config.json b/bluetooth_demo_H01/project.config.json new file mode 100644 index 0000000..85164c5 --- /dev/null +++ b/bluetooth_demo_H01/project.config.json @@ -0,0 +1,52 @@ +{ + "description": "项目配置文件,详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html", + "setting": { + "urlCheck": true, + "es6": false, + "enhance": true, + "postcss": true, + "preloadBackgroundData": false, + "minified": true, + "newFeature": false, + "coverView": true, + "nodeModules": false, + "autoAudits": false, + "showShadowRootInWxmlPanel": true, + "scopeDataCheck": false, + "uglifyFileName": false, + "checkInvalidKey": true, + "checkSiteMap": true, + "uploadWithSourceMap": true, + "compileHotReLoad": false, + "lazyloadPlaceholderEnable": false, + "useMultiFrameRuntime": true, + "useApiHook": true, + "useApiHostProcess": true, + "babelSetting": { + "ignore": [], + "disablePlugins": [], + "outputPath": "" + }, + "useIsolateContext": true, + "userConfirmedBundleSwitch": false, + "packNpmManually": false, + "packNpmRelationList": [], + "minifyWXSS": true, + "disableUseStrict": false, + "minifyWXML": true, + "showES6CompileOption": false, + "useCompilerPlugins": false, + "ignoreUploadUnusedFiles": true + }, + "compileType": "miniprogram", + "simulatorType": "wechat", + "simulatorPluginLibVersion": {}, + "projectname": "bluetooth_demo_F01", + "libVersion": "2.23.2", + "appid": "wx39cf431caa22b5c8", + "editorSetting": { + "tabIndent": "insertSpaces", + "tabSize": 2 + }, + "condition": {} +} \ No newline at end of file diff --git a/bluetooth_demo_H01/sitemap.json b/bluetooth_demo_H01/sitemap.json new file mode 100644 index 0000000..ca02add --- /dev/null +++ b/bluetooth_demo_H01/sitemap.json @@ -0,0 +1,7 @@ +{ + "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html", + "rules": [{ + "action": "allow", + "page": "*" + }] +} \ No newline at end of file diff --git a/bluetooth_demo_H01/utils/util.js b/bluetooth_demo_H01/utils/util.js new file mode 100644 index 0000000..7aafdf3 --- /dev/null +++ b/bluetooth_demo_H01/utils/util.js @@ -0,0 +1,30 @@ +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++) { + if (!key) { + if (arr[i] == val) { + return i + } + } else 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); +} +module.exports = { + inArray, + ab2hex, +} diff --git a/bluetooth_demo_L01.zip b/bluetooth_demo_L01.zip new file mode 100644 index 0000000000000000000000000000000000000000..5a748c5cbe06cd85b53b1a8b680e5dd7c50e9e8e GIT binary patch literal 6370 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 literal 0 HcmV?d00001 diff --git a/bluetooth_demo_L01/README.md b/bluetooth_demo_L01/README.md new file mode 100644 index 0000000..97f6d39 --- /dev/null +++ b/bluetooth_demo_L01/README.md @@ -0,0 +1,10 @@ +# #参考使用设备类型 +``` +J02/J02B +L01/02/03/05 + + +``` + +## + diff --git a/bluetooth_demo_L01/app.js b/bluetooth_demo_L01/app.js new file mode 100644 index 0000000..ff15a95 --- /dev/null +++ b/bluetooth_demo_L01/app.js @@ -0,0 +1,5 @@ +//app.js +App({ + onLaunch: function () { + } +}) \ No newline at end of file diff --git a/bluetooth_demo_L01/app.json b/bluetooth_demo_L01/app.json new file mode 100644 index 0000000..36fa20f --- /dev/null +++ b/bluetooth_demo_L01/app.json @@ -0,0 +1,20 @@ +{ + "pages": [ + "pages/index/index" + ], + "window": { + "navigationBarBackgroundColor": "#0082FE", + "navigationBarTextStyle": "white", + "navigationBarTitleText": "蓝牙连接Demo", + "backgroundColor": "#eeeeee", + "backgroundTextStyle": "light" + }, + "plugins": { + "sdkPlugin": { + "version": "2.1.0", + "provider": "wx17e93aad47cdae1a" + } + }, + "style": "v2", + "sitemapLocation": "sitemap.json" +} diff --git a/bluetooth_demo_L01/app.wxss b/bluetooth_demo_L01/app.wxss new file mode 100644 index 0000000..bee9f30 --- /dev/null +++ b/bluetooth_demo_L01/app.wxss @@ -0,0 +1,55 @@ +/**app.wxss**/ +view, +cover-view, +scroll-view, +swiper, +swiper-item, +movable-area, +movable-view, +button, +input, +textarea, +label, +navigator { + box-sizing: border-box; +} + +page { + --safe-bottom: env(safe-area-inset-bottom); +} + +.container { + position: relative; + display: flex; + flex-direction: column; + align-items: center; + width: 100vw; + height: 100vh; + padding-bottom: var(--safe-bottom); +} + +.header { + width: 100%; +} + +.header button { + font-size: 16px; + line-height: 40px; + width: 100% !important; + border-bottom: 1px solid #dfdfdf; +} + +.device_item { + padding: 15px; + border-bottom: 1px solid #dfdfdf; +} + +.weight { + width: 100%; + margin: 15px; + padding-bottom: 15px; + text-align: center; + font-size: 18px; + font-weight: 700; + border-bottom: 1px solid #dfdfdf; +} diff --git a/bluetooth_demo_L01/pages/index/index.js b/bluetooth_demo_L01/pages/index/index.js new file mode 100644 index 0000000..8b93596 --- /dev/null +++ b/bluetooth_demo_L01/pages/index/index.js @@ -0,0 +1,164 @@ +const util = require("../../utils/util"); +const { + inArray, + ab2hex +} = util +const plugin = requirePlugin("sdkPlugin").AiLink; +Page({ + data: { + devices: [], + connected: false, + weight: "", + imp: "", + deviceId: null, + }, + onLoad: function() {}, + // 初始化蓝牙模块 + openBluetoothAdapter() { + wx.openBluetoothAdapter({ + success: (res) => { + console.log('openBluetoothAdapter success', res) + wx.showToast({ + title: '蓝牙连接中', + icon: "none" + }) + this.startBluetoothDevicesDiscovery() + }, + fail: (res) => { + if (res.errCode === 10001) { + wx.showToast({ + title: '请打开蓝牙', + icon: "none" + }) + // 监听本机蓝牙状态变化的事件 + wx.onBluetoothAdapterStateChange((res) => { + console.log('onBluetoothAdapterStateChange', res) + if (res.available) { + this.startBluetoothDevicesDiscovery() + } + }) + } + } + }) + }, + + // 开始搜寻附近的蓝牙外围设备 + startBluetoothDevicesDiscovery() { + if (this._discoveryStarted) { + return + } + this._discoveryStarted = true + wx.startBluetoothDevicesDiscovery({ + allowDuplicatesKey: true, //是否允许重复上报同一设备 + services: [ //要搜索蓝牙设备主 service 的 uuid 列表 + "F0A0", + ], + success: (res) => { + console.log('startBluetoothDevicesDiscovery success', res) + this.onBluetoothDeviceFound() + }, + }) + }, + // 停止搜寻附近的蓝牙外围设备 + stopBluetoothDevicesDiscovery() { + wx.stopBluetoothDevicesDiscovery() + }, + + // 找到新设备的事件 + onBluetoothDeviceFound() { + let that = this + wx.onBluetoothDeviceFound((res) => { + res.devices.forEach(device => { + if (!device.name && !device.localName) { + return + } + if (device.advertisServiceUUIDs[0].indexOf("F0A0") !== -1) { + let value = ab2hex(device.advertisData) + let parseDataRes = plugin.parseBroadcastData(device.advertisData) + let analyzeData = plugin.analyzeBroadcastScaleData(parseDataRes) + let analyzeDataText = analyzeData.text + let data = analyzeData.data + const dataT = {} + const foundDevices = this.data.devices + const idx = inArray(foundDevices, 'deviceId', device.deviceId) + let buffer = device.advertisData.slice(0, 8) + device.mac = new Uint8Array(buffer) + let tempMac = Array.from(device.mac) + tempMac.reverse() + device.macAddr = ab2hex(tempMac, ':').toUpperCase() + + if (idx === -1) { + dataT[`devices[${foundDevices.length}]`] = device + } else { + dataT[`devices[${idx}]`] = device + } + this.setData(dataT) + if (parseDataRes.status == 1) { + let dw1 = "kg" + if (data.weightUnit == "1") { + dw1 = "斤" + } + if (data.weightUnit == "4") { + dw1 = "st:lb" + data = 1 * data + 5 + } + if (data.weightUnit == "6") { + dw1 = "lb" + } + if (data.weightDecimal == "1") { + data.weight = data.weight / 10 + } + if (data.weightDecimal == "2") { + data.weight = data.weight / 100 + } + if (data.weightDecimal == "3") { + data.weight = data.weight / 1000 + } + that.setData({ + weight: analyzeData.text + }) + return + } + } + }) + }) + }, + //监听蓝牙连接状态 + onBLEConnectionStateChange() { + wx.onBLEConnectionStateChange((res) => { + if (!res.connected) { + wx.stopBluetoothDevicesDiscovery(); + setTimeout(() => { + wx.showToast({ + title: '连接已断开', + icon: 'none' + }) + }, 500) + this.setData({ + connected: false, + devices: [], + weight: "", + imp: "" + }) + } + }) + }, + + /** + * 断开蓝牙模块 + */ + closeBluetoothAdapter() { + wx.stopBluetoothDevicesDiscovery(); + wx.closeBluetoothAdapter() + this._discoveryStarted = false + wx.showToast({ + title: '结束流程', + icon: 'none' + }) + this.setData({ + devices: [], + weight: "", + imp: "" + }) + }, +}); diff --git a/bluetooth_demo_L01/pages/index/index.json b/bluetooth_demo_L01/pages/index/index.json new file mode 100644 index 0000000..b55b5a2 --- /dev/null +++ b/bluetooth_demo_L01/pages/index/index.json @@ -0,0 +1,4 @@ +{ + "usingComponents": { + } +} \ No newline at end of file diff --git a/bluetooth_demo_L01/pages/index/index.wxml b/bluetooth_demo_L01/pages/index/index.wxml new file mode 100644 index 0000000..6988dde --- /dev/null +++ b/bluetooth_demo_L01/pages/index/index.wxml @@ -0,0 +1,42 @@ + +module.exports.max = function(n1, n2) { + return Math.max(n1, n2) +} +module.exports.len = function(arr) { + arr = arr || [] + return arr.length +} + + + + + + + + + + {{weight}} + + + + 已发现 {{devices.length}} 个外围设备: + + + + {{item.name}} + (信号强度: {{item.RSSI}}dBm) + + mac地址: {{item.macAddr || item.deviceId}} + + + + + + diff --git a/bluetooth_demo_L01/project.config.json b/bluetooth_demo_L01/project.config.json new file mode 100644 index 0000000..94beee7 --- /dev/null +++ b/bluetooth_demo_L01/project.config.json @@ -0,0 +1,56 @@ +{ + "description": "项目配置文件,详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html", + "setting": { + "urlCheck": true, + "es6": false, + "enhance": true, + "postcss": true, + "preloadBackgroundData": false, + "minified": true, + "newFeature": false, + "coverView": true, + "nodeModules": false, + "autoAudits": false, + "showShadowRootInWxmlPanel": true, + "scopeDataCheck": false, + "uglifyFileName": false, + "checkInvalidKey": true, + "checkSiteMap": true, + "uploadWithSourceMap": true, + "compileHotReLoad": false, + "lazyloadPlaceholderEnable": false, + "useMultiFrameRuntime": true, + "useApiHook": true, + "useApiHostProcess": true, + "babelSetting": { + "ignore": [], + "disablePlugins": [], + "outputPath": "" + }, + "useIsolateContext": true, + "userConfirmedBundleSwitch": false, + "packNpmManually": false, + "packNpmRelationList": [], + "minifyWXSS": true, + "disableUseStrict": false, + "minifyWXML": true, + "showES6CompileOption": false, + "useCompilerPlugins": false, + "ignoreUploadUnusedFiles": true + }, + "compileType": "miniprogram", + "simulatorType": "wechat", + "simulatorPluginLibVersion": {}, + "editorSetting": { + "tabIndent": "insertSpaces", + "tabSize": 2 + }, + "projectname": "bluetooth_demo_L01", + "libVersion": "2.23.2", + "appid": "wxcea3504a31518eb6", + "packOptions": { + "ignore": [], + "include": [] + }, + "condition": {} +} \ No newline at end of file diff --git a/bluetooth_demo_L01/sitemap.json b/bluetooth_demo_L01/sitemap.json new file mode 100644 index 0000000..ca02add --- /dev/null +++ b/bluetooth_demo_L01/sitemap.json @@ -0,0 +1,7 @@ +{ + "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html", + "rules": [{ + "action": "allow", + "page": "*" + }] +} \ No newline at end of file diff --git a/bluetooth_demo_L01/utils/util.js b/bluetooth_demo_L01/utils/util.js new file mode 100644 index 0000000..7aafdf3 --- /dev/null +++ b/bluetooth_demo_L01/utils/util.js @@ -0,0 +1,30 @@ +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++) { + if (!key) { + if (arr[i] == val) { + return i + } + } else 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); +} +module.exports = { + inArray, + ab2hex, +} diff --git a/bluetooth_demo_L10.zip b/bluetooth_demo_L10.zip new file mode 100644 index 0000000000000000000000000000000000000000..6c90f1946ea1a792ea7f75acef21721f1faa3fc8 GIT binary patch literal 37932 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 H1Lo|1p#o+i literal 0 HcmV?d00001 diff --git a/bluetooth_demo_L11/app.js b/bluetooth_demo_L11/app.js new file mode 100644 index 0000000..ff15a95 --- /dev/null +++ b/bluetooth_demo_L11/app.js @@ -0,0 +1,5 @@ +//app.js +App({ + onLaunch: function () { + } +}) \ No newline at end of file diff --git a/bluetooth_demo_L11/app.json b/bluetooth_demo_L11/app.json new file mode 100644 index 0000000..eb60991 --- /dev/null +++ b/bluetooth_demo_L11/app.json @@ -0,0 +1,14 @@ +{ + "pages": [ + "pages/index/index" + ], + "window": { + "navigationBarBackgroundColor": "#0082FE", + "navigationBarTextStyle": "white", + "navigationBarTitleText": "蓝牙连接Demo", + "backgroundColor": "#eeeeee", + "backgroundTextStyle": "light" + }, + "style": "v2", + "sitemapLocation": "sitemap.json" +} diff --git a/bluetooth_demo_L11/app.wxss b/bluetooth_demo_L11/app.wxss new file mode 100644 index 0000000..bee9f30 --- /dev/null +++ b/bluetooth_demo_L11/app.wxss @@ -0,0 +1,55 @@ +/**app.wxss**/ +view, +cover-view, +scroll-view, +swiper, +swiper-item, +movable-area, +movable-view, +button, +input, +textarea, +label, +navigator { + box-sizing: border-box; +} + +page { + --safe-bottom: env(safe-area-inset-bottom); +} + +.container { + position: relative; + display: flex; + flex-direction: column; + align-items: center; + width: 100vw; + height: 100vh; + padding-bottom: var(--safe-bottom); +} + +.header { + width: 100%; +} + +.header button { + font-size: 16px; + line-height: 40px; + width: 100% !important; + border-bottom: 1px solid #dfdfdf; +} + +.device_item { + padding: 15px; + border-bottom: 1px solid #dfdfdf; +} + +.weight { + width: 100%; + margin: 15px; + padding-bottom: 15px; + text-align: center; + font-size: 18px; + font-weight: 700; + border-bottom: 1px solid #dfdfdf; +} diff --git a/bluetooth_demo_L11/pages/index/index.js b/bluetooth_demo_L11/pages/index/index.js new file mode 100644 index 0000000..c2e5746 --- /dev/null +++ b/bluetooth_demo_L11/pages/index/index.js @@ -0,0 +1,155 @@ +const util = require("../../utils/util"); +const { + inArray, + ab2hex +} = util + +Page({ + data: { + devices: [], + deviceId: null, + connected: false, + weight: "", + imp: "", + tetx: '' + }, + onLoad: function() {}, + // 初始化蓝牙模块 + openBluetoothAdapter() { + wx.openBluetoothAdapter({ + success: (res) => { + console.log('openBluetoothAdapter success', res) + wx.showToast({ + title: '蓝牙连接中', + icon: "none" + }) + this.startBluetoothDevicesDiscovery() + }, + fail: (res) => { + if (res.errCode === 10001) { + wx.showToast({ + title: '请打开蓝牙', + icon: "none" + }) + // 监听本机蓝牙状态变化的事件 + wx.onBluetoothAdapterStateChange((res) => { + console.log('onBluetoothAdapterStateChange', res) + if (res.available) { + this.startBluetoothDevicesDiscovery() + } + }) + } + } + }) + }, + + // 开始搜寻附近的蓝牙外围设备 + startBluetoothDevicesDiscovery() { + if (this._discoveryStarted) { + return + } + this._discoveryStarted = true + wx.startBluetoothDevicesDiscovery({ + allowDuplicatesKey: true, //是否允许重复上报同一设备 + success: (res) => { + console.log('startBluetoothDevicesDiscovery success', res) + this.onBluetoothDeviceFound() + }, + }) + }, + // 停止搜寻附近的蓝牙外围设备 + stopBluetoothDevicesDiscovery() { + wx.stopBluetoothDevicesDiscovery() + }, + + // 找到新设备的事件 + onBluetoothDeviceFound() { + let that = this + wx.onBluetoothDeviceFound((res) => { + res.devices.forEach(device => { + if (!device.name && !device.localName) { + let value = ab2hex(device.advertisData, "") + let id = value.substring(12, 16) + if (value.indexOf('c0') !== -1 && id == '0002') { + let buff = device.advertisData.slice(-6) + device.mac = new Uint8Array(buff) // 保存广播数据中的mac地址,这是由于iOS不直接返回mac地址 + let tempMac = Array.from(device.mac) + device.macAddr = ab2hex(tempMac, ':').toUpperCase() + let msg = parseInt(value.substring(16, 18), 16).toString(2) + let weight = parseInt(value.substring(4, 8), 16)//体重 + let type = msg.substring(5, 6) //0实时,1稳定 + let num = msg.substring(3, 5) //小数点 + let unit = msg.substring(1, 3) //单位 + let dw1 = "kg" + if (unit == "10") { + dw1 = "lb" + } + if (num == "00") { + weight = parseInt(value.substring(4, 8), 16) / 10 + } + if (num == "10") { + if (unit == "10") { + dw1 = "lb" + weight = parseInt(value.substring(4, 8), 16) / 10 + } else { + weight = parseInt(value.substring(4, 8), 16) / 100 + } + } + that.setData({ + weight: "实时体重:" + weight + dw1, + }) + if (type == '1') { + that.setData({ + weight: "稳定体重:" + weight + dw1, + imp: "阻抗:" + parseInt(value.substring(8, 12), 16) / 10, + }) + } + } + return + } + + }) + }) + }, + //监听蓝牙连接状态 + onBLEConnectionStateChange() { + wx.onBLEConnectionStateChange((res) => { + if (!res.connected) { + wx.stopBluetoothDevicesDiscovery(); + setTimeout(() => { + wx.showToast({ + title: '连接已断开', + icon: 'none' + }) + }, 500) + this.setData({ + connected: false, + devices: [], + weight: "", + imp: "", + text: '' + + }) + } + }) + }, + + /** + * 断开蓝牙模块 + */ + closeBluetoothAdapter() { + wx.stopBluetoothDevicesDiscovery(); + wx.closeBluetoothAdapter() + this._discoveryStarted = false + wx.showToast({ + title: '结束流程', + icon: 'none' + }) + this.setData({ + devices: [], + weight: "", + imp: "", + text: '' + }) + }, +}); diff --git a/bluetooth_demo_L11/pages/index/index.json b/bluetooth_demo_L11/pages/index/index.json new file mode 100644 index 0000000..b55b5a2 --- /dev/null +++ b/bluetooth_demo_L11/pages/index/index.json @@ -0,0 +1,4 @@ +{ + "usingComponents": { + } +} \ No newline at end of file diff --git a/bluetooth_demo_L11/pages/index/index.wxml b/bluetooth_demo_L11/pages/index/index.wxml new file mode 100644 index 0000000..fe7a5ec --- /dev/null +++ b/bluetooth_demo_L11/pages/index/index.wxml @@ -0,0 +1,35 @@ + + module.exports.max = function(n1, n2) { + return Math.max(n1, n2) + } + module.exports.len = function(arr) { + arr = arr || [] + return arr.length + } + + + + + + + + + + {{weight}} + {{imp}} + {{text}} + + 已发现 {{devices.length}} 个外围设备: + + + + {{item.name}} + (信号强度: {{item.RSSI}}dBm) + + mac地址: {{item.macAddr || item.deviceId}} + + + + diff --git a/bluetooth_demo_L11/project.config.json b/bluetooth_demo_L11/project.config.json new file mode 100644 index 0000000..267a2b8 --- /dev/null +++ b/bluetooth_demo_L11/project.config.json @@ -0,0 +1,46 @@ +{ + "description": "项目配置文件,详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html", + "setting": { + "urlCheck": true, + "scopeDataCheck": false, + "coverView": true, + "es6": false, + "postcss": true, + "compileHotReLoad": false, + "lazyloadPlaceholderEnable": false, + "preloadBackgroundData": false, + "minified": true, + "autoAudits": false, + "newFeature": false, + "uglifyFileName": false, + "uploadWithSourceMap": true, + "useIsolateContext": false, + "nodeModules": false, + "enhance": true, + "useMultiFrameRuntime": true, + "useApiHook": true, + "useApiHostProcess": true, + "showShadowRootInWxmlPanel": true, + "packNpmManually": false, + "packNpmRelationList": [], + "minifyWXSS": true, + "disableUseStrict": false, + "ignoreUploadUnusedFiles": true, + "minifyWXML": true + }, + "compileType": "miniprogram", + "simulatorType": "wechat", + "simulatorPluginLibVersion": {}, + "editorSetting": { + "tabIndent": "insertSpaces", + "tabSize": 2 + }, + "projectname": "bluetooth_demo", + "libVersion": "2.23.2", + "appid": "wxcea3504a31518eb6", + "packOptions": { + "ignore": [], + "include": [] + }, + "condition": {} +} \ No newline at end of file diff --git a/bluetooth_demo_L11/sitemap.json b/bluetooth_demo_L11/sitemap.json new file mode 100644 index 0000000..ca02add --- /dev/null +++ b/bluetooth_demo_L11/sitemap.json @@ -0,0 +1,7 @@ +{ + "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html", + "rules": [{ + "action": "allow", + "page": "*" + }] +} \ No newline at end of file diff --git a/bluetooth_demo_L11/utils/util.js b/bluetooth_demo_L11/utils/util.js new file mode 100644 index 0000000..7aafdf3 --- /dev/null +++ b/bluetooth_demo_L11/utils/util.js @@ -0,0 +1,30 @@ +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++) { + if (!key) { + if (arr[i] == val) { + return i + } + } else 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); +} +module.exports = { + inArray, + ab2hex, +}