Skip to content

Commit c2e3d31

Browse files
committed
reformatted too long strings and unnecessary f-strings with Mu & Black
1 parent 2f8fcc1 commit c2e3d31

File tree

1 file changed

+310
-9
lines changed

1 file changed

+310
-9
lines changed

examples/requests_api_fitbit.py

Lines changed: 310 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
# Coded for Circuit Python 8.2
44

55
import os
6-
import board
76
import time
87
import microcontroller
98
import ssl
@@ -91,6 +90,7 @@ def time_calc(input_time):
9190
print(f"Top NVM Again (just to make sure): {top_nvm}")
9291
print(f"Settings.toml Initial Refresh Token: {Fitbit_First_Refresh_Token}")
9392

93+
latest_15_avg = "Latest 15 Minute Averages"
9494
while True:
9595
# Use Settings.toml refresh token on first run
9696
if top_nvm != Fitbit_First_Refresh_Token:
@@ -118,7 +118,8 @@ def time_calc(input_time):
118118
# ----------------------------- POST FOR REFRESH TOKEN -----------------------
119119
if debug:
120120
print(
121-
f"FULL REFRESH TOKEN POST:{fitbit_oauth_token}{fitbit_oauth_refresh_token}"
121+
f"FULL REFRESH TOKEN POST:{fitbit_oauth_token}"
122+
+ f"{fitbit_oauth_refresh_token}"
122123
)
123124
print(f"Current Refresh Token: {Refresh_Token}")
124125
# TOKEN REFRESH POST
@@ -151,7 +152,7 @@ def time_calc(input_time):
151152
microcontroller.nvm[0:64] = nvmtoken
152153
if debug:
153154
print(f"Next Token for NVM: {nvmtoken.decode()}")
154-
print(f"Next token written to NVM Successfully!")
155+
print("Next token written to NVM Successfully!")
155156
except OSError as e:
156157
print("OS Error:", e)
157158
continue
@@ -195,6 +196,7 @@ def time_calc(input_time):
195196
fitbit_get_response = requests.get(url=FITBIT_SOURCE, headers=fitbit_header)
196197
try:
197198
fitbit_json = fitbit_get_response.json()
199+
intraday_response = fitbit_json["activities-heart-intraday"]["dataset"]
198200
except ConnectionError as e:
199201
print("Connection Error:", e)
200202
print("Retrying in 10 seconds")
@@ -203,7 +205,7 @@ def time_calc(input_time):
203205
print(f"Full API GET URL: {FITBIT_SOURCE}")
204206
print(f"Header: {fitbit_header}")
205207
# print(f"JSON Full Response: {fitbit_json}")
206-
# print(f"Intraday Full Response: {fitbit_json["activities-heart-intraday"]["dataset"]}")
208+
# print(f"Intraday Full Response: {intraday_response}")
207209

208210
try:
209211
# Fitbit's sync to your mobile device & server every 15 minutes in chunks.
@@ -265,18 +267,317 @@ def time_calc(input_time):
265267
activities_latest_heart_value14 = fitbit_json[
266268
"activities-heart-intraday"
267269
]["dataset"][response_length - 15]["value"]
270+
latest_15_avg = "Latest 15 Minute Averages"
268271
print(
269-
f"Latest 15 Minute Averages: {activities_latest_heart_value14},{activities_latest_heart_value13},{activities_latest_heart_value12},{activities_latest_heart_value11},{activities_latest_heart_value10},{activities_latest_heart_value9},{activities_latest_heart_value8},{activities_latest_heart_value7},{activities_latest_heart_value6},{activities_latest_heart_value5},{activities_latest_heart_value4},{activities_latest_heart_value3},{activities_latest_heart_value2},{activities_latest_heart_value1},{activities_latest_heart_value0}"
272+
f"{latest_15_avg}"
273+
+ f"{activities_latest_heart_value14},"
274+
+ f"{activities_latest_heart_value13},"
275+
+ f"{activities_latest_heart_value12},"
276+
+ f"{activities_latest_heart_value11},"
277+
+ f"{activities_latest_heart_value10},"
278+
+ f"{activities_latest_heart_value9},"
279+
+ f"{activities_latest_heart_value8},"
280+
+ f"{activities_latest_heart_value7},"
281+
+ f"{activities_latest_heart_value6},"
282+
+ f"{activities_latest_heart_value5},"
283+
+ f"{activities_latest_heart_value4},"
284+
+ f"{activities_latest_heart_value3},"
285+
+ f"{activities_latest_heart_value2},"
286+
+ f"{activities_latest_heart_value1},"
287+
+ f"{activities_latest_heart_value0}"
270288
)
271289
else:
272-
print(f"Waiting for latest 15 values sync...")
273-
print(f"Not enough values for today to display yet.")
274-
print(f"No display from midnight to 00:15")
290+
print("Waiting for latest 15 values sync...")
291+
print("Not enough values for today to display yet.")
292+
print("No display from midnight to 00:15")
275293

276294
except KeyError as keyerror:
277295
print(f"Key Error: {keyerror}")
278296
print(
279-
f"Too Many Requests, Expired token, invalid permission, or (key:value) pair error."
297+
"Too Many Requests, Expired token,"
298+
+ "invalid permission,"
299+
+ "or (key:value) pair error."
300+
)
301+
continue
302+
303+
print("Board Uptime: ", time_calc(time.monotonic())) # Board Up-Time seconds
304+
print("\nFinished!")
305+
print("Next Update in: ", time_calc(sleep_time))
306+
print("===============================")
307+
308+
except (ValueError, RuntimeError) as e:
309+
print("Failed to get data, retrying\n", e)
310+
time.sleep(60)
311+
continue
312+
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."
280581
)
281582
continue
282583

0 commit comments

Comments
 (0)