R.I.P. 希望大家都能健康顺利的跑过终点,逝者安息。
Running page runners
- GitHub Actions 管理自动同步跑步进程及自动生成新的页面
- Gatsby 生成的静态网页,速度快
- 支持 Vercel(推荐) 和 GitHub Pages 自动部署
- React Hooks
- Mapbox 进行地图展示
- Nike 及 Runtastic(Adidas Run) 以及佳明(佳明中国)及 Keep 等,自动备份 gpx 数据,方便备份及上传到其它软件
因为数据存在 gpx 和 data.db 中,理论上支持几个软件一起,你可以把之前各类 app 的数据都同步到这里(建议本地同步,之后 actions 选择正在用的 app)
注:如果你不想公开数据,可以选择 strava 的模糊处理,或 private 仓库。
- Strava
- Nike Run Club
- Garmin
- Garmin-cn
- Keep
- 悦跑圈
- 咕咚
- 郁金香运动
- GPX
- TCX
- FIT
- Tcx+Strava(upload all tcx data to strava)
- Gpx+Strava(upload all tcx data to strava)
- Nike+Strava(Using NRC Run, Strava backup data)
- Garmin_to_Strava(Using Garmin Run, Strava backup data)
- Strava_to_Garmin(Using Strava Run, Garmin backup data)
git clone https://github.com/yihong0618/running_page.git --depth=1
pip3 install -r requirements.txt
yarn install
yarn develop
访问 http://localhost:8000/ 查看
#构建
# NRC
docker build -t running_page:latest . --build-arg app=NRC --build-arg nike_refresh_token=""
# Garmin
docker build -t running_page:latest . --build-arg app=Garmin --build-arg email="" --build-arg password=""
# Garmin-CN
docker build -t running_page:latest . --build-arg app=Garmin-CN --build-arg email="" --build-arg password=""
# Strava
docker build -t running_page:latest . --build-arg app=Strava --build-arg client_id="" --build-arg client_secret="" --build-arg refresh_token=""
#Nike_to_Strava
docker build -t running_page:latest . --build-arg app=Nike_to_Strava --build-arg nike_refresh_token="" --build-arg client_id="" --build-arg client_secret="" --build-arg refresh_token=""
#启动
docker run -itd -p 80:80 running_page:latest
#访问
访问 ip:80 查看
建议有能力的同学把代码中的 Mapbox token 自己的 Mapbox token
const MAPBOX_TOKEN =
'pk.eyJ1IjoieWlob25nMDYxOCIsImEiOiJja2J3M28xbG4wYzl0MzJxZm0ya2Fua2p2In0.PNKfkeQwYuyGOTT_x9BJ4Q';
- 在仓库目录下找到
gatsby-config.js
,找到以下内容并修改成你自己想要的。
siteMetadata: {
siteTitle: 'Running Page', #网站标题
siteUrl: 'https://yihong.run', #网站域名
logo: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQTtc69JxHNcmN1ETpMUX4dozAgAN6iPjWalQ&usqp=CAU', #左上角LOGO
description: 'Personal site and blog',
navLinks: [
{
name: 'Blog', #右上角导航名称
url: 'https://yihong.run/running', #右上角导航链接
},
{
name: 'About',
url: 'https://github.com/yihong0618/running_page/blob/master/README-CN.md',
},
],
},
- 修改
src/utils/const.js
文件中的样式:
// styling: 关闭虚线:设置为 `false`
const USE_DASH_LINE = true;
// styling: 透明度:[0, 1]
const LINE_OPACITY = 0.4;
- 隐私保护:
设置下面环境变量:
IGNORE_START_END_RANGE = 200 # 忽略每个 polyline 的起点和终点的长度(单位:米)。
IGNORE_RANGE = 200 # 忽略下面 polyline 中每个点的距离的圆圈(单位:米)。
IGNORE_POLYLINE = ktjrFoemeU~IorGq}DeB # 包含要忽略的点的折线。
# 在保存到数据库之前进行过滤,你会丢失一些数据,但可以保护你的隐私,如果你使用的是公共仓库,建议设置为1。不设置可关闭。
IGNORE_BEFORE_SAVING = 1
你可一用这个,来制作你的 IGNORE_POLYLINE
。如果你在中国,请使用卫星图制作,避免火星坐标漂移。
下载您的 Nike Run Club/Strava/Garmin/Garmin-cn/Keep 数据,别忘了在 total
页面生成可视化 SVG
Make your GPX
data
把其它软件生成的 gpx files 拷贝到 GPX_OUT 之后运行
python3(python) scripts/gpx_sync.py
Make your TCX
data
把其它软件生成的 tcx files 拷贝到 TCX_OUT 之后运行
python3(python) scripts/tcx_sync.py
Make your FIT
data
把其它软件生成的 fit files 拷贝到 FIT_OUT 之后运行
python3(python) scripts/fit_sync.py
获取您的 Keep 数据
确保自己的账号能用手机号 + 密码登陆 (不要忘记添加 secret 和更改自己的账号,在 GitHub Actions 中), 注:海外手机号需要换成国内 +86 的手机号
python3(python) scripts/keep_sync.py ${your mobile} ${your password}
示例:
python3(python) scripts/keep_sync.py 13333xxxx example
注:我增加了 keep 可以导出 gpx 功能(因 keep 的原因,距离和速度会有一定缺失), 执行如下命令,导出的 gpx 会加入到 GPX_OUT 中,方便上传到其它软件
python3(python) scripts/keep_sync.py ${your mobile} ${your password} --with-gpx
示例:
python3(python) scripts/keep_sync.py 13333xxxx example --with-gpx
路线偏移修正
如果您得到的运动路线与实际路线对比有整体偏移,可以修改代码中的参数进行修正
注:Keep 目前采用的是 GCJ-02 坐标系,因此导致得到运动数据在使用 WGS-84 坐标系的平台(Mapbox、佳明等)中显示轨迹整体偏移
- 修改
scripts/keep_sync.py
文件中的参数:
# If your points need trans from gcj02 to wgs84 coordinate which use by Mappbox
TRANS_GCJ02_TO_WGS84 = True
获取您的悦跑圈数据
获取登陆验证码:
确保自己的账号能用手机号 + 验证码登陆
点击获取验证码
注:不要在手机输入验证码,拿到验证码就好,用这个验证码放到下方命令中
python3(python) scripts/joyrun_sync.py ${your mobile} ${your 验证码}
示例:
python3(python) scripts/joyrun_sync.py 13333xxxx xxxx
注:我增加了 joyrun 可以导出 gpx 功能,执行如下命令,导出的 gpx 会加入到 GPX_OUT 中,方便上传到其它软件
python3(python) scripts/joyrun_sync.py ${your mobile} ${your 验证码} --with-gpx
示例:
python3(python) scripts/joyrun_sync.py 13333xxxx example --with-gpx
注:因为验证码有过期时间,我增加了 cookie uid sid 登陆的方式,uid 及 sid 在您登陆过程中会在控制台打印出来
示例:
python3(python) scripts/joyrun_sync.py 1393xx30xxxx 97e5fe4997d20f9b1007xxxxx --from-uid-sid --with-gpx
获取您的咕咚数据
python3(python) scripts/codoon_sync.py ${your mobile or email} ${your password}
示例:
python3(python) scripts/codoon_sync.py 13333xxxx xxxx
注:我增加了 Codoon 可以导出 gpx 功能,执行如下命令,导出的 gpx 会加入到 GPX_OUT 中,方便上传到其它软件
python3(python) scripts/codoon_sync.py ${your mobile or email} ${your password} --with-gpx
示例:
python3(python) scripts/codoon_sync.py 13333xxxx xxxx --with-gpx
注:因为登录 token 有过期时间限制,我增加了 refresh_token&user_id 登陆的方式,refresh_token 及 user_id 在您登陆过程中会在控制台打印出来
示例:
python3(python) scripts/codoon_sync.py 54bxxxxxxx fefxxxxx-xxxx-xxxx --from-auth-token
路线偏移修正
如果您得到的运动路线与实际路线对比有整体偏移,可以修改代码中的参数进行修正
注:咕咚最初采用 GCJ-02 坐标系,在 2014 年 3 月份左右升级为 WGS-84 坐标系,导致升级之前的运动数据在使用 WGS-84 坐标系的平台(Mapbox、佳明等)中显示轨迹整体偏移
- 修改
scripts/codoon_sync.py
文件中的参数:
注:TRANS_END_DATE 需要根据您的实际情况设定,程序会修正这一天之前的运动记录
# If your points need trans from gcj02 to wgs84 coordinate which use by Mappbox
TRANS_GCJ02_TO_WGS84 = True
# trans the coordinate data until the TRANS_END_DATE, work with TRANS_GCJ02_TO_WGS84 = True
TRANS_END_DATE = "2014-03-24"
获取您的郁金香运动数据
郁金香运动数据的获取方式采用开放平台授权模式,通过访问RunningPage 授权页面获取账号 TOKEN(不会过期,只能访问 2021 年之后的数据),并在仓库的 GitHub Actions 环境配置中添加
TULIPSPORT_TOKEN
配置。
python3(python) scripts/tulipsport_sync.py ${tulipsport_token}
示例:
python3(python) scripts/tulipsport_sync.py nLgy****RyahI
获取您的 Garmin 数据
如果你只想同步跑步数据增加命令 --only-run
如果你想同步 tcx
格式,增加命令 --tcx
如果你想同步 fit
格式,增加命令 --fit
python3(python) scripts/garmin_sync.py ${your email} ${your password}
示例:
python3(python) scripts/garmin_sync.py example@gmail.com example
获取您的 Garmin-CN 数据
如果你只想同步跑步数据请增加 --only-run
如果你想同步 tcx
格式,增加命令 --tcx
如果你想同步 fit
格式,增加命令 --fit
python3(python) scripts/garmin_sync.py ${your email} ${your password} --is-cn
示例:
python3(python) scripts/garmin_sync.py example@gmail.com example --is-cn
仅同步跑步数据:
python3(python) scripts/garmin_sync.py example@gmail.com example --is-cn --only-run
获取 Nike Run Club 数据
请注意:当您选择将 running_page 部署在自己的服务器上时,由于 Nike 已经封禁了一部分 IDC 的服务器 IP 段,您的服务器可能不能正常同步 Nike Run Club 的数据并显示
403 error
,这时您将不得不选择其他的托管方式。
获取 Nike 的 refresh_token
- 登录 Nike 官网
- In Developer -> Application-> Storage -> https:unite.nike.com 中找到 refresh_token
python3(python) scripts/nike_sync.py ${nike refresh_token}
示例:
python3(python) scripts/nike_sync.py eyJhbGciThiMTItNGIw******
获取 Strava 数据
-
注册/登陆 Strava 账号
-
登陆成功后打开 Strava Developers -> Create & Manage Your App
-
使用以下链接请求所有权限 将 ${your_id} 替换为 My API Application 中的 Client ID 后访问完整链接
https://www.strava.com/oauth/authorize?client_id=${your_id}&response_type=code&redirect_uri=http://localhost/exchange_token&approval_prompt=force&scope=read_all,profile:read_all,activity:read_all,profile:write,activity:write
- 提取授权后返回链接中的 code 值 例如:
http://localhost/exchange_token?state=&code=1dab37edd9970971fb502c9efdd087f4f3471e6e&scope=read,activity:write,activity:read_all,profile:write,profile:read_all,read_all
code
数值为:
1dab37edd9970971fb502c9efdd087f4f3471e6
6. 使用 Client_id、Client_secret、Code 请求 refresh_token
在 终端/iTerm
中执行:
curl -X POST https://www.strava.com/oauth/token \
-F client_id=${Your Client ID} \
-F client_secret=${Your Client Secret} \
-F code=${Your Code} \
-F grant_type=authorization_code
示例:
curl -X POST https://www.strava.com/oauth/token \
-F client_id=12345 \
-F client_secret=b21******d0bfb377998ed1ac3b0 \
-F code=d09******b58abface48003 \
-F grant_type=authorization_code
- 同步数据至 Strava 在项目根目录执行:
第一次同步 Strava 数据时需要更改在 strava_sync.py 中的第 12 行代码 False 改为 True,运行完成后,再改为 False。
如果你只想同步跑步数据增加命令 --only-run
python3(python) scripts/strava_sync.py ${client_id} ${client_secret} ${refresh_token}
其他资料参见 https://developers.strava.com/docs/getting-started https://github.com/barrald/strava-uploader https://github.com/strava/go.strava
上传所有的 tcx 格式的跑步数据到 strava
- 完成 strava 的步骤
- 把 tcx 文件全部拷贝到 TCX_OUT 中
- 在项目根目录下执行:
python3(python) scripts/tcx_to_strava_sync.py ${client_id} ${client_secret} ${strava_refresh_token}
示例:
python3(python) scripts/tcx_to_strava_sync.py xxx xxx xxx
或
python3(python) scripts/tcx_to_strava_sync.py xxx xxx xxx --all
- 如果你已经上传过需要跳过判断增加参数
--all
上传所有的 gpx 格式的跑步数据到 strava
- 完成 strava 的步骤
- 把 gpx 文件全部拷贝到 GPX_OUT 中
- 在项目根目录下执行:
python3(python) scripts/gpx_to_strava_sync.py ${client_id} ${client_secret} ${strava_refresh_token}
示例:
python3(python) scripts/gpx_to_strava_sync.py xxx xxx xxx
或
python3(python) scripts/gpx_to_strava_sync.py xxx xxx xxx --all
- 如果你已经上传过需要跳过判断增加参数
--all
获取 Nike Run Club
的跑步数据然后同步到 Strava
- 完成 nike 和 strava 的步骤
- 在项目根目录下执行:
python3(python) scripts/nike_to_strava_sync.py ${nike_refresh_token} ${client_id} ${client_secret} ${strava_refresh_token}
示例:
python3(python) scripts/nike_to_strava_sync.py eyJhbGciThiMTItNGIw****** xxx xxx xxx
获取你的佳明
的跑步数据,然后同步到 Strava
- 完成 garmin 和 strava 的步骤
- 在项目根目录下执行:
python3(python) scripts/garmin_to_strava_sync.py ${client_id} ${client_secret} ${strava_refresh_token} ${garmin_email} ${garmin_password} --is-cn
示例:
python3(python) scripts/garmin_to_strava_sync.py xxx xxx xxx xx xxx
获取你的Strava
的跑步数据然后同步到 Garmin
- 完成 garmin 和 strava 的步骤,同时,还需要在 Github Actions secret 那新增 Strava 配置:
secrets.STRAVA_EMAIL
、secrets.STRAVA_PASSWORD
- 在项目根目录下执行:
python3(python) scripts/strava_to_garmin_sync.py ${{ secrets.STRAVA_CLIENT_ID }} ${{ secrets.STRAVA_CLIENT_SECRET }} ${{ secrets.STRAVA_CLIENT_REFRESH_TOKEN }} ${{ secrets.GARMIN_EMAIL }} ${{ secrets.GARMIN_PASSWORD }} ${{ secrets.STRAVA_EMAIL }} ${{ secrets.STRAVA_PASSWORD }}
如果你的佳明账号是中国区,执行如下的命令:
python3(python) scripts/strava_to_garmin_sync.py ${{ secrets.STRAVA_CLIENT_ID }} ${{ secrets.STRAVA_CLIENT_SECRET }} ${{ secrets.STRAVA_CLIENT_REFRESH_TOKEN }} ${{ secrets.GARMIN_CN_EMAIL }} ${{ secrets.GARMIN_CN_PASSWORD }} ${{ secrets.STRAVA_EMAIL }} ${{ secrets.STRAVA_PASSWORD }} --is-cn
如果要在同步到Garmin的运动记录中添加Garmin设备信息,需要添加--use_fake_garmin_device
参数,这将在同步的Garmin锻炼记录中添加一个Garmin设备(默认情况下为 Garmin Forerunner 245
,您可以在garmin_device_adaptor.py
中更改设备信息),运动记录中有了设备信息之后就可以同步到其他APP中,比如数字心动(攒上马积分)这类不能通过Apple Watch同步的APP,当然也可以同步到Keep,悦跑圈,咕咚等APP。
最终执行的命令如下:
python3(python) scripts/strava_to_garmin_sync.py ${{ secrets.STRAVA_CLIENT_ID }} ${{ secrets.STRAVA_CLIENT_SECRET }} ${{ secrets.STRAVA_CLIENT_REFRESH_TOKEN }} ${{ secrets.GARMIN_CN_EMAIL }} ${{ secrets.GARMIN_CN_PASSWORD }} ${{ secrets.STRAVA_EMAIL }} ${{ secrets.STRAVA_PASSWORD }} --use_fake_garmin_device
注意:首次初始化的时候,如果你有大量的 strava 跑步数据,可能有些数据会上传失败,只需要多重试几次即可。
生成数据展示
注:感兴趣的同学可以改下方参数 (--special-distance 10 --special-distance2 20, 10km~20km 展示为 special-color1 20km 以上展示为 special-color2, --min-distance 10.0 用来筛选 10km 以上的)
python3(python) scripts/gen_svg.py --from-db --title "${{ env.TITLE }}" --type github --athlete "${{ env.ATHLETE }}" --special-distance 10 --special-distance2 20 --special-color yellow --special-color2 red --output assets/github.svg --use-localtime --min-distance 0.5
python3(python) scripts/gen_svg.py --from-db --title "${{ env.TITLE_GRID }}" --type grid --athlete "${{ env.ATHLETE }}" --output assets/grid.svg --min-distance 10.0 --special-color yellow --special-color2 red --special-distance 20 --special-distance2 40 --use-localtime
生成年度环形数据
python3(python) scripts/gen_svg.py --from-db --type circular --use-localtime
更多展示效果参见: https://github.com/flopp/GpxTrackPoster
使用 Cloudflare 部署
-
在
Pages
中点击Create a project
以连接到你的仓库 -
点击
Begin setup
后,修改项目的Build settings
。 -
在
Framework preset
中选择Gatsby
框架。 -
向下滚动,点击
Environment variables
修改变量如下:Variable name =
PYTHON_VERSION
, Value =3.7
-
点击
Save and Deploy
,完成部署。
部署到 GitHub Pages
- 为 GitHub Actions 添加代码提交权限
访问仓库的
Settings > Actions > General
页面,找到Workflow permissions
的设置项,将选项配置为Read and write permissions
,支持 CI 将运动数据更新后提交到仓库中。 - 更新配置并提交代码
- 更新./gatsby-config.js中的
siteMetadata
节点; (按需)如果启用自定义域名模式或者变更 Fork 后的仓库名称,请变更pathPrefix
的值。 - 更新 GitHub CI 的配置 .github/workflows/run_data_sync.yml 中的配置;
- (按需)如需使用自定义域名,可以修改 .github/workflows/gh-pages.yml 中的
fqdn
(默认已注释掉) - 在仓库的
Settings > Secrets and variables > Actions
页面添加对应服务的环境配置信息,参考不同平台配置。
- 更新./gatsby-config.js中的
- 同步数据并发布 GitHub Pages
- 手动触发
Run Data Sync
的 Github Action 完成数据同步,完成后会自动触发Publish GitHub Pages
的任务执行,等待执行完成; - 开通仓库 GitHub Pages 功能,选择
gh-pages
分支和/(root)
目录。
- 手动触发
修改 GitHub Actions Token
Actions 源码 需要做如下步骤
测试发现,不同厂商在写fit文件的时候有略微差异。
已调试设备:
- 佳明手表
- 迈金码表
如果发现自己的fit文件解析有问题。可以提issue。
- 完善这个文档
- 支持佳明,佳明中国
- 支持 keep
- 支持苹果自带运动
- 支持 nike + strava
- 支持咕咚
- 尝试支持小米运动
- 支持英语
- 完善代码
- 清理整个项目
- 完善前端代码
- better actions
- tests
- 支持不同的运动类型
- 任何 Issues PR 均欢迎。
- 可以提交 PR share 自己的 Running page 在 README 中。
提交 PR 前:
- 使用 black 对 Python 代码进行格式化。(
black .
)
- @flopp 特别棒的项目 GpxTrackPoster
- @danpalmer 原始的 UI 设计
- @shaonianche icon 设计及文档
- @geekplux 帮助及鼓励,重构了前端代码,学到了不少
- @ben-29 搞定了咕咚,和我一起搞定了悦跑圈,太厉害了
- @MFYDev Wiki
谢谢就够了
https://www.strava.com/settings/api https://developers.strava.com/docs/#rate-limiting
等待时间限制(这里是 strava 接口请求限制),不要关闭终端,这里会自动执行下一组上传数据
Strava API Rate Limit Exceeded. Retry after 100 seconds
Strava API Rate Limit Timeout. Retry in 799.491622 seconds