Last active
March 16, 2024 20:24
-
-
Save ItHasU/ba934eaa7cb29c8e5373d22b1dfc125a to your computer and use it in GitHub Desktop.
This code allows to retrieve data from the Garmin Connect website for your own use.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
CONFIG=${1-config.json} | |
# Constants | |
ERRORS="errors.log" | |
LOGIN_FILENAME="/tmp/garmin-login.html" | |
AUTH_FILENAME="/tmp/auth.html" | |
SESSIONID_FILENAME="/tmp/sessionid.txt" | |
function connect() { | |
echo -n "Reading config ... " | |
if [ -e "${CONFIG}" ] | |
then | |
USERNAME=`jq -r .email ${CONFIG}` | |
PASSWORD=`jq -r .password ${CONFIG}` | |
MIN_DATE=`jq -r .min_date ${CONFIG}` | |
if [[ ${USERNAME} == "" ]] | |
then | |
echo "invalid email" | |
exit 1 | |
fi | |
if [[ ${PASSWORD} == "" ]] | |
then | |
echo "invalid password" | |
exit 1 | |
fi | |
if [[ ${MIN_DATE} == "" ]] | |
then | |
echo "invalid min_date" | |
exit 1 | |
fi | |
echo "done" | |
else | |
echo "${CONFIG} not found" | |
echo "Write a file ${CONFIG} containing:" '{"email":"...", "password":"...", "min_date":"2018-01-01"}' | |
exit 1 | |
fi | |
echo -n "Connecting as ${USERNAME} ... " | |
URL='https://sso.garmin.com/sso/signin?service=https%3A%2F%2Fconnect.garmin.com%2Fmodern%2F&webhost=https%3A%2F%2Fconnect.garmin.com&source=https%3A%2F%2Fconnect.garmin.com%2Ffr-FR%2Fsignin&redirectAfterAccountLoginUrl=https%3A%2F%2Fconnect.garmin.com%2Fmodern%2F&redirectAfterAccountCreationUrl=https%3A%2F%2Fconnect.garmin.com%2Fmodern%2F&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso&locale=fr_FR&id=gauth-widget&cssUrl=https%3A%2F%2Fstatic.garmincdn.com%2Fcom.garmin.connect%2Fui%2Fcss%2Fgauth-custom-v1.2-min.css&privacyStatementUrl=%2F%2Fconnect.garmin.com%2Ffr-FR%2Fprivacy%2F&clientId=GarminConnect&rememberMeShown=true&rememberMeChecked=false&createAccountShown=true&openCreateAccount=false&displayNameShown=false&consumeServiceTicket=false&initialFocus=true&embedWidget=false&generateExtraServiceTicket=true&generateTwoExtraServiceTickets=false&generateNoServiceTicket=false&globalOptInShown=true&globalOptInChecked=false&mobile=false&connectLegalTerms=true&locationPromptShown=true' | |
curl -s -v --data "username=${USERNAME}&password=${PASSWORD}&embed=false" --output "${AUTH_FILENAME}" "${URL}" 2>>${ERRORS} | |
RES=$? | |
if [ $RES -ne 0 ] | |
then | |
echo -e "\033[31mfailed loading ($RES)\033[0m" | |
exit | |
fi | |
awk 'match($0, /\?ticket=.*\"/) { print substr($0, RSTART+8, RLENGTH-9); exit; }' ${AUTH_FILENAME} > /tmp/token | |
if [ $? -ne 0 ] | |
then | |
echo -e "\033[31mfailed parsing\033[0m" | |
exit | |
fi | |
TOKEN=`cat /tmp/token` | |
if [[ "${TOKEN}" == "" ]] | |
then | |
echo -e "\033[31mfailed\033[0m" | |
exit | |
fi | |
echo "${TOKEN}" | |
echo -n "Fetching session id ... " | |
URL="https://connect.garmin.com/modern/?ticket=${TOKEN}" | |
curl -s -v -c ${SESSIONID_FILENAME} "${URL}" 2>>${ERRORS} | |
RES=$? | |
if [ $RES -ne 0 ] | |
then | |
echo -e "\033[31mfailed loading ($RES)\033[0m" | |
exit | |
fi | |
awk 'match($0, /\SESSIONID\s[^\s]+/) { print substr($0, RSTART+10, RLENGTH); exit; }' ${SESSIONID_FILENAME} > /tmp/sessionid | |
if [ $? -ne 0 ] | |
then | |
echo -e "\033[31mfailed parsing\033[0m" | |
exit | |
fi | |
SESSIONID=`cat /tmp/sessionid` | |
if [[ "${SESSIONID}" == "" ]] | |
then | |
echo -e "\033[31mfailed\033[0m" | |
exit | |
fi | |
echo ${SESSIONID} | |
} | |
function getLogin() { | |
COOKIE="cookie: SESSIONID=${SESSIONID}" | |
URL="https://connect.garmin.com/modern/" | |
echo -n "Fetching login ... " | |
curl -s -H "${COOKIE}" -v --output "${LOGIN_FILENAME}" "${URL}" 2>>${ERRORS} | |
RES=$? | |
if [ $RES -ne 0 ] | |
then | |
echo -e "\033[31mfailed loading ($RES)\033[0m" | |
exit | |
fi | |
awk 'match($0, /displayName\\\":\\\"[^\\]*\\\"/) { print substr($0, RSTART+16, RLENGTH-18); exit; }' ${LOGIN_FILENAME} > /tmp/login | |
if [ $? -ne 0 ] | |
then | |
echo -e "\033[31mfailed parsing\033[0m" | |
exit | |
fi | |
LOGIN=`cat /tmp/login` | |
if [[ "${LOGIN}" == "" ]] | |
then | |
echo -e "\033[31mfailed\033[0m" | |
exit | |
fi | |
# Success, TODO: Check data were loaded correctly | |
echo -e "\033[32m${LOGIN}\033[0m" | |
} | |
function get() { | |
COOKIE="cookie: SESSIONID=${SESSIONID}" | |
NAME=$1 | |
URL=$2 | |
FILENAME="data/${CURRENT_DATE}_${NAME}.json" | |
if [ -e ${FILENAME} ] | |
then | |
# Already existing | |
echo -ne "~\033[34m${NAME}\033[0m, " | |
else | |
# Fetch data | |
curl -s -H "${COOKIE}" -v --output "${FILENAME}" "${URL}" 2>>${ERRORS} | |
if [ $? -eq 0 ] | |
then | |
# Success, TODO: Check data were loaded correctly | |
echo -ne "+\033[32m${NAME}\033[0m, " | |
else | |
# Error | |
echo -ne "!\033[31m${NAME}\033[0m, " | |
fi | |
fi | |
} | |
############################################################################### | |
# Init error files | |
date > ${ERRORS} | |
############################################################################### | |
# Connect using ${CONFIG} | |
############################################################################### | |
connect | |
############################################################################### | |
# Fetch login for given session ID | |
# This is usually a good test to check if SESSIONID is correct | |
############################################################################### | |
getLogin | |
############################################################################### | |
# Last chance to exit | |
############################################################################### | |
# echo "Will now retrieve data from ${MIN_DATE} to $(date -I)" | |
# read -n1 -r -p "Press space to continue..." key | |
# echo | |
############################################################################### | |
# Get data from yesterday to min date | |
# Will only write new data | |
############################################################################### | |
CURRENT_DATE=`date -I` | |
while [ "${CURRENT_DATE}" != "${MIN_DATE}" ]; do | |
CURRENT_DATE=$(date -I -d "${CURRENT_DATE} - 1 day") | |
echo -n "${CURRENT_DATE}: " | |
ERRORS=0 | |
get summary "https://connect.garmin.com/modern/proxy/usersummary-service/usersummary/daily/${LOGIN}?calendarDate=${CURRENT_DATE}" | |
get activities "https://connect.garmin.com/modern/proxy/activitylist-service/activities/fordailysummary/${LOGIN}?calendarDate=${CURRENT_DATE}" | |
get sleep "https://connect.garmin.com/modern/proxy/wellness-service/wellness/dailySleepData/${LOGIN}?date=${CURRENT_DATE}&nonSleepBufferMinutes=60" | |
get steps "https://connect.garmin.com/modern/proxy/wellness-service/wellness/dailySummaryChart/${LOGIN}?date=${CURRENT_DATE}" | |
get movements "https://connect.garmin.com/modern/proxy/wellness-service/wellness/dailyMovement/${LOGIN}?calendarDate=${CURRENT_DATE}" | |
get heartrate "https://connect.garmin.com/modern/proxy/wellness-service/wellness/dailyHeartRate/${LOGIN}?date=${CURRENT_DATE}" | |
if [[ $ERRORS == 0 ]] | |
then | |
echo -en "done\r" | |
else | |
echo "failed" | |
exit | |
fi | |
done | |
echo |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment