Skip to content

Commit

Permalink
Merge branch 'main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
TrafficCop authored Jan 15, 2024
2 parents e2672d1 + 8a6a186 commit d4f33c7
Show file tree
Hide file tree
Showing 50 changed files with 12,955 additions and 17,245 deletions.
2 changes: 1 addition & 1 deletion CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
- Tristan Peng (tristan.peng@stanford.edu)
- Hetav Modi (hetav.1805@gmail.com)
- Jack Hung (jjhung66@stanford.edu)
- Saarth Shah (sashah@ucsd.edu)
- Saarth Shah (saarth@berkeley.edu)
- Suvan Kumar (kumarsuvan0@gmail.com)
- Hee Jung Choi (cheejung@stanford.edu)
9 changes: 9 additions & 0 deletions docs/source/infosheet/infosheet.csv
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,12 @@ Dexcom,Pro CGM,`dexcom/pro_cgm`,OAuth 2.0,yes,link
Withings,Body+,`withings/bodyplus`,OAuth 2.0,yes,link
Withings,ScanWatch,`withings/scanwatch`,OAuth 2.0,yes,link
Polar,Verity Sense,`polar/verity_sense`,only email and password,yes,link
Cronometer, Cronometer App, 'cromometer/Cronometer', only email and password,yes,link
MyFitnessPal, MyFitnessPal App, 'myfitnesspal/myfitnesspal', browser cookies,yes,link
Google, Fitness, 'google/googlefit', authorization_code,yes,link
Strava, Strava App, 'strava/strava', client_id client_secret and refresh_token,yes, link
Polar,Vantage V2,`polar/vantage`,only email and password,yes,link
Oura,Ring 3,`oura/oura_ring3`,OAuth 2.0,yes,link
Fitbit,Sense,`fitbit/fitbit_sense`,OAuth 2.0,yes,link
Fitbit,Charge 4,`fitbit/fitbit_charge_4`,OAuth 2.0,yes,link
Coros,Pace 2,`coros/coros_pace_2`,only email and password,yes,link
9,155 changes: 3,063 additions & 6,092 deletions docs/source/notebooks/cronometer.ipynb

Large diffs are not rendered by default.

6,254 changes: 1,891 additions & 4,363 deletions docs/source/notebooks/google_fit.ipynb

Large diffs are not rendered by default.

378 changes: 163 additions & 215 deletions docs/source/notebooks/my_fitness_pal.ipynb

Large diffs are not rendered by default.

4,365 changes: 1,760 additions & 2,605 deletions docs/source/notebooks/polar_vantage.ipynb

Large diffs are not rendered by default.

5,770 changes: 2,373 additions & 3,397 deletions docs/source/notebooks/strava.ipynb

Large diffs are not rendered by default.

36 changes: 36 additions & 0 deletions docs/source/reference/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,39 @@ Devices
.. autoclass:: wearipedia.devices.withings.ScanWatch
:members:
:show-inheritance:

.. autoclass:: wearipedia.devices.cromometer.Cronometer
:members:
:show-inheritance:

.. autoclass:: wearipedia.devices.myfitnesspal.MyFitnessPal
:members:
:show-inheritance:

.. autoclass:: wearipedia.devices.google.GoogleFitness
:members:
:show-inheritance:

.. autoclass:: wearipedia.devices.strava.Strava
:members:
:show-inheritance:

.. autoclass:: wearipedia.devices.polar.PolarVantage
:members:
:show-inheritance:

.. autoclass:: wearipedia.devices.coros.Coros_pace_2
:members:
:show-inheritance:

.. autoclass:: wearipedia.devices.oura.Oura_Ring_3
:members:
:show-inheritance:

.. autoclass:: wearipedia.devices.fitbit.Fitbit_charge_4
:members:
:show-inheritance:

.. autoclass:: wearipedia.devices.fitbit.Fitbit_sense
:members:
:show-inheritance:
1,106 changes: 576 additions & 530 deletions poetry.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ exclude = '''
| dist
| env
| venv
| docs
)/
'''

Expand Down
28 changes: 14 additions & 14 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,41 @@ ansicon==1.89.0 ; python_version >= "3.8" and python_version < "4.0" and platfor
beautifulsoup4==4.12.2 ; python_version >= "3.8" and python_version < "4.0"
blessed==1.20.0 ; python_version >= "3.8" and python_version < "4.0"
browser-cookie3==0.19.1 ; python_version >= "3.8" and python_version < "4.0"
certifi==2023.7.22 ; python_version >= "3.8" and python_version < "4.0"
charset-normalizer==3.2.0 ; python_version >= "3.8" and python_version < "4.0"
certifi==2023.11.17 ; python_version >= "3.8" and python_version < "4.0"
charset-normalizer==3.3.2 ; python_version >= "3.8" and python_version < "4.0"
click==8.1.7 ; python_version >= "3.8" and python_version < "4.0"
cloudscraper==1.2.71 ; python_version >= "3.8" and python_version < "4.0"
colorama==0.4.6 ; python_version >= "3.8" and python_version < "4.0"
commonmark==0.9.1 ; python_version >= "3.8" and python_version < "4.0"
fbm==0.3.0 ; python_version >= "3.8" and python_version < "4.0"
garminconnect==0.1.55 ; python_version >= "3.8" and python_version < "4.0"
idna==3.4 ; python_version >= "3.8" and python_version < "4.0"
idna==3.6 ; python_version >= "3.8" and python_version < "4.0"
jeepney==0.8.0 ; python_version >= "3.8" and (sys_platform == "bsd" or sys_platform == "linux") and python_version < "4.0"
jinxed==1.2.0 ; python_version >= "3.8" and python_version < "4.0" and platform_system == "Windows"
lxml==4.9.3 ; python_version >= "3.8" and python_version < "4.0"
lz4==4.3.2 ; python_version >= "3.8" and python_version < "4.0"
jinxed==1.2.1 ; python_version >= "3.8" and python_version < "4.0" and platform_system == "Windows"
lxml==4.9.4 ; python_version >= "3.8" and python_version < "4.0"
lz4==4.3.3 ; python_version >= "3.8" and python_version < "4.0"
measurement==3.2.2 ; python_version >= "3.8" and python_version < "4.0"
mpmath==1.3.0 ; python_version >= "3.8" and python_version < "4.0"
myfitnesspal==2.0.1 ; python_version >= "3.8" and python_version < "4.0"
myfitnesspal==2.1.0 ; python_version >= "3.8" and python_version < "4.0"
numpy==1.24.4 ; python_version >= "3.8" and python_version < "4.0"
pandas==1.5.3 ; python_version >= "3.8" and python_version < "4.0"
polyline==2.0.0 ; python_version >= "3.8" and python_version < "4.0"
pycryptodomex==3.19.0 ; python_version >= "3.8" and python_version < "4.0"
pygments==2.16.1 ; python_version >= "3.8" and python_version < "4.0"
polyline==2.0.1 ; python_version >= "3.8" and python_version < "4.0"
pycryptodomex==3.20.0 ; python_version >= "3.8" and python_version < "4.0"
pygments==2.17.2 ; python_version >= "3.8" and python_version < "4.0"
pyparsing==3.1.1 ; python_version >= "3.8" and python_version < "4.0"
python-dateutil==2.8.2 ; python_version >= "3.8" and python_version < "4.0"
pytz==2023.3.post1 ; python_version >= "3.8" and python_version < "4.0"
requests-toolbelt==1.0.0 ; python_version >= "3.8" and python_version < "4.0"
requests==2.31.0 ; python_version >= "3.8" and python_version < "4.0"
rich==12.6.0 ; python_version >= "3.8" and python_version < "4.0"
scipy==1.9.3 ; python_version >= "3.8" and python_version < "4.0"
shellingham==1.5.3 ; python_version >= "3.8" and python_version < "4.0"
shellingham==1.5.4 ; python_version >= "3.8" and python_version < "4.0"
six==1.16.0 ; python_version >= "3.8" and python_version < "4.0"
soupsieve==2.5 ; python_version >= "3.8" and python_version < "4.0"
sympy==1.12 ; python_version >= "3.8" and python_version < "4.0"
tqdm==4.66.1 ; python_version >= "3.8" and python_version < "4.0"
typer[all]==0.6.1 ; python_version >= "3.8" and python_version < "4.0"
typing-extensions==4.7.1 ; python_version >= "3.8" and python_version < "3.9"
urllib3==2.0.4 ; python_version >= "3.8" and python_version < "4.0"
wcwidth==0.2.6 ; python_version >= "3.8" and python_version < "4.0"
typing-extensions==4.9.0 ; python_version >= "3.8" and python_version < "3.9"
urllib3==2.1.0 ; python_version >= "3.8" and python_version < "4.0"
wcwidth==0.2.13 ; python_version >= "3.8" and python_version < "4.0"
wget==3.2 ; python_version >= "3.8" and python_version < "4.0"
128 changes: 128 additions & 0 deletions tests/devices/coros/test_coros_pace_2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
from datetime import datetime, timedelta

import pytest
from dateutil import parser

import wearipedia


