javascript - 由于异步执行 ble.scan,基于设备名称的 Cordova BLE 自动连接(无需用户操作)失败

标签 javascript cordova

我正在使用 cordova 和 BLE 插件开发一个应用程序。我想通过 BLE 根据硬编码的已知 device.name 自动连接到 ESP32,而无需用户按下连接按钮。

我的想法是:

在设备准备就绪时运行扫描:

scanForDevices: function(){ 
    ble.scan([], 10, app.onDiscoverDevice, app.onError); 
    app.getDevIdFromList(); 
},

用发现的所有设备构建一个数组:

  onDiscoverDevice: function(device) { 
     deviceList[deviceNr] = [device.name, device.id, device.rssi]; 
     deviceNr = deviceNr + 1 ; 
  },

当 ble.scan 函数完成时,运行 app.getDevIdFromList() 来检查我的设备名称是否在列表中,如果是则开始连接:

getDevIdFromList: function(){ 
   for (var i = 0; i < deviceList.length; i++) 
       { if (deviceList[i][0]== "myDeviceName")
          { myDeviceDetected = "true"; 
            myDeviceId = deviceList[i][1]; 
            app.connect(); 
          } 
       } 
       if (myDeviceDetected == "false"){
           app.onBtDetectionError(); 
       } },

问题似乎是在 ble.scan 完成之前调用 getDevIdFromList (运行异步?),导致 getDevIdFromList 处理不完整甚至空数组,即使我的设备可用,也会抛出 onBtDetectionError 。

知道如何解决这个问题吗? 谢谢!

(另请参阅我在 BLE 插件 github #597 上提出的问题,但正如所有者指出的那样,这更多是堆栈溢出的问题)

最佳答案

由于扫描是异步的,因此逻辑变得更加复杂。一种方法是等待扫描完成,然后检查结果。

connectByName: function(name) {

    const devices = [];

    // scan and save devices to a list
    ble.startScan([], d => devices.push(d));

    // check the list when the scan stop
    setTimeout(() => {
        ble.stopScan();

        const device = devices.filter(d => d.name === name)[0];
        if (device) {
            ble.connect(device.id, app.onConnected, app.onDisconnected);
        } else {
            console.log(`Couldn't find device ${name}`);
        }
    }, 5000);
},

这工作正常,但您始终需要等待扫描完成。即使扫描立即找到设备,也需要等待超时。另一种方法是在扫描时过滤设备。

connectByName: function(name) {

    let scanning = true;

    ble.startScan([], device => {
        if (device.name === name) {
            ble.stopScan();
            scanning = false;
            ble.connect(device.id, app.onConnected, app.onDisconnected);
        } else {
            console.log(`Skipping ${device.name} ${device.id}`);
        }
    });

    // set timer to stop the scan after a while
    setTimeout(() => {
        if (scanning) {
            ble.stopScan(); 
            console.log(`Couldn't find device ${name}`);
        }
    }, 5000);
},

第二种方法通常更好,因为它可以更快地连接。

如果您仅在 Android 上运行,并且您有设备的 MAC 地址,则无需扫描即可连接。 (iOS 仍然需要您扫描。)

onDeviceReady: function() {
    // connect by MAC address on startup
    const MAC_ADDRESS = 'E4:86:1E:4E:5A:FB';
    ble.connect(MAC_ADDRESS, app.onConnected, app.onDisconnected);
},

还有一个新的自动连接功能,只要手机在设备的范围内,就会自动连接和断开连接。 (这在 iOS 上还不能很好地工作。)

onDeviceReady: function() {
    // Auto connect whenever the device is in range
    const MAC_ADDRESS = 'E4:86:1E:4E:5A:FB';
    ble.autoConnect(MAC_ADDRESS, app.onConnected, app.onDisconnected);
},

参见https://gist.github.com/don/e423ed19f16e1367b96d04ecf51533cc完整版本的index.js

关于javascript - 由于异步执行 ble.scan,基于设备名称的 Cordova BLE 自动连接(无需用户操作)失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50776972/

相关文章:

javascript - Eloquent Javascript 第 6 章中的示例 6.3 有必要这么复杂吗?

ios - 在 iOS 10 Cordova/Phonegap 应用程序中禁用捏合缩放

javascript - 加载 url 时隐藏 UL

javascript - 确定焦点事件 : click or tabstop

android - 如何在 ionic 中关闭应用程序时使设备 token 不注销

javascript - 在 Cordova 触发 deviceready 之前初始化应用程序

node.js - Windows 上的 Cordova inAppBrowser 插件问题

ios - ionic : Managing Multiple iOS Builds

javascript - 将 blob 作为分段上传会导致 500mb 后在 Chrome 上出现 net::ERR_FILE_NOT_FOUND

javascript - jquery 插件中的 .on ("click.stupidtable") 是什么?