1

I've used a Smart Scale since 2020 with its own app which eventually became Zepp Life.

Having acquired a Garmin a while ago, would be a pity to lose all that data.

The good news is that we can pull data from other accounts or activity trackers into Garmin Connect in the import page.

So, I exported the Body data as CSV from Zepp Life.

The data looks like this

time,weight,height,bmi,fatRate,bodyWaterRate,boneMass,metabolism,muscleRate,visceralFat
2020-09-01 08:00:17+0000,83.6,186.0,24.1,0.0,0.0,0.0,0.0,0.0,0.0
2020-09-01 22:02:16+0000,82.8,186.0,23.9,0.0,0.0,0.0,0.0,0.0,0.0

After trying to import, realized that Garmin doesn't support uploading that file.

The question emerging is then which format does the CSV need have to be able to upload it in Garmin?

Tiago Peres
  • 1,497

1 Answers1

1

Thanks to someone in Reddit, found that it's something like this

Body
weight,bmi,fat,date,time
83.6,24.1,0.0,2020-09-01,08:00:17
82.8,23.9,0.0,2020-09-01,22:02:16

Eventually also found here as well.

So, initially created a simple Python script that reads weight and body composition data from a "zep_life.csv" file, and converted it into a CSV format that was ready to be imported into Garmin

This time I wasn't getting a warning anymore but it got stuck

image

as in, nothing seemed to have happend.

I figured it had to do with the size of the file.

So, instead of generating only one file, I generated one file per year and it worked

image

This was the used script

import csv
import datetime

INPUT_CSV = "zep_life.csv"

def zep_to_garmin_csv(): """ Reads a CSV file named "zep_life.csv" and writes multiple yearly CSVs named "garmin_ready_<year>.csv". Each output file has the first line "Body", followed by "weight,bmi,fat,date,time" as headers. Rows are based on the 'time' field in the input, split by year.

Usage:
    1. Place &quot;zep_life.csv&quot; in the same directory as this script.
    2. Run this script.
    3. For each year encountered in &quot;zep_life.csv&quot;, a file named 
       &quot;garmin_ready_&lt;year&gt;.csv&quot; will be created.

Requirements:
    - The input CSV must have the columns: &quot;time&quot;, &quot;weight&quot;, &quot;bmi&quot;, &quot;fatRate&quot;.
    - &quot;time&quot; must be in a format parseable by datetime.strptime with 
      &quot;%Y-%m-%d %H:%M:%S%z&quot;.
    - &quot;fatRate&quot; of &quot;null&quot; or empty is replaced with &quot;0.0&quot;.
&quot;&quot;&quot;
yearly_writers = {}
with open(INPUT_CSV, mode=&quot;r&quot;, encoding=&quot;utf-8-sig&quot;) as fin:
    reader = csv.DictReader(fin)
    for row in reader:
        raw_time = row.get(&quot;time&quot;, &quot;&quot;).strip()
        weight_str = row.get(&quot;weight&quot;, &quot;&quot;).strip()
        bmi_str = row.get(&quot;bmi&quot;, &quot;&quot;).strip()
        fat_str = row.get(&quot;fatRate&quot;, &quot;&quot;).strip()

        if not raw_time or not weight_str:
            continue

        try:
            dt = datetime.datetime.strptime(raw_time, &quot;%Y-%m-%d %H:%M:%S%z&quot;)
        except ValueError:
            continue

        date_str = dt.strftime(&quot;%Y-%m-%d&quot;)  # &quot;YYYY-MM-DD&quot;
        time_str = dt.strftime(&quot;%H:%M:%S&quot;)  # &quot;HH:MM:SS&quot;

        if fat_str.lower() in (&quot;null&quot;, &quot;&quot;):
            fat_str = &quot;0.0&quot;

        # If we haven't opened a file for this year yet, do so and write headers.
        year = dt.year
        if year not in yearly_writers:
            fout = open(f&quot;garmin_ready_{year}.csv&quot;, &quot;w&quot;, newline=&quot;&quot;, encoding=&quot;utf-8&quot;)
            writer = csv.writer(fout)

            # First line: &quot;Body&quot;
            writer.writerow([&quot;Body&quot;])

            # Second line: headers
            writer.writerow([&quot;weight&quot;, &quot;bmi&quot;, &quot;fat&quot;, &quot;date&quot;, &quot;time&quot;])

            # Store it in the dictionary
            yearly_writers[year] = (fout, writer)

        # Write the row to the proper year's CSV.
        _, csv_writer = yearly_writers[year]
        csv_writer.writerow([weight_str, bmi_str, fat_str, date_str, time_str])

# Close all the files
for fout, _ in yearly_writers.values():
    fout.close()

print(&quot;Done! Split files by year.&quot;)


if name == "main": zep_to_garmin_csv()

Tiago Peres
  • 1,497