@pytest.mark.parametrize("real", [True, False])
def test_coros_pace_2_synthetic(real):
start_dates = [datetime(2009, 11, 30), datetime(2021, 4, 4), datetime(2022, 6, 10)]
end_dates = [datetime(2009, 12, 1), datetime(2021, 4, 5), datetime(2022, 6, 11)]

for start_date, end_date in zip(start_dates, end_dates):
device = wearipedia.get_device(
"coros/coros_pace_2",
synthetic_start_date=datetime.strftime(start_date, "%Y-%m-%d"),
synthetic_end_date=datetime.strftime(end_date, "%Y-%m-%d"),
)

if real:
wearipedia._authenticate_device("coros/coros_pace_2", device)

helper_test(device, start_date, end_date, real)


def helper_test(device, start_synthetic, end_synthetic, real):
sleep = device.get_data(
"sleep",
params={
"start_date": datetime.strftime(start_synthetic, "%Y-%m-%d"),
"end_date": datetime.strftime(end_synthetic, "%Y-%m-%d"),
},
)

steps = device.get_data(
"steps",
params={
"start_date": datetime.strftime(start_synthetic, "%Y-%m-%d"),
"end_date": datetime.strftime(end_synthetic, "%Y-%m-%d"),
},
)
exercise_time = device.get_data(
"exercise_time",
params={
"start_date": datetime.strftime(start_synthetic, "%Y-%m-%d"),
"end_date": datetime.strftime(end_synthetic, "%Y-%m-%d"),
},
)
heart_rate = device.get_data(
"heart_rate",
params={
"start_date": datetime.strftime(start_synthetic, "%Y-%m-%d"),
"end_date": datetime.strftime(end_synthetic, "%Y-%m-%d"),
},
)
sports = device.get_data(
"sports",
params={
"start_date": datetime.strftime(start_synthetic, "%Y-%m-%d"),
"end_date": datetime.strftime(end_synthetic, "%Y-%m-%d"),
},
)
active_energy = device.get_data(
"active_energy",
params={
"start_date": datetime.strftime(start_synthetic, "%Y-%m-%d"),
"end_date": datetime.strftime(end_synthetic, "%Y-%m-%d"),
},
)

sleep_arr = []
for ele in sleep:
sleep_time = ele["data"]["statisticData"]["dayDataList"][0]["sleepData"][
"totalSleepTime"
]
assert (
sleep_time < 1440
), f"Sleep time should be less than 1440 minutes but was {sleep_time}"
sleep_arr.append(sleep_time)
assert len(sleep_arr) > 0, "No sleep data found"

steps_arr = []
for ele in steps:
step_count = ele["data"]["statisticData"]["dayDataList"][0]["step"]
assert (
step_count < 100000
), f"Step count should be less than 100000 but was {step_count}"
steps_arr.append(step_count)
assert len(steps_arr) > 0, "No step data found"

exercise_time_arr = []
for ele in exercise_time:
exercise_duration = ele["data"]["statisticData"]["dayDataList"][0]["motionTime"]
assert (
exercise_duration < 1440
), f"Exercise duration should be less than 1440 minutes but was {exercise_duration}"
exercise_time_arr.append(exercise_duration)
assert len(exercise_time_arr) > 0, "No exercise time data found"

heart_rate_arr = []
for ele in heart_rate:
avg_heart_rate = ele["data"]["statisticData"]["dayDataList"][0][
"heartRateData"
]["avgHeartRate"]
assert (
avg_heart_rate < 121
), f"Avg. heart rate should be less than 121 but was {avg_heart_rate}"
heart_rate_arr.append(avg_heart_rate)
assert len(heart_rate_arr) > 0, "No heart rate data found"

sports_arr = []
for ele in sports:
duration = ele["data"][0]["duration"]
assert (
duration < 1440
), f"Sports duration should be less than 1440 minutes but was {duration}"
sports_arr.append(duration)
assert len(sports_arr) > 0, "No sports data found"

active_energy_arr = []
for ele in active_energy:
calorie_count = ele["data"]["statisticData"]["dayDataList"][0]["calorie"]
assert (
calorie_count < 10000
), f"Calorie count should be less than 10000 but was {calorie_count}"
active_energy_arr.append(calorie_count)
assert len(active_energy_arr) > 0, "No active energy data found"
138 changes: 138 additions & 0 deletions tests/devices/fitbit/test_fitbit_charge_4.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
from datetime import datetime, timedelta

import pytest
from dateutil import parser

import wearipedia


