|
import math |
|
import requests |
|
import plotly.express as px |
|
import plotly.graph_objects as go |
|
from plotly.subplots import make_subplots |
|
from datetime import date, timedelta |
|
import pandas as pd |
|
import numpy as np |
|
|
|
headers = { |
|
'DI-Backend': 'connectapi.garmin.com', |
|
'Authorization': '', |
|
'Cookie': '', |
|
} |
|
|
|
def request(url: str): |
|
r = requests.get(url, headers=headers) |
|
if r.status_code != 200: |
|
print(url) |
|
print(r.status_code) |
|
print(r.text) |
|
exit() |
|
return r |
|
|
|
def get_dates(beg: date, end: date, period: int): |
|
dates = [] |
|
cbeg = beg |
|
while cbeg < end: |
|
cend = cbeg + timedelta(days=period) |
|
if cend > end: |
|
cend = end |
|
dates.append([cbeg, cend]) |
|
cbeg = cend + timedelta(days=1) |
|
return dates |
|
|
|
def get_hrv_summaries(beg: date, end: date): |
|
print(f"Get HRV Summaries between {beg} and {end}") |
|
x = [] |
|
y_hrv_last_night_avg = [] |
|
y_hrv_weekly_avg = [] |
|
y_hrv_blower = [] |
|
y_hrv_bupper = [] |
|
dates = get_dates(beg, end, 366) |
|
for beg, end in dates: |
|
url = f'https://connect.garmin.com/hrv-service/hrv/daily/{beg}/{end}' |
|
r = request(url) |
|
|
|
hrvs = r.json().get("hrvSummaries") |
|
for hrv in hrvs: |
|
x.append(hrv.get("calendarDate")) |
|
y_hrv_last_night_avg.append(hrv.get("lastNightAvg")) |
|
y_hrv_weekly_avg.append(hrv.get("weeklyAvg")) |
|
baseline = hrv.get("baseline") |
|
if baseline: |
|
y_hrv_blower.append(baseline.get("balancedLow")) |
|
y_hrv_bupper.append(baseline.get("balancedUpper")) |
|
else: |
|
y_hrv_blower.append(None) |
|
y_hrv_bupper.append(None) |
|
return x, y_hrv_last_night_avg, y_hrv_weekly_avg, y_hrv_blower, y_hrv_bupper |
|
|
|
def get_sleep_stats(beg: date, end: date): |
|
print(f"Get Sleep Stats between {beg} and {end}") |
|
x = [] |
|
y = [] |
|
dates = get_dates(beg, end, 27) |
|
for bdate, edate in dates: |
|
url = f'https://connect.garmin.com/sleep-service/stats/sleep/daily/{bdate}/{edate}' |
|
r = request(url) |
|
|
|
inds = r.json().get("individualStats") |
|
for ind in inds: |
|
x.append(ind.get("calendarDate")) |
|
sleep = ind.get("values").get("totalSleepTimeInSeconds") / 3600 |
|
y.append(sleep) |
|
return x, y |
|
|
|
# main |
|
|
|
beg = date.fromisoformat('2022-11-04') |
|
end = date.today() |
|
|
|
x1, y_hrv_last_night_avg, y_hrv, y_bl, y_bu = get_hrv_summaries(beg, end) |
|
x2, y = get_sleep_stats(beg, end) |
|
|
|
# Merge datasets |
|
|
|
hrv_df = pd.DataFrame({ |
|
'x': x1, |
|
'y_ln_hrv': y_hrv_last_night_avg, |
|
'y_hrv': y_hrv, |
|
'y_bl': y_bl, |
|
'y_bu': y_bu |
|
}) |
|
sleep_df = pd.DataFrame({ |
|
'x': x2, |
|
'y_sleep': y |
|
}) |
|
|
|
df = pd.merge(hrv_df, sleep_df, on='x', how='outer') |
|
df['x'] = pd.to_datetime(df['x']) |
|
df['y_sleep_7da'] = df['y_sleep'].rolling(min_periods=3, window=7).mean() |
|
df['color'] = np.where(df['y_sleep'] < 7, 'red', 'green') |
|
|
|
fig = make_subplots( |
|
rows=3, |
|
cols=1, |
|
shared_xaxes=True, |
|
subplot_titles=['Last Night Average HRV', '7-day Average HRV', 'Sleep Amount (green is >= 7 hours, black=7 day average)'] |
|
) |
|
fig.append_trace(go.Scatter(x=df['x'], y=df['y_ln_hrv'], line_color='green', name="last night average hrv", showlegend=False), 1, 1) |
|
fig.append_trace(go.Scatter(x=df['x'], y=df['y_hrv'], line_color='blue', name="7 day average hrv", showlegend=False), 2, 1) |
|
fig.append_trace(go.Scatter(x=df['x'], y=df['y_bl'], line_color='darkgrey', name="", showlegend=False), 2, 1) |
|
fig.append_trace(go.Scatter(x=df['x'], y=df['y_bu'], line_color='darkgrey', name="", showlegend=False), 2, 1) |
|
fig.append_trace(go.Bar(x=df['x'], y=df['y_sleep'], marker_color=df['color'], name="sleep in hours", showlegend=False), 3, 1) |
|
fig.append_trace(go.Scatter(x=df['x'], y=df['y_sleep_7da'], marker_color='black', name="7 day average", showlegend=False), 3, 1) |
|
|
|
fig.show() |