-
• #27
So to answer your question - what is wait() - it was a hack that I knew would one day need to be discussed. Its the bad bit of code below:
// quick hack function wait(ms){ var start = new Date().getTime(); var end = start; while(end < start + ms) { end = new Date().getTime(); } }
What is really needed is a yield(ms) function that gracefully yields but comes back to the same thread in ms time.
So the question is how to code using timers something like this:
function setupPSMOO() { log_debug("setupGPS() PSMOO"); UBX_CFG_RESET(); wait(100); UBX_CFG_PM2(settings.update, settings.search); wait(20); UBX_CFG_RXM(); wait(20); UBX_CFG_SAVE(); wait(20); }
-
• #28
so to investigate the chaining of these setTimeout()s I decide to generalise the problem to:
function func() { func_1(); wait(delay_1); func_2(); wait(delay_2); func_3(); wait(delay_3); func_4(); wait(delay_4); }
which can be implemented as....
const delay_1 = 1000; const delay_2 = 3000; const delay_3 = 5000; const delay_4 = 7000; function func_1() {console.log("func_1 " + new Date().toString().split(" ")[4]);} function func_2() {console.log("func_2 " + new Date().toString().split(" ")[4]);} function func_3() {console.log("func_3 " + new Date().toString().split(" ")[4]);} function func_4() {console.log("func_4 " + new Date().toString().split(" ")[4]);} function func() { console.log("START: " + new Date().toString().split(" ")[4]); func_1(); setTimeout(function() { func_2(); setTimeout(function() { func_3(); setTimeout(function() { func_4(); setTimeout(function() { // no op console.log("END: " + new Date().toString().split(" ")[4]); }, delay_4); }, delay_3); }, delay_2); }, delay_1); } func();
when run through the emulator I can see that this works.
> >START: 00:02:41 func_1 00:02:41 > func_2 00:02:43 func_3 00:02:47 func_4 00:02:53 END: 00:03:01 >
But it is ugly as sin :(
-
• #29
E.showMessage("Configuring GPS") on its own, it flashes on screen and is gone very quickly
Is it possible that
setupGPS();
or something like that clears the screen?But it is ugly as sin :(
That is why JavaScript has promises...
function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } log_debug("setupGPS() PSMOO"); Promise.resolve().then(function() { UBX_CFG_RESET(); return delay(100); }).then(function() { UBX_CFG_PM2(settings.update, settings.search); return delay(20); }).then(function() { UBX_CFG_RXM(); return delay(20); }).then(function() { UBX_CFG_SAVE(); return delay(20); }).then(function() { // finished! });
It's just one of the gotchas of working with JS. Since it's not actually multithreaded you can't just
yield
- and it's one of the reasons I don't provide await
function in Espruino (because it'd just get abused ;). -
• #30
Very nice. Will have to read up on Promises. Many thanks for your help. Might be able to push the gpssetup App tonight or tomorrow.
-
• #31
GPS Setup is pretty much ready. I have most of the code in my repository.
Switched to using promises and noticed that I dont think the delay() function is working as expected.LOG USING EXISTING (hacky loop) METHOD
> ____ _ | __|___ ___ ___ _ _|_|___ ___ | __|_ -| . | _| | | | | . | |____|___| _|_| |___|_|_|_|___| |_| espruino.com 2v08.167 (c) 2019 G.Williams 1612906951505.60473632812 : loadSettings() 1612906951580.55590820312 : [object Object] 1612906960116.4140625 : exitSetup() 1612906960118.94702148437 : [object Object] 1612906960754.65869140625 : setupGPS() PSMOO <<== time between 1612906961038.22802734375 : Powering GPS Off <<== is 284ms see 'Configuring GPS' message
CONSOLE LOG USING PROMISES
> ____ _ | __|___ ___ ___ _ _|_|___ ___ | __|_ -| . | _| | | | | . | |____|___| _|_| |___|_|_|_|___| |_| espruino.com 2v08.167 (c) 2019 G.Williams 1612907245516.38134765625 : loadSettings() 1612907245591.24096679687 : [object Object] 1612907262076.53149414062 : exitSetup() 1612907262078.91186523437 : [object Object] 1612907262716.82080078125 : setupGPS() PSMOO <<== time between 1612907262723.29052734375 : Powering GPS Off <<== is 7ms ERROR: Invalid RX or TX pins ERROR: Invalid RX or TX pins ERROR: Invalid RX or TX pins ERROR: Invalid RX or TX pins >
The 4 ERROR: Invalid RX or TX pins messages look like they are a response to config commands being sent too fast to the GPS. Also the time between calling setupGPS() and 'Powering off GPS' log message is only 7ms with the promises code.
-
• #32
Aha - cracked it. In order for this to work, the PowerOff GPS has to be part of the promise chain otherwise the GPS will be powered off before any of the setup functions get called.
This log shows that the GPS was getting powered off before the config functions had been called.
1612911680439.88598632812 : loadSettings() 1612911680515.14233398437 : [object Object] 1612911688460.4853515625 : exitSetup() 1612911688462.83520507812 : [object Object] 1612911689101.75122070312 : setupGPS() PSMOO 1612911689108.15991210937 : Powering GPS Off 1612911689112.61547851562 : UBX_CFG_RESET() ERROR: Invalid RX or TX pins 1612911689242.68139648437 : UBX_CFG_PM2() ERROR: Invalid RX or TX pins 1612911689335.45483398437 : UBX_CFG_RXM() ERROR: Invalid RX or TX pins 1612911689370.275390625 : UBX_CFG_SAVE() ERROR: Invalid RX or TX pins > > >
Now using this code:
function setupPSMOO() { log_debug("setupGPS() PSMOO"); Promise.resolve().then(function() { UBX_CFG_RESET(); return delay(100); }).then(function() { UBX_CFG_PM2(settings.update, settings.search); return delay(20); }).then(function() { UBX_CFG_RXM(); return delay(20); }).then(function() { UBX_CFG_SAVE(); return delay(20); }).then(function() { log_debug("Powering GPS Off"); /* * must be part of the promise chain to ensure that * setup does not return and powerOff before config functions * have run * */ Bangle.setGPSPower(0); return delay(20); }); }
I can see everything working properly.
1612912276800.58569335937 : loadSettings() 1612912276876.20825195312 : [object Object] 1612912286403.42993164062 : exitSetup() 1612912286405.77978515625 : [object Object] 1612912287045.123046875 : setupGPS() PSMOO 1612912287053.27124023437 : UBX_CFG_RESET() 1612912287181.38403320312 : UBX_CFG_PM2() 1612912287272.99780273437 : UBX_CFG_RXM() 1612912287307.84887695312 : UBX_CFG_SAVE() 1612912287355.33422851562 : Powering GPS Off >
Yeah - getting code ready for pull request. Many thanks for all you help @Gordon.
-
• #33
Great - thanks! Just merged it :)
-
• #34
Thanks Gordon, what should be done with the now redundant gpsservice widget ?
Should I delete the directory and filesd in gpsservice and remove gps.js and osref.js from multiclock ?I have made myself a clock like osref.js that allows me to turn the GPS on / off through button presses, still perfecting it and will do a pull request for that soon.
-
• #35
Great! Thanks! Yes - first I'd remove gps.js/osref.js and anything that uses the
gpsservice
widget.I think we should probably only remove
gpsservice
once there's a fix for http://forum.espruino.com/conversations/358212/?offset=25#comment15811818 but I'll try and do that today
Have ended up with the hybrid approach below. Nothing gets displayed with the code block you suugested. With E.showMessage("Configuring GPS") on its own, it flashes on screen and is gone very quickly. The approach below gives long enough to see the message.