Bangle 2 kb.tap() sending same key over and over.

Posted on
  • I think I have the same problem as this thread, but with the Bangle 2. I'm trying to make a simple presentation remote app that will send left/right arrow HID keyboard events. Everything works, except after a couple of keypresses the last pressed key just starts repeating. I'm attaching a gif to show the problem.

    In the gif I first press the Bangle 2 button a couple of times which triggers a right key press. After a few presses, the right key just starts repeating over and over. Not even closing the app helps, which leads me to believe this is a problem where the second command calling NRF.sendHIDReport([0,0,0,0,0,0,0,0]... which is supposed to reset the key press doesn't get triggered for some reason. It happens super frequently though, only requiring 3-4 presses to go into this error state every time.

    Below is my app. This is the second iteration where I tried to prevent multiple key presses by keeping track of a key currently being sent using a "currentlySendingKey" boolean. What I found was that it seems like my callback for the tap() event doesn't trigger, so once one buggy key has been sent, currentlySendingKey stays true forever.

    PS. I would also love some guidance on how I can connect my app to the console when it's in a paired HID state, it doesn't show up in the Web IDE if it's paired to the Mac.

    const storage = require('Storage');
    const settings = storage.readJSON('setting.json', 1) || { };
    
    var usbHidEnabled = false;
    
    let currentlySendingKey = false;
    
    var forward, backward;
    
    // Power savings stuff
    Bangle.setLocked(false);
    Bangle.setOptions({ lockTimeout: 0 });
    
    if (settings.HID=="kb" || settings.HID=="kbmedia") {
      usbHidEnabled = true;
    
      // https://www.espruino.com/BLE+Keyboard + presentor app
      // https://www.espruino.com/modules/USBKeyb­oard.js
      const kb = require("ble_hid_keyboard");
      NRF.setServices(undefined, { hid : kb.report });
    
      // http://forum.espruino.com/conversations/­325524/
      NRF.setConnectionInterval(100); // Test to see if it reduces keystroke ghosting
    
      forward = function (cb) { 
        if(!currentlySendingKey) {
          currentlySendingKey = true;
          try {
            kb.tap(kb.KEY.RIGHT, 0, function(data) {
              currentlySendingKey = false;
              console.log("Sent!", data);
            });
          } catch(e) {
            currentlySendingKey = false;
            console.log("Could not send forward event", e);
          }
        }
      };
      backward = function (cb) {
        if(!currentlySendingKey) {
          currentlySendingKey = true;
          try {
            kb.tap(kb.KEY.LEFT, 0, function(data) {
              currentlySendingKey = false;
              console.log("Sent!", data);
            });
          } catch(e) {
            currentlySendingKey = false;
            console.log("Could not send backward event", e);
          }
        }
     };
    } else {
      E.showPrompt("Keyboard HID support disabled.", {
        title: "Warning",
        buttons: { "Enable" : true, "Quit" : false},
      }).then(function(enable) {
        if (enable) {
          settings.HID = "kb";
          require("Storage").write('setting.json',­ settings);
          setTimeout(load, 1000, "presentation_remote.app.js"); // TODO: Change to my app
        } else {
          setTimeout(load, 1000); // Goes back to default app(?)
        }
      });
    }
    
    function drawApp() {
      g.clear();
      E.showMessage('Click button to progress to next slide. Press screen to go back.', 'Remote');
    }
    
    // Basically checks that we passed the above stuff
    if (usbHidEnabled) {
      // Look for pin
      setWatch(function(data) {
        console.log("> Go forward", data);
         forward();
      }, BTN1, { edge: "rising", repeat: true, debounce: 50 });
    
      Bangle.on('touch', (button, data) => { 
        console.log("< Go back", button, data);
        backward();
      });
    
      drawApp();
    }
    
  • After adding debug logging to a file, I found that the following error is thrown when the key stops working.

    Error: ERR 0x13 (:3174)
    

    Based on some googling this seems to correspond to "NRF_ERROR_TIMEOUT". Any advice on how to handle these errors (maybe to retry, or at the very least make sure the keyboard doesn't go into a broken state) would be much appreciated!

    Edit
    Upon further testing and logging directly on the display of the watch, the 0x13 error is very rare. The issue also happens without triggering any exception in .tap().

  • Which firmware version are you on? It'd be good to know to track down what place that error comes from.

    And when this happens, does the kb.tap callback still get called? And does it happen when only when you press the button quickly, or even when you're leaving a few seconds between each press.

    You probably figured this out, but the repetition is because the Mac didn't get the 'key up' event and it still thinks the key is pressed down. So as a quick, hacky fix you could call NRF.sendHIDReport([0,0,0,0,0,0,0,0]...) another time after tap calls back.

    One potential reason for issues could be connection power saving - so you could try calling NRF.setConnectionInterval(7.5) and see if that makes the error go away for you. You might not want it to go quite that fast long-term, but it might be a good way to debug

    PS. I would also love some guidance on how I can connect my app to the console when it's in a paired HID state, it doesn't show up in the Web IDE if it's paired to the Mac.

    Yes, that's a pain. I believe it's an OS-related thing though, and if you were able to develop on Android/Chrome OS/Linux I believe those would at least work (maybe windows, but I'm not 100% sure).

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

Bangle 2 kb.tap() sending same key over and over.

Posted by Avatar for khromov @khromov

Actions