Announcement

Collapse
No announcement yet.

1hz Watch Faces - Q&A

Collapse
X
  • Time
  • Show
Clear All
new posts

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

    NOTE: I should have mentioned this before, but you want to use a 2.3.x SDK for this project!
    Attached Files
    Last edited by jim_m_58; 05-26-2017, 08:24 AM.
    My Connect IQ Apps in the Store
    Facebook - Instagram -
    Twitter

  • #2
    Thanks for sharing Jim!
    My Connect IQ apps
    I only run so I can wear a Garmin!

    Comment


    • #3
      Thank you Jim!
      Current Fenix5X + Tempe + Foot Pod
      Previous Fenix2, Fenix3 : SN 46300xxxx

      My apps

      Comment


      • #4
        One of the things here, is there could be some things found that you simply can't/don't want to do in onPartialUpdate(). So note those things here.

        Something I heard (I think it was at the Summit), was you don't want to load any resources. Anything you need should be loaded prior to onPartialUpdate()
        Last edited by jim_m_58; 05-26-2017, 06:42 AM.
        My Connect IQ Apps in the Store
        Facebook - Instagram -
        Twitter

        Comment


        • #5
          I have another project for very simple watch face with a very simple background process. If there is interest, I'll post that, but maybe in a new thread.

          The watch face itself displays the current time (no 1hz or 12/24), as well as the background data it has seen. And the background process simply returns a string with HH:MM when it's run (a temporal event every few minutes). It's got a number of Sys.println() calls to see when things happen in the sim. But if you sideload it and have a <myapp>.txt log, it will show if something is running in the foreground process or the background one was the one did that Sys.println().
          My Connect IQ Apps in the Store
          Facebook - Instagram -
          Twitter

          Comment


          • #6
            I think the "Always Active" 1hz feature is a great addition!
            Jim's code has been very useful as a guide.

            Recently, I've been busy experimenting with a "marching invader" watchface.. a different take on displaying the seconds! Here's what it looks like...

            Vaders! at high power
            https://gfycat.com/FluidJointEel

            Vaders! at 1hz
            https://gfycat.com/FrighteningHonorableCoypu

            I can tell you now — the game logic plus juggling multiple dynamic clip frames was tricky to shoe-horn into a 50ms budget.
            What I've found, is that the power budget is very easy to exceed if you need to render anything "big" on the screen in any form.

            So, using too large a clipping size, or using too many clipping frames will exceed the budget. My example uses about 5 clipping frames at most.
            Also accessing a dictionary, iterating though an array, or accessing multiple objects can cause a process to exceed the power budget.

            Cheers..

            Comment


            • #7
              looks nice! a bit slowish but fluid animations
              My best Connect IQ apps:Other:

              Comment


              • #8
                Franco. It's even harder when the max avg is 30ms and not 50ms

                I forced exceeding the budget and here's what I see from the delegate:

                Code:
                Average execution time: 53.728001
                Allowed execution time: 30.000000
                I forced this by simply skipping the dc.setClip() with onPartialUpdate().
                Last edited by jim_m_58; 06-03-2017, 08:15 AM.
                My Connect IQ Apps in the Store
                Facebook - Instagram -
                Twitter

                Comment


                • #9
                  Thanks for great example Jim!

                  I have been fiddling around with this and managed to get always active seconds in watch models which support it. I created separate space for seconds, and my setClip() is adjusted just for seconds field.

                  However now minutes are not updated anymore, those are left below onUpdate() where they use to be. I am calling onPartialUpdate() only in case partial updates are allowed:
                  Code:
                  partialUpdatesAllowed = ( Toybox.WatchUi.WatchFace has :onPartialUpdate );
                  and if watch is in sleep mode. I can see from console Sys.println's that onPartialUpdate() is called, but how an earth is minutes not updated under onUpdate() anymore? I can see from Sys.println's that onUpdate is "run" every minute and onPartialUpdate() every second

                  On watch models that do not support "always active" seconds minutes are working as they used to be.

                  Comment


                  • #10
                    Originally posted by Jan_72 View Post
                    Thanks for great example Jim!

                    I have been fiddling around with this and managed to get always active seconds in watch models which support it. I created separate space for seconds, and my setClip() is adjusted just for seconds field.

                    However now minutes are not updated anymore, those are left below onUpdate() where they use to be. I am calling onPartialUpdate() only in case partial updates are allowed:
                    Code:
                    partialUpdatesAllowed = ( Toybox.WatchUi.WatchFace has :onPartialUpdate );
                    and if watch is in sleep mode. I can see from console Sys.println's that onPartialUpdate() is called, but how an earth is minutes not updated under onUpdate() anymore? I can see from Sys.println's that onUpdate is "run" every minute and onPartialUpdate() every second

                    On watch models that do not support "always active" seconds minutes are working as they used to be.
                    Do you clear the clip again in onUpdate()?

                    Not sure, hard to say without code where things go wrong... I was messing around a lot only to find out I had reversed two lines of code by accident causing some coordinates to be out of sync.
                    My ConnectIQ apps

                    Comment


                    • #11
                      My guess is that you aren't doing a clearClip() or not doing it at the right time. Without the clearClip() working properly, the only area of the screen that updates is where your last setClip() defines, so all that will update on the screen will be the seconds even from onUpdate().

                      In the code I posted, notice where I do the clearClip(). I have it commented out at the end of onPartialUpdate() with a comment noting that doing it there didn't see to work right (at least as of last time I tried which was the 2.3.0.beta1), and I do the clearClip at the start of onUpdate() (with the proper checks) instead.
                      My Connect IQ Apps in the Store
                      Facebook - Instagram -
                      Twitter

                      Comment


                      • #12
                        Originally posted by FlipStone View Post
                        Do you clear the clip again in onUpdate()?

                        Not sure, hard to say without code where things go wrong... I was messing around a lot only to find out I had reversed two lines of code by accident causing some coordinates to be out of sync.
                        Thanks! this was it. I was doing it on wrong place (at end of the PartialUpdate() DOH

                        Comment


                        • #13
                          With Jim's help we found that if you have System.println statements in onPartialUpdate, it may cause onPartialUpdate to not execute at all on an actual device.
                          This happens if you are debugging the actual device by writing to the log file.

                          This works in the simulator which is misleading when trying to figure out why onPartialUpdate doesn't work on the actual device.

                          Println statements are very slow on actual devices and causes the onPartialUpdate to exceed its budget and therefor not execute.

                          Just posting this scenario here to warn and inform others.
                          My Connect IQ apps
                          I only run so I can wear a Garmin!

                          Comment


                          • #14
                            Originally posted by HermoT View Post
                            With Jim's help we found that if you have System.println statements in onPartialUpdate, it may cause onPartialUpdate to not execute at all on an actual device.
                            This happens if you are debugging the actual device by writing to the log file.

                            This works in the simulator which is misleading when trying to figure out why onPartialUpdate doesn't work on the actual device.

                            Println statements are very slow on actual devices and causes the onPartialUpdate to exceed its budget and therefor not execute.

                            Just posting this scenario here to warn and inform others.
                            This actually should not be a problem. Calls to println will not execute on hardware during a partial update, but they should not incur any budget hit, or cause any problems.

                            Can you create a bug report for this issue?

                            Comment


                            • #15
                              Originally posted by Brian.ConnectIQ View Post
                              This actually should not be a problem. Calls to println will not execute on hardware during a partial update, but they should not incur any budget hit, or cause any problems.

                              Can you create a bug report for this issue?

                              Will do
                              My Connect IQ apps
                              I only run so I can wear a Garmin!

                              Comment

                              Working...
                              X