Data Privacy in ConnectStats

I recently saw a negative review on the App Store for ConnectStats warning users that ConnectStats is not a Garmin app and therefore people should avoid giving away login information in the app as the data may get stolen.

Keeping data secure both on your phone or online has been a key guiding principle in how I tried to implement the app. So while I understand the concern, I felt it was a bit unfair.

I have been careful to make sure the data isn’t shared and the passwords are never sent to me. I also made the app open source so that people can check for themselves what it is doing.

I felt it may be worth to write a bit of details on what is ConnectStats doing with your data and password, with link to the code. So people can either let me know if I miss something or feel better about using the app.

Your login information

Garmin Website service

The app can connect directly to the Garmin website to retrieve information. In order to do that it needs to have access and store your username and password. To do that it stores the password in the keychain of your phone and never locally in a way someone looking at the files saved from connectstats could retrieve. It then relies on the iPhone keychain mechanism which Apple can ensure is secure. The key file to look at to see how it’s done is GCAppPasswordManager.

Strava and Withings services

For the Strava and Withings service, the authentication process uses the OAuth 2.0 so the password is never even seen by ConnectStats. The library I use to manage the OAuth 2.0 is provided by Google , and you can see in the file used by connectstats how the tokens are retrieved from the keychain in this file for Strava for example via this call:

ConnectStats service

ConnectStats also maintains a service that can receive the fit file from the new Garmin Health API. In that case the the authentication is done via OAuth 1.0a. So the passwords are never seen by ConnectStats or its web server, but only tokens are exchanged with Garmin. These tokens are then saved into the keychain of your phone as well as on the database in the server. Note that the server is open sourced as well. While the server is open sourced, the configuration files containing the database passwords and other secret keys are only saved on the server and not in the code. The website is hosted on Godaddy, a reputable company, and I rely on their security to make sure the access to the website is secured.

Your Activities Data

On the phone

Your activity data is kept on the phone and stored locally. So it will be as secure as you keep your phone. You can also see that if you try to run the app in airplane mode all the browsing of statistics and downloaded data will work. Of course you need a connection to download new data…

On connectstats server

With the new Garmin Health API service, ConnectStats needs to maintain a database in a server containing your activities. This is the case if you choose in the app Garmin as a service and source to be All or ConnectStats. If you choose Garmin WebSite only then the data will be accessed directly from the Garmin servers. Note that this is not the officially supported method from Garmin, can and has been subject to outage in the past due to undocumented changes to their website.

If the data is stored on the ConnectStats server, the access to that data is done via an OAuth 1.0 process. Both the app and the server keep a secret token, and use that to do the authentication. The tokens are provided by Garmin, so in order to access your data you will need to do a successful login on the Garmin service and obtain the token this way.

ConnectStats does not maintain any types of user name or its own passwords/user system, which means the data stored on the server can not be traced back to you. Everything is linked and identified by the sha1 hash tokens obtained by Garmin, which look something like this aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d.

The only person with access to the database with your data is myself, and no one else helps me or has access to the login information. If that ever changes, I’ll make sure to talk about it in this blog.

Note that if you use the source for Garmin data to be both the website AND connectstats service (what I recommend), you will need to enter your login details in the app (as in the Garmin website section), but that data will stay on your phone in your keychain. It will never be uploaded to the connectstats server. So on the server it will still be impossible to link the data saved in the database to your Garmin user account, email or username as well.

Bug Reports

When you send a bug report, this will send the log information, which will look something like the below. This is mostly information that helps me see what has happened and try to understand the problems. You can see in the code everything that is logged by looking for calls to the function RZLog. No sensitive information, like password is logged.

You can choose before sending a bug report to include activities. If this is selected in addition the log above, the internal database of activities saved on your phone is sent as well. This contains all the high level data (distance, heart rate, timings, etc) that allows reconstruction of the statistics page. In addition it will include all the details of the currently selected activity in the detail page (only one full detailed activity). These details contains all the gps points.

Because when you send a bug report, I ask for an email address so I can reply to you, in this case that data could be traced back to an individual with that email. But as mentioned before, I am the only one that receive that email or have access to the files where they are saved on my server. This by the way is the same server hosted by GoDaddy where I have host all the data for ConnectStats.

Conclusion

I hope this will relieve any concerns any one could have about privacy of their data in ConnectStats.

Happy to answer any more questions, and of course if anyone finds holes or gap in how I implemented ConnectStats, feel free to reach out either by comment below or via email or GitHub issue.

2016 year review and double counted activities

It’s time again to look at the past year summary. How did I do?

