Compare commits
3 Commits
411b92d9b9
...
e4a1acd7b0
| Author | SHA1 | Date |
|---|---|---|
|
|
e4a1acd7b0 | |
|
|
4ff1bb8e67 | |
|
|
a161319690 |
|
|
@ -1,322 +1,325 @@
|
|||
const util = require("../../utils/util");
|
||||
const {
|
||||
inArray,
|
||||
ab2hex
|
||||
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()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
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()
|
||||
},
|
||||
// 开始搜寻附近的蓝牙外围设备
|
||||
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: ""
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
// 找到新设备的事件
|
||||
onBluetoothDeviceFound() {
|
||||
wx.onBluetoothDeviceFound((res) => {
|
||||
res.devices.forEach(device => {
|
||||
if (!device.name && !device.localName) {
|
||||
return
|
||||
}
|
||||
console.log("name", device.name)
|
||||
if (device.name.indexOf('AiLink_') != -1 || device.name.toLowerCase().indexOf(
|
||||
'pcf01') != -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
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
// 获取蓝牙设备的 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 //写入设置
|
||||
}
|
||||
}
|
||||
// 获取蓝牙设备某个服务中所有特征值(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.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)
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
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: ""
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 断开蓝牙模块
|
||||
*/
|
||||
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: ""
|
||||
})
|
||||
},
|
||||
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
# #参考使用设备类型
|
||||
```
|
||||
F01PRO
|
||||
|
||||
```
|
||||
|
||||
##
|
||||
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
//app.js
|
||||
App({
|
||||
onLaunch: function () {
|
||||
}
|
||||
})
|
||||
|
|
@ -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"
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -0,0 +1,271 @@
|
|||
const util = require("../../utils/util");
|
||||
const {
|
||||
inArray,
|
||||
ab2hex
|
||||
} = util
|
||||
const plugin = requirePlugin("sdkPlugin").AiLink;
|
||||
Page({
|
||||
data: {
|
||||
devices: [],
|
||||
connected: false,
|
||||
name: '',
|
||||
height: "",
|
||||
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,
|
||||
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('G02') != -1) {
|
||||
wx.stopBluetoothDevicesDiscovery()
|
||||
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: [],
|
||||
height: "",
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 获取蓝牙设备的 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('FFF0') > -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
|
||||
|
||||
function PrefixZero(num, n) {
|
||||
return (Array(n).join(0) + num).slice(-n);
|
||||
}
|
||||
wx.hideLoading()
|
||||
wx.getBLEDeviceCharacteristics({
|
||||
deviceId,
|
||||
serviceId,
|
||||
success: (res) => {
|
||||
for (let i = 0; i < res.characteristics.length; i++) {
|
||||
let item = res.characteristics[i];
|
||||
if (item.uuid.indexOf('0000FFF1') != -1) {
|
||||
this.notifyBLECharacteristicValue(deviceId, serviceId, item.uuid)
|
||||
}
|
||||
}
|
||||
},
|
||||
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((characteristic) => {
|
||||
let value = ab2hex(characteristic.value, "");
|
||||
let data = parseInt(value.substring(7, 10), 16)
|
||||
let unit = parseInt(value.substring(10, 12))
|
||||
let digit = parseInt(value.substring(12, 14))
|
||||
let unit2 = 'cm'
|
||||
if (digit == "1") {
|
||||
data = data / 10
|
||||
}
|
||||
if (digit == "2") {
|
||||
data = data / 100
|
||||
}
|
||||
if (unit == "0") {
|
||||
unit2 = "cm"
|
||||
}
|
||||
if (unit == "1") {
|
||||
unit2 = "inch"
|
||||
}
|
||||
if (unit == "2") {
|
||||
unit2 = "ft"
|
||||
let data1 = data / 12
|
||||
let data2 = Number(data1 - Math.floor(data1)) * 12
|
||||
let height = Math.floor(data1) + "'" + data2.toFixed(1)
|
||||
that.setData({
|
||||
height: "身高是:" + height + unit2
|
||||
})
|
||||
} else {
|
||||
that.setData({
|
||||
height: "身高是:" + data + unit2
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 断开蓝牙模块
|
||||
*/
|
||||
closeBluetoothAdapter() {
|
||||
wx.closeBluetoothAdapter()
|
||||
this._discoveryStarted = false
|
||||
wx.showToast({
|
||||
title: '断开蓝牙模块',
|
||||
icon: 'none'
|
||||
})
|
||||
this.setData({
|
||||
devices: [],
|
||||
height: "",
|
||||
})
|
||||
},
|
||||
// 断开与低功耗蓝牙设备的连接
|
||||
closeBLEConnection() {
|
||||
wx.closeBLEConnection({
|
||||
deviceId: this._deviceId
|
||||
})
|
||||
wx.showToast({
|
||||
title: '断开蓝牙连接',
|
||||
icon: 'none'
|
||||
})
|
||||
this.setData({
|
||||
connected: false,
|
||||
devices: [],
|
||||
text: "",
|
||||
height: "",
|
||||
weight: "",
|
||||
imp: ""
|
||||
})
|
||||
},
|
||||
|
||||
});
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"usingComponents": {
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<wxs module="utils">
|
||||
module.exports.max = function(n1, n2) {
|
||||
return Math.max(n1, n2)
|
||||
}
|
||||
module.exports.len = function(arr) {
|
||||
arr = arr || []
|
||||
return arr.length
|
||||
}
|
||||
</wxs>
|
||||
|
||||
<view class="container">
|
||||
<view class="header">
|
||||
<button bindtap="openBluetoothAdapter">开始扫描</button>
|
||||
<button bindtap="stopBluetoothDevicesDiscovery">停止扫描</button>
|
||||
<button bindtap="closeBluetoothAdapter">结束流程</button>
|
||||
</view>
|
||||
<view class="weight">
|
||||
<view>{{height}}</view>
|
||||
</view>
|
||||
<view class="devices_summary">已发现 {{devices.length}} 个外围设备:</view>
|
||||
<scroll-view class="device_list" scroll-y scroll-with-animation>
|
||||
<view wx:for="{{devices}}" wx:key="index" data-device-id="{{item.deviceId}}"
|
||||
data-name="{{item.name || item.localName}}" data-mac="{{item.mac}}" data-index="{{index}}"
|
||||
bindtap="createBLEConnection" class="device_item" hover-class="device_item_hover">
|
||||
<view style="font-size: 32rpx;">
|
||||
<text style="color:#000;font-weight:bold">{{item.name}}</text>
|
||||
<text style="font-size:26rpx">(信号强度: {{item.RSSI}}dBm)</text>
|
||||
</view>
|
||||
<view style="font-size: 26rpx">mac地址: {{item.macAddr || item.deviceId}}</view>
|
||||
<!-- <view style="font-size: 26rpx">广播数据:{{item.analyzeDataText}}</view> -->
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
</view>
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
{
|
||||
"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,
|
||||
"condition": false
|
||||
},
|
||||
"compileType": "miniprogram",
|
||||
"simulatorType": "wechat",
|
||||
"simulatorPluginLibVersion": {},
|
||||
"projectname": "bluetooth_demo_F01",
|
||||
"libVersion": "2.23.2",
|
||||
"appid": "wx39cf431caa22b5c8",
|
||||
"editorSetting": {
|
||||
"tabIndent": "insertSpaces",
|
||||
"tabSize": 2
|
||||
},
|
||||
"condition": {},
|
||||
"packOptions": {
|
||||
"ignore": [],
|
||||
"include": []
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html",
|
||||
"projectname": "bluetooth_demo_F01"
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
|
||||
"rules": [{
|
||||
"action": "allow",
|
||||
"page": "*"
|
||||
}]
|
||||
}
|
||||
|
|
@ -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,
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,8 @@
|
|||
# #参考使用设备类型
|
||||
```
|
||||
F01PRO
|
||||
|
||||
```
|
||||
|
||||
##
|
||||
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
//app.js
|
||||
App({
|
||||
onLaunch: function () {
|
||||
}
|
||||
})
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"pages": [
|
||||
"pages/index/index"
|
||||
],
|
||||
"window": {
|
||||
"navigationBarBackgroundColor": "#0082FE",
|
||||
"navigationBarTextStyle": "white",
|
||||
"navigationBarTitleText": "蓝牙连接Demo",
|
||||
"backgroundColor": "#eeeeee",
|
||||
"backgroundTextStyle": "light"
|
||||
},
|
||||
"style": "v2",
|
||||
"sitemapLocation": "sitemap.json"
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -0,0 +1,393 @@
|
|||
const util = require("../../utils/util");
|
||||
const {
|
||||
inArray,
|
||||
ab2hex,
|
||||
toHex,
|
||||
gethms
|
||||
} = util
|
||||
Page({
|
||||
data: {
|
||||
devices: [],
|
||||
connected: false,
|
||||
name: '',
|
||||
Mode: "",
|
||||
text: "",
|
||||
weight: "",
|
||||
kcal: "",
|
||||
uuid1: "",
|
||||
uuid2: "",
|
||||
uuid3: "",
|
||||
active: "",
|
||||
timeList: [],
|
||||
deviceId: null,
|
||||
serviceId: null
|
||||
},
|
||||
onLoad: function() {
|
||||
let that = this
|
||||
that.data.timeList = gethms()
|
||||
that.data.time_m = that.data.timeList[0][1].substring(0, 2)
|
||||
that.data.time_s = that.data.timeList[1][0].substring(0, 2)
|
||||
},
|
||||
// 初始化蓝牙模块
|
||||
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"
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
// 开始搜寻附近的蓝牙外围设备
|
||||
startBluetoothDevicesDiscovery() {
|
||||
wx.startBluetoothDevicesDiscovery({
|
||||
allowDuplicatesKey: true,
|
||||
interval: 200, //上报设备的间隔
|
||||
services: [],
|
||||
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('YPC') != -1) {
|
||||
wx.stopBluetoothDevicesDiscovery()
|
||||
const foundDevices = this.data.devices
|
||||
const idx = inArray(foundDevices, 'deviceId', device.deviceId)
|
||||
const data = {}
|
||||
const tempMac = device.name.substring(7, 19)
|
||||
device.macAddr = tempMac.substring(0, tempMac.length - 1)
|
||||
.replace(/(.{2})(?!$)/g, '$1:') + tempMac.substring(tempMac.length - 1);
|
||||
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
|
||||
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({
|
||||
devices: [],
|
||||
weight: "",
|
||||
text: "",
|
||||
Mode: "",
|
||||
kcal: "",
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 获取蓝牙设备的 serviceId
|
||||
getBLEDeviceServices(deviceId) {
|
||||
wx.getBLEDeviceServices({
|
||||
deviceId,
|
||||
success: (res) => {
|
||||
for (let i = 0; i < res.services.length; i++) {
|
||||
let service = res.services[i];
|
||||
if (service.uuid.indexOf('FFE0') > -1) {
|
||||
this.data.serviceId = service.uuid
|
||||
this.data.deviceId = deviceId
|
||||
this.getBLEDeviceCharacteristics(deviceId, service.uuid)
|
||||
wx.showLoading({
|
||||
title: '获取设备的UUID成功',
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 获取蓝牙设备某个服务中所有特征值(characteristic)
|
||||
/**
|
||||
* read: true读,write: true写,notify: true广播
|
||||
*/
|
||||
getBLEDeviceCharacteristics(deviceId, serviceId) {
|
||||
let that = this
|
||||
this._deviceId = deviceId
|
||||
this._serviceId = serviceId
|
||||
this._device.serviceId = serviceId
|
||||
wx.showLoading({
|
||||
title: '连接成功',
|
||||
})
|
||||
wx.getBLEDeviceCharacteristics({
|
||||
deviceId,
|
||||
serviceId,
|
||||
success: (res) => {
|
||||
console.log("服务的特征值成功:", res)
|
||||
for (let i = 0; i < res.characteristics.length; i++) {
|
||||
let item = res.characteristics[i];
|
||||
if (item.uuid.indexOf('0000FFE4') != -1) {
|
||||
that.data.uuid1 = item.uuid //主服务 UUID
|
||||
} else if (item.uuid.indexOf('0000FF12') != -1) {
|
||||
that.data.uuid2 = item.uuid //写入设置
|
||||
}
|
||||
}
|
||||
setTimeout(function() { //下发密码指令
|
||||
let j = Number(165 + 10 + 1 + 8 + 8 + 8 + 8 + 8 + 8).toString(16)
|
||||
let str = "A50A01080808080808" + j.substr(j.length - 2, 2)
|
||||
that.SendData(str)
|
||||
}, 300)
|
||||
setTimeout(function() { //设置体重指令 默认100斤
|
||||
let num = parseInt(100).toString();
|
||||
let m = Number(165 + 5 + 8 + Number(num)).toString(16)
|
||||
let send = "A50508" + Number(num).toString(16) + m.substr(m.length - 2,
|
||||
2)
|
||||
that.SendData(send)
|
||||
}, 600)
|
||||
wx.notifyBLECharacteristicValueChange({
|
||||
deviceId,
|
||||
serviceId,
|
||||
characteristicId: that.data.uuid1,
|
||||
state: true,
|
||||
})
|
||||
wx.notifyBLECharacteristicValueChange({
|
||||
deviceId,
|
||||
serviceId,
|
||||
characteristicId: that.data.uuid2,
|
||||
state: true,
|
||||
})
|
||||
that.notifyBLECharacteristicValue()
|
||||
},
|
||||
fail(res) {
|
||||
console.error('getBLEDeviceCharacteristics', res)
|
||||
}
|
||||
})
|
||||
},
|
||||
notifyBLECharacteristicValue() {
|
||||
let that = this;
|
||||
wx.notifyBLECharacteristicValueChange({
|
||||
state: true, // 启用 notify 功能
|
||||
deviceId: that.data.deviceId,
|
||||
serviceId: that.data.serviceId,
|
||||
characteristicId: that.data.uuid1,
|
||||
success(res) {
|
||||
wx.onBLECharacteristicValueChange((characteristic) => {
|
||||
let value = ab2hex(characteristic.value, "");
|
||||
let count = parseInt(value.substring(8, 12), 16)
|
||||
let Ycount = parseInt(value.substring(12, 16), 16) //设置次数
|
||||
let time = parseInt(value.substring(16, 20), 16) //运行时间/秒
|
||||
let timeDown = parseInt(value.substring(20, 24), 16) //倒计时时间
|
||||
let type = parseInt(value.substring(30, 32), 16) //当前状态
|
||||
let weight = parseInt(value.substring(32, 34), 16) //重量
|
||||
let kcal = parseInt(value.substring(34, 38), 16) / 10 //卡路里
|
||||
let minutes = 0
|
||||
let seconds = 0
|
||||
let time_m = "00"
|
||||
let time_s = "00"
|
||||
let j = null
|
||||
let str = null
|
||||
if (value == '5a05090169') { //模式设置成功
|
||||
setTimeout(function() {
|
||||
j = Number(165 + 5 + 5).toString(16)
|
||||
str = "A5050500" + j.substr(j.length - 2, 2)
|
||||
that.SendData(str) //开始
|
||||
}, 900)
|
||||
setTimeout(function() {
|
||||
j = Number(165 + 5 + 3).toString(16)
|
||||
str = "A5050300" + j.substr(j.length - 2, 2)
|
||||
that.SendData(str) //连续
|
||||
}, 1200)
|
||||
|
||||
}
|
||||
if (value == '5a05080168') {
|
||||
setTimeout(function() { //自由模式
|
||||
that.data.Mode = "自由模式"
|
||||
j = Number(165 + 8 + 9).toString(16)
|
||||
str = "A5080900000000" + j.substr(j.length - 2, 2)
|
||||
that.SendData(str) //连续
|
||||
console.log("模式模式")
|
||||
}, 300)
|
||||
}
|
||||
console.log("value", value, type, that.data.active)
|
||||
if (type == 0 || type == 4) {
|
||||
if (that.data.active != 2 && count != 0) { //自由模式 + 计数
|
||||
minutes = Math.floor((time % 3600) / 60)
|
||||
seconds = time % 60
|
||||
}
|
||||
if (that.data.active == 2) { //计时
|
||||
let T = Number(timeDown) - Number(time)
|
||||
minutes = Math.floor((T % 3600) / 60)
|
||||
seconds = T % 60
|
||||
}
|
||||
time_m = minutes > 9 ? minutes : '0' + minutes
|
||||
time_s = seconds > 9 ? seconds : '0' + seconds
|
||||
that.setData({
|
||||
Mode: that.data.Mode,
|
||||
weight: "跳绳个数:" + count,
|
||||
text: "时长:" + time_m + ':' + time_s,
|
||||
kcal: "消耗卡路里:" + Math.floor(kcal),
|
||||
})
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
// 模式切换
|
||||
handleStart(e) {
|
||||
let that = this
|
||||
let m = null
|
||||
let send = null
|
||||
console.log("ind", ind)
|
||||
that.data.active = e.currentTarget.dataset.name
|
||||
let ind = e.currentTarget.dataset.name
|
||||
if (ind == 1) { // 1自由
|
||||
m = Number(165 + 8 + 9).toString(16)
|
||||
send = "A5080900000000" + m.substr(m.length - 2, 2)
|
||||
that.data.Mode = "自由模式"
|
||||
}
|
||||
if (ind == 2) { //2定时 默认60秒
|
||||
m = Number(165 + 8 + 9 + 60).toString(16)
|
||||
send = "A508090000" + toHex(60, 4) + m.substr(m.length - 2, 2)
|
||||
that.data.Mode = "定时模式"
|
||||
}
|
||||
if (ind == 3) { //3定数 默认50个
|
||||
m = Number(165 + 8 + 9 + 50).toString(16)
|
||||
send = "A50809" + toHex(50, 4) + "0000" + m.substr(m.length - 2, 2)
|
||||
that.data.Mode = "定数模式"
|
||||
}
|
||||
console.log("send", send)
|
||||
that.SendData(send)
|
||||
that.stopBluetoothDevicesDiscovery()
|
||||
},
|
||||
SendData(str) {
|
||||
let that = this
|
||||
let buf = new Uint8Array(str.match(/[\da-f]{2}/gi).map(function(h) {
|
||||
return parseInt(h, 16)
|
||||
}))
|
||||
wx.writeBLECharacteristicValue({
|
||||
deviceId: that.data.deviceId,
|
||||
serviceId: that.data.serviceId,
|
||||
characteristicId: that.data.uuid2,
|
||||
value: buf.buffer,
|
||||
success: res => {
|
||||
console.log('下发指令', res.errMsg)
|
||||
wx.showToast({
|
||||
title: '下发指令成功',
|
||||
duration: 2000,
|
||||
icon: 'none'
|
||||
})
|
||||
},
|
||||
fail: res => {
|
||||
wx.showToast({
|
||||
title: '下发指令失败',
|
||||
duration: 2000,
|
||||
icon: 'none'
|
||||
})
|
||||
console.log("失败", res);
|
||||
},
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 断开蓝牙模块
|
||||
*/
|
||||
closeBluetoothAdapter() {
|
||||
wx.closeBluetoothAdapter()
|
||||
this._discoveryStarted = false
|
||||
wx.showToast({
|
||||
title: '断开蓝牙模块',
|
||||
icon: 'none'
|
||||
})
|
||||
this.setData({
|
||||
devices: [],
|
||||
weight: "",
|
||||
text: "",
|
||||
Mode: "",
|
||||
kcal: "",
|
||||
})
|
||||
},
|
||||
// 断开与低功耗蓝牙设备的连接
|
||||
closeBLEConnection() {
|
||||
wx.closeBLEConnection({
|
||||
deviceId: this._deviceId
|
||||
})
|
||||
wx.showToast({
|
||||
title: '断开蓝牙连接',
|
||||
icon: 'none'
|
||||
})
|
||||
this.setData({
|
||||
devices: [],
|
||||
weight: "",
|
||||
text: "",
|
||||
Mode: "",
|
||||
kcal: "",
|
||||
})
|
||||
},
|
||||
|
||||
});
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"usingComponents": {
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
<wxs module="utils">
|
||||
module.exports.max = function(n1, n2) {
|
||||
return Math.max(n1, n2)
|
||||
}
|
||||
module.exports.len = function(arr) {
|
||||
arr = arr || []
|
||||
return arr.length
|
||||
}
|
||||
</wxs>
|
||||
|
||||
<view class="container">
|
||||
<view class="header">
|
||||
<button bindtap="openBluetoothAdapter">开始扫描</button>
|
||||
<button bindtap="closeBluetoothAdapter">结束流程</button>
|
||||
<button bindtap="handleStart" data-name="1">自由跳模式</button>
|
||||
<button bindtap="handleStart" data-name="2">倒计数模式</button>
|
||||
<button bindtap="handleStart" data-name="3">倒计时模式</button>
|
||||
</view>
|
||||
<view class="weight">
|
||||
<view>{{Mode}}</view>
|
||||
<view>{{weight}}</view>
|
||||
<view>{{text}}</view>
|
||||
<view>{{kcal}}</view>
|
||||
</view>
|
||||
<view class="devices_summary">已发现 {{devices.length}} 个外围设备:</view>
|
||||
<scroll-view class="device_list" scroll-y scroll-with-animation>
|
||||
<view wx:for="{{devices}}" wx:key="index"
|
||||
data-device-id="{{item.deviceId}}"
|
||||
data-name="{{item.name || item.localName}}"
|
||||
data-mac="{{item.mac}}"
|
||||
data-index="{{index}}"
|
||||
class="device_item"
|
||||
bindtap="createBLEConnection"
|
||||
hover-class="device_item_hover">
|
||||
<view style="font-size: 32rpx;">
|
||||
<text style="color:#000;font-weight:bold">{{item.name}}</text>
|
||||
<text style="font-size:26rpx">(信号强度: {{item.RSSI}}dBm)</text>
|
||||
</view>
|
||||
<view style="font-size: 26rpx">mac地址: {{item.macAddr || item.deviceId}}</view>
|
||||
<!-- <view style="font-size: 26rpx">广播数据:{{item.analyzeDataText}}</view> -->
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
</view>
|
||||
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
{
|
||||
"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,
|
||||
"condition": false
|
||||
},
|
||||
"compileType": "miniprogram",
|
||||
"simulatorType": "wechat",
|
||||
"simulatorPluginLibVersion": {},
|
||||
"projectname": "bluetooth_demo_F01",
|
||||
"libVersion": "3.8.6",
|
||||
"appid": "wx39cf431caa22b5c8",
|
||||
"editorSetting": {
|
||||
"tabIndent": "insertSpaces",
|
||||
"tabSize": 2
|
||||
},
|
||||
"condition": {},
|
||||
"packOptions": {
|
||||
"ignore": [],
|
||||
"include": []
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html",
|
||||
"projectname": "bluetooth_demo_F01"
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
|
||||
"rules": [{
|
||||
"action": "allow",
|
||||
"page": "*"
|
||||
}]
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
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);
|
||||
}
|
||||
|
||||
//转16进制位数不足补0
|
||||
function toHex(num, length) {
|
||||
return num.toString(16).padStart(length, '0');
|
||||
}
|
||||
// 跳绳分秒时间选择
|
||||
function gethms(type) {
|
||||
var mindata = []
|
||||
var secondData = []
|
||||
let timeList = []
|
||||
for (var i = 0; i <= 59; i++) {
|
||||
i = i > 9 ? i : '0' + i
|
||||
mindata.push(i + '分');
|
||||
}
|
||||
for (var i = 0; i <= 59; i++) {
|
||||
i = i > 9 ? i : '0' + i
|
||||
secondData.push(i + '秒');
|
||||
}
|
||||
timeList[0] = mindata
|
||||
timeList[1] = secondData
|
||||
return timeList
|
||||
}
|
||||
module.exports = {
|
||||
inArray,
|
||||
ab2hex,
|
||||
toHex,
|
||||
gethms
|
||||
}
|
||||
Loading…
Reference in New Issue