本文整理汇总了Python中tapiriik.services.interchange.UploadedActivity.TZ方法的典型用法代码示例。如果您正苦于以下问题:Python UploadedActivity.TZ方法的具体用法?Python UploadedActivity.TZ怎么用?Python UploadedActivity.TZ使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类tapiriik.services.interchange.UploadedActivity
的用法示例。
在下文中一共展示了UploadedActivity.TZ方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Python代码示例。
示例1: DownloadActivityList
# 需要导入模块: from tapiriik.services.interchange import UploadedActivity [as 别名]
# 或者: from tapiriik.services.interchange.UploadedActivity import TZ [as 别名]
def DownloadActivityList(self, serviceRecord, exhaustive=False):
cookies = self._get_cookies(record=serviceRecord)
activities = []
exclusions = []
pageUri = self.OpenFitEndpoint + "/fitnessActivities.json"
while True:
logger.debug("Req against " + pageUri)
res = requests.get(pageUri, cookies=cookies)
res = res.json()
for act in res["items"]:
activity = UploadedActivity()
activity.ServiceData = {"ActivityURI": act["uri"]}
if len(act["name"].strip()):
activity.Name = act["name"]
activity.StartTime = dateutil.parser.parse(act["start_time"])
if isinstance(activity.StartTime.tzinfo, tzutc):
activity.TZ = pytz.utc # The dateutil tzutc doesn't have an _offset value.
else:
activity.TZ = pytz.FixedOffset(activity.StartTime.tzinfo._offset.total_seconds() / 60) # Convert the dateutil lame timezones into pytz awesome timezones.
activity.StartTime = activity.StartTime.replace(tzinfo=activity.TZ)
activity.EndTime = activity.StartTime + timedelta(seconds=float(act["duration"]))
activity.Stats.MovingTime = ActivityStatistic(ActivityStatisticUnit.Time, value=timedelta(seconds=float(act["duration"]))) # OpenFit says this excludes paused times.
# Sometimes activities get returned with a UTC timezone even when they are clearly not in UTC.
if activity.TZ == pytz.utc:
# So, we get the first location in the activity and calculate the TZ from that.
try:
firstLocation = self._downloadActivity(serviceRecord, activity, returnFirstLocation=True)
except APIExcludeActivity:
pass
else:
activity.CalculateTZ(firstLocation)
activity.AdjustTZ()
logger.debug("Activity s/t " + str(activity.StartTime))
activity.Stats.Distance = ActivityStatistic(ActivityStatisticUnit.Meters, value=float(act["total_distance"]))
types = [x.strip().lower() for x in act["type"].split(":")]
types.reverse() # The incoming format is like "walking: hiking" and we want the most specific first
activity.Type = None
for type_key in types:
if type_key in self._activityMappings:
activity.Type = self._activityMappings[type_key]
break
if not activity.Type:
exclusions.append(APIExcludeActivity("Unknown activity type %s" % act["type"], activityId=act["uri"]))
continue
activity.CalculateUID()
activities.append(activity)
if not exhaustive or "next" not in res or not len(res["next"]):
break
else:
pageUri = res["next"]
return activities, exclusions
示例2: DownloadActivityList
# 需要导入模块: from tapiriik.services.interchange import UploadedActivity [as 别名]
# 或者: from tapiriik.services.interchange.UploadedActivity import TZ [as 别名]
def DownloadActivityList(self, serviceRecord, exhaustive=False):
#http://connect.garmin.com/proxy/activity-search-service-1.0/json/activities?&start=0&limit=50
cookies = self._get_cookies(record=serviceRecord)
page = 1
pageSz = 50
activities = []
exclusions = []
while True:
logger.debug("Req with " + str({"start": (page - 1) * pageSz, "limit": pageSz}))
res = requests.get("http://connect.garmin.com/proxy/activity-search-service-1.0/json/activities", params={"start": (page - 1) * pageSz, "limit": pageSz}, cookies=cookies)
res = res.json()["results"]
if "activities" not in res:
break # No activities on this page - empty account.
for act in res["activities"]:
act = act["activity"]
if "beginLatitude" not in act or "endLatitude" not in act or (act["beginLatitude"] is act["endLatitude"] and act["beginLongitude"] is act["endLongitude"]):
exclusions.append(APIExcludeActivity("No points", activityId=act["activityId"]))
continue
if "sumDistance" not in act:
exclusions.append(APIExcludeActivity("No distance", activityId=act["activityId"]))
continue
activity = UploadedActivity()
try:
activity.TZ = pytz.timezone(act["activityTimeZone"]["key"])
except pytz.exceptions.UnknownTimeZoneError:
activity.TZ = pytz.FixedOffset(float(act["activityTimeZone"]["offset"]) * 60)
logger.debug("Name " + act["activityName"]["value"] + ":")
if len(act["activityName"]["value"].strip()) and act["activityName"]["value"] != "Untitled":
activity.Name = act["activityName"]["value"]
# beginTimestamp/endTimestamp is in UTC
activity.StartTime = pytz.utc.localize(datetime.utcfromtimestamp(float(act["beginTimestamp"]["millis"])/1000))
if "sumElapsedDuration" in act:
activity.EndTime = activity.StartTime + timedelta(0, round(float(act["sumElapsedDuration"]["value"])))
elif "sumDuration" in act:
activity.EndTime = activity.StartTime + timedelta(minutes=float(act["sumDuration"]["minutesSeconds"].split(":")[0]), seconds=float(act["sumDuration"]["minutesSeconds"].split(":")[1]))
else:
activity.EndTime = pytz.utc.localize(datetime.utcfromtimestamp(float(act["endTimestamp"]["millis"])/1000))
logger.debug("Activity s/t " + str(activity.StartTime) + " on page " + str(page))
activity.AdjustTZ()
# TODO: fix the distance stats to account for the fact that this incorrectly reported km instead of meters for the longest time.
activity.Distance = float(act["sumDistance"]["value"]) * (1.60934 if act["sumDistance"]["uom"] == "mile" else 1) * 1000 # In meters...
activity.Type = self._resolveActivityType(act["activityType"]["key"])
activity.CalculateUID()
activity.UploadedTo = [{"Connection": serviceRecord, "ActivityID": act["activityId"]}]
activities.append(activity)
logger.debug("Finished page " + str(page) + " of " + str(res["search"]["totalPages"]))
if not exhaustive or int(res["search"]["totalPages"]) == page:
break
else:
page += 1
return activities, exclusions
示例3: DownloadActivityList
# 需要导入模块: from tapiriik.services.interchange import UploadedActivity [as 别名]
# 或者: from tapiriik.services.interchange.UploadedActivity import TZ [as 别名]
def DownloadActivityList(self, serviceRecord, exhaustive=False):
cookies = self._get_cookies(serviceRecord)
activities = []
exclusions = []
pageUri = self.OpenFitEndpoint + "/fitnessActivities.json"
while True:
logger.debug("Req against " + pageUri)
res = requests.get(pageUri, cookies=cookies)
res = res.json()
for act in res["items"]:
activity = UploadedActivity()
if len(act["name"].strip()):
activity.Name = act["name"]
activity.StartTime = dateutil.parser.parse(act["start_time"])
activity.TZ = pytz.FixedOffset(activity.StartTime.tzinfo._offset.total_seconds() / 60) # Convert the dateutil lame timezones into pytz awesome timezones.
activity.StartTime = activity.StartTime.replace(tzinfo=activity.TZ)
activity.EndTime = activity.StartTime + timedelta(seconds=float(act["duration"]))
logger.debug("Activity s/t " + str(activity.StartTime))
activity.Distance = float(act["total_distance"])
activity.Type = self._activityMappings[act["type"].lower()]
activity.CalculateUID()
activity.UploadedTo = [{"Connection": serviceRecord, "ActivityURI": act["uri"]}]
activities.append(activity)
if not exhaustive or "next" not in res or not len(res["next"]):
break
else:
pageUri = res["next"]
return activities, exclusions
示例4: DownloadActivityList
# 需要导入模块: from tapiriik.services.interchange import UploadedActivity [as 别名]
# 或者: from tapiriik.services.interchange.UploadedActivity import TZ [as 别名]
def DownloadActivityList(self, svcRecord, exhaustive=False):
activities = []
exclusions = []
before = earliestDate = None
while True:
logger.debug("Req with before=" + str(before) + "/" + str(earliestDate))
resp = requests.get("https://www.strava.com/api/v3/athletes/" + str(svcRecord.ExternalID) + "/activities", headers=self._apiHeaders(svcRecord), params={"before": before})
self._logAPICall("list", (svcRecord.ExternalID, str(earliestDate)), resp.status_code == 401)
if resp.status_code == 401:
raise APIException("No authorization to retrieve activity list", block=True, user_exception=UserException(UserExceptionType.Authorization, intervention_required=True))
earliestDate = None
reqdata = resp.json()
if not len(reqdata):
break # No more activities to see
for ride in reqdata:
activity = UploadedActivity()
activity.TZ = pytz.timezone(re.sub("^\([^\)]+\)\s*", "", ride["timezone"])) # Comes back as "(GMT -13:37) The Stuff/We Want""
activity.StartTime = pytz.utc.localize(datetime.strptime(ride["start_date"], "%Y-%m-%dT%H:%M:%SZ"))
logger.debug("\tActivity s/t " + str(activity.StartTime))
if not earliestDate or activity.StartTime < earliestDate:
earliestDate = activity.StartTime
before = calendar.timegm(activity.StartTime.astimezone(pytz.utc).timetuple())
if ride["start_latlng"] is None or ride["end_latlng"] is None or ride["distance"] is None or ride["distance"] == 0:
exclusions.append(APIExcludeActivity("No path", activityId=ride["id"]))
logger.debug("\t\tNo pts")
continue # stationary activity - no syncing for now
activity.EndTime = activity.StartTime + timedelta(0, ride["elapsed_time"])
activity.UploadedTo = [{"Connection": svcRecord, "ActivityID": ride["id"]}]
actType = [k for k, v in self._reverseActivityTypeMappings.items() if v == ride["type"]]
if not len(actType):
exclusions.append(APIExcludeActivity("Unsupported activity type %s" % ride["type"], activityId=ride["id"]))
logger.debug("\t\tUnknown activity")
continue
activity.Type = actType[0]
activity.Distance = ride["distance"]
activity.Name = ride["name"]
activity.Private = ride["private"]
activity.AdjustTZ()
activity.CalculateUID()
activities.append(activity)
if not exhaustive or not earliestDate:
break
return activities, exclusions
示例5: DownloadActivityList
# 需要导入模块: from tapiriik.services.interchange import UploadedActivity [as 别名]
# 或者: from tapiriik.services.interchange.UploadedActivity import TZ [as 别名]
def DownloadActivityList(self, svcRecord, exhaustive=False):
# grumble grumble strava api sucks grumble grumble
# http://app.strava.com/api/v1/rides?athleteId=id
activities = []
exclusions = []
before = earliestDate = None
while True:
resp = requests.get("https://www.strava.com/api/v3/athletes/" + str(svcRecord.ExternalID) + "/activities", headers=self._apiHeaders(svcRecord), params={"before": before})
logger.debug("Req with before=" + str(before) + "/" + str(earliestDate))
earliestDate = None
reqdata = resp.json()
if not len(reqdata):
break # No more activities to see
for ride in reqdata:
activity = UploadedActivity()
activity.TZ = pytz.timezone(re.sub("^\([^\)]+\)\s*", "", ride["timezone"])) # Comes back as "(GMT -13:37) The Stuff/We Want""
activity.StartTime = pytz.utc.localize(datetime.strptime(ride["start_date"], "%Y-%m-%dT%H:%M:%SZ"))
logger.debug("\tActivity s/t " + str(activity.StartTime))
if not earliestDate or activity.StartTime < earliestDate:
earliestDate = activity.StartTime
before = calendar.timegm(activity.StartTime.astimezone(pytz.utc).timetuple())
if ride["start_latlng"] is None or ride["end_latlng"] is None or ride["distance"] is None or ride["distance"] == 0:
exclusions.append(APIExcludeActivity("No path", activityId=ride["id"]))
continue # stationary activity - no syncing for now
if ride["start_latlng"] == ride["end_latlng"]:
exclusions.append(APIExcludeActivity("Only one waypoint", activityId=ride["id"]))
continue # Only one waypoint, one would assume.
activity.EndTime = activity.StartTime + timedelta(0, ride["elapsed_time"])
activity.UploadedTo = [{"Connection": svcRecord, "ActivityID": ride["id"]}]
actType = [k for k, v in self._reverseActivityTypeMappings.items() if v == ride["type"]]
if not len(actType):
exclusions.append(APIExcludeActivity("Unsupported activity type", activityId=ride["id"]))
continue
activity.Type = actType[0]
activity.Distance = ride["distance"]
activity.Name = ride["name"]
activity.AdjustTZ()
activity.CalculateUID()
activities.append(activity)
if not exhaustive or not earliestDate:
break
return activities, exclusions
示例6: DownloadActivityList
# 需要导入模块: from tapiriik.services.interchange import UploadedActivity [as 别名]
# 或者: from tapiriik.services.interchange.UploadedActivity import TZ [as 别名]
def DownloadActivityList(self, serviceRecord, exhaustive=False):
# http://ridewithgps.com/users/1/trips.json?limit=200&order_by=created_at&order_dir=asc
# offset also supported
page = 1
pageSz = 50
activities = []
exclusions = []
while True:
logger.debug("Req with " + str({"start": (page - 1) * pageSz, "limit": pageSz}))
# TODO: take advantage of their nice ETag support
params = {"offset": (page - 1) * pageSz, "limit": pageSz}
params = self._add_auth_params(params, record=serviceRecord)
res = requests.get("http://ridewithgps.com/users/{}/trips.json".format(serviceRecord.ExternalID), params=params)
res = res.json()
total_pages = math.ceil(int(res["results_count"]) / pageSz)
for act in res["results"]:
if "first_lat" not in act or "last_lat" not in act:
exclusions.append(APIExcludeActivity("No points", activityId=act["activityId"]))
continue
if "distance" not in act:
exclusions.append(APIExcludeActivity("No distance", activityId=act["activityId"]))
continue
activity = UploadedActivity()
activity.TZ = pytz.timezone(act["time_zone"])
logger.debug("Name " + act["name"] + ":")
if len(act["name"].strip()):
activity.Name = act["name"]
activity.StartTime = pytz.utc.localize(datetime.strptime(act["departed_at"], "%Y-%m-%dT%H:%M:%SZ"))
activity.EndTime = activity.StartTime + timedelta(seconds=self._duration_to_seconds(act["duration"]))
logger.debug("Activity s/t " + str(activity.StartTime) + " on page " + str(page))
activity.AdjustTZ()
activity.Distance = float(act["distance"]) # This value is already in meters...
# Activity type is not implemented yet in RWGPS results; we will assume cycling, though perhaps "OTHER" wouuld be correct
activity.Type = ActivityType.Cycling
activity.CalculateUID()
activity.UploadedTo = [{"Connection": serviceRecord, "ActivityID": act["id"]}]
activities.append(activity)
logger.debug("Finished page {} of {}".format(page, total_pages))
if not exhaustive or total_pages == page or total_pages == 0:
break
else:
page += 1
return activities, exclusions
示例7: DownloadActivityList
# 需要导入模块: from tapiriik.services.interchange import UploadedActivity [as 别名]
# 或者: from tapiriik.services.interchange.UploadedActivity import TZ [as 别名]
def DownloadActivityList(self, serviceRecord, exhaustive=False):
session = self._get_session(serviceRecord)
list_params = self._with_auth(session, {"count": 20, "offset": 1})
activities = []
exclusions = []
while True:
list_resp = session.get("https://api.nike.com/me/sport/activities", params=list_params)
list_resp = list_resp.json()
for act in list_resp["data"]:
activity = UploadedActivity()
activity.ServiceData = {"ID": act["activityId"]}
if act["status"] != "COMPLETE":
exclusions.append(APIExcludeActivity("Not complete", activityId=act["activityId"], permanent=False, userException=UserException(UserExceptionType.LiveTracking)))
continue
activity.StartTime = dateutil.parser.parse(act["startTime"]).replace(tzinfo=pytz.utc)
activity.EndTime = activity.StartTime + self._durationToTimespan(act["metricSummary"]["duration"])
tz_name = act["activityTimeZone"]
# They say these are all IANA standard names - they aren't
if tz_name in self._timezones:
tz_name = self._timezones[tz_name]
activity.TZ = pytz.timezone(tz_name)
if act["activityType"] in self._activityMappings:
activity.Type = self._activityMappings[act["activityType"]]
activity.Stats.Distance = ActivityStatistic(ActivityStatisticUnit.Kilometers, value=float(act["metricSummary"]["distance"]))
activity.Stats.Strides = ActivityStatistic(ActivityStatisticUnit.Strides, value=int(act["metricSummary"]["steps"]))
activity.Stats.Energy = ActivityStatistic(ActivityStatisticUnit.Kilocalories, value=float(act["metricSummary"]["calories"]))
activity.CalculateUID()
activities.append(activity)
if len(list_resp["data"]) == 0 or not exhaustive:
break
list_params["offset"] += list_params["count"]
return activities, exclusions
示例8: DownloadActivityList
# 需要导入模块: from tapiriik.services.interchange import UploadedActivity [as 别名]
# 或者: from tapiriik.services.interchange.UploadedActivity import TZ [as 别名]
def DownloadActivityList(self, serviceRecord, exhaustive=False):
#http://connect.garmin.com/proxy/activity-search-service-1.0/json/activities?&start=0&limit=50
session = self._get_session(record=serviceRecord)
page = 1
pageSz = 100
activities = []
exclusions = []
while True:
logger.debug("Req with " + str({"start": (page - 1) * pageSz, "limit": pageSz}))
self._rate_limit()
retried_auth = False
while True:
res = session.get("http://connect.garmin.com/proxy/activity-search-service-1.0/json/activities", params={"start": (page - 1) * pageSz, "limit": pageSz})
# It's 10 PM and I have no clue why it's throwing these errors, maybe we just need to log in again?
if res.status_code == 403 and not retried_auth:
retried_auth = True
session = self._get_session(serviceRecord, skip_cache=True)
else:
break
try:
res = res.json()["results"]
except ValueError:
res_txt = res.text # So it can capture in the log message
raise APIException("Parse failure in GC list resp: %s" % res.status_code)
if "activities" not in res:
break # No activities on this page - empty account.
for act in res["activities"]:
act = act["activity"]
activity = UploadedActivity()
# Don't really know why sumSampleCountTimestamp doesn't appear in swim activities - they're definitely timestamped...
activity.Stationary = "sumSampleCountSpeed" not in act and "sumSampleCountTimestamp" not in act
activity.GPS = "endLatitude" in act
activity.Private = act["privacy"]["key"] == "private"
try:
activity.TZ = pytz.timezone(act["activityTimeZone"]["key"])
except pytz.exceptions.UnknownTimeZoneError:
activity.TZ = pytz.FixedOffset(float(act["activityTimeZone"]["offset"]) * 60)
logger.debug("Name " + act["activityName"]["value"] + ":")
if len(act["activityName"]["value"].strip()) and act["activityName"]["value"] != "Untitled": # This doesn't work for internationalized accounts, oh well.
activity.Name = act["activityName"]["value"]
if len(act["activityDescription"]["value"].strip()):
activity.Notes = act["activityDescription"]["value"]
# beginTimestamp/endTimestamp is in UTC
activity.StartTime = pytz.utc.localize(datetime.utcfromtimestamp(float(act["beginTimestamp"]["millis"])/1000))
if "sumElapsedDuration" in act:
activity.EndTime = activity.StartTime + timedelta(0, round(float(act["sumElapsedDuration"]["value"])))
elif "sumDuration" in act:
activity.EndTime = activity.StartTime + timedelta(minutes=float(act["sumDuration"]["minutesSeconds"].split(":")[0]), seconds=float(act["sumDuration"]["minutesSeconds"].split(":")[1]))
else:
activity.EndTime = pytz.utc.localize(datetime.utcfromtimestamp(float(act["endTimestamp"]["millis"])/1000))
logger.debug("Activity s/t " + str(activity.StartTime) + " on page " + str(page))
activity.AdjustTZ()
if "sumDistance" in act and float(act["sumDistance"]["value"]) != 0:
activity.Stats.Distance = ActivityStatistic(self._unitMap[act["sumDistance"]["uom"]], value=float(act["sumDistance"]["value"]))
activity.Type = self._resolveActivityType(act["activityType"]["key"])
activity.CalculateUID()
activity.ServiceData = {"ActivityID": int(act["activityId"])}
activities.append(activity)
logger.debug("Finished page " + str(page) + " of " + str(res["search"]["totalPages"]))
if not exhaustive or int(res["search"]["totalPages"]) == page:
break
else:
page += 1
return activities, exclusions
示例9: DownloadActivityList
# 需要导入模块: from tapiriik.services.interchange import UploadedActivity [as 别名]
# 或者: from tapiriik.services.interchange.UploadedActivity import TZ [as 别名]
def DownloadActivityList(self, serviceRecord, exhaustive=False):
headers = self._getAuthHeaders(serviceRecord)
activities = []
exclusions = []
pageUri = self.OpenFitEndpoint + "/fitnessActivities.json"
activity_tz_cache_raw = cachedb.sporttracks_meta_cache.find_one({"ExternalID": serviceRecord.ExternalID})
activity_tz_cache_raw = activity_tz_cache_raw if activity_tz_cache_raw else {"Activities":[]}
activity_tz_cache = dict([(x["ActivityURI"], x["TZ"]) for x in activity_tz_cache_raw["Activities"]])
while True:
logger.debug("Req against " + pageUri)
res = requests.get(pageUri, headers=headers)
try:
res = res.json()
except ValueError:
raise APIException("Could not decode activity list response %s %s" % (res.status_code, res.text))
for act in res["items"]:
activity = UploadedActivity()
activity.ServiceData = {"ActivityURI": act["uri"]}
if len(act["name"].strip()):
activity.Name = act["name"]
# Longstanding ST.mobi bug causes it to return negative partial-hour timezones as "-2:-30" instead of "-2:30"
fixed_start_time = re.sub(r":-(\d\d)", r":\1", act["start_time"])
activity.StartTime = dateutil.parser.parse(fixed_start_time)
if isinstance(activity.StartTime.tzinfo, tzutc):
activity.TZ = pytz.utc # The dateutil tzutc doesn't have an _offset value.
else:
activity.TZ = pytz.FixedOffset(activity.StartTime.tzinfo.utcoffset(activity.StartTime).total_seconds() / 60) # Convert the dateutil lame timezones into pytz awesome timezones.
activity.StartTime = activity.StartTime.replace(tzinfo=activity.TZ)
activity.EndTime = activity.StartTime + timedelta(seconds=float(act["duration"]))
activity.Stats.TimerTime = ActivityStatistic(ActivityStatisticUnit.Seconds, value=float(act["duration"])) # OpenFit says this excludes paused times.
# Sometimes activities get returned with a UTC timezone even when they are clearly not in UTC.
if activity.TZ == pytz.utc:
if act["uri"] in activity_tz_cache:
activity.TZ = pytz.FixedOffset(activity_tz_cache[act["uri"]])
else:
# So, we get the first location in the activity and calculate the TZ from that.
try:
firstLocation = self._downloadActivity(serviceRecord, activity, returnFirstLocation=True)
except APIExcludeActivity:
pass
else:
try:
activity.CalculateTZ(firstLocation, recalculate=True)
except:
# We tried!
pass
else:
activity.AdjustTZ()
finally:
activity_tz_cache[act["uri"]] = activity.StartTime.utcoffset().total_seconds() / 60
logger.debug("Activity s/t " + str(activity.StartTime))
activity.Stats.Distance = ActivityStatistic(ActivityStatisticUnit.Meters, value=float(act["total_distance"]))
types = [x.strip().lower() for x in act["type"].split(":")]
types.reverse() # The incoming format is like "walking: hiking" and we want the most specific first
activity.Type = None
for type_key in types:
if type_key in self._activityMappings:
activity.Type = self._activityMappings[type_key]
break
if not activity.Type:
exclusions.append(APIExcludeActivity("Unknown activity type %s" % act["type"], activityId=act["uri"], userException=UserException(UserExceptionType.Other)))
continue
activity.CalculateUID()
activities.append(activity)
if not exhaustive or "next" not in res or not len(res["next"]):
break
else:
pageUri = res["next"]
logger.debug("Writing back meta cache")
cachedb.sporttracks_meta_cache.update({"ExternalID": serviceRecord.ExternalID}, {"ExternalID": serviceRecord.ExternalID, "Activities": [{"ActivityURI": k, "TZ": v} for k, v in activity_tz_cache.items()]}, upsert=True)
return activities, exclusions
示例10: DownloadActivityList
# 需要导入模块: from tapiriik.services.interchange import UploadedActivity [as 别名]
# 或者: from tapiriik.services.interchange.UploadedActivity import TZ [as 别名]
def DownloadActivityList(self, serviceRecord, exhaustive=False):
#http://connect.garmin.com/proxy/activity-search-service-1.0/json/activities?&start=0&limit=50
page = 1
pageSz = 100
activities = []
exclusions = []
while True:
logger.debug("Req with " + str({"start": (page - 1) * pageSz, "limit": pageSz}))
res = self._request_with_reauth(serviceRecord, lambda session: session.get("https://connect.garmin.com/modern/proxy/activity-search-service-1.0/json/activities", params={"start": (page - 1) * pageSz, "limit": pageSz}))
try:
res = res.json()["results"]
except ValueError:
res_txt = res.text # So it can capture in the log message
raise APIException("Parse failure in GC list resp: %s - %s" % (res.status_code, res.text))
if "activities" not in res:
break # No activities on this page - empty account.
for act in res["activities"]:
act = act["activity"]
activity = UploadedActivity()
# Don't really know why sumSampleCountTimestamp doesn't appear in swim activities - they're definitely timestamped...
activity.Stationary = "sumSampleCountSpeed" not in act and "sumSampleCountTimestamp" not in act
activity.GPS = "endLatitude" in act
activity.Private = act["privacy"]["key"] == "private"
try:
activity.TZ = pytz.timezone(act["activityTimeZone"]["key"])
except pytz.exceptions.UnknownTimeZoneError:
activity.TZ = pytz.FixedOffset(float(act["activityTimeZone"]["offset"]) * 60)
logger.debug("Name " + act["activityName"]["value"] + ":")
if len(act["activityName"]["value"].strip()) and act["activityName"]["value"] != "Untitled": # This doesn't work for internationalized accounts, oh well.
activity.Name = act["activityName"]["value"]
if len(act["activityDescription"]["value"].strip()):
activity.Notes = act["activityDescription"]["value"]
# beginTimestamp/endTimestamp is in UTC
activity.StartTime = pytz.utc.localize(datetime.utcfromtimestamp(float(act["beginTimestamp"]["millis"])/1000))
if "sumElapsedDuration" in act:
activity.EndTime = activity.StartTime + timedelta(0, round(float(act["sumElapsedDuration"]["value"])))
elif "sumDuration" in act:
activity.EndTime = activity.StartTime + timedelta(minutes=float(act["sumDuration"]["minutesSeconds"].split(":")[0]), seconds=float(act["sumDuration"]["minutesSeconds"].split(":")[1]))
else:
activity.EndTime = pytz.utc.localize(datetime.utcfromtimestamp(float(act["endTimestamp"]["millis"])/1000))
logger.debug("Activity s/t " + str(activity.StartTime) + " on page " + str(page))
activity.AdjustTZ()
if "sumDistance" in act and float(act["sumDistance"]["value"]) != 0:
activity.Stats.Distance = ActivityStatistic(self._unitMap[act["sumDistance"]["uom"]], value=float(act["sumDistance"]["value"]))
if "device" in act and act["device"]["key"] != "unknown":
devId = DeviceIdentifier.FindMatchingIdentifierOfType(DeviceIdentifierType.GC, {"Key": act["device"]["key"]})
ver_split = act["device"]["key"].split(".")
ver_maj = None
ver_min = None
if len(ver_split) == 4:
# 2.90.0.0
ver_maj = int(ver_split[0])
ver_min = int(ver_split[1])
activity.Device = Device(devId, verMaj=ver_maj, verMin=ver_min)
activity.Type = self._resolveActivityType(act["activityType"]["key"])
activity.CalculateUID()
activity.ServiceData = {"ActivityID": int(act["activityId"])}
activities.append(activity)
logger.debug("Finished page " + str(page) + " of " + str(res["search"]["totalPages"]))
if not exhaustive or int(res["search"]["totalPages"]) == page:
break
else:
page += 1
return activities, exclusions
示例11: DownloadActivityList
# 需要导入模块: from tapiriik.services.interchange import UploadedActivity [as 别名]
# 或者: from tapiriik.services.interchange.UploadedActivity import TZ [as 别名]
def DownloadActivityList(self, serviceRecord, exhaustive=False):
def mapStatTriple(act, stats_obj, key, units):
if "%s_max" % key in act and act["%s_max" % key]:
stats_obj.update(ActivityStatistic(units, max=float(act["%s_max" % key])))
if "%s_min" % key in act and act["%s_min" % key]:
stats_obj.update(ActivityStatistic(units, min=float(act["%s_min" % key])))
if "%s_avg" % key in act and act["%s_avg" % key]:
stats_obj.update(ActivityStatistic(units, avg=float(act["%s_avg" % key])))
# http://ridewithgps.com/users/1/trips.json?limit=200&order_by=created_at&order_dir=asc
# offset also supported
activities = []
exclusions = []
# They don't actually support paging right now, for whatever reason
params = self._add_auth_params({}, record=serviceRecord)
res = requests.get("http://ridewithgps.com/users/{}/trips.json".format(serviceRecord.ExternalID), params=params)
res = res.json()
# Apparently some API users are seeing this new result format - I'm not
if type(res) is dict:
res = res.get("results", [])
if res == []:
return [], [] # No activities
for act in res:
if "distance" not in act:
exclusions.append(APIExcludeActivity("No distance", activity_id=act["id"], user_exception=UserException(UserExceptionType.Corrupt)))
continue
if "duration" not in act or not act["duration"]:
exclusions.append(APIExcludeActivity("No duration", activity_id=act["id"], user_exception=UserException(UserExceptionType.Corrupt)))
continue
activity = UploadedActivity()
logger.debug("Name " + act["name"] + ":")
if len(act["name"].strip()):
activity.Name = act["name"]
if len(act["description"].strip()):
activity.Notes = act["description"]
activity.GPS = act["is_gps"]
activity.Stationary = not activity.GPS # I think
# 0 = public, 1 = private, 2 = friends
activity.Private = act["visibility"] == 1
activity.StartTime = dateutil.parser.parse(act["departed_at"])
try:
activity.TZ = pytz.timezone(act["time_zone"])
except pytz.exceptions.UnknownTimeZoneError:
# Sometimes the time_zone returned isn't quite what we'd like it
# So, just pull the offset from the datetime
if isinstance(activity.StartTime.tzinfo, tzutc):
activity.TZ = pytz.utc # The dateutil tzutc doesn't have an _offset value.
else:
activity.TZ = pytz.FixedOffset(activity.StartTime.tzinfo.utcoffset(activity.StartTime).total_seconds() / 60)
activity.StartTime = activity.StartTime.replace(tzinfo=activity.TZ) # Overwrite dateutil's sillyness
activity.EndTime = activity.StartTime + timedelta(seconds=self._duration_to_seconds(act["duration"]))
logger.debug("Activity s/t " + str(activity.StartTime))
activity.AdjustTZ()
activity.Stats.Distance = ActivityStatistic(ActivityStatisticUnit.Meters, float(act["distance"]))
mapStatTriple(act, activity.Stats.Power, "watts", ActivityStatisticUnit.Watts)
mapStatTriple(act, activity.Stats.Speed, "speed", ActivityStatisticUnit.KilometersPerHour)
mapStatTriple(act, activity.Stats.Cadence, "cad", ActivityStatisticUnit.RevolutionsPerMinute)
mapStatTriple(act, activity.Stats.HR, "hr", ActivityStatisticUnit.BeatsPerMinute)
if "elevation_gain" in act and act["elevation_gain"]:
activity.Stats.Elevation.update(ActivityStatistic(ActivityStatisticUnit.Meters, gain=float(act["elevation_gain"])))
if "elevation_loss" in act and act["elevation_loss"]:
activity.Stats.Elevation.update(ActivityStatistic(ActivityStatisticUnit.Meters, loss=float(act["elevation_loss"])))
# Activity type is not implemented yet in RWGPS results; we will assume cycling, though perhaps "OTHER" wouuld be correct
activity.Type = ActivityType.Cycling
activity.CalculateUID()
activity.ServiceData = {"ActivityID": act["id"]}
activities.append(activity)
return activities, exclusions
示例12: DownloadActivityList
# 需要导入模块: from tapiriik.services.interchange import UploadedActivity [as 别名]
# 或者: from tapiriik.services.interchange.UploadedActivity import TZ [as 别名]
def DownloadActivityList(self, serviceRecord, exhaustive=False):
activities = []
exclusions = []
earliestDate = None
earliestFirstPageDate = None
paged = False
while True:
before = "" if earliestDate is None else earliestDate.astimezone(pytz.utc).strftime("%Y-%m-%d %H:%M:%S UTC")
params = {"authToken": serviceRecord.Authorization["AuthToken"], "maxResults": 45, "before": before}
logger.debug("Req with " + str(params))
response = requests.get("http://api.mobile.endomondo.com/mobile/api/workout/list", params=params)
if response.status_code != 200:
if response.status_code == 401 or response.status_code == 403:
raise APIException("No authorization to retrieve activity list", block=True, user_exception=UserException(UserExceptionType.Authorization, intervention_required=True))
raise APIException("Unable to retrieve activity list " + str(response))
data = response.json()
if "error" in data and data["error"]["type"] == "AUTH_FAILED":
raise APIException("No authorization to retrieve activity list", block=True, user_exception=UserException(UserExceptionType.Authorization, intervention_required=True))
track_ids = []
this_page_activities = []
for act in data["data"]:
startTime = pytz.utc.localize(datetime.strptime(act["start_time"], "%Y-%m-%d %H:%M:%S UTC"))
if earliestDate is None or startTime < earliestDate: # probably redundant, I would assume it works out the TZes...
earliestDate = startTime
logger.debug("activity pre")
if not act["has_points"]:
logger.warning("\t no pts")
exclusions.append(APIExcludeActivity("No points", activityId=act["id"]))
continue # it'll break strava, which needs waypoints to find TZ. Meh
if "tracking" in act and act["tracking"]:
logger.warning("\t tracking")
exclusions.append(APIExcludeActivity("In progress", activityId=act["id"], permanent=False))
continue # come back once they've completed the activity
track_ids.append(act["id"])
activity = UploadedActivity()
activity.StartTime = startTime
activity.EndTime = activity.StartTime + timedelta(0, round(act["duration_sec"]))
logger.debug("\tActivity s/t " + str(activity.StartTime))
if int(act["sport"]) in self._activityMappings:
activity.Type = self._activityMappings[int(act["sport"])]
activity.UploadedTo = [{"Connection": serviceRecord, "ActivityID": act["id"]}]
this_page_activities.append(activity)
cached_track_tzs = cachedb.endomondo_activity_cache.find({"TrackID":{"$in": track_ids}})
cached_track_tzs = dict([(x["TrackID"], x) for x in cached_track_tzs])
logger.debug("Have" + str(len(cached_track_tzs.keys())) + "/" + str(len(track_ids)) + " cached TZ records")
for activity in this_page_activities:
# attn service makers: why #(*%$ can't you all agree to use naive local time. So much simpler.
cachedTrackData = None
track_id = activity.UploadedTo[0]["ActivityID"]
if track_id not in cached_track_tzs:
logger.debug("\t Resolving TZ for %s" % activity.StartTime)
cachedTrackData = self._downloadRawTrackRecord(serviceRecord, track_id)
try:
self._populateActivityFromTrackData(activity, cachedTrackData, minimumWaypoints=True)
except APIExcludeActivity as e:
e.ExternalActivityID = track_id
logger.info("Encountered APIExcludeActivity %s" % str(e))
exclusions.append(e)
continue
if not activity.TZ:
logger.info("Couldn't determine TZ")
exclusions.append(APIExcludeActivity("Couldn't determine TZ", activityId=track_id))
continue
cachedTrackRecord = {"Owner": serviceRecord.ExternalID, "TrackID": track_id, "TZ": pickle.dumps(activity.TZ), "StartTime": activity.StartTime}
cachedb.endomondo_activity_cache.insert(cachedTrackRecord)
else:
activity.TZ = pickle.loads(cached_track_tzs[track_id]["TZ"])
activity.AdjustTZ() # Everything returned is in UTC
activity.UploadedTo[0]["ActivityData"] = cachedTrackData
activity.Waypoints = []
activity.CalculateUID()
activities.append(activity)
if not paged:
earliestFirstPageDate = earliestDate
if not exhaustive or ("more" in data and data["more"] is False):
break
else:
paged = True
return activities, exclusions
示例13: DownloadActivityList
# 需要导入模块: from tapiriik.services.interchange import UploadedActivity [as 别名]
# 或者: from tapiriik.services.interchange.UploadedActivity import TZ [as 别名]
def DownloadActivityList(self, serviceRecord, exhaustive=False):
#http://connect.garmin.com/proxy/activity-search-service-1.0/json/activities?&start=0&limit=50
cookies = self._get_cookies(record=serviceRecord)
page = 1
pageSz = 100
activities = []
exclusions = []
while True:
logger.debug("Req with " + str({"start": (page - 1) * pageSz, "limit": pageSz}))
self._rate_limit()
res = requests.get("http://connect.garmin.com/proxy/activity-search-service-1.0/json/activities", params={"start": (page - 1) * pageSz, "limit": pageSz}, cookies=cookies)
try:
res = res.json()["results"]
except ValueError:
res_txt = res.text # So it can capture in the log message
raise APIException("Parse failure in GC list resp: %s" % res.status_code)
if "activities" not in res:
break # No activities on this page - empty account.
for act in res["activities"]:
act = act["activity"]
if "sumDistance" not in act:
exclusions.append(APIExcludeActivity("No distance", activityId=act["activityId"], userException=UserException(UserExceptionType.Corrupt)))
continue
activity = UploadedActivity()
if "sumSampleCountSpeed" not in act and "sumSampleCountTimestamp" not in act: # Don't really know why sumSampleCountTimestamp doesn't appear in swim activities - they're definitely timestamped...
activity.Stationary = True
else:
activity.Stationary = False
activity.Private = act["privacy"]["key"] == "private"
try:
activity.TZ = pytz.timezone(act["activityTimeZone"]["key"])
except pytz.exceptions.UnknownTimeZoneError:
activity.TZ = pytz.FixedOffset(float(act["activityTimeZone"]["offset"]) * 60)
logger.debug("Name " + act["activityName"]["value"] + ":")
if len(act["activityName"]["value"].strip()) and act["activityName"]["value"] != "Untitled": # This doesn't work for internationalized accounts, oh well.
activity.Name = act["activityName"]["value"]
if len(act["activityDescription"]["value"].strip()):
activity.Notes = act["activityDescription"]["value"]
# beginTimestamp/endTimestamp is in UTC
activity.StartTime = pytz.utc.localize(datetime.utcfromtimestamp(float(act["beginTimestamp"]["millis"])/1000))
if "sumElapsedDuration" in act:
activity.EndTime = activity.StartTime + timedelta(0, round(float(act["sumElapsedDuration"]["value"])))
elif "sumDuration" in act:
activity.EndTime = activity.StartTime + timedelta(minutes=float(act["sumDuration"]["minutesSeconds"].split(":")[0]), seconds=float(act["sumDuration"]["minutesSeconds"].split(":")[1]))
else:
activity.EndTime = pytz.utc.localize(datetime.utcfromtimestamp(float(act["endTimestamp"]["millis"])/1000))
logger.debug("Activity s/t " + str(activity.StartTime) + " on page " + str(page))
activity.AdjustTZ()
# TODO: fix the distance stats to account for the fact that this incorrectly reported km instead of meters for the longest time.
activity.Stats.Distance = ActivityStatistic(self._unitMap[act["sumDistance"]["uom"]], value=float(act["sumDistance"]["value"]))
activity.Type = self._resolveActivityType(act["activityType"]["key"])
activity.CalculateUID()
activity.ServiceData = {"ActivityID": act["activityId"]}
activities.append(activity)
logger.debug("Finished page " + str(page) + " of " + str(res["search"]["totalPages"]))
if not exhaustive or int(res["search"]["totalPages"]) == page:
break
else:
page += 1
return activities, exclusions
示例14: _populate_sbr_activity
# 需要导入模块: from tapiriik.services.interchange import UploadedActivity [as 别名]
# 或者: from tapiriik.services.interchange.UploadedActivity import TZ [as 别名]
def _populate_sbr_activity(self, api_sbr_activity, usersettings):
# Example JSON feed (unimportant fields have been removed)
# [{
# "EventId": 63128401, # Internal ID
# "EventType": 3, # Swim (3), bike (1), or run (2)
# "EventDate": "4/22/2016",
# "EventTime": "7:44 AM", # User's time, time zone not specified
# "Planned": false, # Training plan or actual data
# "TotalMinutes": 34.97,
# "TotalKilometers": 1.55448,
# "AverageHeartRate": 125,
# "MinimumHeartRate": 100,
# "MaximumHeartRate": 150,
# "MemberId": 999999,
# "MemberUsername": "Smith",
# "HasDeviceUpload": true,
# "DeviceUploadFile": "http://beginnertriathlete.com/discussion/storage/workouts/555555/abcd-123.fit",
# "RouteName": "", # Might contain a description of the event
# "Comments": "", # Same as above. Not overly often used.
# }, ... ]
activity = UploadedActivity()
workout_id = api_sbr_activity["EventId"]
eventType = api_sbr_activity["EventType"]
eventDate = api_sbr_activity["EventDate"]
eventTime = api_sbr_activity["EventTime"]
totalMinutes = api_sbr_activity["TotalMinutes"]
totalKms = api_sbr_activity["TotalKilometers"]
averageHr = api_sbr_activity["AverageHeartRate"]
minimumHr = api_sbr_activity["MinimumHeartRate"]
maximumHr = api_sbr_activity["MaximumHeartRate"]
deviceUploadFile = api_sbr_activity["DeviceUploadFile"]
# Basic SBR data does not include GPS or sensor data. If this event originated from a device upload,
# DownloadActivity will find it.
activity.Stationary = True
# Same as above- The data might be there, but it's not supplied in the basic activity feed.
activity.GPS = False
activity.Private = usersettings["Privacy"]
activity.Type = self._workoutTypeMappings[str(eventType)]
# Get the user's timezone from their profile. (Activity.TZ should be mentioned in the object hierarchy docs?)
# Question: I believe if DownloadActivity finds device data, it will overwrite this. Which is OK with me.
# The device data will most likely be more accurate.
try:
activity.TZ = pytz.timezone(usersettings["TimeZone"])
except pytz.exceptions.UnknownTimeZoneError:
activity.TZ = pytz.timezone(self._serverDefaultTimezone)
# activity.StartTime and EndTime aren't mentioned in the object hierarchy docs, but I see them
# set in all the other providers.
activity.StartTime = dateutil.parser.parse(
eventDate + " " + eventTime,
dayfirst=False).replace(tzinfo=activity.TZ)
activity.EndTime = activity.StartTime + timedelta(minutes=totalMinutes)
# We can calculate some metrics from the supplied data. Would love to see some non-source code documentation
# on each statistic and what it expects as input.
activity.Stats.Distance = ActivityStatistic(ActivityStatisticUnit.Kilometers,
value=totalKms)
activity.Stats.HR = ActivityStatistic(ActivityStatisticUnit.BeatsPerMinute,
avg=float(averageHr),
min=float(minimumHr),
max=float(maximumHr))
activity.Stats.MovingTime = ActivityStatistic(ActivityStatisticUnit.Seconds,
value=float(totalMinutes * 60))
activity.Stats.TimerTime = ActivityStatistic(ActivityStatisticUnit.Seconds,
value=float(totalMinutes * 60))
# While BT does support laps, the current API doesn't report on them - a limitation that may need to be
# corrected in a future update. For now, treat manual entries as a single lap. As more and more people upload
# workouts using devices anyway, this probably matters much less than it once did.
lap = Lap(stats=activity.Stats, startTime=activity.StartTime, endTime=activity.EndTime)
activity.Laps = [lap]
# Not 100% positive how this is utilized, but it is common for all providers. Detects duplicate downloads?
activity.CalculateUID()
# If a device file is attached, we'll get more details about this event in DownloadActivity
activity.ServiceData = {
"ID": int(workout_id),
"DeviceUploadFile": deviceUploadFile
}
return activity
示例15: DownloadActivityList
# 需要导入模块: from tapiriik.services.interchange import UploadedActivity [as 别名]
# 或者: from tapiriik.services.interchange.UploadedActivity import TZ [as 别名]
def DownloadActivityList(self, serviceRecord, exhaustive=False):
# http://connect.garmin.com/proxy/activity-search-service-1.0/json/activities?&start=0&limit=50
cookies = self._get_cookies(record=serviceRecord)
page = 1
pageSz = 100
activities = []
exclusions = []
while True:
logger.debug("Req with " + str({"start": (page - 1) * pageSz, "limit": pageSz}))
self._rate_limit()
res = requests.get(
"http://connect.garmin.com/proxy/activity-search-service-1.0/json/activities",
params={"start": (page - 1) * pageSz, "limit": pageSz},
cookies=cookies,
)
res = res.json()["results"]
if "activities" not in res:
break # No activities on this page - empty account.
for act in res["activities"]:
act = act["activity"]
if "sumDistance" not in act:
exclusions.append(APIExcludeActivity("No distance", activityId=act["activityId"]))
continue
activity = UploadedActivity()
if (
"sumSampleCountSpeed" not in act and "sumSampleCountTimestamp" not in act
): # Don't really know why sumSampleCountTimestamp doesn't appear in swim activities - they're definitely timestamped...
activity.Stationary = True
else:
activity.Stationary = False
try:
activity.TZ = pytz.timezone(act["activityTimeZone"]["key"])
except pytz.exceptions.UnknownTimeZoneError:
activity.TZ = pytz.FixedOffset(float(act["activityTimeZone"]["offset"]) * 60)
logger.debug("Name " + act["activityName"]["value"] + ":")
if (
len(act["activityName"]["value"].strip()) and act["activityName"]["value"] != "Untitled"
): # This doesn't work for internationalized accounts, oh well.
activity.Name = act["activityName"]["value"]
if len(act["activityDescription"]["value"].strip()):
activity.Notes = act["activityDescription"]["value"]
# beginTimestamp/endTimestamp is in UTC
activity.StartTime = pytz.utc.localize(
datetime.utcfromtimestamp(float(act["beginTimestamp"]["millis"]) / 1000)
)
if "sumElapsedDuration" in act:
activity.EndTime = activity.StartTime + timedelta(
0, round(float(act["sumElapsedDuration"]["value"]))
)
elif "sumDuration" in act:
activity.EndTime = activity.StartTime + timedelta(
minutes=float(act["sumDuration"]["minutesSeconds"].split(":")[0]),
seconds=float(act["sumDuration"]["minutesSeconds"].split(":")[1]),
)
else:
activity.EndTime = pytz.utc.localize(
datetime.utcfromtimestamp(float(act["endTimestamp"]["millis"]) / 1000)
)
logger.debug("Activity s/t " + str(activity.StartTime) + " on page " + str(page))
activity.AdjustTZ()
# TODO: fix the distance stats to account for the fact that this incorrectly reported km instead of meters for the longest time.
activity.Stats.Distance = ActivityStatistic(
self._unitMap[act["sumDistance"]["uom"]], value=float(act["sumDistance"]["value"])
)
def mapStat(gcKey, statKey, type, useSourceUnits=False):
nonlocal activity, act
if gcKey in act:
value = float(act[gcKey]["value"])
if math.isinf(value):
return # GC returns the minimum speed as "-Infinity" instead of 0 some times :S
activity.Stats.__dict__[statKey].update(
ActivityStatistic(self._unitMap[act[gcKey]["uom"]], **({type: value}))
)
if useSourceUnits:
activity.Stats.__dict__[statKey] = activity.Stats.__dict__[statKey].asUnits(
self._unitMap[act[gcKey]["uom"]]
)
if "sumMovingDuration" in act:
activity.Stats.MovingTime = ActivityStatistic(
ActivityStatisticUnit.Time, value=timedelta(seconds=float(act["sumMovingDuration"]["value"]))
)
if "sumDuration" in act:
activity.Stats.TimerTime = ActivityStatistic(
ActivityStatisticUnit.Time,
value=timedelta(
minutes=float(act["sumDuration"]["minutesSeconds"].split(":")[0]),
seconds=float(act["sumDuration"]["minutesSeconds"].split(":")[1]),
),
)
mapStat(
"minSpeed", "Speed", "min", useSourceUnits=True
) # We need to suppress conversion here, so we can fix the pace-speed issue below
#.........这里部分代码省略.........