Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

看了几天代码,有几个自己的想法不知道对不对? #646

Open
Vensent opened this issue Apr 10, 2024 · 22 comments
Open

看了几天代码,有几个自己的想法不知道对不对? #646

Vensent opened this issue Apr 10, 2024 · 22 comments

Comments

@Vensent
Copy link
Contributor

Vensent commented Apr 10, 2024

首先感谢yihong大神,这个开源项目真的很赞!

  • 然后是workflow和action,只要是部署成功一次之后,后续Github会自动帮我们运行拉取的操作么?如果是的话频率大概是多久一次呢?

  • 折腾成功了终于把页面弄出来了,符合预期,想问问可否把我页面也加到yihong大神的readme里面(跑步正好10年,诚惶诚恐)。页面地址:https://vensent.github.io/workouts_page/

  • 最近Garmin 945坏掉了,因为在OPPO上班,想强力支持一波我司的手表,所以最近换手表了,所以关于页面有些问题我想这么搞你看看行不行。

  • 我首先拉一个主发布分支(也就是master),就只用Garmin的数据,其他所有的数据都不管。

  • 为了发布更干净,我拉第二个数据分支(data_retrieve),前提是公司OPPO手表欢太健康的数据先通过手机上的账号绑定同步到keep,然后定时拉取keep到gpx的文件夹下,然后运行导入gpx到strava,然后再运行strava to Garmin和strava to Garmin CN,这样能保证第一个分支以及网页能拉到最新的数据。

能行不,这个思路?

@yihong0618
Copy link
Owner

  1. 对,一天跑一次可以自己更改
  2. 可以
  3. 应该行但需要你比较能折腾
    之后我加你到 readme 里~

@SongJgit
Copy link
Contributor

SongJgit commented Apr 11, 2024

@Vensent @yihong0618 第五点和我的工作流相似,不过我是华为运动健康 -> Keep -> Strava。

我也是昨天才开始用running page,根据自己的想法修改了一些,完成了上面的工作流,但是还不算完善(在读博,确实没有太多时间搞)。

我是在@ben的基础上做的(因为他支持更多的运动类型)。

华为运动健康 -> Keep是可以APP自动绑定的,这点和OPPO一致。

只考虑 Keep 保存GPX,然后自动上传到strava即可。

目前支持的是 running, walking,cycling,因为现在我自己平时也就这些,后续可能根据需要添加远足,登山,爬楼。

  1. 为了快速实现,我是直接把keep_sync.py复制出了keep_sync_running.py,keep_sync_walking.py,keep_sync_cycling.py,分别对应上面的运动类型(ugly code)。

  2. 然后分别将里面对应的接口改为

# in keep_sync_running.py
RUN_DATA_API = "https://api.gotokeep.com/pd/v3/stats/detail?dateUnit=all&type=running&lastDate={last_date}"
RUN_LOG_API = "https://api.gotokeep.com/pd/v3/runninglog/{run_id}"

# in keep_sync_walking.py
RUN_DATA_API = "https://api.gotokeep.com/pd/v3/stats/detail?dateUnit=all&type=hiking&lastDate={last_date}"
RUN_LOG_API = "https://api.gotokeep.com/pd/v3/hikinglog/{run_id}"

# in keep_sync_cycling.py
RUN_DATA_API = "https://api.gotokeep.com/pd/v3/stats/detail?dateUnit=all&type=cycling&lastDate={last_date}"
RUN_LOG_API = "https://api.gotokeep.com/pd/v3/cyclinglog/{run_id}"
  1. 然后里面对应的数据类型分别修改为
run_data["dataType"] == "outdoorRunning"
run_data["dataType"] == "outdoorCycling"
run_data["dataType"] == "outdoorWalking"
  1. 当然相应的也要修改
