From e010cc4e95b71ca6135c46f6f054b6be1cf1b37d Mon Sep 17 00:00:00 2001 From: shuai58 <2973810292@qq.com> Date: Wed, 8 Dec 2021 09:18:31 +0800 Subject: [PATCH] =?UTF-8?q?2021/12/08=20=E8=93=9D=E7=89=99=E5=87=BA?= =?UTF-8?q?=E5=8E=82=E6=B5=8B=E8=AF=95=E5=B0=8F=E7=A8=8B=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 5 + app.json | 16 ++ app.wxss | 68 ++++++ pages/PCD01PRO/index.js | 328 +++++++++++++++++++++++++++++ pages/PCD01PRO/index.json | 4 + pages/PCD01PRO/index.wxml | 42 ++++ pages/PCD01PRO/index.wxss | 1 + pages/PCH0809/index.js | 422 ++++++++++++++++++++++++++++++++++++++ pages/PCH0809/index.json | 4 + pages/PCH0809/index.wxml | 51 +++++ pages/PCH0809/index.wxss | 104 ++++++++++ pages/index/index.js | 344 +++++++++++++++++++++++++++++++ pages/index/index.json | 4 + pages/index/index.wxml | 16 ++ project.config.json | 71 +++++++ sitemap.json | 7 + utils/util.js | 30 +++ 17 files changed, 1517 insertions(+) create mode 100644 app.js create mode 100644 app.json create mode 100644 app.wxss create mode 100644 pages/PCD01PRO/index.js create mode 100644 pages/PCD01PRO/index.json create mode 100644 pages/PCD01PRO/index.wxml create mode 100644 pages/PCD01PRO/index.wxss create mode 100644 pages/PCH0809/index.js create mode 100644 pages/PCH0809/index.json create mode 100644 pages/PCH0809/index.wxml create mode 100644 pages/PCH0809/index.wxss create mode 100644 pages/index/index.js create mode 100644 pages/index/index.json create mode 100644 pages/index/index.wxml create mode 100644 project.config.json create mode 100644 sitemap.json create mode 100644 utils/util.js diff --git a/app.js b/app.js new file mode 100644 index 0000000..ff15a95 --- /dev/null +++ b/app.js @@ -0,0 +1,5 @@ +//app.js +App({ + onLaunch: function () { + } +}) \ No newline at end of file diff --git a/app.json b/app.json new file mode 100644 index 0000000..9994e3b --- /dev/null +++ b/app.json @@ -0,0 +1,16 @@ +{ + "pages": [ + "pages/index/index", + "pages/PCD01PRO/index", + "pages/PCH0809/index" + ], + "window": { + "navigationBarBackgroundColor": "#0082FE", + "navigationBarTextStyle": "white", + "navigationBarTitleText": "蓝牙连接Demo", + "backgroundColor": "#eeeeee", + "backgroundTextStyle": "light" + }, + "style": "v2", + "sitemapLocation": "sitemap.json" +} diff --git a/app.wxss b/app.wxss new file mode 100644 index 0000000..e18f0d0 --- /dev/null +++ b/app.wxss @@ -0,0 +1,68 @@ +/**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; +} +.list{ + width: 100%; + height: auto; + display: flex; + justify-content: space-around; + flex-wrap: wrap; +} +.item{ + padding: 15px; + background: #f7f7f7; + border-radius: 10px; + margin-top: 15px; +} diff --git a/pages/PCD01PRO/index.js b/pages/PCD01PRO/index.js new file mode 100644 index 0000000..5020739 --- /dev/null +++ b/pages/PCD01PRO/index.js @@ -0,0 +1,328 @@ +const util = require("../../utils/util"); +const { + inArray, + ab2hex +} = util + +Page({ + data: { + devices: [], + connected: false, + cmd: '', + name: '', + weight: "", + text: "", + 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 列表 + "FFE0", + ], + success: (res) => { + console.log('startBluetoothDevicesDiscovery success', res) + this.onBluetoothDeviceFound() + }, + }) + }, + // 停止搜寻附近的蓝牙外围设备 + stopBluetoothDevicesDiscovery() { + wx.stopBluetoothDevicesDiscovery() + }, + + // 找到新设备的事件 + onBluetoothDeviceFound() { + wx.onBluetoothDeviceFound((res) => { + res.devices.forEach(device => { + 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 + } + console.log("131", data) + 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 + 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 => { + this._connLoading = false + 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: "", + 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) { + this._deviceId = deviceId + this._serviceId = serviceId + this._device.serviceId = serviceId + wx.getBLEDeviceCharacteristics({ + deviceId, + serviceId, + success: (res) => { + console.log('getBLEDeviceCharacteristics success', res.characteristics) + wx.showLoading({ + title: '获取特征值成功', + }) + //FFE1:write: true, FFE2:notify: true,FFE3:read: true, write: true, notify: true, + for (let i = 0; i < res.characteristics.length; i++) { + let characteristic = res.characteristics[i]; + if (characteristic.uuid.indexOf("FFE2") != -1) { + if (characteristic.properties.notify == true) { + this.notifyBLECharacteristicValue(deviceId, serviceId, characteristic + .uuid) + console.log("ffe2服务的notifyId获取成功") + } + if (characteristic.properties.read == true) { + that.readId = characteristic.uuid + } + if (characteristic.properties.write == true) { + that.writeId = characteristic.uuid + } + break; + } + } + }, + fail(res) { + console.error('getBLEDeviceCharacteristics', res) + } + }) + }, + //解析蓝牙返回数据 + notifyBLECharacteristicValue(deviceId, serviceId, notifyId) { + let that = this + wx.notifyBLECharacteristicValueChange({ + state: true, // 启用 notify 功能 + deviceId: deviceId, + serviceId: serviceId, + characteristicId: notifyId, + success(res) { + wx.onBLECharacteristicValueChange(function(res) { + let value = ab2hex(res.value); + let num = value.substring(18, 19) + let dw = value.substring(19, 20) + let typeInfo = value.substring(10, 12) + console.log("16进制转化:", value); + if (value.length == 26) { + let data = parseInt(value.substring(13, 18), 16) + let dw1 = "kg" + if (dw == "1") { + dw1 = "斤" + console.log("体重单位:斤") + } + if (dw == "4") { + dw1 = "st:lb" + console.log("体重单位:st:lb,计算方法:1 * data + 5") + } + if (dw == "6") { + dw1 = "lb" + console.log("体重单位:lb") + } + if (num == "1") { + data = parseInt(value.substring(13, 18), 16) / 10 + console.log("体重小数点后1位") + } + if (num == "2") { + data = parseInt(value.substring(13, 18), 16) / 100 + console.log("体重小数点后2位") + } + if (num == "3") { + data = parseInt(value.substring(13, 18), 16) / 1000 + console.log("体重小数点后3位") + } + if (typeInfo == "01") { + console.log("实时体重:", data) + that.setData({ + weight: "实时体重是:" + data + dw1 + }) + } + if (typeInfo == "02") { + console.log("稳定体重:", data) + that.setData({ + weight: "稳定体重是:" + data + dw1 + }) + } + } + if (value.length == 30) { + console.log("阻抗值:", value) + if (typeInfo == "03") { + let imp = parseInt(value.substring(17, 22), 16) + that.setData({ + imp: "阻抗值:" + imp + }) + } + + } + if (value.toUpperCase() == "A90026023000589A") { + console.log("测量完成") + that.setData({ + text: "测量完成" + }) + } + }); + }, + fail(res) { + console.log("测量失败", res.value); + } + }); + }, + + /** + * 断开蓝牙模块 + */ + closeBluetoothAdapter() { + wx.closeBluetoothAdapter() + this._discoveryStarted = false + wx.showToast({ + title: '断开蓝牙模块', + icon: 'none' + }) + this.setData({ + devices: [], + weight: "", + text: "", + imp: "" + }) + }, + // 断开与低功耗蓝牙设备的连接 + closeBLEConnection() { + wx.closeBLEConnection({ + deviceId: this._deviceId + }) + wx.showToast({ + title: '断开蓝牙连接', + icon: 'none' + }) + this.setData({ + connected: false, + devices: [], + text: "", + weight: "", + imp: "" + }) + }, + +}); diff --git a/pages/PCD01PRO/index.json b/pages/PCD01PRO/index.json new file mode 100644 index 0000000..b55b5a2 --- /dev/null +++ b/pages/PCD01PRO/index.json @@ -0,0 +1,4 @@ +{ + "usingComponents": { + } +} \ No newline at end of file diff --git a/pages/PCD01PRO/index.wxml b/pages/PCD01PRO/index.wxml new file mode 100644 index 0000000..cbe4525 --- /dev/null +++ b/pages/PCD01PRO/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}} + {{imp}} + {{text}} + + 已发现 {{devices.length}} 个外围设备: + + + + {{item.name}} + (信号强度: {{item.RSSI}}dBm) + + mac地址: {{item.macAddr || item.deviceId}} + + + + + + diff --git a/pages/PCD01PRO/index.wxss b/pages/PCD01PRO/index.wxss new file mode 100644 index 0000000..23ef694 --- /dev/null +++ b/pages/PCD01PRO/index.wxss @@ -0,0 +1 @@ +/* pages/PCD01PRO/index.wxss */ \ No newline at end of file diff --git a/pages/PCH0809/index.js b/pages/PCH0809/index.js new file mode 100644 index 0000000..0639308 --- /dev/null +++ b/pages/PCH0809/index.js @@ -0,0 +1,422 @@ +const util = require("../../utils/util"); +const { + inArray, + ab2hex +} = util + +Page({ + data: { + devices: [], + connected: false, + cmd: '', + name: '', + weight: "", + text: "", + imp: "", + height: '', + isType: false, + sendVal: true, + pwdModal: false, + uuid1: null, + uuid2: null, + uuid3: null, + deviceId: null, + serviceId: null + }, + onLoad: function() { + // let value = "A90026051401020001439A"; + // let num = value.substring(18, 19) + // let type = value.substring(8, 10) + // let imp = parseInt(value.substring(10, 14), 16) + // console.log("16进制转化:", value, num, type, imp); + }, + // 初始化蓝牙模块 + 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 列表 + "FFE0", + ], + success: (res) => { + console.log('startBluetoothDevicesDiscovery success', res) + this.onBluetoothDeviceFound() + }, + }) + }, + // 停止搜寻附近的蓝牙外围设备 + stopBluetoothDevicesDiscovery() { + wx.stopBluetoothDevicesDiscovery() + }, + + // 找到新设备的事件 + onBluetoothDeviceFound() { + wx.onBluetoothDeviceFound((res) => { + res.devices.forEach(device => { + 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 + } + console.log("131", data) + 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 + 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 => { + this._connLoading = false + 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, + isType: false, + devices: [], + weight: "", + 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.data.serviceId = res.services[i].uuid + this.data.deviceId = deviceId + this.getBLEDeviceCharacteristics(deviceId, res.services[i].uuid) + return + } + } + } + }) + }, + + // 获取蓝牙设备某个服务中所有特征值(characteristic) + /** + * read: true读,write: true写,notify: true广播 + */ + getBLEDeviceCharacteristics(deviceId, serviceId) { + this._deviceId = deviceId + this._serviceId = serviceId + this._device.serviceId = serviceId + let that = this + wx.getBLEDeviceCharacteristics({ + deviceId, + serviceId, + success: (res) => { + wx.hideLoading() + console.log('getBLEDeviceCharacteristics success', res.characteristics) + for (let i = 0; i < res.characteristics.length; i++) { + let item = res.characteristics[i]; + if (item.uuid.indexOf('FFE1') != -1) { + that.data.uuid1 = item.uuid //主服务 UUID + } else if (item.uuid.indexOf('FFE2') != -1) { + that.data.uuid2 = item.uuid //写入设置 + } else if (item.uuid.indexOf('FFE3') != -1) { + that.data.uuid3 = item.uuid //监听数据 + } + } + that.setData({ + isType: true, + }) + wx.notifyBLECharacteristicValueChange({ + deviceId, + serviceId, + characteristicId: that.data.uuid2, + state: true, + }) + wx.notifyBLECharacteristicValueChange({ + deviceId, + serviceId, + characteristicId: that.data.uuid3, + state: true, + }) + wx.onBLECharacteristicValueChange((res) => { + let value = ab2hex(res.value); + console.log("16进制转化:", value); + let num = value.substring(18, 19) + let dw = value.substring(19, 20) + let type = value.substring(8, 10) + let typeInfo = value.substring(10, 12) + console.log("16进制转化:", value); + if (type == '10') { + let data = parseInt(value.substring(13, 18), 16) + let dw1 = "kg" + if (dw == "1") { + dw1 = "斤" + console.log("体重单位:斤") + } + if (dw == "4") { + dw1 = "st:lb" + console.log("体重单位:st:lb,计算方法:1 * data + 5") + } + if (dw == "6") { + dw1 = "lb" + console.log("体重单位:lb") + } + if (num == "1") { + data = parseInt(value.substring(13, 18), 16) / 10 + console.log("体重小数点后1位") + } + if (num == "2") { + data = parseInt(value.substring(13, 18), 16) / 100 + console.log("体重小数点后2位") + } + if (num == "3") { + data = parseInt(value.substring(13, 18), 16) / 1000 + console.log("体重小数点后3位") + } + if (typeInfo == "01") { + console.log("实时体重:", data) + that.setData({ + weight: "实时体重是:" + data + dw1 + }) + } + if (typeInfo == "02") { + console.log("稳定体重:", data) + that.setData({ + weight: "稳定体重是:" + data + dw1 + }) + } + } + if (type == "14" ) { //身高模式 + let height = parseInt(value.substring(10, 14), 16) + that.setData({ + height: "您的身高是:" + height + }) + console.log("身高模式:", height) + } + if (type == "11") { + console.log("阻抗值:", value) + if (typeInfo == "03" || typeInfo == "04") { + let imp = parseInt(value.substring(17, 22), 16) + that.setData({ + imp: "阻抗值:" + imp + }) + } + } + if (value.toUpperCase() == "A90026023000589A") { + console.log("测量完成") + that.setData({ + text: "测量完成" + }) + } + }); + }, + fail(res) { + console.error('getBLEDeviceCharacteristics', res) + } + }) + }, + handleHeight(e) { + let that = this + let type = e.currentTarget.dataset.name + if (type == '1') { + let j = Number(26 + 3 + 6 + 1).toString(16) + let str = "A9002603060100" + j.substr(j.length - 2, 2) + "9A" + let buf = new Uint8Array(str.match(/[\da-f]{2}/gi).map(function(h) { + return parseInt(h, 16) + })) + that.sendData(buf.buffer) + } + if (type == '3') { + that.setData({ + pwdModal: true, + }) + } + }, + confirmPwd() { + let that = this + console.log(that.data.pwdInput) + if (!that.data.pwdInput) { + wx.showToast({ + title: '请输入重量', + icon: 'none' + }) + return + } else { + let w = Number(that.data.pwdInput.replace(/[&\|\\\*^%$#@\.-]/g, "")) + let j = Number(26 + 7 + 40 + w + 3 + 2).toString(16) + let atr = w.toString(16) + let num = 2 + if (that.data.pwdInput.toString().split(".")[1].length) { + num = Number(that.data.pwdInput.toString().split(".")[1].length) + } + let str = "A90026074003" + atr + num + "000" + j.substr(j.length - 2, 2) + "9a" + console.log("协议:", j, j.substr(j.length - 2, 2), w, atr, num, str) + let buf = new Uint8Array(str.match(/[\da-f]{2}/gi).map(function(h) { + return parseInt(h, 16) + })) + that.sendData(buf.buffer) + } + }, + sendData(buffer) { + let that = this + console.log("指令信息", that.data.deviceId, that.data.serviceId, ab2hex(buffer)) + wx.writeBLECharacteristicValue({ + deviceId: that.data.deviceId, + serviceId: that.data.serviceId, + characteristicId: that.data.uuid2, + value: buffer, + success: res => { + console.log('下发指令', res.errMsg) + wx.showToast({ + title: '下发指令成功', + icon: 'none' + }) + this.setData({ + pwdModal: false, + }) + }, + fail: res => { + wx.showToast({ + title: '下发指令失败', + icon: 'none' + }) + this.setData({ + pwdModal: false, + }) + console.log("失败", res); + }, + }) + }, + closeModal() { + this.setData({ + pwdModal: false, + }) + }, + /** + * 断开蓝牙模块 + */ + closeBluetoothAdapter() { + wx.closeBluetoothAdapter() + this._discoveryStarted = false + wx.showToast({ + title: '断开蓝牙模块', + icon: 'none' + }) + this.setData({ + devices: [], + weight: "", + text: "", + imp: "", + isType: false + }) + }, + // 断开与低功耗蓝牙设备的连接 + closeBLEConnection() { + wx.closeBLEConnection({ + deviceId: this._deviceId + }) + wx.showToast({ + title: '断开蓝牙连接', + icon: 'none' + }) + this.setData({ + connected: false, + isType: false, + devices: [], + text: "", + weight: "", + imp: "" + }) + }, + +}); diff --git a/pages/PCH0809/index.json b/pages/PCH0809/index.json new file mode 100644 index 0000000..b55b5a2 --- /dev/null +++ b/pages/PCH0809/index.json @@ -0,0 +1,4 @@ +{ + "usingComponents": { + } +} \ No newline at end of file diff --git a/pages/PCH0809/index.wxml b/pages/PCH0809/index.wxml new file mode 100644 index 0000000..1998a86 --- /dev/null +++ b/pages/PCH0809/index.wxml @@ -0,0 +1,51 @@ + + module.exports.max = function(n1, n2) { + return Math.max(n1, n2) + } + module.exports.len = function(arr) { + arr = arr || [] + return arr.length + } + + + + + + + + + + + + {{weight}} + {{imp}} + {{height}} + {{text}} + + 已发现 {{devices.length}} 个外围设备: + + + + {{item.name}} + (信号强度: {{item.RSSI}}dBm) + + mac地址: {{item.macAddr || item.deviceId}} + + + + + + + 标定重量 + + + + + 取消 + 确定 + + + diff --git a/pages/PCH0809/index.wxss b/pages/PCH0809/index.wxss new file mode 100644 index 0000000..e57bbb6 --- /dev/null +++ b/pages/PCH0809/index.wxss @@ -0,0 +1,104 @@ +/* pages/PCH0809/index.wxss */ +.modal_wrapper { + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: -1; + background: rgba(0, 0, 0, 0.5); + transition: .4s all; + height: 200vh; + opacity: 0; +} + +.modal_wrapper_show { + transform: translateY(-100vh); + opacity: 1; + overflow-x: hidden; + overflow-y: auto; + z-index: 1000; +} + +.remindModal { + position: absolute; + bottom: 50vh; + left: 50%; + z-index: 101; + transform: translate(-50%, 50%); + background: #fff; + width: 600rpx; + padding: 40rpx 60rpx; + border-radius: 20rpx; +} + +.remindModal_title { + padding: 10rpx 30rpx 50rpx; + text-align: center; + font-size: 32rpx; +} + +.remindModal_content { + font-size: 30rpx; + line-height: 1.6; + text-align: center; + padding-top: 30rpx; + min-height: 100rpx; +} + +.remindModal_btn { + margin-top: 80rpx; + margin-bottom: 10rpx; + display: flex; + justify-content: space-evenly; +} + +.remindModal_cancel_btn { + display: flex; + align-items: center; + justify-content: center; + width: 45%; + height: 100rpx; + border: 1px solid transparent; + margin: auto; + background: #dfdfdf; + color: #fff; + font-size: 16px; + letter-spacing: 2rpx; + border-radius: 10px; + white-space: nowrap; +} + +.modal_input_wrap { + width: 100%; + height: 80rpx; + padding: 0 10rpx; + border: 1px solid #dcdcdc; + border-radius: 10rpx; +} + +.modal_input { + width: 100%; + height: 100%; + padding: 10rpx; + font-size: 30rpx; +} + +.confirm_btn { + display: flex; + align-items: center; + justify-content: center; + width: 45%; + height: 100rpx; + border: 1px solid transparent; + margin: auto; + background: #1977FF; + color: #fff; + font-size: 16px; + letter-spacing: 2rpx; + border-radius: 10px; + white-space: nowrap; +} + +.item_hover { + background-color: rgba(0, 0, 0, .1); +} diff --git a/pages/index/index.js b/pages/index/index.js new file mode 100644 index 0000000..3a44a08 --- /dev/null +++ b/pages/index/index.js @@ -0,0 +1,344 @@ +const util = require("../../utils/util"); +const { + inArray, + ab2hex +} = util + +Page({ + data: { + devices: [], + connected: false, + cmd: '', + name: '', + weight: "", + text: "", + imp: "", + deviceId: null, + }, + onLoad: function() { + }, + // 初始化蓝牙模块 + editclick: function(e) { + let type = e.currentTarget.dataset.name + if (type == 'PCD01PRO') { + wx.navigateTo({ + url: `/pages/PCD01PRO/index` + }) + return + } + if (type == 'PCH0809') { + wx.navigateTo({ + url: `/pages/PCH0809/index` + }) + return + } + }, + 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 列表 + "FFE0", + ], + success: (res) => { + console.log('startBluetoothDevicesDiscovery success', res) + this.onBluetoothDeviceFound() + }, + }) + }, + // 停止搜寻附近的蓝牙外围设备 + stopBluetoothDevicesDiscovery() { + wx.stopBluetoothDevicesDiscovery() + }, + + // 找到新设备的事件 + onBluetoothDeviceFound() { + wx.onBluetoothDeviceFound((res) => { + res.devices.forEach(device => { + 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 + } + console.log("131", data) + 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 + 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 => { + this._connLoading = false + 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: "", + 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) { + this._deviceId = deviceId + this._serviceId = serviceId + this._device.serviceId = serviceId + wx.getBLEDeviceCharacteristics({ + deviceId, + serviceId, + success: (res) => { + console.log('getBLEDeviceCharacteristics success', res.characteristics) + wx.showLoading({ + title: '获取特征值成功', + }) + //FFE1:write: true, FFE2:notify: true,FFE3:read: true, write: true, notify: true, + for (let i = 0; i < res.characteristics.length; i++) { + let characteristic = res.characteristics[i]; + if (characteristic.uuid.indexOf("FFE2") != -1) { + if (characteristic.properties.notify == true) { + this.notifyBLECharacteristicValue(deviceId, serviceId, characteristic + .uuid) + console.log("ffe2服务的notifyId获取成功") + } + if (characteristic.properties.read == true) { + that.readId = characteristic.uuid + } + if (characteristic.properties.write == true) { + that.writeId = characteristic.uuid + } + break; + } + } + }, + fail(res) { + console.error('getBLEDeviceCharacteristics', res) + } + }) + }, + //解析蓝牙返回数据 + notifyBLECharacteristicValue(deviceId, serviceId, notifyId) { + let that = this + wx.notifyBLECharacteristicValueChange({ + state: true, // 启用 notify 功能 + deviceId: deviceId, + serviceId: serviceId, + characteristicId: notifyId, + success(res) { + wx.onBLECharacteristicValueChange(function(res) { + let value = ab2hex(res.value); + let num = value.substring(18, 19) + let dw = value.substring(19, 20) + let typeInfo = value.substring(10, 12) + console.log("16进制转化:", value); + if (value.length == 26) { + let data = parseInt(value.substring(13, 18), 16) + let dw1 = "kg" + if (dw == "1") { + dw1 = "斤" + console.log("体重单位:斤") + } + if (dw == "4") { + dw1 = "st:lb" + console.log("体重单位:st:lb,计算方法:1 * data + 5") + } + if (dw == "6") { + dw1 = "lb" + console.log("体重单位:lb") + } + if (num == "1") { + data = parseInt(value.substring(13, 18), 16) / 10 + console.log("体重小数点后1位") + } + if (num == "2") { + data = parseInt(value.substring(13, 18), 16) / 100 + console.log("体重小数点后2位") + } + if (num == "3") { + data = parseInt(value.substring(13, 18), 16) / 1000 + console.log("体重小数点后3位") + } + if (typeInfo == "01") { + console.log("实时体重:", data) + that.setData({ + weight: "实时体重是:" + data + dw1 + }) + } + if (typeInfo == "02") { + console.log("稳定体重:", data) + that.setData({ + weight: "稳定体重是:" + data + dw1 + }) + } + } + if (value.length == 30) { + console.log("阻抗值:", value) + if (typeInfo == "03") { + let imp = parseInt(value.substring(17, 22), 16) + that.setData({ + imp: "阻抗值:" + imp + }) + } + + } + if (value.toUpperCase() == "A90026023000589A") { + console.log("测量完成") + that.setData({ + text: "测量完成" + }) + } + }); + }, + fail(res) { + console.log("测量失败", res.value); + } + }); + }, + + /** + * 断开蓝牙模块 + */ + closeBluetoothAdapter() { + wx.closeBluetoothAdapter() + this._discoveryStarted = false + wx.showToast({ + title: '断开蓝牙模块', + icon: 'none' + }) + this.setData({ + devices: [], + weight: "", + text: "", + imp: "" + }) + }, + // 断开与低功耗蓝牙设备的连接 + closeBLEConnection() { + wx.closeBLEConnection({ + deviceId: this._deviceId + }) + wx.showToast({ + title: '断开蓝牙连接', + icon: 'none' + }) + this.setData({ + connected: false, + devices: [], + text: "", + weight: "", + imp: "" + }) + }, + +}); diff --git a/pages/index/index.json b/pages/index/index.json new file mode 100644 index 0000000..b55b5a2 --- /dev/null +++ b/pages/index/index.json @@ -0,0 +1,4 @@ +{ + "usingComponents": { + } +} \ No newline at end of file diff --git a/pages/index/index.wxml b/pages/index/index.wxml new file mode 100644 index 0000000..fd90807 --- /dev/null +++ b/pages/index/index.wxml @@ -0,0 +1,16 @@ + + module.exports.max = function(n1, n2) { + return Math.max(n1, n2) + } + module.exports.len = function(arr) { + arr = arr || [] + return arr.length + } + + + + + PCD01PRO + PCH08/09 + + diff --git a/project.config.json b/project.config.json new file mode 100644 index 0000000..327660f --- /dev/null +++ b/project.config.json @@ -0,0 +1,71 @@ +{ + "description": "项目配置文件", + "packOptions": { + "ignore": [] + }, + "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": false, + "babelSetting": { + "ignore": [], + "disablePlugins": [], + "outputPath": "" + }, + "useIsolateContext": true, + "userConfirmedBundleSwitch": false, + "packNpmManually": false, + "packNpmRelationList": [], + "minifyWXSS": true, + "showES6CompileOption": false + }, + "compileType": "miniprogram", + "libVersion": "2.16.0", + "projectname": "bluetooth_demo", + "debugOptions": { + "hidedInDevtools": [] + }, + "scripts": {}, + "isGameTourist": false, + "simulatorType": "wechat", + "simulatorPluginLibVersion": {}, + "appid": "wxcea3504a31518eb6", + "condition": { + "search": { + "list": [] + }, + "conversation": { + "list": [] + }, + "game": { + "list": [] + }, + "plugin": { + "list": [] + }, + "gamePlugin": { + "list": [] + }, + "miniprogram": { + "list": [] + } + } +} \ No newline at end of file diff --git a/sitemap.json b/sitemap.json new file mode 100644 index 0000000..ca02add --- /dev/null +++ b/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/utils/util.js b/utils/util.js new file mode 100644 index 0000000..b00f2de --- /dev/null +++ b/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) { + var hexArr = Array.prototype.map.call( + new Uint8Array(buffer), + function(bit) { + return ('00' + bit.toString(16)).slice(-2) + } + ) + return hexArr.join(""); +} +module.exports = { + inArray, + ab2hex, +}