蓝牙耳机丢了,我花几分钟写了一个小程序,找到了!​

2024-11-11 08:30   重庆  


点击关注公众号,“技术干货” 及时达!

前言

你是否曾经经历过蓝牙耳机不知道丢到哪里去的困扰?特别是忙碌的早晨,准备出门时才发现耳机不见了,整个心情都被影响。幸运的是,随着技术的进步,我们可以利用一些简单的小程序和蓝牙技术轻松找到丢失的耳机。今天,我要分享的是我如何通过一个自制的小程序,利用蓝牙发现功能,成功定位自己的耳机。这不仅是一次有趣的技术尝试,更是对日常生活中类似问题的一个智能化解决方案。

蓝牙耳机丢失的困扰

现代生活中,蓝牙耳机几乎是每个人的必备品。然而,耳机的体积小、颜色常常与周围环境融为一体,导致丢失的情况时有发生。传统的寻找方式依赖于我们对耳机放置地点的记忆,但往往不尽人意。这时候,如果耳机还保持在开机状态,我们就可以借助蓝牙技术进行定位。然而,市场上大部分设备并没有自带这类功能,而我们完全可以通过编写小程序实现。

蓝牙发现功能的原理

蓝牙发现功能是通过设备之间的信号传输进行连接和识别的。当一个蓝牙设备处于开机状态时,它会周期性地广播自己的信号,周围的蓝牙设备可以接收到这些信号并进行配对。这个过程的背后其实是信号的强度和距离的关系。当我们在手机或其他设备上扫描时,能够检测到耳机的存在,但并不能直接告诉我们耳机的具体位置。此时,我们可以通过信号强弱来推测耳机的大概位置。

实现步骤:从构想到实践

有了这个想法后,我决定动手实践。首先,我使用微信小程序作为开发平台,利用其内置的蓝牙接口实现设备扫描功能。具体步骤如下:

  • • 「环境搭建」:选择微信小程序作为平台主要因为其开发简便且自带蓝牙接口支持。
  • • 「蓝牙接口调用」:调用wx.openBluetoothAdapter初始化蓝牙模块,确保设备的蓝牙功能开启。
  • • 「设备扫描」:通过wx.startBluetoothDevicesDiscovery函数启动设备扫描,并使用wx.onBluetoothDeviceFound监听扫描结果。
  • • 「信号强度分析」:通过读取蓝牙信号强度(RSSI),结合多次扫描的数据变化,推测设备的距离,最终帮助定位耳机。

在代码的实现过程中,信号强度的变化尤为重要。根据RSSI值的波动,我们可以判断耳机是在靠近还是远离,并通过走动测试信号的变化,逐渐缩小搜索范围。

下面是我使用 Taro 实现的全部代码:

