Sunday 27 December 2020

Fit File Reader and Converter to Text - FIT to CSV

 Fit File csv to Text Converter V1.0

I've been writing a number of Window Applications in C# using Microsoft Visual Studio over the past few years. This is mainly to keep my brain active and develop my software skills

I wrote a few small applications to try the software and workout what to do but really started making some progress when I started to develop an application to download and process my Strava data. There's a number of posts on this Blog about that including the latest version (which is here). This development goes in fits and starts as it's more of a winter/dark evening activity - the rest of the year I'd rather be cycling and generating the data than processing it.

I have also written a TCX file reader which is (here).

More recently I used the Fit API to process the .FIT files generated by my Garmin. This was primarily to get the Di2 shift data from the file that is not readily accessible via Strava or other tools - although the website https://di2stats.com/ does support this. This desire to see my Di2 data resulted in my Di2 Fit File Analyser, and the latest version here here

The current aim is to integrate both the TCX and FIT file readers into a single application alongside the Strava data so providing a one-stop shop for the main cycling data file formats. Then I can use this application to analyse and display the data from various sources in tabular, graphical and statistical formats

As I am not a software developer by training, I can write software but it's a bit ad-hoc and made up as I go along. This has made some of the applications quite difficult to support and develop, so I have decided to restart to an extent by re-writing the Di2 Fit File anlayser just to read, store and export fit files. I have attempted to code it better in away that supports easier development and maintenance. I'll then add in the TCX file format before integrating the Strava data and this release is the first attempt in that journey. However it's often 2 steps forward 1 step back as I try to learn how to make better code, and although it's a lot better in this version compared to the Di2 version it's still not ideal

The "Fit File Tool" in this release does nothing other than read fit files, store the data in a SQL database, display the data from the file along with a summary of that data, and allow an export of the data in csv or Tab seperated format. 

The application can be downloaded here.

What it Does and Assumptions

On installtion it should add a Start Menu shortcut and open the application:


During the first instal it should create the SQL data base in the Application folder and you'll see a window as below (note that the list box displayed here will not be present)

You can open the folder where the application has been installed by Selecting File and "Show Working Folder":


The working folder will be in some obscure location (I have not yet worked out how to install in a nmnore sensible location):


To process a data file simply press the "Load Fit File" Button, browse to a location where they are situated and press OK:


You can load multiple files at once if required. I have loaded 332 files in a single operation with no issues

During the processing the data for each Fit file will be displayed once processing is complete, and a progress bar will be displayed:

 

Once all the data is loaded you can select any file from the List Box or just reload it.

Right clicking on the data display will allow it to be exported:


Other Information

  • Depenfing on ride duration and number of sensors it takes from 1.5-10 seconds to process a fit file on my system
  • All data is stored in an SQL database.
  • The database is called "Fit_File_datrabase.mdf"
  • There is no option to define an alternative databse name or storage location
  • All data is stored in 2 tables - one table is for the record (time stamped data) and the other for storing a summary of the activity data
  • The record table has columns for all time stamped data defined by the FIT standard. I can only test this with the cycling data fit files I have
  • Whilst the database can store all fit data it only displays columns with actual data in it
  • The activity summary data is as per the Strava Activity Summary data for future compatibility (see abvove)
  • There is some processing of the record data:
    • A unique identifier for the fit file is created (to be equivalent to the Strava Activity Id). This is created by converting the file name to a true date and time value and then converting this to the Unix Epoch. For a single user this should be unique
    • The Latitude and Longitude columns are converted from the Garnin 32 bit number to actual longitude and latitude
    • Sometimes the data stream for a column is blank from the original data source
    • If the Speed Column contains blank values these are set to 0
    • If the Power Column contains blank values these are set to 0
    • If the start of the Latituide/Longitiude colums are blank the value of the first non-blank row is filled in from row 0 to that row (assumption is that the GPS has not synched)
    • If the end of the Latituide/Longitiude colums are blank the value of the last non-blank rows  arefilled in from that row to the last row

It's been tested reasonably well, however it's by no means a professional piece of software. If problems occur then turn logging to "Ultra" from the file menu, and load a single file. Then review the file "application.log" in the Working folder and contact me via this Blog



Sunday 1 November 2020

What did CoVid 19 meant for my cycling in 2020

(Updated 1 Nov 2020)

Firstly under no circumstances is the post ignoring or dismissing the seriousness of the CoVid19 Pandemic which, at the time of writing, is far from over and looks if we are entering a second wave at least as significant as the first wave back in March 2020

