DIY Data Field

Former Member
Former Member
Application is still pending to be approved, topic is created to be used as a communication hub during and after public beta test.

Do/Design It Yourself Data Field.

Disclaimer:
Application has hundreds of use-cases due to fully user-configurable setup, therefore it is prone to bugs. This project is not sponsored and I'm the only developer working on it in my own free time. Although I'd gladly accept reasonable criticism and improvement suggestions, I do not guarantee that bugs will be fixed and new features added in a timely manner/at all. If this approach is not acceptable for you, then, please, do not leave bad reviews just because I didn't resolve your specific case. Thanks for understanding.

Preface:
There's a lot of things custom activity recorders can do, which native Garmin apps cannot, but sometimes there's no need to invent a bicycle if there's one already itching for a ride. Some capabilities like local watch personal records, structured workouts information and advanced running dynamics will most certainly never be exposed to ConnectIQ API layer, therefore it's sometimes more efficient to use native software, but no one prevents us to use it with a twist. The main idea of this data-field type application is to give user a tool to design his own data field layout in WYSIWYG manner. The web application makes that possible providing cross-platform compatibility at the same time the only requirement being the HTML5 compatible browser. This app is not considered to be an ultimate DF which "replaces them all" as there's always something new and intriguing, which developer may envision, but I hope that this data field will help new and existing users to explore the Garmin ConnectIQ capabilities providing some unique features, which I didn't encounter in existing apps.

First things first: there's a web application, which allows to design data field layout and produces configuration string as a result. This configuration string can only be delivered to data field using standard settings means i.e. you will need either Garmin Express installed on compatible PC or Garmin Connect Mobile on your mobile device. Web app uses HTML5 local storage, changes are saved after each user action, therefore it's safe to leave your work half done and proceed from the same point sometime later. I do not own hardware to test with Apple devices, therefore any problems in that department can be explored and fixed only by sending me detailed explanations and, of course, the configuration string itself. Current version with the default layout setup was tested for several weeks in simulator and for several of my personal runs proving to be rather stable to go live, but of course there's no guarantee that this app will function without hitches on your specific device. Currently, I do not have a reliable hosting for my personal web apps, therefore data field designer will reside on Google Apps Engine servers using free account bandwidth/limitations (as there are almost no server-side computations, I think this will suffice for a while) at least if/until it'll become popular enough for the users to complain about page availability. Current implementation with the default layout setup works on the edge of stability and there was also a price to pay during watch code optimization, which lead to efficient but very unreadable code. This means that for older devices there may be no improvements, only bug fixes. But for modern devices like Forerunner735XT and on we still have additional 10kb of available memory, which can be used for new logic like new data values and/or additional app parameters (e.g. waypoints). Sometimes network latency and/or Google servers accessibility seems to impact resources load time and wrong font may be displayed first time the web app is started, to fix this simply press F5 (refresh page) in browser.

Current settings are 4 lines for definition itself (these should be copy/pasted without changes directly from web app), Target Pace for pacemaker values (should be entered as string in <min>:<sec> format, e.g. "5:40" as in min/km) and Milestones, which are just fixed distances comma separated list, they are expressed in kilometers and may contain fractional values using dot delimiter (e.g. 0.5,1,1.5, etc). It'necessary to enter values in kilometers, but they will be converted before display depending on watch settings.

