You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

点击按钮替换数组旧值为新值的BLE Web应用开发问题

解决方案

要解决多次扫描导致数组持续变长的问题,需从重置数组、避免重复事件监听器、按固定索引更新数据三个维度修改代码:

1. 每次扫描前重置全局数组

由于devices、ids、distances是全局常量数组,无法直接重新赋值,可通过length = 0清空数组内容,确保每次扫描从空状态开始收集数据。

2. 移除重复的事件监听器

每次调用scan()会新增advertisementreceived监听器,多次点击会导致多个监听器同时工作。需保存监听器引用,在扫描结束或出错时移除。

3. 按固定索引更新设备数据

利用beaconMapping中定义的设备索引,直接替换数组对应位置的元素,而非使用push()追加,确保数组长度始终固定为3。

修改后的完整代码

import * as trilateration from './trilateration.js';
import context from './context.js';

const beaconMapping = {
  'ESP32_1': 0,
  'ESP32_2': 1,
  'ESP32_3': 2,
}

const DISTANCE_SCALAR = 1;

console.log("Init");
const devices = [];
const ids = [];
const beaconuuid = [];
const distances = [];
let advertisementListener; // 保存事件监听器引用

const SCAN_TIME = 10000;

// 添加基站到三边定位系统
trilateration.addBeacon(0, trilateration.vector(10.1, 7.0));
trilateration.addBeacon(1, trilateration.vector(0, 0));
trilateration.addBeacon(2, trilateration.vector(10.1, 0));

document.getElementById("scan").onclick = scan;

async function scan() {
  console.log("Scanning...");
  // 重置全局数组,清空上次扫描数据
  devices.length = 0;
  ids.length = 0;
  distances.length = 0;

  let options = {
    acceptAllAdvertisements: true,
    acceptAllDevices: true,
  };

  try {
    log("Requesting Bluetooth Scan with options: " + JSON.stringify(options));
    const scan = await navigator.bluetooth.requestLEScan(options);

    log("Scan started with:");
    log(" acceptAllAdvertisements: " + scan.acceptAllAdvertisements);
    log(" active: " + scan.active);
    log(" keepRepeatedDevices: " + scan.keepRepeatedDevices);
    log(" filters: " + JSON.stringify(scan.filters));

    // 定义事件监听器并保存引用
    advertisementListener = (event) => {
      let name = event.device.name;
      if (name && name.startsWith("ESP32")) {
        console.log("Found");
        const obj = {
          device: event.device,
          uuids: event.uuids,
          rssi: event.rssi,
          tx: event.txPower,
          distance: calculateDistance(event.rssi, event.txPower) * DISTANCE_SCALAR,
        };
        console.log(obj);
        console.log(obj.tx, obj.rssi, obj.distance, name);

        const beaconIndex = beaconMapping[event.device.name];
        if (beaconIndex !== undefined) {
          // 按固定索引替换数据,而非push追加
          devices[beaconIndex] = obj;
          ids[beaconIndex] = event.device.id;
          distances[beaconIndex] = obj.distance;
          trilateration.setDistance(beaconIndex, obj.distance);
        } else {
          console.error("Name not found in mapping");
        }

        // 确保三个设备的数据都有效时再计算位置
        if (distances.every(d => d !== undefined)) {
          var pos = trilateration.calculatePosition();
          console.log(pos);
          console.log("Distances are length", distances.length)
          console.log("X: " + pos.x + "; Y: " + pos.y);
          context.fillRect(pos.x * 100, pos.y * 100, 20, 20);
        }

        showBeaconInfo(obj);
      }
    };

    navigator.bluetooth.addEventListener("advertisementreceived", advertisementListener);

    setTimeout(stopScan, SCAN_TIME);

    function stopScan() {
      console.log("List of all devices detected:");
      console.log(devices);
      console.log(ids)
      console.log(beaconuuid);
      console.log(distances)
      log("Stopping scan...");
      // 移除事件监听器,避免重复监听
      navigator.bluetooth.removeEventListener("advertisementreceived", advertisementListener);
      scan.stop();
      log("Stopped.  scan.active = " + scan.active);
    }
  } catch (error) {
    log("Argh! " + error);
    // 出错时也要移除监听器,防止内存泄漏
    if (advertisementListener) {
      navigator.bluetooth.removeEventListener("advertisementreceived", advertisementListener);
    }
  }
}

关键修改说明

  • 数组重置:在scan()开头通过length = 0清空数组,保证每次扫描的初始状态干净。
  • 事件监听器管理:用变量保存监听器引用,扫描结束或出错时移除,避免多次点击导致多监听器同时触发。
  • 固定索引更新:通过beaconMapping获取的索引直接替换数组对应位置元素,确保数组长度始终为3,对应三个ESP设备。
  • 位置计算条件优化:将distances.length > 2改为distances.every(d => d !== undefined),避免部分设备未扫描到时的错误计算。

内容的提问来源于stack exchange,提问作者Milan Langhendries

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 10:10:31