Fortunately so far my self and my family seem to have got through with minimal major disruption and health impact which is a huge bonus

I've also been fortunate to have been in continuous employment, almost as normal for the duration so far although with some pretty small changes in the scheme of things

Just before the lock down started we had moved to start putting some people on  furlough and getting those that could to work from home. We also moved those remaining on site to a double day shift pattern. The result was that we could maintain a level of Social Distancing whilst working to keep some key product development running to meet key milestones.

The outcome for me was that I was working and running my team as normal but on a shift pattern of 6.00 to 13.45 (early shift) and 14.00 to 21.45 (late shift). These were also modified shift patterns to avoid conflict at the normal shift changeover. I have worked shifts a number of years ago and would rather not have been doing them as it's hard work, and disruptive to sleep patterns if nothing else. What I wanted to take from that earlier experience was that I did not get up and "wait to go to work" on the late shift, and did not get home from the early shift and fall asleep, meaning I was unable to go to sleep in the evening for the early start. 

Fortunately the UK Government allowed one session of "individual daily exercise". The exact definition of what that meant in terms of duration and distance from home was not fully clear, but I saw it as I could ride my bike, on my own and as long as I avoided other people I would meet the requirements. Whilst I rode for more than an hour I did tend to keep closer to home that I would normally by choosing routes than looped around my house or rode out and back several time like spokes of a wheel. I certainly reduced the number of rides that went more than 15-20 miles from my house, conscious that if there were any issues it would mean that my wife had a longer (and probably what would be classed as non-essential) journey to rescue me if needed. Fortunately that didn't happen, and I started taken an extra inner tube "just in case.

So as a result of the shift pattern, desire to not sit at home, and good weather I started riding for 1-2 hours per day. This was made more attractive because there was almost no traffic. I have ridden some closed sportives and at times it was like riding on closed roads

Shortly this became a habit and without really realising it I was racking up significant mileage. I was also riding on new roads and finding new places to ride that I'd never seen before in 1o years of riding in the area