@pytest.mark.parametrize("real", [True, False])
def test_fitbit_charge_4_synthetic(real):
start_dates = [datetime(2009, 11, 30), datetime(2021, 4, 4), datetime(2022, 6, 10)]
end_dates = [datetime(2009, 12, 1), datetime(2021, 4, 5), datetime(2022, 6, 11)]

for start_date, end_date in zip(start_dates, end_dates):
device = wearipedia.get_device(
"fitbit/fitbit_charge_4",
synthetic_start_date=datetime.strftime(start_date, "%Y-%m-%d"),
synthetic_end_date=datetime.strftime(end_date, "%Y-%m-%d"),
)

if real:
wearipedia._authenticate_device("fitbit/fitbit_charge_4", device)

helper_test(device, start_date, end_date, real)


def helper_test(device, start_synthetic, end_synthetic, real):
sleep = device.get_data(
"sleep",
params={
"start_date": datetime.strftime(start_synthetic, "%Y-%m-%d"),
"end_date": datetime.strftime(end_synthetic, "%Y-%m-%d"),
},
)

steps = device.get_data(
"steps",
params={
"start_date": datetime.strftime(start_synthetic, "%Y-%m-%d"),
"end_date": datetime.strftime(end_synthetic, "%Y-%m-%d"),
},
)
minutesVeryActive = device.get_data(
"minutesVeryActive",
params={
"start_date": datetime.strftime(start_synthetic, "%Y-%m-%d"),
"end_date": datetime.strftime(end_synthetic, "%Y-%m-%d"),
},
)
minutesLightlyActive = device.get_data(
"minutesLightlyActive",
params={
"start_date": datetime.strftime(start_synthetic, "%Y-%m-%d"),
"end_date": datetime.strftime(end_synthetic, "%Y-%m-%d"),
},
)
minutesFairlyActive = device.get_data(
"minutesFairlyActive",
params={
"start_date": datetime.strftime(start_synthetic, "%Y-%m-%d"),
"end_date": datetime.strftime(end_synthetic, "%Y-%m-%d"),
},
)
distance = device.get_data(
"distance",
params={
"start_date": datetime.strftime(start_synthetic, "%Y-%m-%d"),
"end_date": datetime.strftime(end_synthetic, "%Y-%m-%d"),
},
)
minutesSedentary = device.get_data(
"minutesSedentary",
params={
"start_date": datetime.strftime(start_synthetic, "%Y-%m-%d"),
"end_date": datetime.strftime(end_synthetic, "%Y-%m-%d"),
},
)
minutesAsleep = []
for datapoint in sleep:
minutesAsleep.append(datapoint["minutesAsleep"])
assert len(minutesAsleep) >= 1, "Number of sleep data points should be at least 1"
assert (
sum(minutesAsleep) / len(minutesAsleep) < 800
), f"Average minutes asleep should be less than 800 but was {sum(minutesAsleep) / len(minutesAsleep)}"

steps_arr = []
for datapoint in steps:
steps_arr.append(datapoint["value"])
assert len(steps_arr) >= 1, "Number of steps data points should be at least 1"
assert (
sum(steps_arr) / len(steps_arr) < 20000
), f"Average steps should be less than 20000 but was {sum(steps_arr) / len(steps_arr)}"

light = []
for datapoint in minutesLightlyActive:
light.append(datapoint["value"])
assert (
datapoint["value"] < 1440
), f"Value should be less than 1440 but was {datapoint['value']}"
assert len(light) >= 1, "Number of light activity data points should be at least 1"

fair = []
for datapoint in minutesFairlyActive:
fair.append(datapoint["value"])
assert (
datapoint["value"] < 1440
), f"Value should be less than 1440 but was {datapoint['value']}"
assert (
len(fair) >= 1
), "Number of fairly active minutes data points should be at least 1"

very = []
for datapoint in minutesVeryActive:
very.append(datapoint["value"])
assert (
datapoint["value"] < 1440
), f"Value should be less than 1440 but was {datapoint['value']}"
assert (
len(very) >= 1
), "Number of very active minutes data points should be at least 1"

sedentary = []
for datapoint in minutesSedentary:
sedentary.append(datapoint["value"])
assert (
datapoint["value"] < 1440
), f"Value should be less than 1440 but was {datapoint['value']}"
assert (
len(sedentary) >= 1
), "Number of sedentary minutes data points should be at least 1"

distance_arr = []
for datapoint in distance:
distance_arr.append(datapoint["value"])
assert (
sum(distance_arr) / len(distance_arr) < 30
), f"Average distance should be less than 30 but was {sum(distance_arr) / len(distance_arr)}"
assert len(distance_arr) >= 1, "Number of distance data points should be at least 1"
Loading

0 comments on commit d4f33c7

Please sign in to comment.