PUCK Ble HID keyboard

Posted on
Page
of 2
Prev
/ 2
  • At first glance: I see that the actual keyboard tapping got lost...

    @tronic98776, can you explain me a bit more what you mean by

    laying around ... in an editor so I can get some output in the browser.

    If you mean by that that you made an html page with js and run it in chrome, you need to emulate the keyboard / the module that you pull in because you do not have the actual ble hardware that does the tap. You can do such an emulation....

    I you mean by that you use the Espruino IDE (in the browser) and use the puck, no special things are needed.

    For the latter, let's look how you can add a console log that preserves the previous function.

    ,   _send: function(c) {
            console.log("About to send char",c);
            kb.tap(kb.KEY[c],0,this._sent.bind(this)­);
        }
    
    ,   _sent: function() {
            console.log("Char",this.string.charAt(0)­,"has been sent / tapped")
            this.string = this.string.substring(1);
            console.log("Left to send / tap is",this.string);
            if (this.string.length > 0) {
                console.log("Since length of this.string is",this.string.length
                           ,"and is > 0, next char 'in line' -"
                           ,this.string.charAt(0)," - has to be sent / tapped.")
                this._send(this.string.charAt(0));
            } else {
                console.log("Since nothing is left to tap / send - all is tapped");
                console.log("/ sent, (FIFO  is empty), nothing has to be done");
                console.log(" anymore and  'logical recursion' stops/ends  here.");
            }
        }
    

    Line 3 means: tap - send - this char c, and when done resume with _sent().

    Note why I put the commas as first thing of a thing and NOT at the end of a thing is so I can simply copy blocks from and to anywhere without worrying of the comma (except first), ... the comma is actually a continuation character for the parsing / tokenizing and has only to be there when something same follows... so I put the things together that 'belong' together...

    Regarding the kb.KEY[c] has nothing to do with the 'normal' understanding of arrays..., because after all, kb.KEYis not an array but an typical object with lots of lots of properties, andc` is NOT a number but a character (even if is the character 1 which looks like the number 1). The used approach is the addressing of an object property with the property name as variable:

    Given the JS object var obj = { propA: "A", propN: 1}; and string var propAName = "propA";, the following expressions obj.propA, obj["propA"] and obj[propAName] are all the very same... this is JS..

    Back to keyboard in the code example: KEY of kb.KEY is such an object - as you can see in the module http://www.espruino.com/modules/ble_hid_­keyboard.js - who's properties are now dynamically pulled w/ the variable c: if var c = "A";, then KEY[c] is the same as KEY.A and KEY["A"].

  • By "playing around", I was using an editor and the console in Chrome to try and get my head around callbacks. In the end I went through a number of the tutorials on w3schools and think I have a better idea of it now. I wanted to add console.logs so I could see exactly when/where the code was failing because I would need to be disconnected from the IDE to test the BLE HID sending.

    I am conscious that I am taking up your time in what may be considered my JS education rather than anything Espruino specific. I am grateful of everybody who has contributed to this thread.

    @allObjects, I tried implementing your updated code with the console.logs. (here is the entire script)

    
    var kb = require("ble_hid_keyboard");
    NRF.setServices(undefined, { hid : kb.report });
    
    // setup of you convenience hidKeyBoardObject... (here or later)
    var hidKBD = ( { string: ""
                    
    , type: function(s) { 
        this.string += s; 
        if (this.string.length == s.length) { 
                          
                          
          this._send(this.string.charAt(0)); // get first char out
      } }
    ,   _send: function(c) {
            console.log("About to send char",c);
            kb.tap(kb.KEY[c],0,this._sent.bind(this)­);
        }
    ,   _sent: function() {
            console.log("Char",this.string.charAt(0)­,"has been sent / tapped");
            this.string = this.string.substring(1);
            console.log("Left to send / tap is",this.string);
            if (this.string.length > 0) {
                console.log("Since length of this.string is",this.string.length
                           ,"and is > 0, next char 'in line' -"
                           ,this.string.charAt(0)," - has to be sent / tapped.");
                this._send(this.string.charAt(0));
            } else {
                console.log("Since nothing is left to tap / send - all is tapped");
                console.log("/ sent, (FIFO  is empty), nothing has to be done");
                console.log(" anymore and  'logical recursion' stops/ends  here.");
            }
        }
    });
    
    // setup and other code functions of yours (here or before hidKBD)
       // invoke your set up code as needed (init and getting connections)
       function startSend(){
         hidKBD.type("ABC");}
      // hidKBD.type("XYZ");
    
    	
    setWatch(startSend, BTN, {edge:"rising",repeat:true,debounce:50})­;
    
    
    
    

    I can now see that I am getting an error after the second character has been sent, here is the full console output from espruino IDE:

    BLE Connected, queueing BLE restart for later
    About to send char A
    Char A has been sent / tapped
    Left to send / tap is BC
    Since length of this.string is 2 and is > 0, next char 'in line' - B - has to be sent / tapped.
    About to send char B
    Char B has been sent / tapped
    Left to send / tap is C
    Since length of this.string is 1 and is > 0, next char 'in line' - C - has to be sent / tapped.
    About to send char C
    Uncaught Error: Got BLE error 0x3004 (NO_TX_PACKETS)
    at line 1 col 104
    ...0,0,0],function(){a&&a()})})

                              ^
    

    in function "tap" called from line 16 col 49

        kb.tap(kb.KEY[c],0,this._sent.bind(this)­);
                                                ^
    

    in function "_send" called from line 26 col 45

            this._send(this.string.charAt(0));
                                            ^
    

    in function "a" called from line 1 col 6
    a&&a()

     ^
    

    in function called from system
    ab

  • Look pretty internal to me... I tried to do the loop as close as possible, may be too close. Give this variation a shot:

    ,   _send: function(c) {
            console.log("About to send char",c);
            setTimeout(function(_){
                kb.tap(kb.KEY[c],0,_._sent.bind(_)); },1,this);
        }
    

    What it does: It decouples the sending form 'current JS thread'. @Gordon may know if this does matter or not regarding breaking the 'call-chain'.

  • Thank you @allObjects. I have this working now. Initially it had the same error, but after increasing the setTimeout from 1 to 50, it worked in the console. However, it would fail if anything was added to FIFO string whilst a send was in progress, but increasing the setTimeout to 100 has cured this.

    To get it to type the string over bluetooth I had to get rid of all the console.logs. Here is the code I have working now:

    
    function onInit() {
      var kb = require("ble_hid_keyboard");
    NRF.setServices(undefined, { hid : kb.report });
    
    // setup of you convenience hidKeyBoardObject... (here or later)
    var hidKBD = ( { string: ""
                    
    , type: function(s) { 
        this.string += s; 
        if (this.string.length == s.length) { 
                          
                          
          this._send(this.string.charAt(0)); // get first char out
      } }
    ,   _send: function(c) {
           // console.log("About to send char",c);
            setTimeout(function(_){
                kb.tap(kb.KEY[c],0,_._sent.bind(_)); },100,this);
        }
    ,   _sent: function() {
            //console.log("Char",this.string.charAt(­0),"has been sent / tapped");
            this.string = this.string.substring(1);
            //console.log("Left to send / tap is",this.string);
            if (this.string.length > 0) {
              //  console.log("Since length of this.string //is",this.string.length
      //                     ,"and is > 0, next char 'in line' -"
                           //,this.string.charAt(0)," - has to be sent / tapped.");
                this._send(this.string.charAt(0));
            } //else {
              //  console.log("Since nothing is left to tap / send - all is tapped");
                //console.log("/ sent, (FIFO  is empty), nothing has to be done");
                //console.log(" anymore and  'logical recursion' stops/ends  here.");
            //}
        }
    });
    
    // setup and other code functions of yours (here or before hidKBD)
       // invoke your set up code as needed (init and getting connections)
       function startSend(){
         hidKBD.type("ABCCANNONBALL");}
      // hidKBD.type("XYZ");
    
    	
    setWatch(startSend, BTN, {edge:"rising",repeat:true,debounce:50})­;
    }
    
    
    
  • Kind of surprised that the timeout in line 19 has to be so long. Without logging I would expect that none should be needed, since ._sent() is a callback after all.

    I expect this to work:

    ,   _send: function(c) {
           kb.tap(kb.KEY[c],0,this._sent.bind(this)­);
        }
    
  • You are right. I hadn't retried it after I removed the logging. It's working now without the timeout. Thanks again.

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

PUCK Ble HID keyboard

Posted by Avatar for tronic98776 @tronic98776

Actions