The following are some of the changes that I saw, in no particular order:

  • My average weekly mileage rose to 220-250/week
  • I completed the Strava 1250km/month, Climbing challenge and Grand Fondo 3 chalenges months in a row (I had only completed all 3 in a month once before)
  • Despite the high mileage the altitude gain was relatively low as I was staying closer to home and the "bigger" climbs are further away than I was riding
  • I had to change the chains on my Giant and Scott about 6 months earlier than expected
  • I needed to buy some more cycling shorts (as I was wearing the ones I had so often and the laundry couldn't keep up)
  • I rode 11 consecutive days in a row in June
  • Typically I rode for 24-25 days every month in April-June
  • By the beginning of September I had achieved my 5000 mile "target" and by the beginning of October I'd already done more miles that all other years bar one
  • My average speed is higher on both my "good" bikes in 2020 vs 2019
  • I have only ridden (commuted) to work about 4 times in total this year (vs. probably 30-40 normally)
  • It was difficult to get spare parts for bikes such was demand
  • The spare parts that were available were a lot more expensive that normal
  • I have never seen so many cyclists on the road before (outside of a Sportive)
  • My average speed increased by 0.2mph on both the Scott and the Giant
  • The Velo Midlands was cancelled with no refund - robbing b******s, I won't be doing any of their events again
  • We had to cancel (defer for a year) the cycling holiday to the French Alps. I wanted to go this year at least as it would be the last year of everything thing being "normal" before we leave the EU at the end of 2020
  • I had to join Strava Premium as the changes made to the free version removed quite a few things I liked (like segments). Although this was not CoVid related to be fair.
  • Now that I'm a Premium Strava member I have used the Live Segment feature on my Garmin, and it has surprisingly made a difference. On segment
  • I used more Contact lenses than I have ever used before in a given period. I saw that I could now recycle both the plastic cases (which I did anyway) but also the foil covers. So I've been keeping them ready to recycle next time I go to the opticians:

Used Contact Lens holder mountain:

 


Here are some images and data showing what I have cycle this year so far: 

Sunday 25 October 2020

Di2 Fit File Analyser Tool - V2.0

I have written a small application on C#/.Net to parse .fit files and extract the data. This was primarily so that I could analyse the gear shift data from my Di2 equipped bike. The data is transmitted using Ant+ from a Shimano SM-EWW01 unit and recorded on a Garmin head unit:


The last version of the tool is described here: Di2 Fit File Decoder V1.1.0.4 and the original post is here: Di2 Fit File Decoder V1.1.1

I have updated the application to add a few new features and address some bugs, hence the update to V2.0

New features:

  • Added a new graph to show the "average" gear in each of the chainrings vs date
  • Added data export of tables in both .csv and .tab files via right click context menu
  • Added image export of the charts via right click context menu



Bug Fixes:
  • Found that some fit files were incorrectly analysed as containing no shift data, even though they did contain shifts
Further updates planned:
  • Modify so can store all .fit data, not just data with Di2 Shift data
This application has been the core of updates to my "Strava Data Tool" and will move it to allow either use of Strava data or manual fit file import or both

Access to the folder on my Google drive with the installer files and older versions is here:




As of Oct 2020 I have not yet uploaded the Visual Studio project files, these are to follow

Sunday 10 May 2020

Di2 Fit File Decoder V1.1.0.4

Just a small update to add the distance ridden in each gear combination:


No other changes (some very minor code tweaks only)

Installer file available from this link

Saturday 9 May 2020

Fulcrum Racing 7 (Disc) Wheel Bearing Replacement

Riding my bike to work a few weeks ago I happened to glance down a the front wheel and saw the Though Axle starting to come unwound. This was a pretty concerning observation to say the least so I stopped and reset it only for the same to happen a bit later. The third time I actually removed the wheel properly to look further and realised that one of the bearings had siezed. This was a pretty major issue given that I was still 7-8 miles from work and 10 miles or so from home. I refitted the wheel and carrie don riding cautiously to some squealing and noise, however this seemed to disappear after another mile or so. Checking on (a safe) arrival at work I reasoned that whatever had caused a bearing to fail had eased itself off and whilst not a perfect position to be in I could at least to get home again - as long as I remained careful and went the most direct route

Getting home I removed the wheel again and looked at the bearings. Both sides spun freely although one was clearly more "notchy" than the other. Given that one bearing had siezed solid albeit briefly there was no point in hoping that all was well - I knew that I needed to get them out and replaced.

The manual for these wheels is pretty poor - however once you know what to do its not too bad. First remove the disk brake. Then on the non-disk side use a small (2 or 3mm I think) allen key to undo the cap head grub screw. Loosen this a reasonable amount - its actually a pinch bolt for the bearing load cap. Once it's loose, still with the allen key in the screw use the allen key to unscrew (anti-clockwise) the pre-load completely off the axle,. You can then push the axle through and out the disk brake side. Here's an image of the axle removed (note that I have pushed the bearings back on here so it won't look like this when the axle alone is pushed through):


On the lefthand side is the black preload cap, The right hand end of the axle (the brake disk end) has a ridge not seen in the photo above, so that the axle is pushed in it locates on the ridge in the inner diameter of the bearing.

Having pushed the axle out it's then necessary to knock the bearings out. Given they are scrap (that's why we are removing them) we can be firm but careful. To do this I used a 6" 1/2" drive socket extension and plastic mallet, with the wheel resting on a block of wood. Take care to tap all around the bearing and avoid just trying to knock it out from a single location. Neither of the bearings were tight and both came out easily. The photo below shows the bearing on the disk brake side being removed, the non-disk side bearing is already removed



Having removed the bearings I both measured them and read the part number off the bearing. Here's the bearing part number - it's a 6903RS but what matters is the 6093:

 
 

Using my preferred EBay bearing supplier (AireVelo) the specification came out at OD = 30mm, ID = 17mm, depth = 7mm:

However my measurements disagreed with the 6903 spec - the ID was a nominal 18mm:

 

 
 

Stupidly I believed that the bearing serial number must be correct and ordered a pair. Quite why I did this when I had measured I still don't know, but not surprisingly when they arrived they did not fit, so I had to search for the right size

This came out as a MR18307 - same external dimensions but with the required ID of 18mm




Fortunately the bearings are not expensive and I did not need the bike for a couple of weeks whilst I waited for each set to arrive

When the 2nd (correct) set of bearings arrived I refitted the bearings - basically the reverse of removing them but with the need to be more careful and not damage the new ones when refitting. There were 2 choices to refit - presss in or knock in. I thought about making a small press with washers and using a G Clamp but decided that as they were not tight I would tap them in carefully. My 1/2" drive 21mm socket was almost exactly the right size to sit over the outer race but still fit in the bearing housing



So again with the whell resting on a piece of wood I tapped the bearings in fully and then reassembled the axle. When applying the pre-load with the cap it took a few iterations to make sure that it was tight enough but not too tight. However this design was significantly more tolerant to preload than a traditional cup and cone design, where what can seem like a little extra tighten turn siezes wheel and a little loosening makes it wobble. I also applied a little grease to the bearings when I re-assembled the wheel, however there was none visible when I stripped it down. There was no rust visible in the bearings either sugegsting that the failure was not due to water ingress (and I had ridden the bike a lot all through the year).

In more general terms I have not been overly impressed with these wheels. At 11 months a spoke broke on the rear wheel. I went back to Wiggle to complain and did not get the best initial response. However they agreed to refund the repair costs from my local bike shop. The spoke broke about 3000 miles and then this bearing failure occured at about 3500 miles. Given that I have had other wheels do over 10000 miles with no issues this does not bode that well for the future. Any further failures and they may well go in the bin I suspect (and hate to say). Poeple might say that these are "cheap" wheels and what do you expect, but I expect better durability than that to be honest

Saturday 18 April 2020

Di2 Fit File Decoder V1.1.1

Di2 Fit File Decoder V1.1.1 - Another Update April 2020

This is a small (traditional) Windows desktop application written in C#/.Net to decode a .fit file and extract the data from Shimano Di2 Gearshifting. This gear shift data is monitored using (in my case) the SM-EWW01 unit connected in series with the normal cable routing:



The application was started because I want to plot the gear data in my (much bigger) Strava data extraction tool, so the first step was to get the data and understand it

The fit file format information and sample C# code came from the Ant+ working group (Link) - you need to register, but it's free.

Using the sample console code to decode a fit file I was able to build a simple Windows application to get the gear shift data ("event data"), and the time based data (i.e. the "record "data). I then plotted this data against time/distance in  aline chart, displayed it in a data table and created a simple bar chart/histogram plot of the distribution of time/count in each gear combination.

Version 1 used file storage and V1.1 used a SQL database (as I was more familiar with these having used one for my main Strava Application. I left the code at V1.1 for a while whilst I went back to the Strava application and made some further updates. These were mostly in improving the code quality and readbility based on some learning that I gained from this Di2 application.

However this got the Strava Application up to a better level so I went back to the Di2 Application again to make some further updates to make it easier to bring the relevant code into the Strava application. This includes
  • finding why the database size was so large and fixing it to an extent
  • general minor bug fixes
  • some UI improvements
  • allowing the user to select pre-saved data from the Database and displaying it
  • ability to load and process multiple files simultaneously (i.e. select a whole directory of files)
  • a new feature to display a total time/count bar chart for shifts.

The Application can be downloaded from here (It's an installer file)

The other posts about this software are:
First Release: Here
Second Release: Here

Sunday 29 March 2020

Strava Data Tool Update March 2020 - V3.1 - Released

As posted a few weeks ago I havce now "released" V3.1 of my Strava Forms App

Updates include:
  1. Segments.
  2. Continuous Updating consdering the Strava Rate Limit
The code can be downloaded here (its a Windows installer)

1. Segments
This version sees download and processing of Segment data. It will display a table of all Segments ridden by the Athlete. It will also display the segments ridden during a particular Activity. Double clicking on the row header for a segment will show all the ride times for that segment vs. date

Here's some screen shots to show this

First the Segments for the Athlete:




Here you can see that I have ridden 1683 Activities (Rides) and furing those rides I have ridden 16232 UNIQUE segments. This table will show how many times each segment has been ridden



The table show the segments by name but can be sorted in the normal way by double clicking on a column header. I.e. :



These are segments on my commute hence the high number of times they have been ridden.

Note that some segments seem to be uploaded to Strava with no name (i.e. the name is 0 characters length). These are identified in Strava with unique IDs, but at the moment this application renames them to "** Unnamed **" and groups them together:




Then the Segments for an individual Activity are displayed when an Activity (individual Ride) is selected (double click an activity row header:



Finally the history of a segment can be seen by double clicking on the row header for a segment selected (Uniion Road in this example):



The segment data is downloaded when the the data for an individual activity is requested - i.e. when you either use the menu option "Tools / Download all Activity Data" or an individual activity is selected by clicking on the row header for an activity (as normal). Therefore when starting the Application for the first time there wil be no segments displayed until some activity data has been selected. The Segment tab should update when segments are updated but I have seen inconsistent behaviour here. Closing and restarting the application will force the data to be shown

2. Rate Limits
Strava imposes rate limits for downloading data. This is 600 calls every 15 minutes and 30000 every day

For this application the daily 30000 limit is not an issue it would seem - even heavy use sees not many more than 5-6000 calls per day. However the 15 minute limit is a limiting factor. When using the "Tools / Download all Activity Data" option it will keep making calls until all the data is downloaded. On my system it is not unusual to use this low limit up in 10-12 minutes. The repsonse once this happen is to call an exception which stops the downloads. 

This has now been addressed. The limit is continuously monitored. When it is exceeded the download code loops every 20 secs waiting for the limit to be reset (it happens exactly on the 1/4 hour) and then continues untill all data is acquired.

The balance of calls remaining is displayed in the toolbar:


You can leave the download running  quite happily and it will continue until complete - ihave downloaded all 1630+ activities that I have uploaded several times without issue. It uses 2 calls per activity to download.

Other comments
  1. When the application starts first it checks whether or not it needs to authenticate, and does so if required
  2. It then loads all the data which can take 10-15 seconds
  3. Whne first looking at the Activity (Ride) list it may seem to freeze as it is identifying whcih activities have downloaded data and painting them blue This can take 5-10 seconds

Other changes:
  1. Many more small code "improvements" and tidying
  2. Some changes to make the GUI a little more responsive in a few areas
  3. Some other small improvements and minor error checks
  4. Previously there  has been no check if using a later version of code with an older database version. There are occasionally changes to the database. It now checks if the database is the correct version and aborts if not. In this case you need to delete the .ini file and start again as there is as yet no database upgrade tool

Next Steps
  1. Update the database table creation code for the last 2-3 tables (make sit easier to create the database tables and create DataTables to load data to and from the database
  2. Add Di2 data (from a .fit file)
  3. Continuous small improvements

Sunday 15 March 2020

Strava Data Tool Update March 2020 - V3.1 - Segments Added

Just a quick teaser for a soon to be future release - the application now reads the segments ridden during an activity, and is able to plot out the riders time performance over all occurences that the segment has been ridden

First the Segment list for an activity:


Note that the elevation gain is the maximum less the minimum gradient (so does not account for dips in the segment) - but Strava does not give this data in the segment summary (may be better able to be calculated from the segment stream data when I get to that point)

And here is my historical performance over all the occasions I have ridden the segment (in a time period):


There is more data that I will add here - statistics of the time,a histogram perhaps etc.

The biggest issue though is that the additional Strava Request traffic to get the segments now means that I can only read about 200 activities before the 600 Requests limit per 15 minutes is exceeded

This means that I have not yet been able to read all my 1700 activities into the database with the segment data, so I am going to need to take some other approaches in the workflow to work within the limit. When this is fixed I will release this next version.



The good news is that given all the work over the past few months I spent "improving" the code, this was actually only ~5-6 hours work to get this into a pretty robust state

Saturday 7 March 2020

Cycling in Spain on Costa del Sol near Fuengerola

We had a family holiday in Fuengerola on the Costa Del Sol over the February 2020 Half Term

My son and I hired a couple of bikes for part of the week and did two rides

The first was over to Mijas Pueblo with my son - here:



This ride was warm - but drizzly weather and poor visibility. At the end of the final climb - "Repetidor" my son took a video of me struggling to the top/finish line:




The second was a long climb to Puerto de LagoAbejas (I think):


I did this without my son - he'd planned a loop that was about 85 miles and I knew that I didnt have the legs for that. The ride was basically out the to the highest point and back the same way. It came out to 65 miles and 6500ft of ascent - I was utterly done in by the end

What was great though was - the week before in the UK a ride was full winter gear - these 2 rides were shorts and short sleeves

We hired from Bikestardo - I'd recommend them. Quality bikes delivered and collected. We hired a Felt VR Performance Ultegra 105. The only real issue was that the brakes are reverse to UK - i.e. the right brake - the front in the UK operates the rear on this bike, and vice versa.:

FTP as Calculated by Garmin

I have a Smart Trainer and also a couple of 4iii Power Meters (left side only)

When I bought a Garmin 1030 last year it forced me to use the Garmin Android App (before I just plugged my 800 into my laptop and let it sync to Strava

With the Garmin App you get all sorts of other data that I started to look at - one of which is FTP. I am not sure how it calculates it given I have never gone out to do a FTP test either on the turbo or on the ride - hence I don't think I really believe it. However it gives me a relative benchmark from ride to ride (when measuring power).


I find that it's actually quite demotivating how it seemingly varies relatively easily

Here's a screeenshot of my last 6 months:


My "Garmin FTP" rises during the summer, then drops away over the winter - I peaked at 216W in 2019 before it bled away. I managed to push it back up from about 195W in December 2019 up to 210W in late February by putting some big efforts in on the turbo when riding using the RGT trainer application. I found that the "hilly" Pienza, Paterberg and Ca de Formentor routes suited me to push the power. The flat routes - 8 Bar, Canary Wharf and Borrego Springs don't quite do it for me.

I don't believe the real value and if I did a proper test I am certain it would be lower that this - but it gives a benckmark to compare myself to and equate how I felt on a ride vs. what the numbers say

It also gives a VO2 Max value - I believe this does need a proper test so how this is achieved I don't know. I guess I need to read and see if they publish information in line. However whilst the FTP number is not that great, the VO2 number rates me as between 49-50, which for my age (let's just say it's 50+) rates me as having a Fitness Age of 20 - the top 5% for my age and gender - I'll take that.



Unfortunate Text Cropping

On my Android phone I get various items of "interest" suggested by Google

Obviously the screen is quite small and the descriptive text gets cropped sometimes

This item is somewhat unfortunate in where it was cropped...


What sort of data science are they doing?

Friday 6 March 2020

Strava Data Tool Update March 2020 - V3


There's been a lack of visible progress on this application for 6-8months

This is partly because:
  • the weather was good over the summer and I'd much rather be outside
  • I've written the Di2 decoder application for a change of programming focus ("a change is as a good as a rest")
  • and I have also been making significant changes to the Strava Data Tool "under the bonnet" based on learning from the TCXConverter and Di2 Decoder apps that I wrote and could see benefits in making it easier to mainatin the Strava Tool
  • The Strava tool grew organically making it a nightmare to edit and change the code - this is because I wrote it learning as I went and adding feature ad-hoc and hence there is no design to the code
However the dark winter weather meant that I have been back on this with quite a lot of effort over late 2019/early 2020

I also thought ready to release back in February 2020 but some last minute tetsing showed a major issue when creating a new database. It took me a long time to work out the change that caused this, which was in fact trivial and related to changing to a static SQL class and getting confused with the constructor behaviour

Although the app looks almost identical there is a big change list which includes the following (not-exhaustive) list
  1. Only raw data stored in the database (~60% reduction in database size and improved performance)
  2. Use of SQL_BLOCKCOPY to load data to database tables)
  3. Consistent use of DataTables throughout the app, and programmatic creation of these rather than predifined. Also the Datatable definition are used to programmatically create the Database tables menaing a much greater level of consistency and alignment
  4. Conversion to static for a number of common classes
  5. Introduction of a static Global_Constants class to improve maintainability and readability across the application
  6. A lot of code tidying up
  7. Removal of redundant methods- so the code base is now smaller

  
There's still a lot of improvements to be made:
  1. The most major issues seems to be a change with the authentication process that is less seamless than it was a few months ago - I have yet to resolve this. When you start the application for the first time it will open a web page asking you to approve access to (your) data. This is as designed. However if you then close the application or don't use it for a further 6 hours the application needs to re-authenticate - this is as required by Strava. In theory th eapplication should use one of the tokens set in the first initialisation and silentrly re-authenticate. However it doesn't and it throws an exception "Error #3000 during Web POST, Authentication_Web_POST/Get_Tokens". However if you select OK it will then open a web page and re-authenticate. I need to look at this more
  2. Some database tables still need "re-formatting" to the new process
  3. Lost the ability to export the graph as an image (as I changed how the export feature worked)
  4. Better logging format and verbosity - although its better, it's still a mess
  5. More testing and error trapping - again it's a lot better but still not exhasutive
  6. The redraw code still does not function correctly
  7. Further code general improvements- readability, structure, style etc.
Some features to be added include:
  1. Adding the ability to (manually) load di2 data from a .fit file and asscoiate with existing down loaded data, inluding the statistics and graphical displays (i.e. incorporate my Di2 Decoder application into this application
  2. Adding segments data
  3. Refining the statistics - I think allowing a level of user query building would be good (to an extent). Also getting data per bike and ride type for example - i.e. how many miles in 2019 on Bike X on a trainer
  4. Fixing some of the things athat are still broken

Anyway here are the links to the program
  1. The standalone .exe file is uploaded to here:Link to V3 standalone exe Zip file
  2. The installer package is uploaded to here:  Link to V3 Full installer - Recommended


I strongly recommend using the installer - its been tested and works as I expect it to

As far as I can tell there are no viruses in the zip and there is  no spyware - it just reads your Strava data

Best Help page is here: Notes from release 2.0.0.0