This commit is contained in:
qiaocl 2024-01-05 13:59:49 +08:00
parent 37a3190746
commit 2191f48734
13 changed files with 531 additions and 0 deletions

BIN
bluetooth_demo_J01.zip Normal file

Binary file not shown.

View File

@ -0,0 +1,8 @@
# #参考使用设备类型
```
F01PRO
```
##

View File

@ -0,0 +1,5 @@
//app.js
App({
onLaunch: function () {
}
})

View File

@ -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"
}

View File

@ -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;
}

View File

@ -0,0 +1,304 @@
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
function PrefixZero(num, n) {
return (Array(n).join(0) + num).slice(-n);
}
wx.hideLoading()
wx.getBLEDeviceCharacteristics({
deviceId,
serviceId,
success: (res) => {
console.log('getBLEDeviceCharacteristics success', res.characteristics)
// 初始化插件
plugin.initPlugin(res.characteristics, that._device)
wx.onBLECharacteristicValueChange((characteristic) => {
let bleData = plugin.parseBleData(characteristic.value)
let dw1 = "kg"
if (bleData.status == 0) {
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 == "30" || type == "40") { //体脂模式
let data = parseInt(payload.substring(6, 12), 16)
let msg = parseInt(payload.substring(12, 14), 16).toString(2)
let dw = PrefixZero(msg, 8).substring(4, 8)
let num = PrefixZero(msg, 8).substring(0, 4)
if (dw == "0001") {
dw1 = '斤'
}
if (dw == "0110") {
dw1 = 'lb'
}
if (num == "0001") {
data = data / 10
}
if (num == "0010") {
data = data / 100
}
if (num == "0011") {
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)
let numH = parseInt(payload.substring(10, 12), 16)
if (numH == "1") {
height = height / 10
}
if (numH == "2") {
height = height / 100
}
that.setData({
height: "身高是:" + height
})
}
if (type == "11") { //阻抗模式
if (typeInfo == "03" || typeInfo == "04") {
let imp = parseInt(payload.substring(8, 16), 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: ""
})
},
});

View File

@ -0,0 +1,4 @@
{
"usingComponents": {
}
}

View File

@ -0,0 +1,37 @@
<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>{{weight}}</view>
<view>{{height}}</view>
<view>{{imp}}</view>
<view>{{text}}</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>

View File

@ -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": []
}
}

View File

@ -0,0 +1,4 @@
{
"description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html",
"projectname": "bluetooth_demo_F01"
}

View File

@ -0,0 +1,7 @@
{
"desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
"rules": [{
"action": "allow",
"page": "*"
}]
}

View File

@ -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,
}

BIN
bluetooth_demo_L11.zip Normal file

Binary file not shown.