import React, { useState, useEffect } from "react";import Taro, { useReady } from "@tarojs/taro";import { View, Text } from "@tarojs/components";import { AtButton, AtIcon, AtProgress, AtList, AtListItem } from "taro-ui";import "./index.scss";
const BluetoothEarphoneFinder = () => {  const [isSearching, setIsSearching] = useState(false);  const [devices, setDevices] = useState([]);  const [nearestDevice, setNearestDevice] = useState(null);  const [isBluetoothAvailable, setIsBluetoothAvailable] = useState(false);  const [trackedDevice, setTrackedDevice] = useState(null);
  useEffect(() => {    if (isSearching) {      startSearch();    } else {      stopSearch();    }  }, [isSearching]);
  useEffect(() => {    if (devices.length > 0) {      const nearest = trackedDevice        ? devices.find((d) => d.deviceId === trackedDevice.deviceId)        : devices[0];      setNearestDevice(nearest || null);    } else {      setNearestDevice(null);    }  }, [devices, trackedDevice]);
  const startSearch = () => {    const startDiscovery = () => {      setIsBluetoothAvailable(true);      Taro.startBluetoothDevicesDiscovery({        success: () => {          Taro.onBluetoothDeviceFound((res) => {            const newDevices = res.devices.map((device) => ({              name: device.name || "未知设备",              deviceId: device.deviceId,              rssi: device.RSSI,            }));            setDevices((prevDevices) => {              const updatedDevices = [...prevDevices];              newDevices.forEach((newDevice) => {                const index = updatedDevices.findIndex(                  (d) => d.deviceId === newDevice.deviceId                );                if (index !== -1) {                  updatedDevices[index] = newDevice;                } else {                  updatedDevices.push(newDevice);                }              });              return updatedDevices.sort((a, b) => b.rssi - a.rssi);            });          });        },        fail: (error) => {          console.error("启动蓝牙设备搜索失败:", error);          Taro.showToast({            title: "搜索失败,请重试",            icon: "none",          });          setIsSearching(false);        },      });    };
    Taro.openBluetoothAdapter({      success: startDiscovery,      fail: (error) => {        if (error.errMsg.includes("already opened")) {          startDiscovery();        } else {          console.error("初始化蓝牙适配器失败:", error);          Taro.showToast({            title: "蓝牙初始化失败,请检查蓝牙是否开启",            icon: "none",          });          setIsSearching(false);          setIsBluetoothAvailable(false);        }      },    });  };
  const stopSearch = () => {    if (isBluetoothAvailable) {      Taro.stopBluetoothDevicesDiscovery({        complete: () => {          Taro.closeBluetoothAdapter({            complete: () => {              setIsBluetoothAvailable(false);            },          });        },      });    }  };
  const getSignalStrength = (rssi) => {    if (rssi >= -50) return 100;    if (rssi <= -100) return 0;    return Math.round(((rssi + 100) / 50) * 100);  };
  const getDirectionGuide = (rssi) => {    if (rssi >= -50) return "非常接近!你已经找到了!";    if (rssi >= -70) return "很近了,继续朝这个方向移动!";    if (rssi >= -90) return "正确方向,但还需要继续寻找。";    return "信号较弱,尝试改变方向。";  };
  const handleDeviceSelect = (device) => {    setTrackedDevice(device);    Taro.showToast({      title: `正在跟踪: ${device.name}`,      icon: "success",      duration: 2000,    });  };
  return (    <View className="bluetooth-finder">      {isSearching && (        <View className="loading-indicator">          <AtIcon value="loading-3" size="30" color="#6190E8" />          <Text className="loading-text">搜索中...</Text>        </View>      )}      {nearestDevice && (        <View className="nearest-device">          <Text className="device-name">{nearestDevice.name}</Text>          <AtProgress            percent={getSignalStrength(nearestDevice.rssi)}            status="progress"            isHidePercent          />          <Text className="direction-guide">            {getDirectionGuide(nearestDevice.rssi)}          </Text>        </View>      )}      <View className="device-list">        <AtList>          {devices.map((device) => (            <AtListItem              key={device.deviceId}              title={device.name}              note={`${device.rssi} dBm`}              extraText={                trackedDevice && trackedDevice.deviceId === device.deviceId                  ? "跟踪中"                  : ""              }              arrow="right"              onClick={() => handleDeviceSelect(device)}            />          ))}        </AtList>      </View>      <View className="action-button">        <AtButton          type="primary"          circle          onClick={() => setIsSearching(!isSearching)}        >          {isSearching ? "停止搜索" : "开始搜索"}        </AtButton>      </View>    </View>  );};
export default BluetoothEarphoneFinder;

嘿嘿,功夫不负苦心人,我最终通过自己的小程序找到了我的蓝牙耳机。

实际应用与优化空间

这个小程序的实际效果超出了我的预期。我能够通过它快速找到丢失的耳机,整个过程不到几分钟时间。然而,值得注意的是,由于蓝牙信号会受到环境干扰,例如墙体、金属物等,导致信号强度并不总是精确。在后续的优化中,我计划加入更多的信号处理算法,例如利用三角定位技术,结合多个信号源来提高定位精度。此外,还可以考虑在小程序中加入可视化的信号强度图,帮助用户更直观地了解耳机的大致方位。

一些思考

蓝牙耳机定位这个小程序的开发,展示了技术在日常生活中的强大应用潜力。虽然这个项目看似简单,但背后的原理和实现过程非常具有教育意义。通过这次尝试,我们可以看到,借助开源技术和简单的编程能力,我们能够解决许多日常生活中的实际问题。

参考资料:

  1. 微信小程序官方文档:https://developers.weixin.qq.com


  2. 蓝牙信号强度(RSSI)与距离关系的研究:https://www.bluetooth.com


  3. 个人开发者经验分享: 利用蓝牙发现功能定位设备

点击关注公众号,“技术干货” 及时达!

稀土掘金技术社区
掘金,一个帮助开发者成长的技术社区
 最新文章