yihong0618 / running_page

Make your own running home page
https://running-page.vercel.app
MIT License
3.55k stars 1.02k forks source link

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

Open Vensent opened 5 months ago

Vensent commented 5 months ago

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

能行不,这个思路?

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

@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}"

3. 然后里面对应的数据类型分别修改为

```python
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"
  2. https://github.com/yihong0618/running_page/blob/eae7de259c430121c16b983b28c0fd68553025d7/run_page/utils.py#L95 位置添加一个运动类型的识别。

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条。

所以验证过后就是

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

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

@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. https://github.com/yihong0618/running_page/blob/eae7de259c430121c16b983b28c0fd68553025d7/run_page/utils.py#L95 位置添加一个运动类型的识别。
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 commented 5 months ago

@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. https://github.com/yihong0618/running_page/blob/eae7de259c430121c16b983b28c0fd68553025d7/run_page/utils.py#L95 位置添加一个运动类型的识别。
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 commented 5 months ago

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

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

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

yihong0618 commented 5 months ago

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

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

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

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

Vensent commented 5 months ago

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

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

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

ben-29 commented 5 months ago

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 commented 5 months ago

@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 commented 5 months ago
  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 commented 5 months ago

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

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

Vensent commented 5 months ago

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

SongJgit commented 5 months ago

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

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

SongJgit commented 5 months ago

借这个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 commented 5 months ago

借这个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 commented 5 months ago

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

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

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

SongJgit commented 5 months ago

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

Vensent commented 5 months ago

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

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

Vensent commented 5 months ago

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

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

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

ben-29 commented 5 months ago

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

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

Vensent commented 5 months ago
  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