2016 was a fine year, I ran 1387 km, it is 100km behind 2015. But one aspect bothered me, looking at the distance, there is a clear increase on the graph in December 2015, which put me behind in 2016. It worried me a bit. I couldn’t remember an especially good December last year. Did I have another bug in ConnectStats?

I went to check on Garmin connect and it reported the same distance as connectstats: 1478km for 2015…

Hum. Next step was to go and look at the activities in December last year. The search feature in ConnectStats made it easy, just enter december 2015  in the search box of the activity list. Sure enough, I found some duplicate activities. This started to be very worrying. ConnectStats imported the same activity twice? New bug? After some more investigation, it turned out the problem was in Garmin itself… Quite a few activities in 2015 appear twice on the website as well…

They have a different activity identification number, but they are clearly the same activity except for the altitude gain as you can see on the snapshot above.

Next steps was to add a new feature to ConnectStats to double check for such duplicate activities and ignore them… Well, my stats are now lower only 1310km but correct. And 2016 is ahead of 2015 by 50km! Yeah!

I finally decided to check what Strava reported. My account is linked to import activities automatically. I was curious: would strava have the total including the duplicate as well? It actually didn’t… The total is 5km off from my new corrected total, but I suspect it is simply due to the slightly different way Strava computes the total distance from the gps file.

The fix to search and eliminate duplicate will be included in a new release early next year.

Exciting Bug Reports

You may wonder how bug reports can be exciting. Most of the reports I get are about people having trouble to login or set up the app. Usually either because people Bugsuse the wrong device (vivofit or vivosmart), or have special characters in the password. I actually just fixed the latter, which is great news.

So once in a while I get a bug report from someone that spotted some inconsistency in the stats or numbers reported in the app. This is exciting because it is usually somewhat interesting to track down and also because it helps get the app better and better. It even sometimes happens that people spot inconsistency with other apps or report, and when the other apps was wrong it’s quite satisfying 🙂

Inconsistency between Time in Zone Graphs and Laps

An often overlooked feature of the app is the ability to compute statistics over arbitrary laps. You can of course record laps while you do an activity. But what if later you want to see how you did by kilometres or miles? You may also want to get your stats for all the times you were in a given heart rate zone. Or your half distance split, etc. The app lets you do that, by tapping on the lap header and selecting the type of lap you want.

Someone just noticed that the time in zone was inconsistent between the computed lap and the time in zone graph. As you can see in the graph for instance the 149 to 158 zone is reported with less than 10:00Simulator_Screen_Shot_15_Apr_2016__20_31_00

While the graph is clearly more than 10:00

Simulator_Screen_Shot_15_Apr_2016__20_28_59

Bug feels always silly once you found them. Here I was not accounting properly for each point of the activity where the value changes zone. The laps calculation is somewhat more involved than the time in zone graphs, because it requires keeping track of bunch of stats, like distance, speed or pace, average heart rate, etc. Note that the activity don’t report when the timer was stopped on the watch, so there is also some logic to account for the point where the timer appears to have stopped (long delay between points). It’s not exact and sometimes the logic does not work well.  But here I was just missing one point all together. It’s fixed now for the next version. Here is the correct laps after the fix

Simulator_Screen_Shot_15_Apr_2016__20_29_15

Fast Mile starts in slow section

Sometimes what appears to be a bug, is just a side effect of a feature. One user noticed that sometimes the fastest mile on the map appears to start in a section that is slow (blue). It would appear to not make sense as given the section at the end is faster it should more the fastest mile to be starting on the next point as here:

FastBikeSmoothing

Well, in that case actually the pin is at the exact right location. The blue section is also correct, given how it’s calculated: The gradient color represent the speed modulo some small level of smoothing. Here is the same picture without the smoothing

FastestBikingNoSmoothing

You can see that in that case, the fastest mile start correctly in a red (faster) section. It is hard to decide if this is a bug or a feature. It’s also interesting to see that in the case of a cycling activity (as in the above pictures), the speed is actually quite smooth already, so the smoothing probably not that critical. But in the case of a run, it tends to be much noisier. Given I am first a runner, it was quite obvious to me that without smoothing the gradient was less useful in identifying speed zone.

Here is a running activity with smoothing

SmoothingRun

And the same activity without smoothing, with a much noisier gradient

RunNoSmoothing

ConnectStats does not let you control the smoothing of the gradient on the map. Maybe I’ll add an option for that, or I’ll disable it for biking activities.

 

Activity Deleted Bug

Bugs

[UPDATE] This is now fixed with version 3.0.2

Since Yesterday a change in the Garmin API resulted in ConnectStats reporting some activities were deleted from Garmin Connect when trying to download the details.

 

