espruino/EspruinoAppLoaderCore

setTime() on BangleJs 2 accuracy

Closed this issue · 1 comments

When using Comms.setTime() for my Bangle.Js 2 e.g. from the app loader "Set Bangle.js Time" button under Utilities the time set lags behind nearly a second. I believe accounting for the round trip time would increase the accuracy, this could be done with e.g.

--- a/js/comms.js
+++ b/js/comms.js
@@ -356,9 +356,13 @@ const Comms = {
     we end up with a delay dependent on how long it took
     to open the device chooser. */
     return Comms.write("\x03").then(() => {
+      var t1 = performance.now();
+      Promise.resolve(Comms.write("\nsetTime((new Date()).getTime()/1000)\n")); // noop that includes the execution time of setTime()
+      var t2 = performance.now();
+      const delta = (t2-t1)/2.0;
       let d = new Date();
       let tz = d.getTimezoneOffset()/-60
-      let cmd = '\x10setTime('+(d.getTime()/1000)+');';
+      let cmd = '\x10setTime('+(d.getTime()/1000 + delta)+');';
       // in 1v93 we have timezones too
       cmd += 'E.setTimeZone('+tz+');';
       cmd += "(s=>{s&&(s.timezone="+tz+")&&require('Storage').write('setting.json',s);})(require('Storage').readJSON('setting.json',1))\n";

On my setup the delta is about 0.6 seconds. What do you think?

I'm afraid this doesn't work for several reasons...

  • Promise.resolve doesn't resolve a promise as far as I can see and it returns immediately - you'd need await for that, or to use .then : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/resolve
  • comms.write includes a ~500ms delay while waiting for a response
  • performance.now() is in milliseconds, and then you're adding it to the time which is in seconds - so you're measuring the delay wrong (I guess it's 0.6ms not 0.6 sec), and then correcting it by 1000x too much.

This should provide a slightly more accurate estimate:

var t=performance.now();Puck.write("print('hello')\n", function() { console.log("delay", performance.now()-t,"ms"); }, true)

And if you run it when the Bangle connected, you'll see there's usually about a 20ms delay, which is about what you'd expect (7.5ms connection interval, plus a bit of overhead).

So basically it would seem to be setting the time just fine.

How were you measuring the difference in time that was set?

This code will measure the difference (ignoring the connection interval):

var t = Date.now();console.log("PC", t);Puck.eval("Date.now()", function(e) {console.log("Bangle", e); console.log("Diff", e-t);})
PC 1674204044674
undefined
Bangle 1674204044658.5474
Diff -15.45263671875

Initially I saw a difference of ~170ms which was due to the connection interval being low to save power, but after doing it a few times it sped up and I saw the above - so 15ms difference - but much of that could be from the connection delay, so the actual difference is probably under 10ms.

So I think this is a non-issue. If the clocks are showing the time a little out then that's probably because they use setInterval(1000) which isn't guaranteed to update on the second exactly