-
-
I'm looking for a way to disable the hard-reset that is initiated by holding down the button on power up to clear out any previously saved code and bonding data. Is there a command I can add into my code that will prevent this function?
I understand there are certain risks with doing this but I want to prevent the chance of erasing the code accidentally.
I would like to still have the self-test function intact where you can power up the puck without loading the saved code and without deleting the saved code.
many thanks
-
Thanks for your help.
I've found a workaround, it functions, but its not ideal and I doubt it's very efficient in terms of battery power. I check the RSSI (Signal Strength), and illuminate the LED depending on the result:
NRF.setRSSIHandler(function(rssi) { sigStrength = rssi; }); function checkRssi() { if (sigStrength > -51){ digitalWrite(LED1,1); } else {digitalWrite(LED1,0); } } function myFunction() { myVar = setInterval(checkRssi, 3000); } myFunction();
-
Thank you for your reply Robin
But I had looked previously at those sections, and I have looked at the tutorials and can't find a relevant one. I'm not sure what I'm missing in the documentation you linked to, could you please be more specific.
Perhaps I didn't explain what I wanted to do, I know how to make the LEDs turn on and off, but I want to trigger an LED when a Central device connects to my Puck via BLE using the active Ble HID keyboard service. I am able to connect to the Puck and use it to send keyboard commands to the central device, but I want the connection to trigger a function (like illuminate an LED on the Puck).
Thank you.
-
Hello
I'm using a puck as a ble HID keyboard with NRF.setServices(undefined, { hid : kb.report }); based on this Tutorial:
https://www.espruino.com/BLE+KeyboardWhat I'm looking for is a way to test if it is connected via bluetooth or not, for example to illuminate one of the LEDs when connected.
I've looked through the documentation and searched the forum, but can't find anything.
Help appreciated.
Thanks
-
OK, thanks @Gordon, so I think I understand the problem and why it won't work with the firmware as it is.
It seems from this that what you want is actually a lot simpler than that.
I'm afraid not.
I assumed you wanted to be able to connect with another device while stopping the phone connecting
This is correct. I want to connect the Puck to Phone A, send an HID string to it based on x-event, then, based on y-event I want the Puck to disconnect from Phone A or power-down and then be discoverable and able to connect to Phone B without Phone A ever auto-reconnecting.
I assume that using an E.on function as well as an onInit won't solve my problem? as they are essentially the same thing?
Is there a way to set the Puck to connect without bonding? Would that even work?
Is there a way other than changing the MAC address of making the Puck appear to be a different/unknown device to a previously paired Phone?
Can you think of any other ways around this other than a firmware update?
-
So, if I follow your steps above it works.
But it doesn't work if I add it to the onInit.Here are the first few lines of my code:
function onInit() { var kb = require("ble_hid_keyboard"); NRF.setAddress("c3:92:e6:f6:f6:f6 random"); NRF.setServices(undefined, { hid : kb.report });
Also, when I add the setAddress to my onInit it seems to also prevent the HID service from starting, as when I connect to my android with the onInit as above it no longer connects as a BLE HID.
-
So I'm still having no success with this:
NRF.setAddress("yy:yy:xx:xx:xx:xx random");
With yy:yy being the same as the original hardcoded MAC address to match the address type and avoid the INVALID_BLE_ADDR.
The Puck still advertises and connects to my phone with the original hard-coded MAC address.
The exact steps I have taken.
I am using the web IDE in chrome. On the right hand side I have my BLE HID code (which is all functioning correctly). I connect the Puck to the web Ide. Upload my code from the RHS on to the puck. I then enter NRF.setAddress("C3:92:xx:xx:xx:xx random"); into the command on the left hand side. It returns undefined. I type save(). I type NRF.disconnect(). The Puck disconnects from the web ide. I restart the Puck, by lifting and releasing the battery. I then open the bluetooth settings on my android phone, scan for a new device, I find the Puck, connect and pair with it. I then click on the Puck in my Android bluetooth settings to check the MAC address and it displays the same hard-coded address that is returned when i type NRF.getAddress() into the ide. So as far as I can tell I am not successfully changing the MAC address.I just tried here and it works fine
@Gordon, can you please tell me that exact steps you took to get the change to work
I really appreciate your help on this Gordon.
-
Thank you @Gordon.
Just to make sure I understand - you're connecting to the Puck from a device like a PC or phone?
That is correct I am using the Puck as a Ble HID Keyboard, I want to connect it to my phone, use it to pass a string of characters to the phone (based on an event), then (based on another event) I want to disconnect the Puck from the phone (without touching the phone) and have it not auto-reconnect to the phone.
I had looked at changing the MAC address using each of the 3 variations as I wasn't sure from reading the documentation what each type of address was. It seemed a little confusing to me have a static address that is random?
NRF.setAddress("xx:xx:xx:xx:xx:xx"); NRF.setAddress("xx:xx:xx:xx:xx:xx public"); NRF.setAddress("xx:xx:xx:xx:xx:xx random");
But none of them seemed to have any effect on the device's mac address. I including the line in my onInit() function, I tried having it outside of the function, uploading my code and using the save() command. I have also tried entering it into the command line directly. When entering into the command line on the web IDE, it returns "undefined", then when I check for the change by entering NRF.getAddress(), it just returns the original default MAC address of the Puck. I have tried save(), on the device, then power cycling the puck, but the changes are still not working.
If I can get the MAC address to successfully change with the NRF.setAddress, then this should work as a solution, because I can create a random string on init of the Puck, which will hopefully prevent reconnection to the phone as it will not appear to be a previously paired/bonded device.
On another note, (although this wasn't a solution for me) I was able to change the advertised name with:
NRF.setAdvertising({},{name:"Hello"});
But I couldn't find a way of resetting this back to the default "puck.js xxxx" where I think the xxxx was the last few characters of the MAC address. Is there a command to reset this back to factory default?
-
I'm trying to prevent the puck from automatically reconnecting to a device that it has previously been connected to and paired with. So after the puck has been connected and paired with a device, I want to action a reset/power cycle of the puck and for it to not connect to the device again unless I go through the connection process again on the device.
I know that I can just select "forget this device" from bluetooth settings on the device, but I want a way of implementing this from the puck itself (ie via a button press).
My initial plan was to set it to create a device name containing a random string on init, and then calling a reset() on the button press. This plan failed as the phone/laptop device that the puck has been paired with ignores the fact that the bluetooth device name has changed and still reconnects. I assume it looks at the underlying MAC address instead.
Does anybody know a way of implementing this?
Perhaps there is a mode I can set which enables connection without pairing?
Many thanks.
-
-
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}); }
-
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 -
So I think I'm making some progress here. I've been playing around with the @allObjects solution in an editor so I can get some output in the browser.
// setup of you convenience hidKeyBoardObject... (here or later) var hidKBD = ( { //member of hidKBD, currently empty string: "" , type: function(s) { this.string += s; if (this.string.length = s.length) { this._send(this.string.charAt(0)); } }, //sends first character then references _sent .this so this.string in _sent will be the string from _send _send: function(c) { console.log(c,this._sent.bind(this)); }, //subtracts first letter from string then passes new first letter to _send _sent: function() { this.string = this.string.substring(1); if (this.string.length > 0) { this._send(this.string.charAt(0)); } } } ); // setup and other code functions of yours (here or before hidKBD) //function onInit() { // invoke your set up code as needed (init and getting connections) hidKBD.type("ABC"); //hidKBD.type("XYZ"); //}
I've added some of my own commenting just to verify that I understand what is happening.
But due to the placement of the console.log on line 15, the log returns "A", but then the bind doesn't seem to envoke the _sent function and just prints the contents of _sent in the console:
//console output A ƒ () { this.string = this.string.substring(1); if (this.string.length > 0) { this._send(this.string.charAt(0)); } }
How can I set up something so I can play with the code and have it returning a something representative of the BLE HID output to a browser.
Many thanks guys.
-
Ok, so i've been working my through some JS tutorials to try and get my head around this all. I think I understand the solution from @Gordon. And I think it would be adequate for my task. But I understand the potential issues that could be caused if a command is sent before the previous one has completed. So I really want to learn the method submitted by @allObjects that handles this event. I understand that the idea is create a "queue" of what I want to send and then add to that queue.
Currently I'm having trouble understanding what we are doing here:
, type: function(s) { // feeding the FIFO w/ string to write this.string += s; // add string to FIFO w/ simple concat if (this.string.length == s.length) { // length are the same
Line one is defining a function called hidKBD.type with the parameter s
Line two is hidKBD.string = hidKBD.string + s
Then Line three if the length hidKBD.string is the same as s.....What I'm not sure about is the parameter "s", where are we assigning it some data?
Thanks
-
Wow allObjects, thank you so much. I'm working my way through your thorough post just to make sure I understand it all fully. I'm really grateful for the time you put in. I'll report back when I've got it straight in my head.
Thanks also to Gordon, it was an issue of timing that was causing my problem.
-
OK, thanks Wilberforce. That clears up that part for me, I had tried using setTimeout (see below) as I though it may be a timing issue, it was not successful, but now I understand a little more.
function myCommand2() { setTimeout(sendLowA, 200); setTimeout(sendLowB, 200); setTimeout(sendLowC, 200); }
Now I just need to figure out how to send more characters across.
-
Thank you for your replay Robin.
That is the correct tutorial I was referring to.I had thought that I may have reached the array limit on the tap(), but I'm unsure as I cannot find much detail about the function in documentation. I tried only sending the character's in small chunks, exectuing the function several times but this also failed:
function sendNewTest() { NRF.sendHIDReport([2,0,4], function() { NRF.sendHIDReport([0,0,0]); }); NRF.sendHIDReport([2,0,5], function() { NRF.sendHIDReport([0,0,0]); }); NRF.sendHIDReport([2,0,6], function() { NRF.sendHIDReport([0,0,0]); }); NRF.sendHIDReport([2,0,7], function() { NRF.sendHIDReport([0,0,0]); }); NRF.sendHIDReport([2,0,8], function() { NRF.sendHIDReport([0,0,0]); }); NRF.sendHIDReport([2,0,9], function() { NRF.sendHIDReport([0,0,0]); }); NRF.sendHIDReport([2,0,10], function() { NRF.sendHIDReport([0,0,0]); }); NRF.sendHIDReport([2,0,11], function() { NRF.sendHIDReport([0,0,0]); }); }
Also I found reference using the puck.js for keyboard inputs over BLE on another topic, where Gordon suggests it would be possible at the tend of his first paragraph:
http://forum.espruino.com/conversations/307801/The other confusing thing is (which could be due to my lack of JS knowledge), when sending fewer characters (say 3 for example), why does this work:
> function sendCap() { > // Send 'a' > kb.tap(kb.KEY.A, 0, function() { > // Followed by 'b' > kb.tap(kb.KEY.B, 0, function() { > // Followed by 'c' > kb.tap(kb.KEY.C, 0); > }); > }); > > }
but not this?:
> function myCommand() { > kb.tap(kb.KEY.A, 0); > kb.tap(kb.KEY.B, 0); > kb.tap(kb.KEY.C, 0); > }
Why is it that the tap() has to be nested like that?
-
-
Hello
And thanks in advance for any help. I'm quite new to coding JS, but always keen to learn.
I'm trying to programme my Puck.js to connect to another device as BLE HID Keyboard. I have successfully got this working and I am able to send a character or two to the device after pressing the button on the puck. What I now want to do is send a whole word or sentence from the button press. Here is where I am having issues. I have tried creating many different functions to do this, but none of it seems to work successfully. I seem to reach a maximum series of characters (7), before strange things happen like the the seventh character repeating endlessly.
I tried mapping each of the kb.tap commands to an individual function, but this didn't help things and then I tried using the low level commands too, but this also resulted in the same issues. I'm also a bit confused as to why the example given in the puck tutorial has an "a" followed by "A", but rather than them being separate lines within the function, they are nested within one another (this is likely due to my lack of JS experience), but I couldn't find reference to this practice anywhere.
On my code below you can see I tried to construct a sequence of A,B,C,D,E,F,G,H... to send to my connected device. There are several functions in there that I tried; sendCap, sendLowLevel, sendNewTest and myCommand, none of which worked.
function onInit() { var kb = require("ble_hid_keyboard"); NRF.setServices(undefined, { hid : kb.report }); function sendLowA() { kb.tap(kb.KEY.A, 0); } function sendLowB() { kb.tap(kb.KEY.B, 0); } function sendLowC() { kb.tap(kb.KEY.C, 0); } function sendLowD() { kb.tap(kb.KEY.D, 0); } function sendLowE() { kb.tap(kb.KEY.E, 0); } function sendCap() { // Send 'a' kb.tap(kb.KEY.A, 0, function() { // Followed by 'b' kb.tap(kb.KEY.B, 0, function() { // Followed by 'c' kb.tap(kb.KEY.C, 0, function() { // Followed by 'd' kb.tap(kb.KEY.D, 0, function() { // Followed by 'e' kb.tap(kb.KEY.E, 0, function() { // Followed by 'f' kb.tap(kb.KEY.F, 0, function() { // Followed by 'g' kb.tap(kb.KEY.G, 0, function() { // Followed by 'h' kb.tap(kb.KEY.H, 0, function() { // Followed by 'i' kb.tap(kb.KEY.I, 0); }); }); }); }); }); }); }); }); } function sendLowLevel() { NRF.sendHIDReport([2,0,4, 5, 6, 7, 8, 9, 10, 11 ], function() { NRF.sendHIDReport([2,0,5], function() { NRF.sendHIDReport([2,0,4], function() { NRF.sendHIDReport([0,0,0]); }); }); }); } function sendNewTest() { NRF.sendHIDReport([2,0,4], function() { NRF.sendHIDReport([0,0,0]); }); NRF.sendHIDReport([2,0,5], function() { NRF.sendHIDReport([0,0,0]); }); NRF.sendHIDReport([2,0,6], function() { NRF.sendHIDReport([0,0,0]); }); NRF.sendHIDReport([2,0,7], function() { NRF.sendHIDReport([0,0,0]); }); NRF.sendHIDReport([2,0,8], function() { NRF.sendHIDReport([0,0,0]); }); NRF.sendHIDReport([2,0,9], function() { NRF.sendHIDReport([0,0,0]); }); NRF.sendHIDReport([2,0,10], function() { NRF.sendHIDReport([0,0,0]); }); NRF.sendHIDReport([2,0,11], function() { NRF.sendHIDReport([0,0,0]); }); } function myCommand() { sendLowA(); sendLowB(); sendLowC(); } // trigger btnPressed whenever the button is pressed setWatch(sendNewTest, BTN, {edge:"rising",repeat:true,debounce:50});} // flash the blue LED to indicate button press // digitalWrite(LED3, true); //setTimeout("digitalWrite(LED3, 0);", 100);```
I'm having trouble getting this to work. For eaxample here is what I'm trying to write to .boot0 and have it execute on device start-up, but it's not working for me:
So i have nothing in save(), so do not enter the save() command into the terminal, I just send the above code onto the puck via the IDE, then disconnect from the IDE and restart the puck by cycling the power.
I have tried both including the onInit and leaving it commented out as above.
Do I have something wrong, or is it something to do with the ble_hid_keyboard service not working from boot0?