-
• #2
what about counting 10 calls inside handler with help of global variable and doing
NRF.setRSSIHandler();
only after that?Javascript/espruino is single threaded and event based so until your code ends nothing else runs.
The exception are hardware interrupts and bluetooth stack is also based on those so the rssi handler may be still called in your code despite your busy loop (not sure) but your code resets it very quickly anyway so it has no chance to run 10 times exactly.BTW what is
wait(5000);
? There is no such thing in Espruino and it goes against basic principle of javascriptI'd use
setInterval
with 5 second delay, set the RSSI handler there every 5 seconds and then do as suggested in first line - unset handler after 10 calls are made -
• #3
wait is a function that I added:
function wait(ms){
var start = new Date().getTime();
var end = start;
while(end < start + ms) {end = new Date().getTime();
}
}even after giving the loop inside the variable creates issue as I am running an infinite while loop. And for that, JS is first trying to finish the infinite loop ( which is not happening) keeping the calling of the handler in queue.
Does Espruino supports async/ await? This would have easily solved the issue. Or is there any way to restart the whole code after every complete run?
-
• #4
no async/await (and it would not help you with correctly timing setRSSIHandler anyway) but there is still easy solution, just read again my post. in javascript/Espruino it is bad idea to write long running loops in C/arduino style. In Espruino you have setTimeout,setInterval,setWatch, promises and events.
-
• #5
as for the rssi handler to be called 10 times and compute average I'd do something like
var rssicnt=0; var sum=0; NRF.setRSSIHandler((data)=>{ sum+=data; print(rssicnt,"rssi=",data); if(++rssicnt > 9) { NRF.setRSSIHandler(); print("avg rssi=",sum/10); } });
to do this every 5 seconds you just put it into setIterval
setInterval(()=>{ var rssicnt=0; var sum=0; NRF.setRSSIHandler((data)=>{ sum+=data; print(rssicnt,"rssi=",data); if(++rssicnt > 9) { NRF.setRSSIHandler();print("avg rssi=",sum/10); } }); },5000);
-
• #6
The code @fanoush posted is the best way.
Hard-coding a 'wait' in Espruino (and JS in general) really doesn't work very well.
async/await
is just a wrapper around promises, and Espruino has promises so you can do everything you can with async/await in Espruino, just slightly more verbosely. However in this case I don't think it helps you... -
• #7
Thank you very much. I am new at this platform. And this has teach me not to go with hard code version. Thanks again.
-
• #8
Yes I understand the issue now. Thank you.
-
• #9
Using @fanoush 's code imbedded in your app, the convenience singleton object for handling all RSSI stuff could look like the code below. Working thru the example you will notice that Espruino / JavaScript is completely event driven... and you can take advantage of that even in application components you write. No need to burn cycles like famous (NOP) wait loops do... ;)
NB: Things - such as
NRF.setRSSIHandler()
setting method - not available in your environment - emulator or html doc in browser? ...just fake/emulate it 'intelligently' - see lines59..71
to get meaningful values for (cross) developing and test your logic... Same goes for the missingon()
andemit()
for plain browser js objects - see lines72..77
. With these 'complements', the very same Espruino code runs in html5 document in browser. The html document is attached to the post, just click on its link... ;) --- *click on the second attached html / link* - first one has issues and I could not delete it because forum has issues on edit with loading... / deleting of attachments). HTML code is shown below the Espruino code.// for logging convenience var lon=0, log=function(){console.log.apply(console,arguments);}; // rssis singleton object handling all RSSI matters encapsulated var rssis = { history: [] // [date,value] tuples of samples , maxHist: 10 // max count averaged samples in history , intTime: 5000 // ms interval time of sampling , samples: 5 // count of raw samples for for averaged sample , _intId: 0 // interval id for start/stop control , _cnt: 0 // for sampling control , _sample: function() { // --- takes samples and stores in history var sum = 0 , cnt = this.samples , avrg, hEntry; NRF.setRSSIHandler((data)=>{ lon&&log("C:",data,this._cnt); sum+=data; if (--cnt<1) { NRF.setRSSIHandler(); hEntry = [new Date(), avrg = sum/this.samples]; this.history.splice(0, 0, hEntry); if (this.history.length>this.maxHist) this.history.pop(); this.emit('data', avrg, hEntry, data, this); } } ); } , start: function(clearHistory,_rs) { // --- opt clear history and take samples lon&&log("rssis.start",((_rs)?_rs:""), "clearHistory:", !!clearHistory); if (this._intId) { this.stop(); } if (clearHistory) { this.history = []; } this._intId = setInterval(this._sample.bind(this), this.intTime); return this.history.length; } , isSampling: function() { // --- true when sampling, otherwise false return !!this._intId; } , getHistoryCnt: function() { // --- number of history entries return this.history.length; } , stop: function() { // --- stop taking samples lon&&log("rssis.stop"); if (this._intId) { NRF.setRSSIHandler(); // stops data handler in its tracks this._intId = clearInterval(this._intId); // stops sampling } return this.history.length; } , resume: function() { // --- resume w/ not clearing history return this.start(0,"(resume)"); } , dump: function(asHTML) { // --- return history as lines / html w/ <br> var x=-1,l=this.history.length,h,lines=[]; while(++x<l){h=this.history[x];lines.push(h[0].toString()+": "+h[1]);} lines.push(l); return (asHTML) ? lines.join("<br>")+"<br>" : lines; } }; // to run in emulator or html5 doc in browser have this in place (roughly): var nrfDataEmulatorIntId=0; if (typeof NRF === 'undefined') { var NRF = {}; } NRF.setRSSIHandler = function(dataHandler) { // every 7 ms an emulated value if (dataHandler && ! nrfDataEmulatorIntId) { lon&&log("P:start"); nrfDataEmulatorIntId = setInterval((dataHandler)=>{ var emulatedVal = Math.round((new Date().getTime() % 100) / 10) - 90; lon&&log("P:", emulatedVal); dataHandler(emulatedVal); },13,dataHandler); } else if (! dataHandler && nrfDataEmulatorIntId) { lon&&log("P:stop"); nrfDataEmulatorIntId = clearInterval(nrfDataEmulatorIntId); } }; if (typeof window !== 'undefined'){ lon&&log("in browser js/win"); // for html5 doc let addOnAndEmitTo=function(o,n){ lon&&log("add simple on/emit to "+n);o._eOE={}; o.on=function(e,h){this._eOE[e]=h;};o.emit=function(){var p=[],i,a=arguments,m, u; if(m=this._eOE[a[0]]){for(i=1;i<a.length;i++)p.push(a[i]); m.apply(u,p);}}}; if ( ! rssis.on) { addOnAndEmitTo(rssis,"rssis"); } } // catching rssis 'data'-event rssis.on("data",(avrg, historyItem, rawSample, rssisObj)=>{ lon&&log("rssis 'data' event: ", avrg, historyItem, rawSample, rssisObj.getHistoryCnt()); }); // for dev acceleration function onInit() { rssis.start(); } // for dev acceleration setTimeout(onInit,999); // remove before upload for/with save()
HTML document running the same Espruino code:
<html> <head><title>RSSIs</title></head><body> <h3>RSSIs</h3> <p>Open inspector in develop tools and watch console...</p> <ul> <li><a href="#" onclick="rssis.start();" >start</a></li> <li><a href="#" onclick="rssis.start(1);">start with clearing history</a></li> <li><a href="#" onclick="rssis.stop();" >stop</a></li> <li><a href="#" onclick="rssis.resume();">resume</a></li> <li><a href="#" onclick="ao.h('dmp',rssis.dump(1)+ao.e('dmp').innerHTML);";>dump</li> </ul> <hr><a href="#" onclick="ao.h('dmp','');">clear</a><pre id="dmp"></pre> <!--survival html5 --><script> var ao = { d: document , e: function(ioe) { return ("string"===typeof ioe) ? this.d.getElementById(ioe) : ioe; } , h: function(ioe,h) { var e = this.e(ioe); return e.innerHTML = h; return e; } }</script> <!-- rssis js from Espruino --> <script> // ... ... ... ... Espruino js code from above copied in here... ... ... ... </script> </body> </html>
The
rssis
singleton supports these 'methods' and other:- For start taking samples and store them in history, issue
rssis.start();
- To stop taking samples, issue:
rssis.start();
- To dump the history in the console (anytime), issue
rssi.dump();
To access last data (any time, from the history):
var h; if (rssis.historyCount>0) { h = rssis.history[0]; console.log("RSSSI at", h[0], ": ", h[1]) }
...or simply:
console.log(rssis.history[0][1]);
The objet even emits
'data'
event when adding to the history with these parms (see line #s24
and60ff
`):- most recent averaged sample: avrg
- history entry: [date, avrg]
- most recent raw sample: data
- rssis singleton object
This event can be listen to in the application in a similar way as
rssis
is listening to theNRF 'data'
event:// catching rssis 'data'-event rssis.on("data",(avrg, historyItem, rawSample, rssisObj)=>{ console.log("rssis 'data' event: ', avrg, historyItem, rawSample, rssisObj.getHistoryCnt()); });
With `lon=0' (logging turned off) you get only outputs like this in the console (most recent average rssi value, most recent history event with date and rssi average, most recent raw rssi sample value, and history count):
rssis 'data' event: -85 [ Date: Tue Oct 4 2022 18:34:31 GMT-0700, -85 ] -86 1
Setting
lon=1
(turns logging on and) you get after uploading and console commands (latter indented) output on console like this:> ____ _ | __|___ ___ ___ _ _|_|___ ___ | __|_ -| . | _| | | | | . | |____|___| _|_| |___|_|_|_|___| |_| espruino.com 2v15 (c) 2021 G.Williams > > rssis.start clearHistory: false P:start P: -80 C: -80 0 P: -89 C: -89 0 P: -88 C: -88 0 P: -87 C: -87 0 P: -85 C: -85 0 P:stop rssis 'data' event: -85.8 [ Date: Tue Oct 4 2022 22:30:09 GMT-0700, -85.8 ] -85 1 ----------------------->rssis.dump() // while sampling =[ "Tue Oct 4 2022 22:30:09 GMT-0700: -85.8", 1 ] P:start P: -80 C: -80 0 P: -89 C: -89 0 P: -88 C: -88 0 P: -86 C: -86 0 P: -85 C: -85 0 P:stop rssis 'data' event: -85.6 [ Date: Tue Oct 4 2022 22:30:14 GMT-0700, -85.6 ] -85 2 P:start P: -81 C: -81 0 P: -89 C: -89 0 P: -88 C: -88 0 P: -87 C: -87 0 P: -85 C: -85 0 P:stop rssis 'data' event: -86 [ Date: Tue Oct 4 2022 22:30:19 GMT-0700, -86 ] -85 3 ----------------------->rssis.stop(); // while sampling rssis.stop =3 ----------------------->rssis.dump(); // while not sampling =[ "Tue Oct 4 2022 22:30:19 GMT-0700: -86", "Tue Oct 4 2022 22:30:14 GMT-0700: -85.6", "Tue Oct 4 2022 22:30:09 GMT-0700: -85.8", 3 ] ----------------------->rssis.resume(); // while stopped rssis.start (resume) clearHistory: false =3 P:start P: -89 C: -89 0 P: -88 C: -88 0 P: -86 C: -86 0 P: -85 C: -85 0 P: -84 C: -84 0 P:stop rssis 'data' event: -86.4 [ Date: Tue Oct 4 2022 22:31:17 GMT-0700, -86.4 ] -84 4 ----------------------->rssis.start(1); // while sampling rssis.start clearHistory: true rssis.stop =0 P:start P: -85 C: -85 0 P: -84 C: -84 0 P: -83 C: -83 0 P: -82 C: -82 0 P: -80 C: -80 0 P:stop rssis 'data' event: -82.8 [ Date: Tue Oct 4 2022 22:31:27 GMT-0700, -82.8 ] -80 1 P:start P: -86 C: -86 0 P: -85 C: -85 0 P: -84 C: -84 0 P: -82 C: -82 0 P: -80 C: -80 0 P:stop rssis 'data' event: -83.4 [ Date: Tue Oct 4 2022 22:31:32 GMT-0700, -83.4 ] -80 2 ----------------------->rssis.stop(); // while sampling rssis.stop =2 ----------------------->rssis.dump(); while stopped =[ "Tue Oct 4 2022 22:31:32 GMT-0700: -83.4", "Tue Oct 4 2022 22:31:27 GMT-0700: -82.8", 2 ] >
3 Attachments
- For start taking samples and store them in history, issue
I am trying to run NRF.setRSSIHandler 10 times and print the average value. After that wait for 5 second and rerun the loop again for infinite time. But for JavaScript's callback function issue, it is not giving the expected output. I've tried using several closure solutions but none of them work. Is there any way to get the correct output?
Code: