• I'm trying to see if I can develop a minimal pedometer widget based on using
    Bangle.getHealthStatus("day").steps

    Minimal in the sense that it does 1 thing really well, no settings, simple code that will avoid dependancies. Also want the lowest power drain whilst being useful.

    My code appears to be working but am noticing a few issues:

    1) If you reboot (long BTN1 reset) then Bangle.getHealthStatus("day").steps resets to 0 - you have lost your days step count. This does not happen with widpedom with stores the stepcount to storage using the on.('kill') event.

    2) Noticing throughout the day that Bangle.getHealthStatus("day").steps is a 10, 20, 30 steps ahead of widpedom, this could be me doing lots of code installs , resets etc. To really observe properly I will need to soak test it on a watch that I do nothing but wear for 36-48 hours.

    3) I am showing a 6x8 font version below, but I really want to a nicer small font. Lato comes out at about 500 bytes - which is quite large, even just with the numeric numbers only. What are the factors that mean a font comes out low in bytes - is this just trial and error ?

    4) @ Gordon - is calling Bangle.drawWidgets() - safe in the draw function ? I copied it from widpedom. I tried running from setTimeout that lead to issues.

    5) Is it better to use setInterval(...) or Bangle.on('step',) to trigger redraws.
    setInterval will be predictive, but will it still draw when the LCD is off on a Bangle 1?
    Bangle.on('step',) will redraw when LCD is as well ?
    I am looking for simplest, lowest power drain solution.

    setInterval(()=>WIDGETS["bata"].draw(), 5000);
    Bangle.on('lcdPower', function(on) {
      if (on) WIDGETS["bata"].draw();
    });
    WIDGETS["bata"]={area:"tl",width:12,draw­:function() {
      var steps = Bangle.getHealthStatus("day").steps;
      var w = (steps.toString().length)*12;
      if (w > this.width) {this.width = w; Bangle.drawWidgets();}
      g.reset();
      g.setColor(g.theme.bg);
      g.fillRect(this.x, this.y, this.x + this.width, this.y + 23); // erase background
      g.setColor(g.theme.fg);
      g.setFont('6x8',2);
      g.setFontAlign(-1, 0);
      g.drawString(steps, this.x, this.y + 12);
    }};
    

    Note in the above code I have just hijacked widbata so I dont have to wait for the App Loader to update after a push.

  • 1) If you reboot (long BTN1 reset) then Bangle.getHealthStatus("day").steps resets to 0

    Yes, that's expected. I feel like the amount of times someone will hard-reboot their watch should be basically zero in normal usage though?

    Potentially later this could be improved though (eg scraping the recorded health data on first boot)

    2) Noticing throughout the day that Bangle.getHealthStatus("day").steps is a 10, 20, 30 steps ahead of widpedom

    Well, this probably shows its working better. There are cases (eg if you hard-reboot by long-pressing the button) where widpedom can't store the latest step count

    What are the factors that mean a font comes out low in bytes - is this just trial and error ?

    Its entirely related to width * height * characters.

    If you define the font inside the rendering function, the font will stay in flash memory though so it's less of a big deal

    4) @ Gordon - is calling Bangle.drawWidgets() - safe in the draw function ? I copied it from widpedom.

    It's not great - it's going to cause it to recurse. widpedom really shouldn't be doing that. You could do: setTimeout(() => Bangle.drawWidgets(), 10);return to force it to redraw once everything else is done I guess.

    Is it better to use setInterval(...) or Bangle.on('step',) to trigger redraws

    I'd say to redraw on 'step' - after all, that's when you know something has changed. You can always check Bangle.isLCDOn to skip a redraw

  • times someone will hard-reboot their watch should be basically zero in normal usage though?

    I agree. I only rebooted as things got complicated by running into
    https://github.com/espruino/BangleApps/i­ssues/1249

    Well, this probably shows its working better.

    I agree. There are windows where widpedom could drop steps.

    I have been monitoring for a few days. They basically stay in step unless there is a full reboot or you walk about when widgets are not loaded.

    setTimeout(() => Bangle.drawWidgets(), 10);return

    I initially had that as I though it was the way to do it. But when I ran into #1249 I took it out as I thought I might have caused it.

    But when I try just that 1 line change I get the following on the console when the widget reloads or you come back from choosing an app in the launcher.

    >
    Error: Error: Function or String not supplied!
    Error: Error: Function or String not supplied!
    >
     ____                 _
    |  __|___ ___ ___ _ _|_|___ ___
    |  __|_ -| . |  _| | | |   | . |
    |____|___|  _|_| |___|_|_|_|___|
             |_| espruino.com
     2v11.7 (c) 2021 G.Williams
    Error: Error: Function or String not supplied!
    >
    
  • @Gordon - any ideas what might cause the

    Error: Error: Function or String not supplied!
    

    above ?

  • Error: Error: Function or String not supplied!

    It happens when setInterval/timeout/watch is called with a first argument that's not a function or a string.

    It's hard to believe that setTimeout(() => Bangle.drawWidgets(), 10); is what is causing it. You could add some logging statements to try and see - could there be anything else?

  • I can literally change that 1 line back and forth and cause or stop the error very strange?

  • Might be showing a lack of Espruino knowledge, but why are you wrapping Bangle.drawWidgets rather than setTimeout(Bangle.drawWidgets, 10);? If it is necessary, try putting in the brackets around it. I wonder if it is being evaluated.

  • Doing setTimeout(Bangle.drawWidgets, 10) would run drawWidgets without setting this to anything. I think it may work, but for many functions it would fail

  • My apologies - I should be using

    setTimeout(() => Bangle.drawWidgets(), 10);return
    

    instead I was using:

       setTimeout(Bangle.drawWidgets(), 10);return
    

    I have tested and the error goes away now.

  • Aah so I was on the right lines thinking it was being evaluated, I just overcomplicated my reasoning about why.

  • Have done a pull request for

    • Simple Pedometer, uses 6x8,2 font
    • Lato Pedometer, uses a 6x18 Lato font.
  • Firstly, love the idea of the widget.
    I do seem to have an issue though where the daily count does not reset, and the widget shows an accumulation of steps.

    Happy to give more details here or raise an issue on github.

  • I do seem to have an issue though where the daily count does not reset, and the widget shows an accumulation of steps.

    You'll need to be on 'cutting edge' firmware. 2v11 had that exact issue

  • Oh, my firmware widget says 2v11... hmmm.

    Is there a way to see the exact firmware version from the webIDE? (have tried looking in the docs but can't spot it).

  • Ah looking in the source for the widget I see this

    process.env.VERSION;
    

    This returns "2v11"

    UPDATE: running the following is also giving me incorrect step data;

    Bangle.getHealthStatus("day").steps;
    

    I have looked in the Health Tracking app and can see that on the "per day" view I do not see today's count (?), though I do see todays steps in the "per hour" view. The total of today's "per hour" plus yesterday's "per day" gives me the value that I get from the "Bangle.getHealthStatus("day").steps;".

  • You need 2.11.21 or later.
    You have 2.11.0

  • Ah! Apologies... I completely missed that.

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

minimal pedometer widget based on `Bangle.getHealthStatus("day").steps`

Posted by Avatar for HughB @HughB

Actions