-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGarminConnectActivityExport.py
128 lines (106 loc) · 5 KB
/
GarminConnectActivityExport.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import json
import csv
import codecs
from logging import getLogger
from os.path import join, exists
from re import search, sub
from datetime import date
from requests import session
log = getLogger(__name__)
class GarminConnect:
# lean Python 3 script to export Garmin actitvities to JSON or CSV file
# based on code from Andre Cooke (https://github.com/andrewcooke) https://github.com/andrewcooke/choochoo/blob/master/ch2/fit/download/connect.py
# logic and data from https://github.com/tcgoetz/GarminDB/blob/master/download_garmin.py
# updated to the recent Garmin API specification
# added features to export JSON and CSV
# 2019-08-18
base_url = 'https://connect.garmin.com'
sso_url = 'https://sso.garmin.com/sso'
modern = base_url + '/modern'
signin = sso_url + '/signin'
daily = modern + '/proxy/activitylist-service/activities/search/activities' # updated to the recent Garmin API specification
headers = {
'User-Agent': 'Mozilla/5.0 (compatible; https://github.com/andrewcooke/choochoo)',
'origin': 'https://sso.garmin.com'
}
def __init__(self, log_response=False):
self._r = session()
self._log_response = log_response
def login(self, username, password):
log.info('Connecting to Garmin Connect as %s' % username)
params = {
'webhost': self.base_url,
'service': self.modern,
'source': self.signin,
'redirectAfterAccountLoginUrl': self.modern,
'redirectAfterAccountCreationUrl': self.modern,
'gauthHost': self.sso_url,
'locale': 'en_US',
'id': 'gauth-widget',
'cssUrl': 'https://static.garmincdn.com/com.garmin.connect/ui/css/gauth-custom-v1.2-min.css',
'clientId': 'GarminConnect',
'rememberMeShown': 'true',
'rememberMeChecked': 'false',
'createAccountShown': 'true',
'openCreateAccount': 'false',
'usernameShown': 'false',
'displayNameShown': 'false',
'consumeServiceTicket': 'false',
'initialFocus': 'true',
'embedWidget': 'false',
'generateExtraServiceTicket': 'false'
}
response = self._log_r(self._r.get(self.signin, headers=self.headers, params=params))
response.raise_for_status()
data = {
'username': username,
'password': password,
'embed': 'true',
'lt': 'e1s1',
'_eventId': 'submit',
'displayNameRequired': 'false'
}
response = self._log_r(self._r.post(self.signin, headers=self.headers, params=params, data=data))
response.raise_for_status()
response_url = search(r'"(https:[^"]+?ticket=[^"]+)"', response.text)
if not response_url:
log.debug(response.text)
raise Exception('Could not find response URL')
response_url = sub(r'\\', '', response_url.group(1))
log.debug('Response URL: %s' % response_url)
response = self._log_r(self._r.get(response_url))
response.raise_for_status()
def _log_r(self, response):
if self._log_response:
log.debug('headers: %s' % response.headers)
log.debug('reason: %s' % response.reason)
log.debug('cookies: %s' % response.cookies)
log.debug('history: %s' % response.history)
return response
def get_monitoring_date(self, start_date, end_date): # retrieve activities from start_date to end_date as total numbers of items retrieved is limited by Garmin
response = self._log_r(self._r.get(self.daily + '?' + 'startDate=' + start_date + '&' + 'endDate=' + end_date, headers=self.headers))
print('Retrieving json data stream from ' + self.daily + '?' + 'startDate=' + start_date + '&' + 'endDate=' + end_date)
response.raise_for_status()
return response
def write_csv(self, json_data, filename): # CSV writer
with codecs.open(filename, 'w+', encoding='utf-8') as outf:
writer = csv.DictWriter(outf, json_data[0].keys())
writer.writeheader()
for row in json_data:
writer.writerow(row)
def write_json(self, json_data, filename): # JSON writer
with codecs.open(filename, 'w+', encoding='utf-8') as json_file:
json.dump(json_data, json_file)
def get_monitoring_to_json_file_date(self, start_date, end_date, dir):
f = join(dir, start_date + '_to_' + end_date + '.json')
response = self.get_monitoring_date(start_date, end_date)
j = json.loads(response.content)
self.write_json(j, f)
def get_monitoring_to_csv_file_date(self, start_date, end_date, dir):
f = join(dir, start_date + '_to_' + end_date + '.csv')
response = self.get_monitoring_date(start_date, end_date)
j = json.loads(response.content)
self.write_csv(j, f)
g = GarminConnect()
g.login('youruser', 'yourpassword')
g.get_monitoring_to_json_file_date('2018-01-1', '2018-12-31', 'yourpath')