由于同步执行ble.scan,基于设备名称的Cordova BLE Con​​nect自动(无需用户操作)失败

时间:2018-06-09 17:45:49

标签: 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。

知道怎么解决这个问题吗? THX!

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

1 个答案:

答案 0 :(得分:1)

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

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);
},

还有一个新的autoConnect功能,只要手机在设备范围内,它就会自动连接和断开连接。 (这在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);
},

有关index.js

的完整版本,请参阅https://gist.github.com/don/e423ed19f16e1367b96d04ecf51533cc