• Another day, another rewrite :)

    I've actually got it working now, although I'm still not sure what I changed. I stripped out pretty much everything, rewrote, and then rigged it so on('disconnect') executes NRF.sleep()... the idea being that when the Puck disconnects (for whatever reason), it won't reconnect until manually woken by a keypress.

    I don't mess with advertising or services beyond the initial setup, which unfortunately loses the battery monitor; however, that doesn't seem to make much difference anyway: the device is either connected (no advertising?) or disconnected and sleeping (no advertising)

    I'm also not sure what the drain on this is. Next I'll have to rig it up to test power consumption while sleeping, as that's the ultimate aim. I also have to solve the auto-switch-off that triggered this whole matter in the first place; I'm hoping it's just a case of setTimeout(...NRF.disconnect()..., 1000*60*10) ... clearTimeout().

    For the benefit of anyone else attempting this - https://gist.github.com/tomgidden/875b5a5522deeabd9d1ef389607e434a :

    var hid = require("ble_hid_keyboard");
    
    var is_connected = false;
    
    var ad_values = {};
    var ad_options = { name: "Page-Turn-o-Matic 4000" };
    
    
    var sleep_timeout;
    
    
    // Object to handle multiple-clicking and long-clicking on
    // a button, using EventEmitter.
    function Btn(btn) {
      var o = this;
      o.es = [0,'click','double','triple','quadruple'];
    
      o.br = function (e) {
        if ( 2.0 < e.time - e.lastTime) {
          if (o.h)
            clearTimeout(o.h);
          o.i = o.h = o.l = undefined;
          o.emit('long', 0);
        }
        else {
          // If there's no previous click or it's more than
          // a second ago, it's a new chain of clicks.
          if (!o.i || !o.l || 1.0 < e.time - o.l)
            o.i = 1;
          else
            o.i ++;
    
          o.l = e.time;
    
          if (o.h)
            clearTimeout(o.h);
    
          o.h = setTimeout(function () {
            o.h = undefined;
            if (o.es[o.i]) o.emit(o.es[o.i], o.i);
            o.i = 0;
          }, 400);
        }
      };
    
      o.w = setWatch(o.br, btn, { repeat:true, edge:'falling', debounce : 50 });
    
      return o;
    }
    
    var btn;
    
    function blinken (colour, count)
    {
      digitalWrite([LED1,LED2,LED3], colour);
      setTimeout(function(){
        digitalWrite([LED1,LED2,LED3], 0);
        if (count > 1) {
          setTimeout(function () {
            blinken(colour, --count);
          }, 50);
        }
      }, 25);
    }
    
    function set_sleep_timeout() {
      if (sleep_timeout)
        clearTimeout(sleep_timeout);
    
      sleep_timeout = setTimeout(function () {
        clear_sleep_timeout();
        NRF.disconnect();
      }, 1000*60*5);
    }
    
    function clear_sleep_timeout() {
      if (sleep_timeout) {
        clearTimeout(sleep_timeout);
        sleep_timeout = undefined;
      }
    }
    
    // Connection tracking
    
    function on_connect () {
      blinken(0b011);
      is_connected = true;
    }
    
    function on_disconnect() {
      clear_sleep_timeout();
      blinken(0b101);
      is_connected = false;
      NRF.sleep(); // Prevent reconnection until manually woken
    }
    
    
    // Button click events
    
    function on_click (c) {
      set_sleep_timeout();
      
      if (is_connected) {
        // Single flash - move right
        blinken(0b010, 1);
        hid.tap(hid.KEY.RIGHT, 0);
      }
      else {
        NRF.wake();
        blinken(0b001);
      }
    }
    
    function on_double (c) {
      set_sleep_timeout();
      
      if (is_connected) {
        // Double flash - move left
        blinken(0b010, 2);
        hid.tap(hid.KEY.LEFT, 0);
      }
      else {
        NRF.wake();
        blinken(0b001);
      }
    }
    
    function on_triple (c) {
      NRF.disconnect(); // on('disconnect') causes NRF.sleep
    }
    
    function on_quadruple (c) {
      blinken(0b110);
      NRF.wake();
    }
    
    
    
    // Initialisation
    
    function init () {
      NRF.on('connect', on_connect);
      NRF.on('disconnect', on_disconnect);
    
      NRF.setAdvertising({}, ad_options);
      NRF.setServices(undefined, { hid : hid.report });
    
      btn = new Btn(BTN);
      btn.on('click', on_click);
      btn.on('double', on_double);
      btn.on('triple', on_triple);
      btn.on('quadruple', on_quadruple);
      
      console.log("Note: to activate, either disconnect manually, or NRF.disconnect();"); 
    }
    
    E.on('init', init);
    

    (updated with auto-sleep)

About

Avatar for tom.gidden @tom.gidden started