Skip to content

Commit 4f6ca91

Browse files
committed
reordered imports
for some reason black duplicated the entire script twice. cleaned up hopefully this time.
1 parent c2e3d31 commit 4f6ca91

File tree

1 file changed

+1
-282
lines changed

1 file changed

+1
-282
lines changed

examples/requests_api_fitbit.py

Lines changed: 1 addition & 282 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44

55
import os
66
import time
7-
import microcontroller
87
import ssl
98
import wifi
109
import socketpool
10+
import microcontroller
1111
import adafruit_requests
1212

1313
# Initialize WiFi Pool (There can be only 1 pool & top of script)
@@ -310,284 +310,3 @@ def time_calc(input_time):
310310
time.sleep(60)
311311
continue
312312
time.sleep(sleep_time)
313-
314-
# Fitbit_ClientID = "YourAppClientID"
315-
# Fitbit_Token = "Long 256 character string (SHA-256)"
316-
# Fitbit_First_Refresh_Token = "64 character string"
317-
# Fitbit_UserID = "UserID authorizing the ClientID"
318-
319-
Fitbit_ClientID = os.getenv("Fitbit_ClientID")
320-
Fitbit_Token = os.getenv("Fitbit_Token")
321-
# overides nvm first run only
322-
Fitbit_First_Refresh_Token = os.getenv("Fitbit_First_Refresh_Token")
323-
Fitbit_UserID = os.getenv("Fitbit_UserID")
324-
325-
wifi_ssid = os.getenv("CIRCUITPY_WIFI_SSID")
326-
wifi_pw = os.getenv("CIRCUITPY_WIFI_PASSWORD")
327-
328-
# Time between API refreshes
329-
# 300 = 5 mins, 900 = 15 mins, 1800 = 30 mins, 3600 = 1 hour
330-
sleep_time = 900
331-
332-
333-
# Converts seconds in minutes/hours/days
334-
def time_calc(input_time):
335-
if input_time < 60:
336-
sleep_int = input_time
337-
time_output = f"{sleep_int:.0f} seconds"
338-
elif 60 <= input_time < 3600:
339-
sleep_int = input_time / 60
340-
time_output = f"{sleep_int:.0f} minutes"
341-
elif 3600 <= input_time < 86400:
342-
sleep_int = input_time / 60 / 60
343-
time_output = f"{sleep_int:.1f} hours"
344-
else:
345-
sleep_int = input_time / 60 / 60 / 24
346-
time_output = f"{sleep_int:.1f} days"
347-
return time_output
348-
349-
350-
# Authenticates Client ID & SHA-256 Token to POST
351-
fitbit_oauth_header = {"Content-Type": "application/x-www-form-urlencoded"}
352-
fitbit_oauth_token = "https://api.fitbit.com/oauth2/token"
353-
354-
# Connect to Wi-Fi
355-
print("\n===============================")
356-
print("Connecting to WiFi...")
357-
requests = adafruit_requests.Session(pool, ssl.create_default_context())
358-
while not wifi.radio.ipv4_address:
359-
try:
360-
wifi.radio.connect(wifi_ssid, wifi_pw)
361-
except ConnectionError as e:
362-
print("Connection Error:", e)
363-
print("Retrying in 10 seconds")
364-
time.sleep(10)
365-
print("Connected!\n")
366-
367-
# First run uses settings.toml token
368-
Refresh_Token = Fitbit_First_Refresh_Token
369-
370-
if debug:
371-
print(f"Top NVM Again (just to make sure): {top_nvm}")
372-
print(f"Settings.toml Initial Refresh Token: {Fitbit_First_Refresh_Token}")
373-
374-
while True:
375-
# Use Settings.toml refresh token on first run
376-
if top_nvm != Fitbit_First_Refresh_Token:
377-
Refresh_Token = microcontroller.nvm[0:64].decode()
378-
if debug:
379-
# NVM 64 should match Current Refresh Token
380-
print(f"NVM 64: {microcontroller.nvm[0:64].decode()}")
381-
print(f"Current Refresh_Token: {Refresh_Token}")
382-
else:
383-
if debug:
384-
# First run use settings.toml refresh token instead
385-
print(f"Initial_Refresh_Token: {Refresh_Token}")
386-
387-
try:
388-
if debug:
389-
print("\n-----Token Refresh POST Attempt -------")
390-
fitbit_oauth_refresh_token = (
391-
"&grant_type=refresh_token"
392-
+ "&client_id="
393-
+ str(Fitbit_ClientID)
394-
+ "&refresh_token="
395-
+ str(Refresh_Token)
396-
)
397-
398-
# ----------------------------- POST FOR REFRESH TOKEN -----------------------
399-
if debug:
400-
print(
401-
f"FULL REFRESH TOKEN POST:{fitbit_oauth_token}"
402-
+ f"{fitbit_oauth_refresh_token}"
403-
)
404-
print(f"Current Refresh Token: {Refresh_Token}")
405-
# TOKEN REFRESH POST
406-
fitbit_oauth_refresh_POST = requests.post(
407-
url=fitbit_oauth_token,
408-
data=fitbit_oauth_refresh_token,
409-
headers=fitbit_oauth_header,
410-
)
411-
try:
412-
fitbit_refresh_oauth_json = fitbit_oauth_refresh_POST.json()
413-
414-
fitbit_new_token = fitbit_refresh_oauth_json["access_token"]
415-
if debug:
416-
print("Your Private SHA-256 Token: ", fitbit_new_token)
417-
fitbit_access_token = fitbit_new_token # NEW FULL TOKEN
418-
419-
# If current token valid will respond
420-
fitbit_new_refesh_token = fitbit_refresh_oauth_json["refresh_token"]
421-
Refresh_Token = fitbit_new_refesh_token
422-
fitbit_token_expiration = fitbit_refresh_oauth_json["expires_in"]
423-
fitbit_scope = fitbit_refresh_oauth_json["scope"]
424-
fitbit_token_type = fitbit_refresh_oauth_json["token_type"]
425-
fitbit_user_id = fitbit_refresh_oauth_json["user_id"]
426-
if debug:
427-
print("Next Refresh Token: ", Refresh_Token)
428-
429-
# Store Next Token into NVM
430-
try:
431-
nvmtoken = b"" + fitbit_new_refesh_token
432-
microcontroller.nvm[0:64] = nvmtoken
433-
if debug:
434-
print(f"Next Token for NVM: {nvmtoken.decode()}")
435-
print("Next token written to NVM Successfully!")
436-
except OSError as e:
437-
print("OS Error:", e)
438-
continue
439-
440-
if debug:
441-
# Extraneous token data for debugging
442-
print("Token Expires in: ", time_calc(fitbit_token_expiration))
443-
print("Scope: ", fitbit_scope)
444-
print("Token Type: ", fitbit_token_type)
445-
print("UserID: ", fitbit_user_id)
446-
447-
except KeyError as e:
448-
print("Key Error:", e)
449-
print("Expired token, invalid permission, or (key:value) pair error.")
450-
time.sleep(300)
451-
continue
452-
453-
# ----------------------------- GET DATA -------------------------------------
454-
# POST should respond with current & next refresh token we can GET for data
455-
# 64-bit Refresh tokens will "keep alive" SHA-256 token indefinitely
456-
# Fitbit main SHA-256 token expires in 8 hours unless refreshed!
457-
# ----------------------------------------------------------------------------
458-
detail_level = "1min" # Supported: 1sec | 1min | 5min | 15min
459-
requested_date = "today" # Date format yyyy-MM-dd or today
460-
fitbit_header = {
461-
"Authorization": "Bearer " + fitbit_access_token + "",
462-
"Client-Id": "" + Fitbit_ClientID + "",
463-
}
464-
# Heart Intraday Scope
465-
FITBIT_SOURCE = (
466-
"https://api.fitbit.com/1/user/"
467-
+ Fitbit_UserID
468-
+ "/activities/heart/date/today"
469-
+ "/1d/"
470-
+ detail_level
471-
+ ".json"
472-
)
473-
474-
print("\nAttempting to GET FITBIT Stats!")
475-
print("===============================")
476-
fitbit_get_response = requests.get(url=FITBIT_SOURCE, headers=fitbit_header)
477-
try:
478-
fitbit_json = fitbit_get_response.json()
479-
intraday_response = fitbit_json["activities-heart-intraday"]["dataset"]
480-
except ConnectionError as e:
481-
print("Connection Error:", e)
482-
print("Retrying in 10 seconds")
483-
484-
if debug:
485-
print(f"Full API GET URL: {FITBIT_SOURCE}")
486-
print(f"Header: {fitbit_header}")
487-
# print(f"JSON Full Response: {fitbit_json}")
488-
print(f"Intraday Full Response: {intraday_response}")
489-
490-
try:
491-
# Fitbit's sync to your mobile device & server every 15 minutes in chunks.
492-
# Pointless to poll their API faster than 15 minute intervals.
493-
activities_heart_value = fitbit_json["activities-heart-intraday"]["dataset"]
494-
response_length = len(activities_heart_value)
495-
if response_length >= 15:
496-
activities_timestamp = fitbit_json["activities-heart"][0]["dateTime"]
497-
print(f"Fitbit Date: {activities_timestamp}")
498-
activities_latest_heart_time = fitbit_json["activities-heart-intraday"][
499-
"dataset"
500-
][response_length - 1]["time"]
501-
print(f"Fitbit Time: {activities_latest_heart_time[0:-3]}")
502-
print(f"Today's Logged Pulses : {response_length}")
503-
504-
# Each 1min heart rate is a 60 second average
505-
activities_latest_heart_value0 = fitbit_json[
506-
"activities-heart-intraday"
507-
]["dataset"][response_length - 1]["value"]
508-
activities_latest_heart_value1 = fitbit_json[
509-
"activities-heart-intraday"
510-
]["dataset"][response_length - 2]["value"]
511-
activities_latest_heart_value2 = fitbit_json[
512-
"activities-heart-intraday"
513-
]["dataset"][response_length - 3]["value"]
514-
activities_latest_heart_value3 = fitbit_json[
515-
"activities-heart-intraday"
516-
]["dataset"][response_length - 4]["value"]
517-
activities_latest_heart_value4 = fitbit_json[
518-
"activities-heart-intraday"
519-
]["dataset"][response_length - 5]["value"]
520-
activities_latest_heart_value5 = fitbit_json[
521-
"activities-heart-intraday"
522-
]["dataset"][response_length - 6]["value"]
523-
activities_latest_heart_value6 = fitbit_json[
524-
"activities-heart-intraday"
525-
]["dataset"][response_length - 7]["value"]
526-
activities_latest_heart_value7 = fitbit_json[
527-
"activities-heart-intraday"
528-
]["dataset"][response_length - 8]["value"]
529-
activities_latest_heart_value8 = fitbit_json[
530-
"activities-heart-intraday"
531-
]["dataset"][response_length - 9]["value"]
532-
activities_latest_heart_value9 = fitbit_json[
533-
"activities-heart-intraday"
534-
]["dataset"][response_length - 10]["value"]
535-
activities_latest_heart_value10 = fitbit_json[
536-
"activities-heart-intraday"
537-
]["dataset"][response_length - 11]["value"]
538-
activities_latest_heart_value11 = fitbit_json[
539-
"activities-heart-intraday"
540-
]["dataset"][response_length - 12]["value"]
541-
activities_latest_heart_value12 = fitbit_json[
542-
"activities-heart-intraday"
543-
]["dataset"][response_length - 13]["value"]
544-
activities_latest_heart_value13 = fitbit_json[
545-
"activities-heart-intraday"
546-
]["dataset"][response_length - 14]["value"]
547-
activities_latest_heart_value14 = fitbit_json[
548-
"activities-heart-intraday"
549-
]["dataset"][response_length - 15]["value"]
550-
551-
print(
552-
f"{latest_15_avg}"
553-
+ f"{activities_latest_heart_value14},"
554-
+ f"{activities_latest_heart_value13},"
555-
+ f"{activities_latest_heart_value12},"
556-
+ f"{activities_latest_heart_value11},"
557-
+ f"{activities_latest_heart_value10},"
558-
+ f"{activities_latest_heart_value9},"
559-
+ f"{activities_latest_heart_value8},"
560-
+ f"{activities_latest_heart_value7},"
561-
+ f"{activities_latest_heart_value6},"
562-
+ f"{activities_latest_heart_value5},"
563-
+ f"{activities_latest_heart_value4},"
564-
+ f"{activities_latest_heart_value3},"
565-
+ f"{activities_latest_heart_value2},"
566-
+ f"{activities_latest_heart_value1},"
567-
+ f"{activities_latest_heart_value0}"
568-
)
569-
else:
570-
print("Waiting for latest 15 values sync...")
571-
print("Not enough values for today to display yet.")
572-
print("No display from midnight to 00:15")
573-
574-
except KeyError as keyerror:
575-
print(f"Key Error: {keyerror}")
576-
print(
577-
"Too Many Requests, "
578-
+ "Expired token, "
579-
+ "invalid permission, or "
580-
+ "(key:value) pair error."
581-
)
582-
continue
583-
584-
print("Board Uptime: ", time_calc(time.monotonic())) # Board Up-Time seconds
585-
print("\nFinished!")
586-
print("Next Update in: ", time_calc(sleep_time))
587-
print("===============================")
588-
589-
except (ValueError, RuntimeError) as e:
590-
print("Failed to get data, retrying\n", e)
591-
time.sleep(60)
592-
continue
593-
time.sleep(sleep_time)

0 commit comments

Comments
 (0)