Search code examples
meteorbluetooth-lowenergycordova-plugins

How do I use Meteor and a Cordova BLE plugin to connect to a BLE device


I'm trying to use Meteor and this Cordova plugin -https://github.com/don/cordova-plugin-ble-central - added to my project using meteor add cordova in order to connect to a Bluetooth LE device (TI Sensortag). All I want to do to begin with is, when a link is clicked, to connect to the device and show a message.

I have the following code in the events section of my template javascript.

Template.measure.events({'click [data-action=scan-connect-stream]':
  function(event, template) {
    event.preventDefault();
    if (Meteor.isCordova) {
      Meteor.startup(function () {
          ble.connect('24:09:00:DE:00:42', 
                function(){
                    alert('Connect success');
                    return;
                }, 
                function(){
                    alert('Connect failed');
                    return;
                });
            });
        }
    }
});

My problem is that sometimes the code works and I get a 'Connect success' alert but more often than not it it fails to connect and shows the 'Connect failed' alert. Before I added the return statements in the success and fail callbacks it didn't work at all.

I'm debugging this on an android device (meteor run android-device --verbose) and can see via adb logcat that the BLE Connect event in the Cordova plugin is firing but then doesn't connect. I get the same issue debugging on two different phones and when using a BLE device that isn't a TI Sensortag so I'm guessing this is an problem with the way the plugin is interacting with Meteor (maybe Meteor isn't waiting long enough for a success callback?).

Has anyone used this plugin successfully with Meteor or can anyone provide any clue as to what I'm doing wrong? Should I try wrapping it in a Meteor package or is there any way I can give the plugin more time to respond before the success or fail callbacks fire? Any help would be much appreciated!


Solution

  • For anyone who's having similar issues this is what sorted it for me. I put the ble.connect call into the success callback of the ble.scan function. Not sure why but scanning for a few seconds first does the job.

      Template.measure.events({
        'click [data-action=scan-connect-stream]': function(event, template) {
          event.preventDefault();
          if (Meteor.isCordova) {
            Meteor.startup(function () {
              device_id = '24:09:00:DE:00:42';
              ble.scan([], 5,
                  function(peripherals){
                    connectDevice(device_id);
                  },
                  function(){
                     alert('No devices found');
                  }
                );
            });
          }
        }
      });
    
    
      var connectDevice = function (device_id) {
            ble.connect(device_id,
                            function(){
                              alert('Device ' + device_id + ' connnected');
                              },
                            function(){
                              alert('Couldn\'t connect to device ' + device_id);
                              });
      }
    

    If anyone can explain why the ble.connect won't work on its own that'd be great!

    EDIT: Looking at the Android code it seems that the plugin is designed in such a way that ble.scan has to be called before calling ble.connect. The ble.scan causes a LinkedHashMap in the Android code to be populated with any discovered devices. Only once the device is listed in the LinkedHashMap can you then connect to it using ble.connect.