Default setup is considered to be a "component showcase" and consists of basic building blocks:
- Data values, which are simply text representation of corresponding activity information bits like time or speed, for data values it's possible to change screen coordinates, font, color, number of samples to smooth the value over specified amount of seconds and add optional outline for data to become more readable or dynamically colored on less contrast backgrounds; if text font is selected, then it's also possible to append data value with custom text, e.g. create label with value for another data block;
- Data graphs, these are just rolling data value charts, which represent one selected data value over a set period of time, minimum and maximum graph values are adjusted automatically, number of samples is calculated automatically based on width of graph area and graph bar, all of the other options are similar to data values;
- Graphics elements, these are basic graphical primitives, which allow to customize the layout, add visibility to some values etc; parameters for these elements are mostly self explanatory except for two specific elements of type Arc. These may not only serve as a static view elements, but also can be used to represent a dynamic data value in a manner of a progress bar. For this to happen you need to tick the "Variable" option and select base Data value (currently there's only a limited selection, but this may be a subject to change) accompanied by min and max initial values, these range values are indeed initial as when the underlying data value falls outside of this range, then range is adjusted automatically. For example in bundled layout this feature is used to display the progress to the next kilometer: Elapsed distance is selected as a base value, initial range is specified as 0 to 100 (in this case 100 means 1000m, as the distance values are displayed as 00.00), which means that this arc will grow from start angle to the maximum width angle as the elapsed distance increases during activity acting as a progress bar to the next kilometer. When elapsed distance will become greater than 1000 meters, then ranges will be readjusted using the same range difference as before, in this case minimum value will become 1000m while maximum one will increase to 2000m. Here's a little demo of what you can make using variable value arc (this config is created for semi-round devices, copy/paste this configuration string into import window of web app).
AGUAJA[HIWaVFAJNATXDEAODZQVELEUA[HIWaVFAODU]`DEAOEOQVEVE_A[HIWaVFAABG`[DEAOFDQWE`FHA[HIWaVFAABHGRDEAOF[QWFIFRA[HIWaVFAJNA\ODEAOGQQVFSF\A[HIWaVFAOE]CPCWAODZTMELF\A[HIWaVFAAAAAACWAPDWTMELF\ASADILDAPOE]CPFEABAVDVENQAPQAAAFDJCFACB

Selected element options can be adjusted using the properties panel to the right of the designer canvas. In addition to pixel-by-pixel adjustments, designer canvas allows to drag currently selected element. To drag data value it's not necessary to start drag at any specific point, but for graphs and graphical elements the drag point will be determined based on mouse pointer coordinates: e.g. to resize graph area or rectangle click and drag somewhere around the lower right corner, to adjust the radius of circles and direction arrow start drag outside of the outer radius, to change coordinates - click somewhere near the circle center. For the arcs it's currently possible to change start angle and arc width by activating drag-and-drop near the corresponding arc vertex. Touch support for mobile devices is implemented.

There are still some limitations like direction arrow points only to north or some data values available only on high-end devices like power are not yet implemented etc, but as I already mentioned above, this app is subject to improve especially for the newer devices, where there's a lot of memory available even for the data field type of app. The web app is also meant to be improved especially in a direction to provide the nearest possible WYSIWYG snapshot of what you'll actually see on device, but there are also some limitations like, for example, font, which is used as numeric font in the latest Fenix5/FR935 models is not and won't be publicly available (confirmed by Garmin officials explicitly) and I used nearest lookalike, therefore there still may be some couple of pixel differences here and there between device and web app. For these kinds of problems I can only test and fix using the user-provided layouts in specific device simulator as I'm a simple FR230 owner for real testing and I'm afraid this won't change in the nearest year unless generous users will help me to upgrade.

Web app may eventually become mobile application based on the user feedback (but not for the Apple devices, Android only).
  • Wow @orofab, very nice looking DF!


    Thank you, @PatFelstead. I was just trying to build my 1-page Swiss army knife data field, covering 98% of my needs. :D

    Only two things missing are 'Performance Conditions' and 'Last Lap Pace'. And currently not working is Lap Pace... but I am pretty confident that this app will evolve with time
  • Former Member
    Former Member over 8 years ago
    This calculation seems correct, I agree it shouldn't take into account distance travelled with timer paused manually, this isn't the issue as I only check when moving. Can you post a code snipped so we can review, or you can PM it to me?

    Here you are, maybe I have already got used to the code and don't see obvious mistake:
    if (pT > 3 && info.elapsedDistance != null && info.elapsedTime != null &&
    info.elapsedDistance > 0 && info.elapsedTime > 0)
    {
    // lap pace, pT > 3 == lap values
    if (values[5] < 0) {
    // value[5] == lap number, value[5] < 0 - lap triggered
    values[arrOff + 9] = info.elapsedDistance;
    values[arrOff + 10] = info.elapsedTime;
    retVal = info.currentSpeed;
    //Sys.println("updating lap pace base values");
    } else {
    retVal = info.elapsedTime - values[arrOff + 10];
    retVal = retVal > 0 ? 1000f * (info.elapsedDistance - values[arrOff + 9]) / retVal : 0;
    }
    } else {
    retVal = info.currentSpeed;
    }
  • Former Member
    Former Member over 8 years ago
    Would it be possible to have as well a data value showing the 'Performance condition'.

    Unfortunately I'm not aware of the math behind this value, if you point me into right direction, then I'll implement it.
    Also I was unable to import you definition in actual version of designer app, this is how it is displayed, are you sure you use the https:// version as original market redirect to http:// somehow started the wrong version?
  • Very strange, I imported orofab's definition at work at saw the whole data field, but now at home I see the same thing as you Yevgeny (top 3 numbers only).

    Your code snippet to calculate lap speed in m/s looks correct to me. The only thing I can think of it's a type issue, or an overflow. I'm not 100% sure what compiler is doing, but since retVal is the lap time in ms it is a 32-bit signed integer (type Number) whereas elapsed distance is a float. So maybe try this:

    retVal = retVal > 0 ? 1000f * (info.elapsedDistance - values[arrOff + 9]) / (retVal).toFloat() : 0;

    or perhaps

    retVal = (info.elapsedTime - values[arrOff + 10]).toFloat();
    retVal = retVal > 0 ? 1000f * (info.elapsedDistance - values[arrOff + 9]) / retVal : 0;
  • Very strange, I imported orofab's definition at work at saw the whole data field, but now at home I see the same thing as you Yevgeny (top 3 numbers only).

    Your code snippet to calculate lap speed in m/s looks correct to me. The only thing I can think of it's a type issue, or an overflow. I'm not 100% sure what compiler is doing, but since retVal is the lap time in ms it might be type "long" whereas elapsed distance is a float. So maybe try this:

    retVal = retVal > 0 ? 1000f * (info.elapsedDistance - values[arrOff + 9]) / (retVal).toFloat() : 0;


    It happen to me as well. Try this:

    ---------------
    Local:
    AKDBEAQHJI\FAHOE]CPDVASAG]E]ABAAAAABCABAUHIPNLABJOHXVDHABCEAUHGPUWABJOHXVCFABFPAUHMB_UABJOHXVFEABFPAUHH[ATABJOHXVC]ABFPAUHK[W[ABJOHXVEPABFPAUHaAS[AFJOHXVHXABBIAUHaHWCAFJOHXVHVABB]AUHaHZNAFJOHXVHXABBGASHGPUWAAJOHXVCaAUASHGPWRAAQAAAVCaAUASIAE[^AAQAAAPCaAUAXADaV\CDAAAAAACABDist.ASAD\BLAMAAAAAFCABAXAJD_JCDAAAAAACABTimerASAJHXDADAAAAAFCABAYACBZHCDAAAAAACABLap P.ASOG[DQAGAAAAAFCACAWAG\YKCDAAAAAACABPaceASAG\ZBAGAAAAAGCABAYALYPRCDAAAAAACABAv. P.ASALYQOAHAAAAAFCABAVACJLJCDOE]CPACABCadASACHPaAPAAAAAFCABAUAG\[ECDOE]CPACABHRASAG\[^AVAAAAAFCABAYALNHaCDAAAAAACABAv. HRASALLMWAWAAAAAFCABAVAEMaBCDAAAAAACABAltASADGQKASAAAAAAEABAVAG\\VCDAAAAAACABAscASAG\]GATAAAAAACABAVAJTDSCDAAAAAACABDesASAJ]RNAUAAAAAAAABAVAG\][A[QAAA[BCAB%s%AQHEXOQCEQAABRAI

    --------------
    Garmin Express:
    AKDBEAQHJI\FAHOE]CPDVASAG]E]ABAAAAABCABAUHIPNLABJOHXVDHABCEAUHGPUWABJOHXVCFABFPAUHMB_UABJOHXVFEABFPAUHH[ATABJOHXVC]ABFPAUHK[W[ABJOHXVEPABFPAUHaAS[AFJOHXVHXABBIAUHaHWCAFJOHXVHVABB]AUHaHZNAFJOHXVHXABBGASHGPUWAAJOHXVCaAUASHGPWRAAQAAAVCaAUASIAE[^AAQAAAPCaAUAXA

    DaV\CDAAAAAACABDist.ASAD\BLAMAAAAAFCABAXAJD_JCDAAAAAACABTimerASAJHXDADAAAAAFCABAYACBZHCDAAAAAACABLap P.ASOG[DQAGAAAAAFCACAWAG\YKCDAAAAAACABPaceASAG\ZBAGAAAAAGCABAYALYPRCDAAAAAACABAv. P.ASALYQOAHAAAAAFCABAVACJLJCDOE]CPACABCadASACHPaAPAAAAAFCABAUAG\[ECDOE]CP

    ACABHRASAG\[^AVAAAAAFCABAYALNHaCDAAAAAACABAv. HRASALLMWAWAAAAAFCABAVAEMaBCDAAAAAACABAltASADGQKASAAAAAAEABAVAG\\VCDAAAAAACABAscASAG\]GATAAAAAACABAVAJTDSCDAAAAAACABDesASAJ]RNAUAAAAAAAABAVAG\][A[QAAA[BCAB%s%AQHEXOQCEQAABRAI

    ---------------
  • Former Member
    Former Member over 8 years ago
    Your code snippet to calculate lap speed in m/s looks correct to me. The only thing I can think of it's a type issue, or an overflow. I'm not 100% sure what compiler is doing, but since retVal is the lap time in ms it is a 32-bit signed integer (type Number) whereas elapsed distance is a float. So maybe try this:

    retVal = retVal > 0 ? 1000f * (info.elapsedDistance - values[arrOff + 9]) / (retVal).toFloat() : 0;

    Presumably automatic type conversion should take into an account operation precedence and multiplication by 1000f should have transformed numerator to float, but who knows... I'll release an update tonight to check this, although it breaks my heart seeing the application going all the way down the popular apps list after each update 8))

    It happen to me as well. Try this:

    According to Fabio clearing browser cache helped him, seems like despite me saying "no cache" in page definition explicitly web app compiled code is still cached in some browsers, I'll include recommendation to clear cache next time I publish an update for a web app.

    P.S. When I tried to summarize what's wrong with lap pace, I found out that there's no detailed problem description. To find out the root of the problem we need a reliable reproduction scenario. So, the problem with lap pace is that it becomes zero at unpredictable timer values? If it is, then float conversion may indeed be the problem, but if, for example, it just has different values in comparison to native Garmin field or Flexirunner one, then it may be some kind of memory reallocation problems when scrolling from one connectIQ screen to another. Can someone, please, leave just DIY field and native lap pace on the other screen to test this? Thanks in advance.

    Also, I'd like to suggest the following layout for these tests (values placed in a table-like manner in two adjacent columns): timer time - lap time, average pace - lap pace, elapsed distance - lap distance. This way it'll be easier to analyze whether the lap pace is at least on par with native average pace value within one data field.
  • P.S. When I tried to summarize what's wrong with lap pace, I found out that there's no detailed problem description. To find out the root of the problem we need a reliable reproduction scenario. So, the problem with lap pace is that it becomes zero at unpredictable timer values? If it is, then float conversion may indeed be the problem, but if, for example, it just has different values in comparison to native Garmin field or Flexirunner one, then it may be some kind of memory reallocation problems when scrolling from one connectIQ screen to another. Can someone, please, leave just DIY field and native lap pace on the other screen to test this? Thanks in advance.

    Also, I'd like to suggest the following layout for these tests (values placed in a table-like manner in two adjacent columns): timer time - lap time, average pace - lap pace, elapsed distance - lap distance. This way it'll be easier to analyze whether the lap pace is at least on par with native average pace value within one data field.



    As soon as I start the activity the lap pace freezes to 2:50. If I hit the lap button to generate a new lap, the value in the lap pace freezes to 05:40. After that I can re-hit the lap button as often as I want, the value still remains at 05:40.
    On a second page I have the native lap pace installed and it shows the correct values. Average and actual pace from the DIY data field are, as far as I can tell, same as the native ones.
  • As soon as I start the activity the lap pace freezes to 2:50. If I hit the lap button to generate a new lap, the value in the lap pace freezes to 05:40. After that I can re-hit the lap button as often as I want, the value still remains at 05:40.
    On a second page I have the native lap pace installed and it shows the correct values. Average and actual pace from the DIY data field are, as far as I can tell, same as the native ones.


    So I've done a bit of testing. I've removed the white background and basically inverted all text to white --> lap pace works fine now. Guess it must be a memory issue I had...

    Average pace and current pace show exactly the same as the native Garmin data fields.
    Lap pace however differs a bit, especially noticeable during the first lap. During the first lap, average and lap pace should be the same. On the following laps the native lap pace did not show the same values as the DIY lap pace, however just only by a little bit.

    Also when manually stoping the activity, lap pace continues to change, whereas the native lap pace field shows --:--. Could it be that you are using 'elapsed time' to calculate the lap pace?

    -----------------
    Definition strings:
    AJ^BDAUHIPNLABJOHXVDHABCEAUHGPUWABJOHXVCFABFPAUHMB_UABJOHXVFEABFPAUHH[ATABJOHXVC]ABFPAUHK[W[ABJOHXVEPABFPAUHaAS[AFJOHXVHXABBIAUHaHWCAFJOHXVHVABB]AUHaHZNAFJOHXVHXABBGASHGPUWAAJOHXVCaAUASIAE[^AAQAAAPCaAUASHGPWRAAQAAAVCaAUASAG]E]ABOE]CPBCABAXADaV\CDOE]CPACABD

    ist.ASAD\BLAMOE]CPFCABAXAJD_JCDOE]CPACABTimerASAJHXDACOE]CPFCABAYACDVICDOE]CPACABLap P.ASOG[DQAGOE]CPFCACAWAG\YJCDOE]CPAKABPaceASAG\ZBAGOE]CPGCABAYALWTOCDOE]CPACABAv. P.ASALYQOAHOE]CPFCABAVACJLJCDOE]CPAKABCadASACHPaAPOE]CPFCABAUAG\[ECDOE]CPAKABHRASAG\[^AVO

    E]CPFCABAYALNHaCDOE]CPACABAv. HRASALLMWAWOE]CPFCABAVAEMaBCDOE]CPACABAltASADGQKASOE]CPBEABAVAG\\VCDOE]CPACABAscASAG\]GATOE]CPBCABAVAJTDSCDOE]CPACABDesASAJ]RNAUOE]CPBAABAVAG\][A[QAAA[BCAB%s%AQHEXOQCEQAABRAI
  • Former Member
    Former Member over 8 years ago
    So I've done a bit of testing. I've removed the white background and basically inverted all text to white --> lap pace works fine now. Guess it must be a memory issue I had...

    Average pace and current pace show exactly the same as the native Garmin data fields.
    Lap pace however differs a bit, especially noticeable during the first lap. During the first lap, average and lap pace should be the same. On the following laps the native lap pace did not show the same values as the DIY lap pace, however just only by a little bit.

    Also when manually stoping the activity, lap pace continues to change, whereas the native lap pace field shows --:--. Could it be that you are using 'elapsed time' to calculate the lap pace?

    Thank you for the detailed report. If it would have been a memory issue, then data field would have crashed on watch, so, unfortunately for me this is something more sinister that will require additional research.

    Current version uses elapsed time indeed because
    The average speed in meters per second. The average is computed as the elapsed 3-D accumulated distance divided by the elapsed time.
    which is a citation from API Documentation on average speed value. I've already tried to change it to timer time, but haven't seen a lot of difference in simulator and value is still a little bit different from native average pace, it almost seems like Garmin applies some kind of smoothing to it or that "3-D accumulated distance" differs from the distance reported via activity info available to connectIQ application. As for your previous problem with lap pace showing 2:50 and then 5:40 this seems like you may have used previous format definition, which you updated today after clearing browser cache, and, although this may sound kind of strange, 5:40 is the default pacemaker target pace, which is also stored in the same array, maybe wrong format caused value pointer to address another cell, but that's just speculation...

    P.S. Just checked you definition in Fenix5 simulator and it seems that memory is not an issue at all, check the screenshot and take note of the peak memory consumption which is way below maximum, this means that 26kb watches have a lot of space for the new features.

    P.P.S. Pushed new update which uses timer time instead of elapsed time and explicit conversion to float for intermediate values in lap pace calculation . Please, let me know whether anything changed for the better. Thanks in advance.
  • Former Member
    Former Member over 8 years ago
    Having a similar experience with lap pace but oddly I'm seeing slightly different numbers.

    On start of an activity it jumped to 3:00 and stayed at that until the start of lap 3 when it jumped to 6:00. It stayed at 6:00 for all of lap 3 and lap 4 but then I forgot to check again after to see if it changed again. I had auto lap enabled based on mile splits.

    Another thing I noticed was that the training effect didn't show decimal places on the watch whereas it does on the designer. Whilst on this, the newer watches have two values for training effect - Aerobic and Anaerobic. Is it possible to make both these an option? The datafield looked to be showing Aerobic TE.

    Looking forward to the potential of ETA at next milestone (basically a predicted finish time) and also the possibility of other graphics if memory allows. I'm thinking a variable size line similar to arc so that I can have a straight HR gauge and bar charts based on time in each zone (probably the same thing really).

    Not sure if you are able to extract LTHR from the watch but if so would it be possible to show current HR as a % of LTHR?

    Thanks once again.