Data Field: AppBuilder

By user request, this app lets you define your own data field, based on a simple math formula like cadence / 2.

If you want to get fancy, there's conditional expressions (like IF in Excel), functions for data analysis (like MIN and AVG), and the data field can also display the text of your choice. The resulting data can be (optionally) written to the activity FIT file.

With AppBuilder, you can implement almost any field that involves math, such as: calculating normalized power and saving the data to the FIT activity file, showing the average pace for even-numbered laps, or recording the amount of time you sprinted.

Full documentation and examples here:
http://ciq-appbuilder.blogspot.com/

AppBuilder 5:
Now with new features! AppBuilder 5 is a completely new app, so please check it out in the store if you are interested in any of the new features.
https://apps.garmin.com/en-US/apps/fd690281-9c22-4fee-a81e-3b7f39aa67c5

- Store up to four formulas per app. Switch between formulas directly on the watch, without using a phone or PC. With four clone apps, you can store up to 16 formulas total
- User variables. Allows for powerful formulas where information can be stored at one point, like the start of a lap, and used later. e.g. Lap elevation change
- Improved timeavg() options. Allows for simpler, more flexible normalized power function
- More functions and variables

4 clones of AppBuilder are available in the store, so you can have 2 formulas in the same activity
  • Former Member
    Former Member over 7 years ago
    I just posted a 5 star review for AppBuilder. Having all these functions available to define a datafield is a very impressive accomplishment on your part. I'm using it to alternate in one data field between heart rate and average heart rate and in another data field between Timer and TimeOfDay. The formula I'm using is IF (Timer mod 6 LT 3, -Timer, TimeOfDay) so that I alternate between Timer and TimOfDay every three seconds. I'm very happy with how well these two data fields work on my 920xt. The only improvement that I might like would be to have a new format available of the form Time3(Seconds to [hh:]mm) so that only hours and minutes and not seconds would be displayed. This would allow the Timer and TimeOfDay to be displayed in a larger font. I'm doing hiking and cross-country skiing so that seeing the seconds is not important to me. I realize, of course, that it may not be possible to fit a new format into your software. Thanks again for creating AppBuilder.
  • The only improvement that I might like would be to have a new format available of the form Time3(Seconds to [hh:]mm) so that only hours and minutes and not seconds would be displayed.


    Thanks, @mbankier!

    Actually, there is already a workaround for what you want. Even though many of these requests are not difficult at all to implement, doing so would reduce memory (for formulas) for all users, whether or not they use that feature. So, right now, I'm leaning towards using workarounds where possible.

    I posted this in the page for AppBuilder3. (The examples are spread out over the 4 appbuilder store pages, because unfortunately there is a limit on the amount of text there. I prefer to keep most of the examples in the store, because it's the only website that can be viewed in the Garmin Connect app without opening an external browser. Also because I can be fairly confident that the store pages will remain untouched as long as the app exists.)

    Time of day [24-hour clock], no seconds
    Formula:TimeOfDay div 60
    Display Format: Time

    This will also work for Timer.

    (Note to mod: I quoted the post above me so the poster would get a notification, because @-mentions don't seem to be working in this case.)
  • Full examples for "proper" normalized power, which ignore the first 29 seconds after activity start, lap start and unpausing the timer. Thanks to JTH9 for testing this stuff out.

    Unfortunately the forum is back to it's old tricks, so you will have replace square brackets with round brackets. I have also posted the same formulas, with the proper brackets that you can copy and paste, on the store page for AppBuilder4:
    https://apps.garmin.com/en-US/apps/f...9a39e44e1b9f#0

    1) Normalized Power (native): Activity average
    AVG0[IFS[Timer GTE 30 and [Timer - MAX[if [PREV[timer] eq null, timer, null]] plus 1] gte 30, TIMEAVG0[Power,30]^4]]^0.25

    2) Lap NP (native): Carries the rolling average over from prev lap
    LAPAVG0[IFS[Timer GTE 30 and [Timer - MAX[if [PREV[timer] eq null, timer, null]] plus 1] gte 30, TIMEAVG0[Power,30]^4]]^0.25

    3) Lap NP: Resets at start of each lap
    LAPAVG0[IFS[LapTime GTE 30 and [Timer - MAX[if [PREV[timer] eq null, timer, null]] plus 1] gte 30, TIMEAVG0[Power,30]^4]]^0.25

    Also see these posts:
    https://forums.garmin.com/forum/deve...31#post1310631
    https://forums.garmin.com/forum/deve...52#post1310852

    Technical notes:

    - technically, "timer gte 30" is redundant in these examples, but I'm leaving it in for "clarity"
    - in the formulas above, data for the rolling average of power is still collected by the TIMEAVG0 function (while the watch is not paused), for the first 30 seconds. It just isn't used to calculate the NP value until the initial 30 seconds passes after start/lap/unpause, which is how it should work. The fancy conditions in the IFS are necessary because:
    -- TIMEAVG0 still returns data when the number of samples is smaller than the window size (which is technically wrong). Technically it should collect sample data, but not return an average until the number of samples equals the window size. This situation arises at the start of the activity (from 0 to 29 seconds) and the first 29 seconds after the watch is unpaused (since of course, all rolling average sample data is thrown out at that point).
    -- Even if TIMEAVG0 were changed so that it returned NULL when the number of samples is smaller than the window size, that wouldn't help us in the case of 3), where we want the rolling average at the start of the lap to be undefined or null, since the rolling average really doesn't (and shouldn't) care whether you just lapped your activity or not.
    -- "Timer - MAX[if [PREV[timer] eq null, timer, null]] plus 1]" counts the number of seconds since the watch was unpaused
  • Former Member
    Former Member over 7 years ago
    Wow, thanks for that. I'll try it out in the next few days. :)
  • What a great app! Thank you so much. My use case is on an Edge 1000 Explore, which with recent Garmin software updates, now has a very jumpy gradient field. So I'm using the formula posted in your OP, and playing around a bit with whether it's measured over the past 50 meters or 35 meters. I suspect this is more a Garmin unit question, but is there any way to pull my elevation data from the altimeter in the unit, as opposed to GPS, or quite frankly, even to know which is doing the job?

    Regardless, one feature request, which I don't know whether it falls in the text display category, or is already solved. I would like to display gradient (a) to one decimal point (i.e., 3.5) and (b) with a trailing "%" sign (i.e., 3.5%). Even if I can't get the % sign, can I get the one decimal point with a divide by 10 or something if I use the decimal display option?

    Thanks again for your work and updates.
  • Thanks, rogerinnyc !

    Unfortunately, that information about altitude (GPS vs. barometer) is not available to apps. You can add data screens with both elevation and GPS elevation, but you can't tell which one is used by AppBuilder. According to the SDK:
    Elevation is derived from the most accurate source: Barometer or GPS in order of descending accuracy. If no GPS is present, then barometer readings will be used.


    Unfortunately, displaying only one decimal place and a trailing "%" sign are not currently possible. If you multiply by ten and use the Number format you'll get 35 for 3.5 (for example), but I imagine that's not what you really want.

    There's so many features I would like to add, but at this point I'm worried about impacting memory usage, especially for older devices. Of course, any new features would probably only be added to newer devices at this point. I'll add those to the wishlist!

    But theoretically, even with newer devices, if there's one user who currently uses all available memory for a really complicated formula, and I add one tiny feature, that user's formula will no longer work. And I have no idea if that's the case or not.
  • I just invested in a Humon Hex, which connects to the 935's SMO2 channel via Ant+ giving access to SMO2% and tbH. Is there any way to use these native fields in appbuilder? I am specifically interested in trend of the SMO2%, in the context of a steady state race like a half marathon or a marathon.

    NB There is a Garmin Humon Hex CIQ app but that restricts the use of other fields including Stryd Power etc not to mention setting up intervals. Plus I got burned by the Stryd Garmin app crashing in a big race last year, so would much rather use a data field within the generic run app....
  • dobssi , sorry, muscle oxygen native data isn’t currently available to Connect IQ apps. Garmin is aware of the user interest, though.

    https://forums.garmin.com/forum/deve...-activity-info

    Maybe you can use the Humon data field instead.
    https://apps.garmin.com/en-US/apps/5...1-4152ab1b2ffe
  • Hey everyone:

    As you may have noticed, the wishlist for AppBuilder is getting pretty long. I'm seeing requests for:
    - Arbitrary symbols/text
    - More display formats
    - More data: e.g. barometer, temperature

    A few more things I would've liked to add:
    - Variables with fixed friendly units: e.g. Speed_km_per_h, Distance_miles, etc.
    - More control over how the rolling average is calculated (without workarounds)
    - Making AppBuilder a complex data field (so you can have dynamic labels, colours, and you could use 1 data field for the whole screen, with multiple values)

    What's holding me back on implementing any of this stuff, other than finding free time, is the the amount of memory the app currently uses, especially on older devices. Even on newer devices, I don't want to use up much more memory, in case I break someone's really complex formula.

    With that in mind, I've always had one kinda radical idea about how to save memory in AppBuilder. A pretty big chunk of the app, believe it or not, is just taking the sorta readable formula that you type into app config and converting that into something the app can use. If I took that code out of AppBuilder and put it in a separate web app (like DIY Data Field), then there would be more room for features that people want. I wish there could just be a separate app on the watch to do this, but unfortunately Garmin has designed Connect IQ so apps really can't share data in the necessary way.

    With that in mind, I'm really not sure how much demand there is for a data field app that requires you to use a web app to configure it. If you have an opinion on the matter, please vote in this poll:
    https://forums.garmin.com/forum/deve...eeds-a-web-app
  • Former Member
    Former Member over 7 years ago
    Thanks for your prompt reply! Your following workaround worked for me:
    Time of day [24-hour clock], no seconds
    Formula:TimeOfDay div 60
    Display Format: Time

    I then wrote the following code to have TimeOfDay display as a 12-hour clock without seconds
    IF (TimeOfDay-43200<0,TimeOfDay DIV 60,(TimeOfDay-43200) DIV 60)
    in case someone else might find this useful. Though perhaps this code is already present somewhere else in the AppBuilder forum!