-
• #27
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 -
• #28
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'.
-
• #29
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}); }
-
• #30
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)); }
-
• #31
You are right. I hadn't retried it after I removed the logging. It's working now without the timeout. Thanks again.
At first glance: I see that the actual keyboard tapping got lost...
@tronic98776, can you explain me a bit more what you mean by
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.
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.KEY
is not an array but an typical object with lots of lots of properties, and
c
` 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 stringvar propAName = "propA";
, the following expressionsobj.propA
,obj["propA"]
andobj[propAName]
are all the very same... this is JS..Back to keyboard in the code example:
KEY
ofkb.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 variablec
: ifvar c = "A";
, thenKEY[c]
is the same asKEY.A
andKEY["A"]
.