Puck button integration with android device.

Posted on
  • Hi support, My puck button is just delivered to me. I want to pair it with my Android mobile device and perform a simple task of calling a number when I press the button. Can you please guide/point me to where/how to start?

  • I think something similar has been asked and I think emulating a keyboard was the advice offered. There's a tutorial on that here:

    http://www.espruino.com/Puck.js

  • As @Ollie says, keyboard emulation is probably the best bet - unless you are writing an app.

    See the answers from when this was asked before

  • Thanks Ollie/Gordan,

    Sorry for being bit unclear in my query. I think I'm looking to build an app. Let me clarify bit more if it helps.

    I need this button to work as below: Someone who is visually impaired wants to call an emergency number[say a family member] from his Android phone. Instead of dialling number/searching in phone book, he could just do a single click to call number a, double click call number b from such button which is paired with his phone.

    Your guidance on this will be appreciated.
    Regards,

  • I think an app is the safest solution then. What I'd suggest is:

    • Write an app that listens for BLE advertising events - when it sees the one from the Puck.js address it's set up to work with, it'd look at the advertising data and see what was in the data. Depending on that it'd make a call or do something else
    • You could also send battery status if needed, and the phone app could also show an alert if it hadn't got advertising packets in a while (eg, Puck.js had gone out of range)
    • On the Puck, use NRF.setAdvertising({ 0x1234 : [buttonNumber, buttonPresses] }) when the button is pressed in the way you want (which you use setWatch for)

    Advertising is just something that's broadcast - you're not guaranteed to receive it on the phone - so I'd suggest using a 'buttonPresses' variable that just increments. On the phone, if that's different from the last time you got an advertising packet you know that the button has been pressed between times.

    It beats using something that's set to 1 and then returns to 0, since you could potentially miss all the advertising packets sent while it was 1.

  • Thanks Gordon.

    I agree about app being the solution. I tried your suggestion but nothing seem to work right now for me. I started by trying very simple implementation i.e. send temperature on each click.

    I put following code in Puck:

    setWatch(function(e)
    {
    NRF.setAdvertising({

    0x1809 : [0|E.getTemperature()]
    

    });
    }, BTN, {repeat:true,edge:"rising",debounce:50});

    Now, android side I tried to get this advertised data when Puck button is pressed but there is nothing there. Can you please point me to a sample/link on Android side which can do this? Also if anything done wrong here.

    Regards,

  • Did you disconnect the Web IDE from the Puck first?

    Bluetooth LE devices don't advertise while something is connecting to them.

  • Yes, I disconnected it with Web IDE, then paired it with android device, and then ran the Android App.

    I doubt its the Android code, I could scan the device but do not have the listener method for advertising data I guess. Any pointer regarding this?

    Regards

  • Yes, I disconnected it with Web IDE, then paired it with android device, and then ran the Android App.

    To receive advertising data you don't need to pair.

    In fact, pairing usually creates a connection, which then stops the device from advertising.

    That could be your issue? First, I'd try making sure you can receive the advertising data using nRF connect - then you can see if the problem is Puck.js or your app.

  • Hi Gordon, 

    Thanks, for the reply. I have found the solution to receive advertising data without pairing puck button with android device but I am not sure if I'll need to run a background thread to keep looking for this advertisement OR is there a way to listen to this?

    One more thing, how ca I decode the data currently I am receiving to make sure that the data is sent from my button?

    Regards

  • I'm not entirely sure about how it works on Android I'm afraid - maybe you could ask on stackoverflow or similar.

    Looks like it's already been asked: http://stackoverflow.com/questions/19914244/creating-background-services-for-bluetooth-low-energy-on-android

    It's worth googling - there seem to be a bunch of other posts about it too.

    I'm not quite sure what you mean about decoding the data? could you give an example?

  • I was getting some data on Android side which I assumed needed decoding.

    Since I'm now advertising using NRF.setAdvertising({

    1. I just want to understand now how it works, does setAdvertising
      advertises data just once?
    2. I think that when this data is advertised, it tags along with
      bluetooth info, i.e. when Android side code will get Puck bluetooth
      info, it will get access to this data too.

    So currently I do not have paired button and am accessing bluetooth info of Puck in Android code, I get some data in array but not sure how to interpret it.

    Regards,

  • does setAdvertising advertises data just once?

    No, it keeps advertising every 350ms (or however long you specified in NRF.setAdvertising) forever after.

    when Android side code will get Puck bluetooth info, it will get access to this data too.

    The Puck's name and the advertised data are sent in the same packet, so should arrive in Android together.

    I'm not 100% sure if they're exposed that way, but it seems like it.

    I get some data in array but not sure how to interpret it.

    This might help? http://stackoverflow.com/questions/22016224/ble-obtain-uuid-encoded-in-advertising-packet?answertab=active#tab-top

  • Hi Gordon,

    I have revisited this and think for my requirement I would want to work it after device is paired with phone, otherwise device will read advert from all buttons. While looking I came across NRF.setServices() which sends data only when device is paired. I hope it work like below [see Js code below for Puck]. I now hope I'll find code which will read this service data in android code. Can you suggest your views on this?

    var C = {
      set : "SET",
      update : "UPDATE",
      every_30_sec : 3000
    };
    var iCounter = 0;
    function publishTemp(cmd) {
      //digitalPulse(LED2, 1, 200);
      if (cmd == C.set) 
        NRF.setServices({
          0x1809 : { // Health Thermometer
            0x2A6E: { 
              readable: true,
              broadcast: true,
              value : iCounter
        }}});
      if (cmd == C.update)
        NRF.updateServices({
          0x1809 : { // Health Thermometer
            0x2A6E: {
              readable: true,
              broadcast: true,
              value : iCounter
        }}});
    }

    setWatch(function(e)
      {
        iCounter++;
      print(iCounter);
      }, BTN, {repeat:true,edge:"rising",debounce:50});

    // first time
    publishTemp(C.set);
    // every 30 sec
    setInterval(publishTemp,C.every_30_sec,C.update);

    Regards

  • On Android, why not just do something like:

    // not real code - just to give you an idea
    function onAdvertisingData(data) {
      if (data.address == known_device_address)
       doThingsWithData();
    }
    

    The code you have posted above will work, but maintaining a connection will drain the Puck's batteries at 10x the normal rate (you can use NRF.setLowPowerConnection() to fix that, but then it slows down the connection).

    In addition, Android phones can only maintain 7 active Bluetooth LE connections - if you're thinking of having multiple devices (and the user may have their own devices as well) you might find that you hit that limit

  • Hi Guys, You can easily do this in DroidScript with the BLE plugin

    Here is the Puck.js code:-

    function advertise(url) {
      var d = [0x03, 0x03, 0xAA, 0xFE, 0x13, 0x16,  0xAA, 0xFE, 0x10,  0xF8, 0x03 ];
      d.push.apply(d,url.toString().split(""));
      d[4] = d.length-5;
      NRF.setAdvertising(d, {interval:100});
    }
    
    advertise( "call.false");
    
    function makeCall( call ) {
        advertise( "call."+call  );
        digitalWrite( LED3, call?1:0 );
    }
    
    setWatch(function() {
       makeCall( true );
       setTimeout( function() { makeCall(false) }, 5000 );
    }, BTN, {edge:"rising", debounce:50, repeat:true});
    
    
    

    And Here is the DroidScript code:-

    app.LoadPlugin( "BluetoothLE" );
    
    function OnStart()
    {
      //Create a text control to show debug log.
      lay = app.CreateLayout( "Linear", "VCenter,FillXY" );
      txt = app.CreateText( "", 1, 1, "Log" );
      lay.AddChild( txt );
      app.AddLayout( lay );
    
      //Create Bluetooth LE object.
      ble = app.CreateBluetoothLE();
      ble.SetOnDevice( OnDevice );
      
      //Check for Puck button presses every 3 seconds
      setInterval( CheckForButtonPress, 3000 );
      txt.Log( "ready" );
      calling = false;
    }
    
    function CheckForButtonPress()
    {
        //Do a brief scan to check for puck button press.
        ble.StartScan();
        setTimeout( function(){ble.StopScan()}, 1000 );
    }
    
    //Called when any BLE device is found by the scan.
    function OnDevice( name, address, bonded, rssi, data )
    {
      txt.Log( name + ": " + data.url );
      if( data.url=="https://call.true" ) MakeCall();
    }
    
    //Make the call (limit to one every 5 seconds).
    function MakeCall()
    {
        if( calling ) return;
        txt.Log( "calling", "red" );
        
        calling = true;
        app.Call( "01359555222" );
        setTimeout( function(){calling=false;}, 5000 )
    }
    
    

    You could optionally put the DroidScript code inside a DroidScript service and have it always running in the background on your phone too :)

  • Thanks - that's a really neat example!

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

Puck button integration with android device.

Posted by Avatar for user72040 @user72040

Actions