• 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:

    let count = 0;
    let average = 0;
    //infinite loop
    while (count <1){
      for (let i = 0; i < 10; i++) {
        NRF.setRSSIHandler( function (rssi) {
          let distance = Math.pow(10, ((-56 - (rssi)) / (20))) * 3.28084;
          average = average + distance;
          NRF.setRSSIHandler();
        });
      }
      console.log(average/i);
      wait(5000);
    }
    
  • 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 javascript

    I'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

  • 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?

  • 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.

  • 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);
    
  • 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...

  • Thank you very much. I am new at this platform. And this has teach me not to go with hard code version. Thanks again.

  • Yes I understand the issue now. Thank you.

  • 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 lines 59..71 to get meaningful values for (cross) developing and test your logic... Same goes for the missing on() and emit() for plain browser js objects - see lines 72..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.pus­h(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.em­it=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 #s 24 and 60ff`):

    1. most recent averaged sample: avrg
    2. history entry: [date, avrg]
    3. most recent raw sample: data
    4. rssis singleton object

    This event can be listen to in the application in a similar way as rssis is listening to the NRF '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

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

How to run NRF.setRSSIHandler function in a infinite loop with a wait time?

Posted by Avatar for user148837 @user148837

Actions