Skip to content

Commit

Permalink
Merge pull request #277 from yihong0618/garmin_to_strava
Browse files Browse the repository at this point in the history
feat: garmin to strava
  • Loading branch information
yihong0618 committed Jul 13, 2022
2 parents 4a82b3f + e12f564 commit 166474a
Show file tree
Hide file tree
Showing 10 changed files with 250 additions and 218 deletions.
14 changes: 13 additions & 1 deletion .github/workflows/run_data_sync.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@ on:
- scripts/garmin_sync.py
- scripts/keep_sync.py
- scripts/gpx_sync.py
- scripts/tcx_sync.py
- scripts/garmin_to_strava_sync.py
- requirements.txt

env:
# please change to your own config.
RUN_TYPE: pass # support strava/nike/garmin/garmin_cn/keep/only_gpx/nike_to_strava/strava_to_garmin/strava_to_garmin_cn, Please change the 'pass' it to your own
RUN_TYPE: pass # support strava/nike/garmin/garmin_cn/keep/only_gpx/nike_to_strava/strava_to_garmin/strava_to_garmin_cn/garmin_to_strava/garmin_to_strava_cn, Please change the 'pass' it to your own
ATHLETE: yihong0618
TITLE: Yihong0618 Running
MIN_GRID_DISTANCE: 10 # change min distance here
Expand Down Expand Up @@ -105,6 +107,16 @@ jobs:
run: |
python scripts/strava_to_garmin_sync.py ${{ secrets.STRAVA_CLIENT_ID }} ${{ secrets.STRAVA_CLIENT_SECRET }} ${{ secrets.STRAVA_CLIENT_REFRESH_TOKEN }} ${{ secrets.GRAMIN_CN_EMAIL }} ${{ secrets.GARMIN_CN_PASSWORD }} --is-cn
- name: Run sync Garmin-cn to Strava(Run with Garmin data backup in Strava)
if: env.RUN_TYPE == 'garmin_to_strava_cn'
run: |
python scripts/garmin_to_strava_sync.py ${{ secrets.STRAVA_CLIENT_ID }} ${{ secrets.STRAVA_CLIENT_SECRET }} ${{ secrets.STRAVA_CLIENT_REFRESH_TOKEN }} ${{ secrets.GRAMIN_CN_EMAIL }} ${{ secrets.GARMIN_CN_PASSWORD }} --is-cn
- name: Run sync Garmin to Strava(Run with Garmin data backup in Strava)
if: env.RUN_TYPE == 'garmin_to_strava'
run: |
python scripts/garmin_to_strava_sync.py ${{ secrets.STRAVA_CLIENT_ID }} ${{ secrets.STRAVA_CLIENT_SECRET }} ${{ secrets.STRAVA_CLIENT_REFRESH_TOKEN }} ${{ secrets.GRAMIN_EMAIL }} ${{ secrets.GARMIN_PASSWORD }}
- name: Make svg GitHub profile
if: env.RUN_TYPE != 'pass'
run: |
Expand Down
30 changes: 27 additions & 3 deletions README-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,9 @@ R.I.P. 希望大家都能健康顺利的跑过终点,逝者安息。
- **[咕咚](#codoon咕咚,因咕咚限制单个设备原因,无法自动化)**
- **[GPX](#GPX)**
- **[TCX](#TCX)**
- **[Tcx_to_Strava(upload all tcx data to strava)](#TCX_to_Strava)**
- **[Tcx+Strava(upload all tcx data to strava)](#TCX_to_Strava)**
- **[Nike+Strava(Using NRC Run, Strava backup data)](#nikestrava)**
- **[Strava_to_Garmin(Using Strava Run, Garmin backup data)](#)**
- **[Garmin+Strava(Using Garmin Run, Strava backup data)](#garminstrava)**

## 下载

Expand Down Expand Up @@ -492,6 +492,7 @@ python3(python) scripts/tcx_to_strava_sync.py xxx xxx xxx

</details>


### Nike+Strava

<details>
Expand All @@ -500,7 +501,7 @@ python3(python) scripts/tcx_to_strava_sync.py xxx xxx xxx
<br>

1. 完成 nike 和 strava 的步骤
2. 在项目根目录下执行::
2. 在项目根目录下执行:

```python
python3(python) scripts/nike_to_strava_sync.py ${nike_refresh_token} ${client_id} ${client_secret} ${strava_refresch_token}
Expand All @@ -514,6 +515,29 @@ python3(python) scripts/nike_to_strava_sync.py eyJhbGciThiMTItNGIw****** xxx xx

</details>

### Garmin+Strava

<details>
<summary>Get your <code>Garmin</code> data and upload to strava</summary>

<br>

1. 完成 garmin 和 strava 的步骤
2. 在项目根目录下执行:

```python
python3(python) scripts/garmin_to_strava_sync.py ${client_id} ${client_secret} ${strava_refresch_token} ${garmin_email} ${garmin_password} --is-cn
```

示例:

```python
python3(python) scripts/garmin_to_strava_sync.py xxx xxx xxx xx xxx
```

</details>


### Total Data Analysis

<details>
Expand Down
22 changes: 21 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ English | [简体中文](https://github.com/yihong0618/running_page/blob/master/
- **[TCX](#TCX)**
- **[Nike_to_Strava(Using NRC Run, Strava backup data)](#Nike_to_Strava)**
- **[Tcx_to_Strava(upload all tcx data to strava)](#TCX_to_Strava)**
- **[Strava_to_Garmin(Using Strava Run, Garmin backup data)](#)**
- **[Garmin+Strava(Using Garmin Run, Strava backup data)](#garminstrava)**

## Download

Expand Down Expand Up @@ -405,6 +405,26 @@ python3(python) scripts/nike_to_strava_sync.py eyJhbGciThiMTItNGIw****** xxx xx

</details>

### Garmin+Strava

<details>
<summary>Get your <code>Garmin</code> data and upload to strava</summary>

<br>

1. finish garmin and strava setps
2. Execute in the root directory:

```python
python3(python) scripts/garmin_to_strava_sync.py ${client_id} ${client_secret} ${strava_refresch_token} ${garmin_email} ${garmin_password} --is-cn
```
e.g.

```python
python3(python) scripts/garmin_to_strava_sync.py xxx xxx xxx xx xxx
```


### Total Data Analysis

<details>
Expand Down
4 changes: 4 additions & 0 deletions scripts/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
OUTPUT_DIR = "activities"
GPX_FOLDER = os.path.join(os.getcwd(), "GPX_OUT")
TCX_FOLDER = os.path.join(os.getcwd(), "TCX_OUT")
FOLDER_DICT = {
"gpx": GPX_FOLDER,
"tcx": TCX_FOLDER,
}
SQL_FILE = os.path.join(os.getcwd(), "scripts", "data.db")
JSON_FILE = os.path.join(os.getcwd(), "src", "static", "activities.json")

Expand Down
84 changes: 46 additions & 38 deletions scripts/garmin_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,13 @@
import aiofiles
import cloudscraper
import httpx
from config import GPX_FOLDER, JSON_FILE, SQL_FILE, TCX_FOLDER, config
from config import JSON_FILE, SQL_FILE, FOLDER_DICT, config

from utils import make_activities_file

# logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)

FOLDER_DICT = {
"gpx": GPX_FOLDER,
"tcx": TCX_FOLDER,
}

TIME_OUT = httpx.Timeout(240.0, connect=360.0)
GARMIN_COM_URL_DICT = {
"BASE_URL": "https://connect.garmin.com",
Expand Down Expand Up @@ -285,6 +280,35 @@ async def sem_task(task):
return await asyncio.gather(*(sem_task(task) for task in tasks))


def get_downloaded_ids(folder):
return [i.split(".")[0] for i in os.listdir(folder) if not i.startswith(".")]


async def download_new_activities(
email, password, auth_domain, downloaded_ids, is_only_running, folder, file_type
):
client = Garmin(email, password, auth_domain, is_only_running)
client.login()
# because I don't find a para for after time, so I use garmin-id as filename
# to find new run to generage
activity_ids = await get_activity_id_list(client)
to_generate_garmin_ids = list(set(activity_ids) - set(downloaded_ids))
print(f"{len(to_generate_garmin_ids)} new activities to be downloaded")

start_time = time.time()
await gather_with_concurrency(
10,
[
download_garmin_data(client, id, file_type=file_type)
for id in to_generate_garmin_ids
],
)
print(f"Download finished. Elapsed {time.time()-start_time} seconds")

await client.req.aclose()
return to_generate_garmin_ids


if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("email", nargs="?", help="email of garmin")
Expand Down Expand Up @@ -315,44 +339,28 @@ async def sem_task(task):
auth_domain = (
"CN" if options.is_cn else config("sync", "garmin", "authentication_domain")
)
file_type = options.download_file_type
is_only_running = options.only_run
if email == None or password == None:
print("Missing argument nor valid configuration file")
sys.exit(1)
folder = FOLDER_DICT.get(options.download_file_type, "gpx")
# make gpx dir
folder = FOLDER_DICT.get(file_type, "gpx")
# make gpx or tcx dir
if not os.path.exists(folder):
os.mkdir(folder)

async def download_new_activities():
client = Garmin(email, password, auth_domain, is_only_running)
client.login()

# because I don't find a para for after time, so I use garmin-id as filename
# to find new run to generage
downloaded_ids = [
i.split(".")[0] for i in os.listdir(folder) if not i.startswith(".")
]
activity_ids = await get_activity_id_list(client)
to_generate_garmin_ids = list(set(activity_ids) - set(downloaded_ids))
print(f"{len(to_generate_garmin_ids)} new activities to be downloaded")

start_time = time.time()
file_type = options.download_file_type
await gather_with_concurrency(
10,
[
download_garmin_data(client, id, file_type=file_type)
for id in to_generate_garmin_ids
],
)
print(f"Download finished. Elapsed {time.time()-start_time} seconds")

make_activities_file(
SQL_FILE, folder, JSON_FILE, file_suffix=options.download_file_type
)
await client.req.aclose()
downloaded_ids = get_downloaded_ids(folder)

loop = asyncio.get_event_loop()
future = asyncio.ensure_future(download_new_activities())
future = asyncio.ensure_future(
download_new_activities(
email,
password,
auth_domain,
downloaded_ids,
is_only_running,
folder,
file_type,
)
)
loop.run_until_complete(future)
make_activities_file(SQL_FILE, folder, JSON_FILE, file_suffix=file_type)
108 changes: 0 additions & 108 deletions scripts/garmin_to_garmin.py

This file was deleted.

Loading

1 comment on commit 166474a

@vercel
Copy link

@vercel vercel bot commented on 166474a Jul 13, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

running-page – ./

running-page-git-master-yihong0618.vercel.app
running-page-yihong0618.vercel.app
running-page.vercel.app

Please sign in to comment.