d = {

	"id": int(keep_id),
	
	"name": "cycling from keep",
	
	# future to support others workout now only for run
	
	"type": "Ride", # Run, Walk, Hike ...
	...
  1. 在每个keep_sync_xxx.py中利用parse_points_to_gpx()写入gpx时,增加对应strava运动类型的type,保证上传gpx到strava时能提取到对应的类型。对应的GPX类型分别为:
gpx_track.type = "Run"
gpx_track.type = "Ride"
gpx_track.type = "Walk"
  1. def upload_file_to_strava(client, file_name, data_type, force_to_run=True):
    位置添加一个运动类型的识别。
with open(file_name, "rb") as f:
        x = gpxpy.parse(f)
        try:
            if x.tracks[0].type is not None:
                r = client.upload_activity(
                    activity_file=f, data_type=data_type, activity_type=x.tracks[0].type
                    )
            elif force_to_run:
                r = client.upload_activity(
                    activity_file=f, data_type=data_type, activity_type="run"
                )
             ...
  1. .github/workflows/run_data_sync.yml 中修改了一下, RUN_TYPE: strava,以及keep位置动了一下
      - name: Run sync Keep script
        if: env.RUN_TYPE == 'strava'
        run: |
          python run_page/keep_sync_walking.py ${{ secrets.KEEP_MOBILE }} ${{ secrets.KEEP_PASSWORD }} --with-gpx
          python run_page/keep_sync_cycling.py ${{ secrets.KEEP_MOBILE }} ${{ secrets.KEEP_PASSWORD }} --with-gpx
          python run_page/keep_sync_running.py ${{ secrets.KEEP_MOBILE }} ${{ secrets.KEEP_PASSWORD }} --with-gpx
          python run_page/gpx_to_strava_sync.py ${{ secrets.STRAVA_CLIENT_ID }} ${{ secrets.STRAVA_CLIENT_SECRET }} ${{ secrets.STRAVA_CLIENT_REFRESH_TOKEN }}
  1. 额外加了一个,让仓库干净一点。
      - name: Run clean GPX
        if: env.RUN_TYPE == 'strava'
        run: |
          touch GPX_OUT/tmp.txt
          rm GPX_OUT/*

当然上面的都是可以合并到一起的,但是为了清爽一点,选择了拆开。

不过我这还有一些问题

  1. strava好像上传有限制?我遇到了奇怪的问题。我第一次上传keep导出的gpx时候没有添加类型的区分(也就是5,6步),导致上传到strava后都是”跑步“(还是锻炼啥的,我也忘记了,反正不是实际对应的运动类型),然后又懒得一个个改,就在strava中全给删掉了,在第5步添加运动类型到gpx以后以及第6步添加了上传时类型识别之后,重新运行脚本上传,也提示上传成功,
if x.tracks[0].type is not None:
	r = client.upload_activity(
                    activity_file=f, data_type=data_type, activity_type=x.tracks[0].type
                    ))
	print(x.tracks[0].type)
	print(r)

output:

Walk
<stravalib.client.ActivityUploader object at 0x00000223B14241C0>
Uploading gpx file: D:\Toys\running_page\GPX_OUT\9223370324642451807.gpx to strava, upload_id: 11920271611.

但是,打开strava查看,发现没有任何更新。

我以为是我新生成的gpx有问题,然后我在网页端手动上传相应的gpx,是可以成功识别运动类型并且上传成功的(说明添加了type的gpx没有问题),但是手动上传一天最多30条。

所以验证过后就是

  • keep -> 无type的gpx(原版代码) ->strava (run_page/gpx_to_strava_sync.py未添加type), 成功
  • keep -> 有type的gpx -> strava (run_page/gpx_to_strava_sync.py 添加了type),输出成功,但是网页端没有更新。
  • keep -> 有type的gpx -> strava (网页手动),成功

上面三次的运动记录都是相同的,唯一的区别就是,该数据使用未经过5,6步修改的上传脚本上传过后,我手动在strava中删掉了这条记录。后面使用新脚本生成了新gpx上传提示成功,不过strava没有任何记录,但是手动上传该gpx是可以的。
所以我猜测
”如果在strava中删除了一条由脚本上传的运动记录,该运动记录将无法再次通过脚本上传,必须转成手动上传。但是我无法验证这一条了,因为我这两天没有户外运动。“
不清楚我的猜测对不对,或许有人可以试一下我修改后的脚本,上传全新从未上传过的运动数据。

  1. 第二个问题,那就是keep保存了gpx时(会写入data.db和activity.json)并上传到strava之后,然后运行strava_sync,该记录会被重复写入到activity.json,导致展示页面出现重复数据。
    比如这是我的https://songj.xyz/, 可以发现里面有重复数据
    image

@yihong0618
Copy link
Owner

@Vensent @yihong0618 第五点和我的工作流相似,不过我是华为运动健康 -> Keep -> Strava。

我也是昨天才开始用running page,根据自己的想法修改了一些,完成了上面的工作流,但是还不算完善(在读博,确实没有太多时间搞)。

我是在@ben的基础上做的(因为他支持更多的运动类型)。

华为运动健康 -> Keep是可以APP自动绑定的,这点和OPPO一致。

只考虑 Keep 保存GPX,然后自动上传到strava即可。

目前支持的是 running, walking,cycling,因为现在我自己平时也就这些,后续可能根据需要添加远足,登山,爬楼。

  1. 为了快速实现,我是直接把keep_sync.py复制出了keep_sync_running.py,keep_sync_walking.py,keep_sync_cycling.py,分别对应上面的运动类型(ugly code)。
  2. 然后分别将里面对应的接口改为
# in keep_sync_running.py
RUN_DATA_API = "https://api.gotokeep.com/pd/v3/stats/detail?dateUnit=all&type=running&lastDate={last_date}"
RUN_LOG_API = "https://api.gotokeep.com/pd/v3/runninglog/{run_id}"

# in keep_sync_walking.py
RUN_DATA_API = "https://api.gotokeep.com/pd/v3/stats/detail?dateUnit=all&type=hiking&lastDate={last_date}"
RUN_LOG_API = "https://api.gotokeep.com/pd/v3/hikinglog/{run_id}"

# in keep_sync_cycling.py
RUN_DATA_API = "https://api.gotokeep.com/pd/v3/stats/detail?dateUnit=all&type=cycling&lastDate={last_date}"
RUN_LOG_API = "https://api.gotokeep.com/pd/v3/cyclinglog/{run_id}"
  1. 然后里面对应的数据类型分别修改为
run_data["dataType"] == "outdoorRunning"
run_data["dataType"] == "outdoorCycling"
run_data["dataType"] == "outdoorWalking"
  1. 当然相应的也要修改
d = {

	"id": int(keep_id),
	
	"name": "cycling from keep",
	
	# future to support others workout now only for run
	
	"type": "Ride", # Run, Walk, Hike ...
	...
  1. 在每个keep_sync_xxx.py中利用parse_points_to_gpx()写入gpx时,增加对应strava运动类型的type,保证上传gpx到strava时能提取到对应的类型。对应的GPX类型分别为:
gpx_track.type = "Run"
gpx_track.type = "Ride"
gpx_track.type = "Walk"
  1. def upload_file_to_strava(client, file_name, data_type, force_to_run=True):

    位置添加一个运动类型的识别。
with open(file_name, "rb") as f:
        x = gpxpy.parse(f)
        try:
            if x.tracks[0].type is not None:
                r = client.upload_activity(
                    activity_file=f, data_type=data_type, activity_type=x.tracks[0].type
                    )
            elif force_to_run:
                r = client.upload_activity(
                    activity_file=f, data_type=data_type, activity_type="run"
                )
             ...
  1. .github/workflows/run_data_sync.yml 中修改了一下, RUN_TYPE: strava,以及keep位置动了一下
      - name: Run sync Keep script
        if: env.RUN_TYPE == 'strava'
        run: |
          python run_page/keep_sync_walking.py ${{ secrets.KEEP_MOBILE }} ${{ secrets.KEEP_PASSWORD }} --with-gpx
          python run_page/keep_sync_cycling.py ${{ secrets.KEEP_MOBILE }} ${{ secrets.KEEP_PASSWORD }} --with-gpx
          python run_page/keep_sync_running.py ${{ secrets.KEEP_MOBILE }} ${{ secrets.KEEP_PASSWORD }} --with-gpx
          python run_page/gpx_to_strava_sync.py ${{ secrets.STRAVA_CLIENT_ID }} ${{ secrets.STRAVA_CLIENT_SECRET }} ${{ secrets.STRAVA_CLIENT_REFRESH_TOKEN }}
  1. 额外加了一个,让仓库干净一点。
      - name: Run clean GPX
        if: env.RUN_TYPE == 'strava'
        run: |
          touch GPX_OUT/tmp.txt
          rm GPX_OUT/*

当然上面的都是可以合并到一起的,但是为了清爽一点,选择了拆开。

不过我这还有一些问题

  1. strava好像上传有限制?我遇到了奇怪的问题。我第一次上传keep导出的gpx时候没有添加类型的区分(也就是5,6步),导致上传到strava后都是”跑步“(还是锻炼啥的,我也忘记了,反正不是实际对应的运动类型),然后又懒得一个个改,就在strava中全给删掉了,在第5步添加运动类型到gpx以后以及第6步添加了上传时类型识别之后,重新运行脚本上传,也提示上传成功,
if x.tracks[0].type is not None:
	r = client.upload_activity(
                    activity_file=f, data_type=data_type, activity_type=x.tracks[0].type
                    ))
	print(x.tracks[0].type)
	print(r)

output:

Walk
<stravalib.client.ActivityUploader object at 0x00000223B14241C0>
Uploading gpx file: D:\Toys\running_page\GPX_OUT\9223370324642451807.gpx to strava, upload_id: 11920271611.

但是,打开strava查看,发现没有任何更新。

我以为是我新生成的gpx有问题,然后我在网页端手动上传相应的gpx,是可以成功识别运动类型并且上传成功的(说明添加了type的gpx没有问题),但是手动上传一天最多30条。

所以验证过后就是

  • keep -> 无type的gpx(原版代码) ->strava (run_page/gpx_to_strava_sync.py未添加type), 成功
  • keep -> 有type的gpx -> strava (run_page/gpx_to_strava_sync.py 添加了type),输出成功,但是网页端没有更新。
  • keep -> 有type的gpx -> strava (网页手动),成功

上面三次的运动记录都是相同的,唯一的区别就是,该数据使用未经过5,6步修改的上传脚本上传过后,我手动在strava中删掉了这条记录。后面使用新脚本生成了新gpx上传提示成功,不过strava没有任何记录,但是手动上传该gpx是可以的。 所以我猜测 ”如果在strava中删除了一条由脚本上传的运动记录,该运动记录将无法再次通过脚本上传,必须转成手动上传。但是我无法验证这一条了,因为我这两天没有户外运动。“ 不清楚我的猜测对不对,或许有人可以试一下我修改后的脚本,上传全新从未上传过的运动数据。

  1. 第二个问题,那就是keep保存了gpx时(会写入data.db和activity.json)并上传到strava之后,然后运行strava_sync,该记录会被重复写入到activity.json,导致展示页面出现重复数据。
    比如这是我的https://songj.xyz/, 可以发现里面有重复数据
    image

谢谢分享。

FYI, 我自己用的是 nike_to_strava 因为自己有需求。
https://github.com/yihong0618/run

@DanileLxp
Copy link

@Vensent @yihong0618 第五点和我的工作流相似,不过我是华为运动健康 -> Keep -> Strava。

我也是昨天才开始用running page,根据自己的想法修改了一些,完成了上面的工作流,但是还不算完善(在读博,确实没有太多时间搞)。

我是在@ben的基础上做的(因为他支持更多的运动类型)。

华为运动健康 -> Keep是可以APP自动绑定的,这点和OPPO一致。

只考虑 Keep 保存GPX,然后自动上传到strava即可。

目前支持的是 running, walking,cycling,因为现在我自己平时也就这些,后续可能根据需要添加远足,登山,爬楼。

  1. 为了快速实现,我是直接把keep_sync.py复制出了keep_sync_running.py,keep_sync_walking.py,keep_sync_cycling.py,分别对应上面的运动类型(ugly code)。
  2. 然后分别将里面对应的接口改为
# in keep_sync_running.py
RUN_DATA_API = "https://api.gotokeep.com/pd/v3/stats/detail?dateUnit=all&type=running&lastDate={last_date}"
RUN_LOG_API = "https://api.gotokeep.com/pd/v3/runninglog/{run_id}"

# in keep_sync_walking.py
RUN_DATA_API = "https://api.gotokeep.com/pd/v3/stats/detail?dateUnit=all&type=hiking&lastDate={last_date}"
RUN_LOG_API = "https://api.gotokeep.com/pd/v3/hikinglog/{run_id}"

# in keep_sync_cycling.py
RUN_DATA_API = "https://api.gotokeep.com/pd/v3/stats/detail?dateUnit=all&type=cycling&lastDate={last_date}"
RUN_LOG_API = "https://api.gotokeep.com/pd/v3/cyclinglog/{run_id}"
  1. 然后里面对应的数据类型分别修改为
run_data["dataType"] == "outdoorRunning"
run_data["dataType"] == "outdoorCycling"
run_data["dataType"] == "outdoorWalking"
  1. 当然相应的也要修改
d = {

	"id": int(keep_id),
	
	"name": "cycling from keep",
	
	# future to support others workout now only for run
	
	"type": "Ride", # Run, Walk, Hike ...
	...
  1. 在每个keep_sync_xxx.py中利用parse_points_to_gpx()写入gpx时,增加对应strava运动类型的type,保证上传gpx到strava时能提取到对应的类型。对应的GPX类型分别为:
gpx_track.type = "Run"
gpx_track.type = "Ride"
gpx_track.type = "Walk"
  1. def upload_file_to_strava(client, file_name, data_type, force_to_run=True):

    位置添加一个运动类型的识别。
with open(file_name, "rb") as f:
        x = gpxpy.parse(f)
        try:
            if x.tracks[0].type is not None:
                r = client.upload_activity(
                    activity_file=f, data_type=data_type, activity_type=x.tracks[0].type
                    )
            elif force_to_run:
                r = client.upload_activity(
                    activity_file=f, data_type=data_type, activity_type="run"
                )
             ...
  1. .github/workflows/run_data_sync.yml 中修改了一下, RUN_TYPE: strava,以及keep位置动了一下
      - name: Run sync Keep script
        if: env.RUN_TYPE == 'strava'
        run: |
          python run_page/keep_sync_walking.py ${{ secrets.KEEP_MOBILE }} ${{ secrets.KEEP_PASSWORD }} --with-gpx
          python run_page/keep_sync_cycling.py ${{ secrets.KEEP_MOBILE }} ${{ secrets.KEEP_PASSWORD }} --with-gpx
          python run_page/keep_sync_running.py ${{ secrets.KEEP_MOBILE }} ${{ secrets.KEEP_PASSWORD }} --with-gpx
          python run_page/gpx_to_strava_sync.py ${{ secrets.STRAVA_CLIENT_ID }} ${{ secrets.STRAVA_CLIENT_SECRET }} ${{ secrets.STRAVA_CLIENT_REFRESH_TOKEN }}
  1. 额外加了一个,让仓库干净一点。
      - name: Run clean GPX
        if: env.RUN_TYPE == 'strava'
        run: |
          touch GPX_OUT/tmp.txt
          rm GPX_OUT/*

当然上面的都是可以合并到一起的,但是为了清爽一点,选择了拆开。

不过我这还有一些问题

  1. strava好像上传有限制?我遇到了奇怪的问题。我第一次上传keep导出的gpx时候没有添加类型的区分(也就是5,6步),导致上传到strava后都是”跑步“(还是锻炼啥的,我也忘记了,反正不是实际对应的运动类型),然后又懒得一个个改,就在strava中全给删掉了,在第5步添加运动类型到gpx以后以及第6步添加了上传时类型识别之后,重新运行脚本上传,也提示上传成功,
if x.tracks[0].type is not None:
	r = client.upload_activity(
                    activity_file=f, data_type=data_type, activity_type=x.tracks[0].type
                    ))
	print(x.tracks[0].type)
	print(r)

output:

Walk
<stravalib.client.ActivityUploader object at 0x00000223B14241C0>
Uploading gpx file: D:\Toys\running_page\GPX_OUT\9223370324642451807.gpx to strava, upload_id: 11920271611.

但是,打开strava查看,发现没有任何更新。

我以为是我新生成的gpx有问题,然后我在网页端手动上传相应的gpx,是可以成功识别运动类型并且上传成功的(说明添加了type的gpx没有问题),但是手动上传一天最多30条。

所以验证过后就是

  • keep -> 无type的gpx(原版代码) ->strava (run_page/gpx_to_strava_sync.py未添加type), 成功
  • keep -> 有type的gpx -> strava (run_page/gpx_to_strava_sync.py 添加了type),输出成功,但是网页端没有更新。
  • keep -> 有type的gpx -> strava (网页手动),成功

上面三次的运动记录都是相同的,唯一的区别就是,该数据使用未经过5,6步修改的上传脚本上传过后,我手动在strava中删掉了这条记录。后面使用新脚本生成了新gpx上传提示成功,不过strava没有任何记录,但是手动上传该gpx是可以的。 所以我猜测 ”如果在strava中删除了一条由脚本上传的运动记录,该运动记录将无法再次通过脚本上传,必须转成手动上传。但是我无法验证这一条了,因为我这两天没有户外运动。“ 不清楚我的猜测对不对,或许有人可以试一下我修改后的脚本,上传全新从未上传过的运动数据。

  1. 第二个问题,那就是keep保存了gpx时(会写入data.db和activity.json)并上传到strava之后,然后运行strava_sync,该记录会被重复写入到activity.json,导致展示页面出现重复数据。
    比如这是我的https://songj.xyz/, 可以发现里面有重复数据
    image

新思路不错

@Vensent
Copy link
Contributor Author

Vensent commented Apr 12, 2024

@SongJgit 感觉你说的重复的问题,可以通过切分支或者新拉个仓来解决。就是不同的工作流使用不同的分支或者仓来做,互不影响。

看了你发的我感觉直接用Keep不是什么好办法,太复杂了。因为我在OPPO上班,我准备联系看看接入一下我们公司的开放平台来捞数据,越过keep这一步。

要是这条路打通了可以发个PR么? @yihong0618

@yihong0618
Copy link
Owner

@SongJgit 感觉你说的重复的问题,可以通过切分支或者新拉个仓来解决。就是不同的工作流使用不同的分支或者仓来做,互不影响。

看了你发的我感觉直接用Keep不是什么好办法,太复杂了。因为我在OPPO上班,我准备联系看看接入一下我们公司的开放平台来捞数据,越过keep这一步。

要是这条路打通了可以发个PR么? @yihong0618

当然可以,不过 OPPO 有这么开放么😂

@Vensent
Copy link
Contributor Author

Vensent commented Apr 12, 2024

@SongJgit 感觉你说的重复的问题,可以通过切分支或者新拉个仓来解决。就是不同的工作流使用不同的分支或者仓来做,互不影响。
看了你发的我感觉直接用Keep不是什么好办法,太复杂了。因为我在OPPO上班,我准备联系看看接入一下我们公司的开放平台来捞数据,越过keep这一步。
要是这条路打通了可以发个PR么? @yihong0618

当然可以,不过 OPPO 有这么开放么😂

我联系我们公司的同事帮我开了个健康开放平台的id和token了,有点像Strava的那种认证方式,我先试试看能不能打通。

@ben-29
Copy link
Collaborator

ben-29 commented Apr 12, 2024

2. 第二个问题,那就是keep保存了gpx时(会写入data.db和activity.json)并上传到strava之后,然后运行strava_sync,该记录会被重复写入到activity.json,导致展示页面出现重复数据。
比如这是我的https://songj.xyz/, 可以发现里面有重复数据

@SongJgit 造成重复的原因在这:

13. .github/workflows/run_data_sync.yml 中修改了一下, RUN_TYPE: strava,以及keep位置动了一下

      - name: Run sync Keep script
        if: env.RUN_TYPE == 'strava'
        run: |
          python run_page/keep_sync_walking.py ${{ secrets.KEEP_MOBILE }} ${{ secrets.KEEP_PASSWORD }} --with-gpx
          python run_page/keep_sync_cycling.py ${{ secrets.KEEP_MOBILE }} ${{ secrets.KEEP_PASSWORD }} --with-gpx
          python run_page/keep_sync_running.py ${{ secrets.KEEP_MOBILE }} ${{ secrets.KEEP_PASSWORD }} --with-gpx
          python run_page/gpx_to_strava_sync.py ${{ secrets.STRAVA_CLIENT_ID }} ${{ secrets.STRAVA_CLIENT_SECRET }} ${{ secrets.STRAVA_CLIENT_REFRESH_TOKEN }}

1.keep_sync* 同步了 keep 的 gpx 记录
2.gpx_to_strava_sync 上传 gpx 的同时,也同步了 strava 新上传的记录
而这两个被当成了不同的记录

要想解决重复的问题也很简单,有以下三个方案:

  1. 检查 keep gpx 和 strava 的 run_id 字段, 看能否用同一个
  2. keep_sync* 注释掉保存 data.db 部分,只做 gpx 下载
  3. gpx_to_strava_sync 注释掉同步 strava 部分,只做 gpx 上传

@SongJgit
Copy link
Contributor

@SongJgit 感觉你说的重复的问题,可以通过切分支或者新拉个仓来解决。就是不同的工作流使用不同的分支或者仓来做,互不影响。

看了你发的我感觉直接用Keep不是什么好办法,太复杂了。因为我在OPPO上班,我准备联系看看接入一下我们公司的开放平台来捞数据,越过keep这一步。

要是这条路打通了可以发个PR么? @yihong0618

其实keep这条路还算不错,复杂是因为我说的比较详细,基本都是在描述数据的获取,以及不同app之间的运动类型对齐。比如,keep叫outdoorRunning,但是strava就叫Run,其他的app也都有各自的命名与区分,即使是oppo导出也还是需要和运动类型对齐才能同步上去。

至于oppo直连strava应该是不可能的(好像是因为隐私数据不准出境,比如rq,zepp,华为这些非国内账号本身都可以直连strava,但是国内账号却都不行,甚至之前health sync国内也可以直连,现在好像都不行了,连gps都获取不到了。当然,如果个人做的话可能没这种限制?),我觉得华为,oppo之类的能做到直出gpx就很棒了,或者能直连国内佳明(这样就可以自动同步到国际然后strava了)。

@SongJgit
Copy link
Contributor

  1. 第二个问题,那就是keep保存了gpx时(会写入data.db和activity.json)并上传到strava之后,然后运行strava_sync,该记录会被重复写入到activity.json,导致展示页面出现重复数据。
    比如这是我的https://songj.xyz/, 可以发现里面有重复数据

@SongJgit 造成重复的原因在这:

  1. .github/workflows/run_data_sync.yml 中修改了一下, RUN_TYPE: strava,以及keep位置动了一下
      - name: Run sync Keep script
        if: env.RUN_TYPE == 'strava'
        run: |
          python run_page/keep_sync_walking.py ${{ secrets.KEEP_MOBILE }} ${{ secrets.KEEP_PASSWORD }} --with-gpx
          python run_page/keep_sync_cycling.py ${{ secrets.KEEP_MOBILE }} ${{ secrets.KEEP_PASSWORD }} --with-gpx
          python run_page/keep_sync_running.py ${{ secrets.KEEP_MOBILE }} ${{ secrets.KEEP_PASSWORD }} --with-gpx
          python run_page/gpx_to_strava_sync.py ${{ secrets.STRAVA_CLIENT_ID }} ${{ secrets.STRAVA_CLIENT_SECRET }} ${{ secrets.STRAVA_CLIENT_REFRESH_TOKEN }}

1.keep_sync* 同步了 keep 的 gpx 记录 2.gpx_to_strava_sync 上传 gpx 的同时,也同步了 strava 新上传的记录 而这两个被当成了不同的记录

要想解决重复的问题也很简单,有以下三个方案:

  1. 检查 keep gpx 和 strava 的 run_id 字段, 看能否用同一个
  2. keep_sync* 注释掉保存 data.db 部分,只做 gpx 下载
  3. gpx_to_strava_sync 注释掉同步 strava 部分,只做 gpx 上传

嗯,昨天下午看了一下你的代码之后已经解决了。
1.一开始我考虑过改runid,但是似乎只有上传strava的时候才能知道strava的run id?这个时候才知道runid的话还需要去动数据库,为了简单点,选择放弃该方法。
2.只做gpx下载我也考虑过,但是不写入db的话,后面又要添加新旧记录的判断又会额外增加工作量。
3.我骑车是佳明码表,跑步和徒步是华为运动健康,所以最方便的办法是综合到strava,然后用strava做展示,所以即使注释掉这里的同步strava,我最后还是要用run strava sync来同步展示的😅。

所以最后我的思路是,keep和strava都写入db但是keep不写入act(因为我还需要data.db判断是否已经下载过该keep记录了)。不过这样做的另一个缺点就是,一旦写入了db,后面的gen_svg也需要补充一下过滤条件,过滤掉来自keep的记录,不然会重复统计。但是相对于其他的方法来说,这样的工作量与代码复杂性要小很多。由于我没有仔细读过代码,我不知道这样做是否还会引发其他的bug?

@SongJgit
Copy link
Contributor

SongJgit commented Apr 13, 2024

已经把问题都解决了。
写了一个支持多运动类型的keep_to_strava, 解决了无法上传和重复的问题,不需要额外的增加过滤之类的,也不会重复写入db和activities.json.

这个方案可以作为华为运动健康->strava的解决方案(理论上,只要支持和keep同步就可以同步到strava(包括oppo/vivo?)).
有必要提个PR?@yihong0618

@Vensent
Copy link
Contributor Author

Vensent commented Apr 13, 2024

借这个issue我其实有个一直想问的问题,为啥我们拿到了gpx或者tcx或者fit文件,没有办法直接传到Garmin呢? @SongJgit @yihong0618
我今天看了一下整体的逻辑,把欢太健康(就是OPPO)的数据算是打通了,晚上着手写一下直接oppo2strava,不走keep这一条路。试试看效果。

@SongJgit
Copy link
Contributor

借这个issue我其实有个一直想问的问题,为啥我们拿到了gpx或者tcx或者fit文件,没有办法直接传到Garmin呢? @SongJgit @yihong0618 我今天看了一下整体的逻辑,把欢太健康(就是OPPO)的数据算是打通了,晚上着手写一下直接oppo2strava,不走keep这一条路。试试看效果。

我已经提了相关的pr。
huawei -> keep -> Strava
华为的缺点是无法直接拿到gpx,只能被迫走keep/咕咚/悦跑圈。
OPPO能直接拿到GPX的话,那就可以省略中转,而直接strava了。

@SongJgit
Copy link
Contributor

SongJgit commented Apr 13, 2024

借这个issue我其实有个一直想问的问题,为啥我们拿到了gpx或者tcx或者fit文件,没有办法直接传到Garmin呢? @SongJgit @yihong0618 我今天看了一下整体的逻辑,把欢太健康(就是OPPO)的数据算是打通了,晚上着手写一下直接oppo2strava,不走keep这一条路。试试看效果。

对了,提醒一下,避免掉入我之前的坑里。
我之前提示上传成功,但是实际上失败的原因是因为x = gpxpy.parse(f), 我猜是因为没有释放, 导致上传失败,今天看了strava api之后发现完全不需要额外识别运动类型的,它们会自动解析gpx的type字段。https://developers.strava.com/docs/uploads/

activity_type:
Deprecated: prefer using sport_type, will be ignored if sport_type is included. Overrides type detected from file, if left unspecified type detected from file will be used.

@Vensent
Copy link
Contributor Author

Vensent commented Apr 13, 2024

借这个issue我其实有个一直想问的问题,为啥我们拿到了gpx或者tcx或者fit文件,没有办法直接传到Garmin呢? @SongJgit @yihong0618 我今天看了一下整体的逻辑,把欢太健康(就是OPPO)的数据算是打通了,晚上着手写一下直接oppo2strava,不走keep这一条路。试试看效果。

对了,提醒一下,避免掉入我之前的坑里。 我之前提示上传成功,但是实际上失败的原因是因为x = gpxpy.parse(f), 我猜是因为没有释放, 导致上传失败,今天看了strava api之后发现完全不需要额外识别运动类型的,它们会自动解析gpx的type字段。https://developers.strava.com/docs/uploads/

activity_type:
Deprecated: prefer using sport_type, will be ignored if sport_type is included. Overrides type detected from file, if left unspecified type detected from file will be used.

好的,感谢。

@Vensent
Copy link
Contributor Author

Vensent commented Apr 15, 2024

@yihong0618 @ben-29 问一下二位,我在处理数据的时候,看到直接解析oppo然后转出gpx的文件,和脚本解析出来的keep的有一些差别。
这是keep的数据截图:
image

这是oppo我做的脚本的截图:
image

二者为什么会有移动时长的区别,是因为我处理数据的采样点太多了么,差不多是每秒一次,数组长度在1480左右,而keep的数据长度是580左右。是这个原因么

@SongJgit
Copy link
Contributor

这个应该是keep自己的问题。
因为传到keep里是没有问题的,但是从keep传到strava就会天然的多或少几十米。不知道keep自己内部是怎么处理的数据。
话说,同一个运动,keep导出的和oppo直出的gpx,两者的起始/结束点的时间以及经纬度一致吗。
很期待你的工作,因为我oppo健康里还有一年的运动数据无法导出

@Vensent
Copy link
Contributor Author

Vensent commented Apr 15, 2024

这个应该是keep自己的问题。 因为传到keep里是没有问题的,但是从keep传到strava就会天然的多或少几十米。不知道keep自己内部是怎么处理的数据。 话说,同一个运动,keep导出的和oppo直出的gpx,两者的起始/结束点的时间以及经纬度一致吗。 很期待你的工作,因为我oppo健康里还有一年的运动数据无法导出

@SongJgit 是一致的。
我这边基本上打通了,有一些小bug要调试。但是oppo的数据设计太垃圾了(不得不吐槽我司,真的)两个查询接口做的实在不好恭维。
还有就是这种开发者权限不知道短时间能不能开放给其他人,我帮你问问。方便的话加我个微信吧,我们细聊,vx:86836661

@Vensent
Copy link
Contributor Author

Vensent commented Apr 15, 2024

这个应该是keep自己的问题。 因为传到keep里是没有问题的,但是从keep传到strava就会天然的多或少几十米。不知道keep自己内部是怎么处理的数据。 话说,同一个运动,keep导出的和oppo直出的gpx,两者的起始/结束点的时间以及经纬度一致吗。 很期待你的工作,因为我oppo健康里还有一年的运动数据无法导出

我发现我换了一种更贴近keep的处理方法,能解决上面我说的移动时间的问题。导出的gpx放进佳明connect,甚至会告诉我说keep的一摸一样,重复导入了。两者的起始、结束时间以及经纬度都对的上,这就说明了现在这种做法和keep是一样的结果。

但是现在遇到的问题是如果用这个keep的方式,因为gps一开始可能没有搜到星就跑了,gps打点的数据漏了一部分。导致运动时长要丢失一部分,这个大佬们有没有遇到过,有没有好的处理方法? @ben-29 @yihong0618

@ben-29
Copy link
Collaborator

ben-29 commented Apr 16, 2024

但是现在遇到的问题是如果用这个keep的方式,因为gps一开始可能没有搜到星就跑了,gps打点的数据漏了一部分。导致运动时长要丢失一部分,这个大佬们有没有遇到过,有没有好的处理方法? @ben-29 @yihong0618

没遇到过,在意的话,建议就 跑步的时候,等搜星成功后再开跑。
如果是要 gps 点,没有记录到也没办法了。
如果在意的是时长,记录里有开跑时间吗?在gpx轨迹点最前面插入一个开跑时间的点,可以不

@Vensent Vensent closed this as completed Apr 23, 2024
@Vensent
Copy link
Contributor Author

Vensent commented Apr 23, 2024

  1. 第二个问题,那就是keep保存了gpx时(会写入data.db和activity.json)并上传到strava之后,然后运行strava_sync,该记录会被重复写入到activity.json,导致展示页面出现重复数据。
    比如这是我的https://songj.xyz/, 可以发现里面有重复数据

@SongJgit 造成重复的原因在这:

  1. .github/workflows/run_data_sync.yml 中修改了一下, RUN_TYPE: strava,以及keep位置动了一下
      - name: Run sync Keep script
        if: env.RUN_TYPE == 'strava'
        run: |
          python run_page/keep_sync_walking.py ${{ secrets.KEEP_MOBILE }} ${{ secrets.KEEP_PASSWORD }} --with-gpx
          python run_page/keep_sync_cycling.py ${{ secrets.KEEP_MOBILE }} ${{ secrets.KEEP_PASSWORD }} --with-gpx
          python run_page/keep_sync_running.py ${{ secrets.KEEP_MOBILE }} ${{ secrets.KEEP_PASSWORD }} --with-gpx
          python run_page/gpx_to_strava_sync.py ${{ secrets.STRAVA_CLIENT_ID }} ${{ secrets.STRAVA_CLIENT_SECRET }} ${{ secrets.STRAVA_CLIENT_REFRESH_TOKEN }}

1.keep_sync* 同步了 keep 的 gpx 记录 2.gpx_to_strava_sync 上传 gpx 的同时,也同步了 strava 新上传的记录 而这两个被当成了不同的记录
要想解决重复的问题也很简单,有以下三个方案:

  1. 检查 keep gpx 和 strava 的 run_id 字段, 看能否用同一个
  2. keep_sync* 注释掉保存 data.db 部分,只做 gpx 下载
  3. gpx_to_strava_sync 注释掉同步 strava 部分,只做 gpx 上传

嗯,昨天下午看了一下你的代码之后已经解决了。 1.一开始我考虑过改runid,但是似乎只有上传strava的时候才能知道strava的run id?这个时候才知道runid的话还需要去动数据库,为了简单点,选择放弃该方法。 2.只做gpx下载我也考虑过,但是不写入db的话,后面又要添加新旧记录的判断又会额外增加工作量。 3.我骑车是佳明码表,跑步和徒步是华为运动健康,所以最方便的办法是综合到strava,然后用strava做展示,所以即使注释掉这里的同步strava,我最后还是要用run strava sync来同步展示的😅。

所以最后我的思路是,keep和strava都写入db但是keep不写入act(因为我还需要data.db判断是否已经下载过该keep记录了)。不过这样做的另一个缺点就是,一旦写入了db,后面的gen_svg也需要补充一下过滤条件,过滤掉来自keep的记录,不然会重复统计。但是相对于其他的方法来说,这样的工作量与代码复杂性要小很多。由于我没有仔细读过代码,我不知道这样做是否还会引发其他的bug?

这个数据重复的问题,我这边有一个我觉得比较好的方式,你可以参考一下:

Action的话你使用两个,一个是主Action,用于sync你的主要数据源并展示,同时注意你用一个特定的key来标记使用对应的Cache。

另外一个是数据同步的Action,用于把你的keep同步到Strava(我的是oppo到garmin到strava)的。使用另外一个key来标记特定的缓存Cache。

两个Action各自工作,分别使用不同的db和activitys.json。可以参考我的这笔提交:数据源和页面展示使用不同的Cache

@Vensent Vensent reopened this Apr 23, 2024
@chensoul
Copy link

如何记录 爬楼 ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants