保姆级教程:用UniApp+微信小程序连接蓝牙体重秤(实战项目,含源码)
·
从零构建UniApp蓝牙体重秤小程序:硬件交互与数据解析实战
在智能健康设备普及的今天,蓝牙体重秤已成为家庭健康管理的重要工具。本文将带您深入探索如何基于UniApp框架,开发一个能够与AA系列蓝牙体重秤深度交互的微信小程序。不同于简单的蓝牙连接教程,我们将重点解析硬件协议对接、实时数据流处理以及商业级错误处理机制,提供可直接用于生产环境的代码方案。
1. 开发环境准备与蓝牙基础
1.1 UniApp蓝牙开发环境配置
开发蓝牙相关功能前,需要确保开发环境正确配置。在 manifest.json 中声明蓝牙权限:
{
"mp-weixin": {
"appid": "您的APPID",
"requiredBackgroundModes": ["bluetooth"],
"permission": {
"scope.bluetooth": {
"desc": "需要您的授权才能连接蓝牙设备"
}
}
}
}
关键依赖检查清单:
- UniApp CLI版本≥2.0
- 微信开发者工具最新版
- 真机调试用的Android/iOS设备
- 硬件厂商提供的协议文档(FE60服务UUID)
提示:开发阶段建议关闭微信小程序的域名校验,在"详情->本地设置"中勾选"不校验合法域名"选项。
1.2 蓝牙协议栈核心概念
理解蓝牙协议栈是开发的基础,特别是GATT层的关键组件:
| 组件类型 | 作用描述 | 体重秤应用示例 |
|---|---|---|
| Service | 设备功能集合 | FE60(厂商自定义服务) |
| Characteristic | 服务下的具体数据点 | 体重数据特征值 |
| Property | 特征值属性(read/write/notify等) | notify用于接收实时体重数据 |
蓝牙通信的基本流程可简化为:
- 扫描并过滤目标设备
- 建立GATT连接
- 发现服务与特征值
- 启用特征值通知
- 处理数据流
2. 设备发现与连接管理
2.1 智能设备扫描策略
针对AA系列体重秤的优化扫描方案:
// 设备过滤函数
function filterDevice(devices) {
return devices.filter(device => {
const name = device.name || device.localName || '';
return name.startsWith('AA') &&
!this.connectedDevices.has(device.deviceId);
});
}
// 带缓冲区的设备发现
let discoveryTimer;
function startDiscovery() {
this.devices = [];
uni.startBluetoothDevicesDiscovery({
allowDuplicatesKey: false,
success: () => {
discoveryTimer = setInterval(() => {
uni.getBluetoothDevices({
success: (res) => {
this.devices = filterDevice(res.devices);
}
});
}, 1500); // 1.5秒采集周期
}
});
}
性能优化要点 :
- 设置
allowDuplicatesKey:false避免重复设备 - 使用
deviceId作为设备唯一标识 - 添加连接状态检查防止重复连接
2.2 稳定连接建立机制
建立连接时需要处理多种异常情况:
async function connectDevice(deviceId) {
try {
await this.checkBluetoothState();
const connection = await new Promise((resolve, reject) => {
uni.createBLEConnection({
deviceId,
timeout: 8000, // 8秒超时
success: resolve,
fail: reject
});
});
this.registerDisconnectHandler(deviceId);
return this.discoverServices(deviceId);
} catch (error) {
console.error('Connection failed:', error);
this.handleConnectionError(error);
throw error;
}
}
常见连接问题处理方案:
- 10012超时错误 :增加重试机制,最多3次
- 10004适配器异常 :引导用户重新开启蓝牙
- 10009设备已连接 :先断开旧连接再重试
3. 数据通信与协议解析
3.1 体重数据特征值交互
根据FE60服务协议,实现数据收发:
// 启用通知
function enableNotification(deviceId, serviceId, characteristicId) {
uni.notifyBLECharacteristicValueChange({
deviceId,
serviceId,
characteristicId,
state: true,
type: 'notification',
success: () => {
this.monitorDataStream();
}
});
}
// 数据流监控
function monitorDataStream() {
uni.onBLECharacteristicValueChange(res => {
const rawData = this.ab2hex(res.value);
const weight = this.parseWeightData(rawData);
this.updateDashboard(weight);
});
}
3.2 二进制数据解析方案
AA体重秤的典型数据格式示例:
AA 01 62 00 07 D2 00 00 00 00 00 00 BB
- AA: 帧头
- 01: 数据长度
- 62: 数据类型(体重)
- 07D2: 实际数据(200.2kg)
- BB: 帧尾
解析函数实现:
function parseWeightData(hexStr) {
if (!hexStr || hexStr.length < 12) return null;
const parts = hexStr.match(/.{2}/g);
if (parts[0] !== 'aa' || parts[parts.length-1] !== 'bb') {
throw new Error('Invalid data format');
}
const valueHex = parts[3] + parts[4]; // 大端序
const value = parseInt(valueHex, 16) / 10;
return {
value,
unit: 'kg',
timestamp: Date.now()
};
}
注意:不同厂商协议可能使用小端序(LSB),需根据文档确认字节顺序
4. 用户界面与体验优化
4.1 设备连接状态管理
实现可视化连接状态指示:
<template>
<view class="device-status">
<view v-if="connecting" class="connecting">
<text>连接中...</text>
<progress percent="80" show-info />
</view>
<view v-else-if="connected" class="connected">
<text>已连接: {{ deviceName }}</text>
<view class="signal" :style="signalStyle"></view>
</view>
<view v-else class="disconnected">
<text>未连接设备</text>
</view>
</view>
</template>
<script>
export default {
computed: {
signalStyle() {
return {
width: `${this.rssi + 100}%`,
backgroundColor: this.getSignalColor(this.rssi)
};
}
}
}
</script>
4.2 实时数据可视化
使用ECharts实现体重趋势图:
function initChart() {
this.chart = echarts.init(this.$refs.chart);
this.chart.setOption({
xAxis: {
type: 'time'
},
yAxis: {
name: '体重(kg)'
},
series: [{
type: 'line',
smooth: true,
data: this.weightHistory
}]
});
}
function updateChart(newData) {
this.weightHistory.push([
newData.timestamp,
newData.value
]);
// 保持最近30条记录
if (this.weightHistory.length > 30) {
this.weightHistory.shift();
}
this.chart.setOption({
series: [{
data: this.weightHistory
}]
});
}
5. 生产环境进阶技巧
5.1 蓝牙通信稳定性优化
提升连接稳定性的关键措施:
-
心跳检测机制 :
setInterval(() => { if (this.lastDataTime && Date.now() - this.lastDataTime > 15000) { this.reconnect(); } }, 10000); -
数据校验增强 :
function validateData(data) { const crc = calculateCRC(data.slice(2, -2)); return crc === data[data.length-2]; } -
自动重连策略 :
async function reconnect() { if (this.reconnectAttempts >= 3) return; this.reconnectAttempts++; await this.disconnect(); await new Promise(resolve => setTimeout(resolve, 1000)); return this.connectDevice(this.lastDeviceId); }
5.2 多设备管理方案
支持同时管理多个体重秤设备:
class DeviceManager {
constructor() {
this.devices = new Map();
}
addDevice(device) {
this.devices.set(device.id, {
...device,
connection: null,
data: []
});
}
getDevice(id) {
return this.devices.get(id);
}
removeDevice(id) {
const device = this.devices.get(id);
if (device && device.connection) {
device.connection.close();
}
this.devices.delete(id);
}
}
在实际项目中,发现AA系列体重秤在iOS设备上需要额外添加 writeType: 'writeNoResponse' 参数才能稳定通信,这是经过多次真机测试后得出的经验。建议开发者针对不同平台进行差异化配置,可以使用 uni.getSystemInfoSync().platform 获取当前运行平台。
更多推荐


所有评论(0)