1hz Watch Faces - Q&A

I'm not sure if many folks have been trying the new "always active" watch faces in 2.3.x, but the 2.3.0.beta1 has been out for a month or so now. It's probably getting close to the 2.3.1 SDK release, and thought I'd start a Q&A for the feature, and start with some of what I've picked up in adapting a number of watch faces to use 1hz.

I'll be calling this feature "1hz", as that's what it really is - being able to change the screen on a watch face every second.
The most common thing will likely being the ability to display seconds all the time. One thing I'll note right off, is while you can update the screen every second, the underlying data still changes at the rate it did before, so if you use 1hz for the HR, you won't see the HR change every second.

A few basics.

  • 1hz is only available on some watches. The f5, f5s, f5x, 935, and Q5, but if you support a bunch of different watches, you can easily have it on some and not others.
  • 1hz happens by way of a new onPartialUpdate() for watch faces. onUpdate() is just like it was in the past, and when you are allowed to do a 1hz update, onPartialUpdated() is called. You don't have to change a thing in your code if you don't want to use 1hz.
  • onPartialUpdate() is VERY strict as to how long it can run. You have a "power budget", and the rule is that each minute, the average run time each second can't be greater than 30 milliseconds. This is the tricky part! :)



I started with the Analog Sample in the SDK, which does show what to do, but has some things you don't need to do for digital watch faces - there's no second hand passing over a bunch of different places on the screen with a digital one. The time is in a fixed spot on the screen in most cases.



Anyway's, the first thing I did was cut back to the basics of what was needed for a digital WF. I'll attached a project with a very basic 1hz watch face, but first a few notes about it.

  • vs1hzapp.mc shows how to use the delegate for the power exceeded deligate on watches that have 1hz, and still run on watches that don't do 1hz.
  • vs1hzview.mc I tried to comment as to where to do things, where not to do things, but took a simple approach where I don't just update the seconds at 1hz, I actually do hh:mm:ss. In real code, you likely have a separate space for seconds, and your setClip() will be adjusted for that. I just wanted to get the ball rolling here :). Also, note onEnterSleep() and the code there for 1hz...
  • In onPartialUpdate(), I have a comment about a simple change to make the watch face exceed the power budget, so you can see how that works



Ask questions, suggest other ideas, whatever. That's what this thread is for!

So here's the project! (it might be a bit different than the original one that was lost in the forum update) :

VS1hz-old.zip



NOTE: I should have mentioned this before, but you want to use a 2.3.x SDK for this project!

  • Thanks for the good information to share.

  • Hello guys,

    On my watch face the onPartialUpdate takes less than 30 ms (only updates the seconds) but when the normal onUpdate is called when the minute is changed all the calculations and data drawings take near 300 ms. This causes a visible lag especially when you are concentrating on the seconds.

    I'm afraid I can't get the onUpdate near 30 ms. How do you handle this?

    Thank you

  • onUpdate doesn't have the 30 ms limit.  Only onPartialUpdate does.  Sounds to me that when onUpdate() is called, you are simply "doing too much".  Try commenting out things in onUpdate until you don't see the lag.  

    Are you updating second in onUpdate as well as in onPartialUpdate?

  • Here's the code I use with onPartialUpdate() for onExitSleep() and onEnterSleep, as maybe there's an issue when you transition in and out of low power:

        // The user has just looked at their watch. Timers and animations may be started here.
        function onExitSleep() {
        	inLowPower=false;
        	if(!do1hz) {WatchUi.requestUpdate();}
        }
    
        // Terminate any active timers and prepare for slow updates.
        function onEnterSleep() {
            inLowPower=true;
        	if(!do1hz) {WatchUi.requestUpdate();}   
        }

    do1hz is a boolean I use in onUpdate to see if onPartialUpdate is getting called or not.  Things like the venu/venu2 don't call onPartialUpdate, and the same for some older devices that don't support onPartialUpdate.

  • Yeah I checked your code in this thread Slight smile

    Thanks for the hint, I checked my code's running time almost line by line and it turns out System.getDeviceSettings() takes 20 ms on my Vivoactive 3... So restructered it a bit to pass it as parameter plus I only calculate SunriseSunset every 30 minutes. I went down to an average of 142 ms which is acceptable for me regarding all the drawings on the screen.

  • hey guys! got my wf to work but its power consumption may still be a lot improved, so i am researching relative topics.

    i have some questions:

    -while NOT sleeping, onPartialUpdate is called as well?
    -while sleeping, onUpdate is called? how often?

    pretty sure i saw answers for both but didn't managed to find, so... thanks in advance!  

  • When in low power mode, onPartialUpdate() is called every second, except at the top of the minute when onUpdate() is called.

    When not in low power mode, onPartialUpdate() isn't called, as onUpdate() is called every second.

  • geez. lightning fast. thx!
    yet related to power consumption:

    -findrawableById everytime versus find once and keep view reference in memory;
    -System.getClockTime vs Time.Gregorian.info(Time.now()

  • I don't use layouts in watch faces.  I know the x/y/font.  I tend to use getclockTime() in onPartialUpdate() as all you need is seconds and Time.Gregorian.Info() in onUpdate() so things like the date are available.

  • any special reasons on avoiding layouts for watchfaces?