FitContributor with Data Field WITHOUT having to create entire App?

I need to do something very simple without having to write the code for an entire app. I've created a ConnectIQ Data Field which can easily be added to the pre-existing Garmin Run activity to show ANT+ sensor Power in watts from a force sensor in the running shoe, just like you would inside the Bike activity if you were riding with an ANT+ power meter. This combination with the Run activity allows combination of watts with Running Dynamics fields already available from the Garmin run strap. It works just find for display on the watch, but does not save to the pre-existing .FIT file generation within Garmin's own Run activity. Of course, it can work with the Bike app and save the power in watts, but then the running dynamics are not available there.

Is there any way to use the FitContributor module to simply add this additional Power field to all the other ones already being recording in the Run activity .FIT file? I know you can do this by writing a complete app like the Moxy Sample, but this is for lots of fields in a truly unique configuration and I just need to add one field to the one-second record for power in watts.

It says in the documentation that FitContributor works for a Data Field and App, but it does not say a Data Field WITHOUT creating a custom Watch App.

Any thoughts? Great stuff in the forum on how to use FitContributor with Apps like Moxy sample, but not something simpler. Before I try it on my own, to strip Moxy way down to work as a Data Field for only one value, I'd like to know if it's even possible.

Thanks,

Ironman.Texas
  • As mentioned earlier, the best test right now is a combination of the FIT-to-CSV tool and the actual published application (using the DO NOT PUBLISH tag). Your going to really need to rely on the FIT-to-CSV tool for some of the testing regardless of where the FIT file comes from, a side load or the published app. Connect at this point doesn't support laps (they are in the FIT file though) and depending on whether it is Connect Mobile or the website you will get different results. These issues have been reported but persist to date (listed here: https://forums.garmin.com/showthread.php?364535-Known-Issues-Thread). I would test and iron out your application using the FIT-to-CSV tool and you'll be ready when the rest of the pieces fall into place. If you use native number mapping for your power value (if it should replace native power) then sites like Strava, Training Peaks, and SportTracks will use them right now.
  • GC laps working well, problems with User Settings from Garmin Express download

    Thanks to Travis and LCJ for all your help. I do have the IQ file uploaded and working on Garmin Connect, actually much better than it does in MonkeyGraph. Most all of the lap and summary features are working (though there is a problem with Average Power showing zero, but I think this in my own code because the CSV file also says zero).

    But your responses have me asking more questions:

    1. I have actually six power related fields, which I can choose to display in the simulator using the App Settings Editor, implented the same way as in Monkey Fuel. How do I get this to work when using Garmin Express? Nothing asks for which field (as Stryd Power does to select 3s power). I also have 3s Power for running, and it records fine shows up in GC Graph, but I can't find out how to display it on the watch.

    2. In MonkeyFuel sample, one label is used for all fields. Can I change the value of label to multiple string choices based on the field I want. Of course, I already have all these six field strings, use them to label the FIT output, so I can use them to return the label for "function compute(info)" based on the display property, right? But of course none of this matters if I can't choose the six-field list when accessing via Garmin Express.

    3. LCJ mentions using the NATIVE FIELD id to make this compatible with Strava and Training Peaks for power. But how can I do this for the Run Profile in Garmin, which has no native data field for power? How do I find the native field id numbers (I can't find them in the FIT file, even though they are recorded). Of course, it's easy to simply record a run using the BIKE app and get all the power features I want, but then I loose all the Garmin Running Dynamics fields, which is the whole reason I'm writing a Data Field app for power in running. If I could just load bike ANT+ power into the Run app or Running Dynamics like GCT into the Bike app, I wouldn't even have to write any code. I'm getting all my power data from the info object anyway before calculations and output, no special ANT+ channel or device at all. My ANT+ run insole connects as if it were a bike power meter to the watch.

    Thanks again,

    IronmanTexas
  • The native id numbers can be found in the profile.xls spreadsheet in the FIT SDK.

    You can get the FIT SDK at this link. https://www.thisisant.com/resources/fit/

    You might need to sign up as a developer first which is free.

    On the "Messages" Tab, scroll down to the Activity File Messages. In CIQ you can only write Record, Lap, and Session messages. The numbers in column B identify the native numbers for each specific message.

    Strava does NOT currently support data written in the FIT file by CIQ FIT contributor. It's not just that it doesn't show it. If your file has CIQ data in it, it may not import it at all. It'b been hit or miss on my testing and I can't identify why some files fail. You can express your thoughts on this to Strava on this thread on their support forum.
  • Strava does NOT currently support data written in the FIT file by CIQ FIT contributor. It's not just that it doesn't show it. If your file has CIQ data in it, it may not import it at all. It'b been hit or miss on my testing and I can't identify why some files fail. You can express your thoughts on this to Strava on this thread on their support forum.


    I have a group of Strava users and all of them are getting their power, HR, and cadence FIT data from my developer fields. The distance and speed are not currently being recognized but haven't prevented the files from uploading. I'll test again tonight but I'm pretty sure this is working at least for the ErgIQ users minus the distance and speed elements.
  • The FIT Files in Strava is still hit or miss for me. I just tried uploading 3 fit files. 2 worked in that they show the FIT data except for the CIQ data. 1 failed with a BAD FILE DATA error. Strava has told me they don't support FIT2.0 so they won't help me identify what's bad about the failing files. I've tried finding what's different in the failing files by tweaking things on my side, but I couldn't isolate a source of the problem with just go / no-go for feedback. The failing and passing files look essentially identical to me.
  • Still can't make User Settings work from Garmin Express

    Thanks for all of this. I was able to add the :nativeNum message numbers, found those in the FitSDK.

    But what about the User Settings, which should pop up a pull-down list during Garmin Express download? If I want to display TWO of these fields at once (Lap Power and 3s Power, commonly displayed for interval workouts), do I need to create two different Data Field apps, or can I just download from one repository while selecting two different User Settings for each field display property. Why don't any User Settings show up at all when I download using Garmin Express? Do I need approval for them to work. They work fine in the Simulator with App Settings Editor.

    Thanks,

    IronmanTexas
  • Thanks for all of this. I was able to add the :nativeNum message numbers, found those in the FitSDK.

    But what about the User Settings, which should pop up a pull-down list during Garmin Express download? If I want to display TWO of these fields at once (Lap Power and 3s Power, commonly displayed for interval workouts), do I need to create two different Data Field apps, or can I just download from one repository while selecting two different User Settings for each field display property.


    Not sure I understand the question. You can't have 2 instances of the same data field running at the same time with different settings. You will only have 1 DF shown in Garmin Express. If you have 2 of the same datafield showing on the watch, it shows the same one twice instead of running 2 separate instances (e.g. if they both had a random number generator, they'd always show the same number)

    Why don't any User Settings show up at all when I download using Garmin Express? Do I need approval for them to work. They work fine in the Simulator with App Settings Editor.
    IronmanTexas


    You don't need to be approved for the settings to work. It's easy to get things mixed up when you are mixing sideloaded and Express Installed versions of the same app. It only keeps one of them if they have the same AppID. Make sure the sideloaded version is deleted before installing the Express loaded version.
  • Thanks for all of this. I was able to add the :nativeNum message numbers, found those in the FitSDK.

    But what about the User Settings, which should pop up a pull-down list during Garmin Express download? If I want to display TWO of these fields at once (Lap Power and 3s Power, commonly displayed for interval workouts), do I need to create two different Data Field apps, or can I just download from one repository while selecting two different User Settings for each field display property. Why don't any User Settings show up at all when I download using Garmin Express? Do I need approval for them to work. They work fine in the Simulator with App Settings Editor.

    Thanks,

    IronmanTexas


    Do you have a properties and settings file in the resources directory? Those are needed for the settings to work and show in either Connect Mobile or Express?
  • Here's my resources file. The properties and settings are defined in the resources.xml file.

    <resources>
    <strings>
    <string id="AppName">Moxy 1st Sensor</string>
    <string id="AppVersion">2.3</string>
    <string id="AppSensor">1st</string>
    <string id="thb_label">1st THb</string>
    <string id="thb_units">THb</string>
    <string id="smo2_label">1st SmO2</string>
    <string id="smo2_units">%</string>
    </strings>

    <strings>
    <string id="SensorIdentityTitle">Sensor Id</string>
    <string id="SensorLocationTitle">Sensor Location</string>

    <string id="left_leg">L. Leg</string>
    <string id="left_calf">L. Calf</string>
    <string id="left_shin">L. Shin</string>
    <string id="left_hamstring">L. Ham</string>
    <string id="left_quad">L. Quad</string>
    <string id="left_glute">L. Glute</string>
    <string id="right_leg">R. Leg</string>
    <string id="right_calf">R. Calf</string>
    <string id="right_shin">R. Shin</string>
    <string id="right_hamstring">R. Ham</string>
    <string id="right_quad">R. Quad</string>
    <string id="right_glute">R. Glute</string>
    <string id="torso_back">Torso/Back</string>
    <string id="left_lower_back">L. Lwr. Back</string>
    <string id="left_upper_back">L. Upr. Back</string>
    <string id="right_lower_back">R. Lwr. Back</string>
    <string id="right_upper_back">R. Upr. Back</string>
    <string id="torso_front">Torso/Front</string>
    <string id="left_abdomen">L. Abdomen</string>
    <string id="left_chest">L. Chest</string>
    <string id="right_abdomen">R. Abdomen</string>
    <string id="right_chest">R. Chest</string>
    <string id="left_arm">L. Arm</string>
    <string id="left_shoulder">L. Shoulder</string>
    <string id="left_bicep">L. Bicep</string>
    <string id="left_tricep">L. Tricep</string>
    <string id="left_brachioradialis">L. Ant. Forearm</string>
    <string id="left_forearm_extensors">L. Pos. Forearm</string>
    <string id="right_arm">R. Arm</string>
    <string id="right_shoulder">R. Shoulder</string>
    <string id="right_bicep">R. Bicep</string>
    <string id="right_tricep">R. Tricep</string>
    <string id="right_brachioradialis">R. Ant. Forearm</string>
    <string id="right_forearm_extensors">R. Pos. Forearm</string>
    <string id="neck">Neck</string>
    <string id="throat">Throat</string>
    <string id="none">Location Not Set</string>
    </strings>

    <properties>
    <property id="SensorId" type="number">0</property>
    <property id="SensorLx" type="number">255</property>
    </properties>

    <settings>
    <setting propertyKey="@Properties.SensorLx" title="@Strings.SensorLocationTitle">
    <settingConfig type="list">
    <listEntry value="0">@Rez.Strings.left_leg</listEntry>
    <listEntry value="1">@Rez.Strings.left_calf</listEntry>
    <listEntry value="2">@Rez.Strings.left_shin</listEntry>
    <listEntry value="3">@Rez.Strings.left_hamstring</listEntry>
    <listEntry value="4">@Rez.Strings.left_quad</listEntry>
    <listEntry value="5">@Rez.Strings.left_glute</listEntry>
    <listEntry value="6">@Rez.Strings.right_leg</listEntry>
    <listEntry value="7">@Rez.Strings.right_calf</listEntry>
    <listEntry value="8">@Rez.Strings.right_shin</listEntry>
    <listEntry value="9">@Rez.Strings.right_hamstring</listEntry>
    <listEntry value="10">@Rez.Strings.right_quad</listEntry>
    <listEntry value="11">@Rez.Strings.right_glute</listEntry>
    <listEntry value="12">@Rez.Strings.torso_back</listEntry>
    <listEntry value="13">@Rez.Strings.left_lower_back</listEntry>
    <listEntry value="14">@Rez.Strings.left_upper_back</listEntry>
    <listEntry value="15">@Rez.Strings.right_lower_back</listEntry>
    <listEntry value="16">@Rez.Strings.right_upper_back</listEntry>
    <listEntry value="17">@Rez.Strings.torso_front</listEntry>
    <listEntry value="18">@Rez.Strings.left_abdomen</listEntry>
    <listEntry value="19">@Rez.Strings.left_chest</listEntry>
    <listEntry value="20">@Rez.Strings.right_abdomen</listEntry>
    <listEntry value="21">@Rez.Strings.right_chest</listEntry>
    <listEntry value="22">@Rez.Strings.left_arm</listEntry>
    <listEntry value="23">@Rez.Strings.left_shoulder</listEntry>
    <listEntry value="24">@Rez.Strings.left_bicep</listEntry>
    <listEntry value="25">@Rez.Strings.left_tricep</listEntry>
    <listEntry value="26">@Rez.Strings.left_brachioradialis</listEntry>
    <listEntry value="27">@Rez.Strings.left_forearm_extensors</listEntry>
    <listEntry value="28">@Rez.Strings.right_arm</listEntry>
    <listEntry value="29">@Rez.Strings.right_shoulder</listEntry>
    <listEntry value="30">@Rez.Strings.right_bicep</listEntry>
    <listEntry value="31">@Rez.Strings.right_tricep</listEntry>
    <listEntry value="32">@Rez.Strings.right_brachioradialis</listEntry>
    <listEntry value="33">@Rez.Strings.right_forearm_extensors</listEntry>
    <listEntry value="34">@Rez.Strings.neck</listEntry>
    <listEntry value="35">@Rez.Strings.throat</listEntry>
    <listEntry value="255">@Rez.Strings.none</listEntry>
    </settingConfig>
    </setting>

    <setting propertyKey="@Properties.SensorId" title="@Strings.SensorIdentityTitle">
    <settingConfig type="numeric" required="true" min="0" max="99999" />
    </setting>
    </settings>

    <fitContributions>
    <fitField id="0"
    displayInChart="true"
    sortOrder = "0"
    precision="1"
    chartTitle="@Strings.smo2_label"
    dataLabel="@Strings.smo2_label"
    unitLabel="@Strings.smo2_units"
    fillColor="#00BB00" />

    <fitField id="1"
    displayInChart="true"
    sortOrder="1"
    precision="2"
    chartTitle="@Strings.thb_label"
    dataLabel="@Strings.thb_label"
    unitLabel="@Strings.thb_units"
    fillColor="#C8501E" />

    <fitField id="2"
    displayInActivitySummary="true"
    sortOrder="2"
    dataLabel="@Strings.AppName"
    unitLabel="@Strings.AppVersion" />

    </fitContributions>
    </resources>



    The sensorLX is a sensor location pull-down list in Garmin Express Settings or GCM settings. The sensorId is just the sensor number.
  • :nativeNum works with TrainingPeaks, but ruins GC data in Power column in FIT file.

    If you use native number mapping for your power value (if it should replace native power) then sites like Strava, Training Peaks, and SportTracks will use them right now.


    Like you said, when I put :nativeNum=ID into the createField, they did show up on TrainingPeaks. In my case this was :nativeNum=7,19,20 for Power, Lap Power and Avg. Power, respectively. However, adding the optional paramater for :nativeNum=7 ruined the actual writing to the FIT file from a real 735XT workout with running power. Gave me a really strange column of numbers like 112, 124, 125, nothing related to the 400-600watts actual recorded. Did NOT seem to hurt the Lap Power and Average Power, which I calculated internally in the "function compute(info)" section, but totally ruined the display of the Power data (this is true both in the FitToCSV and the Garmin Connect graphs. Take it out, and everything is fine again. How I'm a conflicting with anything, when I'm just taking info.currentPower, assigning it to a hidden var, and the displaying and writing to the FIT file? Doesn't seem to make sense. The problem is not seeing the data in Connect or TrainingPeaks, just that it appears to be totally unrelated data. Again, Lap Power Average and Sessions AVerage are fine (which I don't really need for TrainingPeaks, since they do a better job of calculating these kinds of things in their software than the watch or Garmin Connect)

    By the way, NONE of these kinds of problems happen with the simulator. It always gives a steady stream of mildly varying power, and everything records, lap averages, and session averages perfectly, every time. And the User Settings. It's such a "village of the happy people" that it seems fictional, unrelated to the real-world behavior on a watch. It's really just a way to find coding bugs.

    I also cannot get User Settings to work at all from Garmin Express, so I've pretty much given up on a single data field app with multiple list items like Power, 3s Power, 10s Power for display. I'm going to have to post two apps anyway to the Connect IQ store, one for GC users and one for TrainingPeaks users (with the :nativeNum parameters added), until Garmin fixes their FIT formatting bug or someone explains to me how to get around it. Can you?

    I know this sounds silly, but it doesn't make any difference what my DEVELOPER ID numbers are (like 0,1,2,3) for fields, right? Using the native numbers for my numbers won't help me get recognized by TrainingPeaks or other systems, right?


    Thanks,

    Ironman Texas