佳明导出.fit文件
-
国际服:https://www.garmin.com/en-US/account/profile
国内服:https://www.garmin.cn/zh-CN/account/profile
-
选择Data Management-Export Your Data,导出所有数据,数据准备完成后会发送邮件提供下载链接
-
所有.fit活动文件在/DI_CONNECT/DI-Connect-Uploaded-Files/中的压缩包内
解析.fit文件
可以用fitparse
库解析.fit文件,选取自己想上传的文件
例如想获取活动时间在2024-1-20之前的文件:
from fitparse import FitFile
fit = FitFile(fit_filepath)
for record in fit.get_messages('record'):timestamp = record.get_value('timestamp')if timestamp and timestamp < cutoff_date:print(f"File {fit_filepath} has a timestamp before 2024/01/20: {timestamp}")break
strava导入.fit文件
-
在 Strava 开发者控制台创建应用:
- 创建 Strava 开发者账户并登录 Strava Developer Portal。
- 创建一个新的应用,网站可以设置成
http://localhost:8080
,用于用户授权后传authorization_code - 获取应用的 Client ID 和 Client Secret
-
用户授权:
-
本地起服务:
import http.server import socketserver import urllib.parse PORT = 8080 Handler = http.server.SimpleHTTPRequestHandler class MyHandler(http.server.BaseHTTPRequestHandler):def do_GET(self):parsed_path = urllib.parse.urlparse(self.path)query_params = urllib.parse.parse_qs(parsed_path.query)if 'code' in query_params:authorization_code = query_params['code'][0]print(f"Authorization code received: {authorization_code}")self.send_response(200)self.end_headers()self.wfile.write(b"Authorization code received successfully")else:self.send_response(400)self.end_headers()self.wfile.write(b"Error: Authorization code not found") with socketserver.TCPServer(("", PORT), MyHandler) as httpd:print(f"Serving at port {PORT}")httpd.serve_forever()
-
替换client_id,在浏览器中访问链接:
https://www.strava.com/oauth/authorize?client_id={client_id}&response_type=code&redirect_uri=http://localhost:8080&scope=activity:write,read&state=random_string&approval_prompt=auto -
在浏览器中授权后,本地服务端获得Authorization Code
-
-
OAuth认证:
- 根据Client ID、Client Secret、Authorization Code,获取有读写权限的Access Token
data = {'client_id': client_id,'client_secret': client_secret,'code': authorization_code,'grant_type': 'authorization_code','redirect_uri': 'http://localhost:8080' } response = requests.post('https://www.strava.com/oauth/token', data=data) if response.status_code == 200:token_data = response.json()new_access_token = token_data['access_token'] # 新的 Access Tokennew_refresh_token = token_data['refresh_token'] # 新的 Refresh Tokenprint(f"New Access Token: {new_access_token}")print(f"New Refresh Token: {new_refresh_token}") else:print(f"Failed to refresh token: {response.text}")
- 根据Client ID、Client Secret、Authorization Code,获取有读写权限的Access Token
-
过期刷新Access Token:
- Refresh Token在Strava创建的应用页面可找到
- 上一步的data改成如下,重新请求获取Access Token
refresh_data = {'client_id': client_id,'client_secret': client_secret,'refresh_token': refresh_token,'grant_type': 'refresh_token' }
-
批量上传.fit文件
upload_url = 'https://www.strava.com/api/v3/uploads'fit_files = [f for f in os.listdir(source_folder) if f.endswith('.fit')]for fit_file in fit_files:fit_filepath = os.path.join(source_folder, fit_file)print(f"Uploading {fit_filepath}...")with open(fit_filepath, 'rb') as f:files = {'file': (fit_file, f, 'application/octet-stream')}params = {'access_token': access_token,'data_type': 'fit', # 上传文件类型为 FIT'name': fit_file, # 设置上传活动的名称,默认用文件名}response = requests.post(upload_url, files=files, data=params)if response.status_code == 201:print(f"Successfully uploaded {fit_file} to Strava.")else:print(f"Failed to upload {fit_file}: {response.text}")