NRF.setScan() stops working

Posted on
  • Hi. I am having a problem when calling a function inside NRF.setScan():

    NRF.setScan(function(d) {
        if (d.id === "xxxx") { 
              //do some stuff here
              setState([0xCC, 0x24, 0x33]); }
    }
    

    When I call setState(), it doesn't return to NRF.setScan:

    function setState(arg) {
        var gatt;  
        NRF.connect(addr).then(function(g) {
          gatt = g;
          return gatt.getPrimaryService("0000ffe5-0000-10­00-8000-00805f9b34fb");
        }).then(function(service) {
          return service.getCharacteristic("0000ffe9-0000­-1000-8000-00805f9b34fb");
        }).then(function(c) {
          characteristic = c;
          return characteristic.writeValue(arg);
        }).then(function() {
          gatt.disconnect();
        });
      }
    

    Any idea why? Other functions return properly, something to do with NRF.connect maybe?

  • I'm not sure what you mean by 'return to setScan'?

    What you're doing seems like it'll cause big problems though. setScan's callback can get called really often - probably several times a second for every device - so that'd mean that setState could get called really often, which would probably cause issues as each NRF.connect will take a few seconds to complete

  • I mean that after setState() is called, NRF.setScan will stop scanning. Actually I check

    d.manufacturerData[0]
    

    so setState() is not called if there is no change in there, and since I change it manually, I do after some seconds, so don't think that's the problem. If for example I put these:

    function setState() {
    print("working");
    }
    

    then it works, scanning will continue normally. Sorry if what I'm saying doesn't make sense, I can post all the code if needed. Thanks.

  • Thanks - I get what you mean. I just tried this and I get the same issues.

    It looks like a bug in Espruino to me. The act of connecting does require scanning, and it looks like the Bluetooth stack just shuts down scanning afterwards rather than leaving it going.

    I'll file an issue for it, but all I can suggest for now is to cancel scanning and the restart it when you're done connecting:

    NRF.setScan(function scanFn(d) {
        if (d.id === "xxxx") { 
              //do some stuff here
              NRF.setScan();
              setState([0xCC, 0x24, 0x33], function() { NRF.setScan(scanFn); }); }
    }
    
    function setState(arg, callback) {
        var gatt;  
        NRF.connect(addr).then(function(g) {
          gatt = g;
          return gatt.getPrimaryService("0000ffe5-0000-10­00-8000-00805f9b34fb");
        }).then(function(service) {
          return service.getCharacteristic("0000ffe9-0000­-1000-8000-00805f9b34fb");
        }).then(function(c) {
          characteristic = c;
          return characteristic.writeValue(arg);
        }).then(function() {
          gatt.disconnect();
          callback();
        }); // probably also want a .catch in here to catch errors and also call 'callback()'
      }
    
  • Thanks Gordon, that works. The only problem I still get with scanning is that the Puck that does it will get unresponsive after a while, not totally, I still can connect to it, but if I write commands in the console of the ide, they are laggish, and most of the time uploading code with get stuck somewhere in the middle, I have to take out the battery. Doing

    reset()
    NRF.setScan()
    

    on the console doesn't fix the problem. Any idea what's wrong? Would setInterval with NRF.findDevices be a better approach to periodically scanning and get data (number) from another Puck?

  • Ahh, yes - that's probably due to a large number of advertisements coming in - more than can be handled by your code at one time. That will often end up causing a FIFO_FULL error message as well.

    I'm very surprised that just calling NRF.setScan() doesn't stop scanning and return things to normal though.

    Are you just trying to connect to a single device with a known ID? If so, why not just call NRF.connect(addr) every so often? If the device isn't there then it'll just error.

    or, you could use NRF.requestDevice, which will do the scanning and checking for you automatically. While in 1v99 it's not much different to findDevices, in the latest versions of the firmware it's much faster and more efficient.

  • I am trying to do something that should be easy, but can't make it work consistently as I intend. I just need to advertise a state (simple numbers 0-10) from one Puck and scan it with the other Puck (using advertising and scanning, without connections). I need to read this state every second or so. What I do now is something like thiss

    NRF.setAdvertising({},{interval:100, manufacturer: 0x0590, manufacturerData:[state]});
    

    on one Puck (call this same line multiple time in different places and time depending on the value of state, not too quick though, manually every 5 seconds or so, is that ok?) and

    NRF.setScan(function scanFn(d) {
        if (d.id !== "xx:xx:xx:xx:xx:xx random") {
          return;
        }
          if (d.manufacturerData) {
            var temp = d.manufacturerData[0];
            print("state = " + temp);
           // do stuff accordingly to state value
    

    The problem is that it can takes a long time (like 3-5 seconds) for scan to pick up the changes and things will hung up sometimes, although that can be my codes fault.

    Can NRF.requestDevice read advertising data (the state) from the other Puck? I am using the latest travis firmware btw (24 august I think).

  • call this .... manually every 5 seconds or so, is that ok?

    Yes, that should be totally fine.

    The problem is that it can takes a long time (like 3-5 seconds) for scan to pick up the changes

    Do you know roughly how often you're getting BLE advertisements from setScan? I think it's quite likely you're in a reasonably congested area and there are so many devices it's having trouble processing fast enough

    Can NRF.requestDevice read advertising data (the state) from the other Puck?

    Yes - you'll get the exact same response you would from setScan.

    For instance if you do this it should be really nice and easy:

    NRF.requestDevice({filters:[{name:"Pixl.­js 8999"}]}).then(function(dev) {
      if (dev.manufacturerData)
        print("State is "+dev.manufacturerData[0]);
    })
    

    It's a shame you can't filter by id at the moment though - only name/services

  • Ok, if you put a cutting edge firmware on there, you can now do:

    NRF.requestDevice({filters:[{id:"xx:xx:x­x:xx:xx:xx random"}]}).then(function(dev) {
      if (dev.manufacturerData)
        print("State is "+dev.manufacturerData[0]);
    })
    

    or:

    NRF.requestDevice({filters:[{manufacture­rData:{0x0590:{}}}]}).then(function(dev)­ {
        print("State is "+dev.manufacturerData[0]);
    })
    

    or even the following, which will use setScan, but with filters to quickly filter out anything you're not interested in:

    NRF.setScan(function(dev) {
        print("State is "+dev.manufacturerData[0]);
    }, {filters:[{manufacturerData:{0x0590:{}}}­]});
    
  • That looks exactly what I need, thanks a lot Gordon, will try cutting edge as soon as I can :)

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

NRF.setScan() stops working

Posted by Avatar for user93564 @user93564

Actions