This happens because the part of the API that ConnectStats use to get the weather is now reporting the same error as when an activity is deleted and that confuses ConnectStats.

I will push a bug fix to the store that will stop downloading the weather for now until I can figure a new API to retrieve it.

Version 3.0.2 was pushed to Apple for approval today, unfortunately pushing a bug fix requires a few days, sometimes up to a week for Apple to approve it. Sorry for the inconvenience caused and thanks for your patience

Statistics on a selection of activities

One feature people repeatedly ask about is the ability to see statistics for a selection of Garmin Activities. It is actually possible by using the search feature.

Let’s say for example I want to see the statistics of all the running activities in july 2015. I first enter that as a search

Simulator Screen Shot 20 Jan 2016, 21.53.35

Then in the statistics page, hit the type button until the term Search appears. It will remind you what the search term was, and then the statistics you see are only using the currently selected list:

Simulator_Screen_Shot_20_Jan_2016__21_53_40

This will be the case for the other stats page as well, here for example I show a scatter plot of Pace versus HR for the running activities of July 2015

Simulator Screen Shot 20 Jan 2016, 21.53.54

Another useful application is to run statistics on a specific activity type, for example all the skiing activities as here, I show how much elevation gain I achieved each month in backcountry skiing. You can see more about skiing here

Simulator Screen Shot 20 Jan 2016, 22.01.22

It is limited though by the current search syntax of ConnectStats, which if there is significant demand, I may extend. Just let me know.

 

ConnectStats 2.5 rejected…

shutterstock_310884725So as per last week post, I had submitted to the apple review process a new version of connectstats with the 3D flyover feature…

Unfortunately, Apple rejected this version. The reason is that the code is using some of the HealthKit API. Actually it is appears to be using it because I am currently working on a version that will let you look at the steps and other information recorded via the Apple Health App or your Apple Watch. It is not yet enabled as I am still working on it and I am waiting until it’s ready for prime time. But the Apple review team rejected it on the basis that my code should not appear to potentially use health data if it’s not clear to the user why.

So I will wait until the next version is ready to release the 3D flyover, at this point would be too painful to patch an old version or  remove that code that I know I will need soon.

Flyover maps in ConnectStats 2.5

Screen Shot 2015-10-31 at 09.36.24I recently saw an article on iOS development, explaining the maps features available to developers. I had never realised it was possible to enable in an app the 3d views you see in the apple Map app. A little bit of fiddling later and you can now see your course in gorgeous 3d views if you have an iPhone that supports it and your city is covered by the feature.

I haven’t really yet figured out how it can help you with training or analysing your data better, but it looks great and is a pretty neat way to relive some of your runs or rides, so here it is available in connectstats 2.5 (under review by apple at the time of this writing)

How to

Screen Shot 2015-10-31 at 09.43.15To enable it, simply go to the detail page, switch to the satellite view and tap anywhere on the map, it will then show you the closest point on your course in 3d. You can then use the normal controls of the map to zoom or move around.

Small Gallery

You can see here a few samples from recent runs. Enjoy!

 

Screen Shot 2015-10-31 at 09.39.02Screen Shot 2015-10-31 at 09.45.29Screen Shot 2015-10-31 at 09.44.27

What the Summary Stats say about September

Looking at the summary stats September turned out a pretty good month for my running.

Looking at the fitness vs fatigue graph section corresponding to september, the line stayed pretty constant, showing I kept my training level pretty constant. Later in the month I pushed a bit more as the peak in fatigue shows.

Simulator_Screen_Shot_17_Oct_2015__21_12_12In the bottom graph, the thicker black line shows the best speed achieved for given distances in september. I achieved my best speed of the year for all distance between 6km and 13km. You can see that as the thicker black line for september is the minimum for the year, and I did quite significantly better in speed than august.

Simulator_Screen_Shot_17_Oct_2015__21_12_27Meanwhile the best heart rate profile shows that this was achieved without pushing the heart rate more than the other months. Actually, the september line (black thick line) stays quite below the max of the year for any duration. This is pretty satisfying: better speed without pushing  much more…

 

What’s new in ConnectStats 2.3

Universal Links

Now, it will be possible to directly open the app in a specific page from an article. It will make it easier for people to navigate to a corresponding page from a post or help on the web. For example this should open the summary page.

Force Touch

For those lucky iPhone 6s owners, you can have quick access to stats, refresh from the home page and you can have preview of an activity without opening it by pressing hard on the main activity list.

Cache Management

A few more options to manage the local cache, and an option to display an icon to quickly identify what activities were downloaded or not.