-
-
-
I'm going nuts. Trying to discover devices, services, characteristics.
When everything exists - no problem.
But I'd like to handle that a service is not defined.This is my simplified code:
NRF.requestDevice({filters: [{namePrefix: 'Puck.js'}]}).then(dev=>{ console.log("device found", dev); return dev.gatt.connect(); }).then(conn=>{ console.log("connected", conn); return conn.getPrimaryService(0x464F); }).then(s=>{ console.log("service found", s); },f=>{ console.log("no service found", f); }).catch(e=>{ console.log( "error:", e ); });
On execution neither
f=>{
nor.catch(e=>{
are called:device found BluetoothDevice { "id": "f9:2d:30:24:38:a4 random", "rssi": -51, "services": [ ], "data": new ArrayBuffer([2, 1, 5, 13, 9, 80, 117, 99, 107, 46, 106, 115, 32, 51, 56, 97, 52]), "name": "Puck.js 38a4" } connected BluetoothRemoteGATTServer { "device": BluetoothDevice { "id": "f9:2d:30:24:38:a4 random", "rssi": -51, "services": [ ], "data": new ArrayBuffer([2, 1, 5, 13, 9, 80, 117, 99, 107, 46, 106, 115, 32, 51, 56, 97, 52]), "name": "Puck.js 38a4", "gatt": ... }, "connected": true } Uncaught Error: Unhandled promise rejection: No Services found
Is this a bug or have I messed up my Promises?
-
Yeah.
Already missed a little piezo speaker on the pucks.
Could do a little rattling sound every time something goes wrong...By the way - this is the code: http://forum.espruino.com/conversations/297473/
-
Thanks @trezm for pointing out. Just changed that bit.
One think I'd like to improve is checking some version number before updating a remote.
Then omit the update if the version is already there or higher.But without reading the response (not possible to receive notifications yet) this is tricky.
Some thoughts:- just execute some verification code and let the peripheral hang up itself. Like
if same or newer then disconnect()
. Problem here: how can the central see the disconnect and move on? Tried it and catch() was not called. Maybe a watchdog with timeout? - implement another service just for reading the version first. More complex and less elegant.
- waiting for a newer release so the UART response can be used.
Other ideas?
- just execute some verification code and let the peripheral hang up itself. Like
-
So this is it.
Thanks to a few hints from @Gordon my first self-propagating Puck.js code
(Kind of worm if you like)Feedback and improvements welcome.
setSleepIndicator( LED3 ); function transfer(device, text, callback) { var char; var result = ""; console.log( "connecting " + device.name ); return device.gatt.connect().then(function(d) { device = d; console.log( "connected" ); return d.getPrimaryService("6e400001-b5a3-f393-e0a9-e50e24dcca9e"); }).then(function(s) { console.log( "service found" ); return s.getCharacteristic("6e400002-b5a3-f393-e0a9-e50e24dcca9e"); }).then(function(c) { char = c; console.log( "characteristic found, sending..." ); function sender(resolve, reject) { if (text.length) { char.writeValue(text.substr(0,20)).then(function() { sender(resolve, reject); }).catch(reject); text = text.substr(20); } else { console.log("finished"); resolve(); } } return new Promise( sender ); }).then(function() { device.disconnect(); if(callback) callback(true); }).catch(function() { console.log( "error" ); if(callback) callback(false); }); } function scan( callback ) { var result = []; NRF.findDevices(function(list) { for( var i = 0; i < list.length; i++ ) { var d = list[ i ]; if( typeof d.name !== "undefined" && d.name.indexOf( "Puck.js" ) === 0 ) { console.log( "found " + d.name ); result.push( d ); } } callback( result ); }); } function spread() { var code = E.dumpStr(); scan( function( queue ) { // recurse through queue function process() { if( queue.length ) { transfer( queue.pop(), code, function( result ) { console.log( "done" ); setTimeout( process, 200 ); }); } } process(); }); } spread();
Output for 4 Pucks:
found Puck.js c9fc found Puck.js f002 found Puck.js 38a4 connecting Puck.js 38a4 connected service found characteristic found, sending... finished done connecting Puck.js f002 connected service found characteristic found, sending... finished done connecting Puck.js c9fc connected service found characteristic found, sending... finished done
-
Thanks again, Gordon.
Adding the timeout solved it:
scan( function( queue ) { // recurse through queue function process() { if( queue.length ) { transfer( queue.pop(), command, function( result ) { console.log( "done" ); setTimeout( process, 150 ); }); } } process(); });
150 ms seems sufficient.
I was able to go down to about 145 ms, but everything below still caused some errors.I'm very thrilled to get the notifications.
Good work - keep it up! -
-
Executing
dump()
logs the current interpreter state to the console.Is there a way to get the same output in a variable?
I can do this for a single function via toString():
>function foo() { : var bar = 123; : return bar; :} =function () { ... } =undefined >var code = foo.toString(); ="function () {\n v" ... ";\n return bar;\n}" =undefined >console.log( code ); function () { var bar = 123; return bar; } =undefined
How can I do the same with the whole interpreter state?
PS: Warning - this is the perfect foundation for writing the first puck.js worm - which I intend to do ;-)
PS2: ...not for harming anyone, but for neatly spreading code through the puck.js field of mine... -
-
Having 5 pucks at hand I'd like to do some round-robin communication:
- request a list of available pucks around me (works)
- iterate through the list (issue A below)
- receive feedback during the UART connection (issue B below)
I am aware, that connection multiple peripherals at the same time is not possible atm, so I do it sequentially (with recursive callbacks).
This is my connection code:
function transfer(device, text, callback) { var char; var result = ""; console.log( "connecting " + device.name ); return device.gatt.connect().then(function(d) { device = d; console.log( "connected" ); return d.getPrimaryService("6e400001-b5a3-f393-e0a9-e50e24dcca9e"); }).then(function(s) { console.log( "service found" ); return s.getCharacteristic("6e400002-b5a3-f393-e0a9-e50e24dcca9e"); }).then(function(c) { char = c; console.log( "characteristic found" ); function sender(resolve, reject) { console.log( "sending" ); if (text.length) { char.writeValue(text.substr(0,20)).then(function() { sender(resolve, reject); }).catch(reject); text = text.substr(20); } else { resolve(); } } return new Promise( sender ); /* }).then(function() { function receiver(resolve, reject) { console.log( "receiving" ); char.readValue().then(function(chunk) { console.log(chunk); if( chunk.length > 0 ) { result += chunk; receiver(resolve, reject); } else { resolve(); } }).catch(reject); } return new Promise( receiver ); */ }).then(function() { device.disconnect(); if (callback) callback(result); }); }
Issue A:
As long as I disable (/**/) the receiving part I can pass commands to the first puck successfully.
But when I try to connect the second one I get BLE error 18 - why?found Puck.js f002
found Puck.js 38a4
found Puck.js c9fc
connecting Puck.js c9fc
connected
service found
characteristic found
sending
sending
done
connecting Puck.js 38a4
Uncaught Error: Unhandled promise rejection: Error: Got BLE error code 18Question: What does that mean and what can I do about it?
Issue B:
I also like to get the feedback of the command sent to the pucks.
So I tried to add the receiver part (in comments) but it always receives the echo of the data I just sent.Question: How can I get the full response and how do I detect the end of a transmission?
I'll upload the full sourcecode as attachment so you have the complete picture.
Thanks in advance,
Christian - request a list of available pucks around me (works)
-
-
reset() and save() do not always work for me:
http://forum.espruino.com/conversations/297205 -
getting worse now after playing around with HID:
>reset(); =undefined _____ _ | __|___ ___ ___ _ _|_|___ ___ | __|_ -| . | _| | | | | . | |_____|___| _|_| |___|_|_|_|___| |_| http://espruino.com 1v89 Copyright 2016 G.Williams Uncaught SyntaxError: Got ?[255] expected EOF at line 1 col 1 ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ... ^
Question:
How can I reset the puck's memory to factory default?
reset()
doesn't seem to work or have side effects. -
-
Maybe it's the WebIDE?
Chrome Version 54.0.2840.98 (64-bit) on OSX 10.11.6 here with WebIDE.I played around with Settings->Communications->Save on Send.
When it is set to "Yes, even execute after 'reset()'" I can remove the code when:- putting on dummy line like
var foo;
on the right hand pane - click "Send to Espruino"
Simple example:
>dump(); function onInit() {digitalPulse(LED1, 1, 100);} pinMode(D29, "input_pulldown", true); =undefined
Not working:
>reset();save(); =undefined Running onInit()... _____ _ | __|___ ___ ___ _ _|_|___ ___ | __|_ -| . | _| | | | | . | |_____|___| _|_| |___|_|_|_|___| |_| http://espruino.com 1v88 Copyright 2016 G.Williams Erasing Flash..... Writing.... Compressed 32000 bytes to 1222 Checking... Done! Running onInit()... >dump(); function onInit() {digitalPulse(LED1, 1, 100);} pinMode(D29, "input_pulldown", true); =undefined
Putting this into the right hand pane finally kills the code (actually it replaces the current code by some dummy code):
var foo;
Send and check:
>Erasing Flash..... Writing... Compressed 32000 bytes to 17 Checking... Done! Loading 17 bytes from flash... =undefined >dump(); var foo = undefined; pinMode(D29, "input_pulldown", true); =undefined
This is strange...
- putting on dummy line like
-
-
Yesterday my 5 pucks arrived. @gordon - superb!
Started to play around a bit and just got stuck at a thing that happened to my pico before:
I tried out a demo, now I want to get rid of it.
So I connect and do this:Connected > >dump() var isOn = false; setWatch(function () { isOn = ! isOn; analogWrite(LED1, (isOn) ? 0.02 : 0); }, "D0", { repeat:true, edge:'rising', debounce : 49 }); setBusyIndicator(D3); digitalWrite(D3, 1); pinMode(D29, "input_pulldown", true); =undefined
Call reset() to kill it:
>reset() =undefined _____ _ | __|___ ___ ___ _ _|_|___ ___ | __|_ -| . | _| | | | | . | |_____|___| _|_| |___|_|_|_|___| |_| http://espruino.com 1v89 Copyright 2016 G.Williams
Call save() to persist the "clean" state:
>save() =undefined Erasing Flash..... Writing.... Compressed 32000 bytes to 1372 Checking... Done!
Should be gone now, or not?
But look here - still there:>dump() var isOn = false; setWatch(function () { isOn = ! isOn; analogWrite(LED1, (isOn) ? 0.02 : 0); }, "D0", { repeat:true, edge:'rising', debounce : 49 }); setBusyIndicator(D3); digitalWrite(D3, 1); pinMode(D29, "input_pulldown", true); =undefined >
So - how can I get rid of the running code?
Maybe I did not understand the concept of reset() and save() properly...
-
@luwar
I2C1.setup( { scl: B8, sda: B9 } );
works - without any delay.
Also right after save() and on power-up. -
-
-
Sorry, no. Tried this before.
Even 2 seconds don't make a change:function onInit() { setTimeout( function() { I2C1.setup({scl:B6, sda:B7}); var lcd = require("HD44780").connectI2C(I2C1); lcd.clear(); lcd.print( "Hello World!" ); }, 2000 ); }
I even use the very same LCD in an Arduino project and can start sending to it right away with no issues there.
Any other idea?
-
-
Beginner with espruino and having some trouble with onInit on my Pico:
function onInit() { I2C1.setup({scl:B6, sda:B7}); var lcd = require("HD44780").connectI2C(I2C1); lcd.clear(); lcd.print( "Hello World!" ); }
Upload and save() works as expected:
>reset(); =undefined _____ _ | __|___ ___ ___ _ _|_|___ ___ | __|_ -| . | _| | | | | . | |_____|___| _|_| |___|_|_|_|___| |_| http://espruino.com 1v88 Copyright 2016 G.Williams >echo(0); =undefined >save() =undefined Erasing Flash..... Writing....... Compressed 81600 bytes to 4445 Checking... Done! Running onInit()...
But when I un- and re-plug USB it's not working - the LCD is staying blank:
Disconnected Connected >Loading 4445 bytes from flash... Running onInit()... =undefined Uncaught InternalError: Timeout on I2C Write Transmit Mode 2 at line 2 col 13 g|4,g|4,g,g]) ^ in function "a" called from line 1 col 7 a(51,1);a(50,1);a(40,1);a(12,1);a(6,1);a(1,1);return{write:a... ^ in function "h" called from line 2 col 15 g|4,g|4,g,g])}) ^ in function "connectI2C" called from line 5 col 49 var lcd = require("HD44780").connectI2C(I2C1); ^ in function called from system =undefined Execution Interrupted during event processing.
Just manually executing load() again and voila - the LCD shows "Hello World!"
>load() =undefined Loading 4445 bytes from flash... Running onInit()...
What's going wrong?
Yes, everything updated to 1v90 already.
The single
.catch
at the end of the chain was the first that I tried.And when that didn't work I added the second parameter in
.then
- but both don't work.Is the single, final
.catch
supposed to work for every rejected Promise in the whole queue?If yes, looks like something with the Promise handling is not working...