This is what practical use of Programming looks like. Not just building front-end and back-end apps and services but manifesting ideas into something real which can improve and help people's daily lives. Kudos.
Thank you so much for these videos. It's an enormous timesaver for me to just see how some things are set up. I love research, and often get lost in it, but sometimes I need to move along quickly.
Hi Scott. I found your channel about a month ago when I was looking to learn C#. Love your videos. Thank you for explaining everything so clearly to us!🙂 I think inorder to change the colour you need, try to create a function with the group.append (line 95) and call it when your blood sugar is higher than 200. But remember to destroy the previous label created. This is one way to achieve this. OR By looking at this code it looks somewhat similar to tkinter python. There's a method called config in tkinter which lets you update labels, texts , canvas, frames on command. This might be useful if this type of method exists in circuit python or adafruit display library.
Hi Scott. I raised a PR some time ago suggesting VS Code put a serial terminal implementation into its core, but unfortunately I do not think the reviewer was an IOT type and did not get why we'd want such an antique! Some add-ins, including the CircuitPython one you mention here, add serial terminal functionality, but in my experience they are often problematic, perhaps because different implementations conflict. They work on some platforms but not others, or get broken when VS Code gets updated, or mysteriously fail when some other add-in is loaded. VS Code has other types of terminal/console implemented in its core and it seems natural to have the daddy of them all too!
Awesome video. I've been looking into those displays for messing around, too. Here are three opportunities for cleaning up the code - for learning purposes. I'm no expert either, but I do use Python just about every day. *First*, in the for loop where you're parsing the JSON, you create a dictionary "sugarDetails" and add the values to it, so you don't need the additional lines below - like setting sugarDetails["sgv"] = entry["svg"] because you already did it in the first line of the for loop. If you liked that style better, you could create an empty dictionary in the first line like sugarDetails = {} and then set each value below. But the real tip is you can use a list comprehension - it's a Python-specific thing (a bit more Pythonic) that'd replace the whole for loop and return a list from a list. sugarDetails = [{"sgv": x.get("sgv"), "date": x.get("date"), "direction": x.get("direction")...} for x in full_data] There are four parts of a list comprehension: 1. "x" - is just the element of the list (aka "entry" in your example). 2. full_data is the list you're looping over. 3. The first part is the transformation you're doing on "x" - in our case, making a new dictionary out of it. 4. There's also an optional part where you could say "[{x.get("date")} for x in full_data if x.get("date") == "2022-07-29")] - where you can add "if" after the list and then a conditional to pre-filter full_data any way you want. Side note 1: The list comprehension is generally a bit faster in my experience. Side note 2: I use x.get("key") in the list comprehension because it just returns None if the key doesn't exist. If you try to access the key with hard brackets - like x["key"], it'll throw an exception if the key doesn't exist - kind of like what you're trying to avoid later with the try/catch. And then a *second* thing you could do to make this a bit nicer - for the if/elif statement mapping strings to those icon constants, you could use a dictionary for the definition: # Mapping Strings to Icons arrowdict = {"Flat": RIGHTARROW, "FortyFiveUp": UPRIGHTARROW, "FortyFiveDown": DOWNRIGHTARROW"... etc} TEXTDIRECTION = arrowdict.get(SUGAR.sugarList[0]["direction"]) And the *third* thing... generally all-caps things are constants (and i referred to them as such). So, the "TEXTDIRECTION" would generally be lowercase or snake case - like "text_direction". Hope that's helpful and again, great video. Love your stuff.
Great video - makes me want to try new things! Circuit Python is a great newbie-friendly environment - just yet another example of Adafruit's unwavering commitment to good out of the box learning experiences. When I retire, I want to work there. :)
I like using the Adafruit RPi adapter for that panel, so I can program it in C#.. Then use VSCode to remotely program it. But that is overkill, I also like using ESP32s on them.
You could, for IoT’s sake just sleep 5 min every loop, but consider that you probably will end up with old data. Old as in up to 5 min. If you start the app just before your Dexcom uploads the new bg value, you will always be stuck out of sync. It’s imho better to calculate the timing based on the timestamp of the previous bg value. When the blood sugar moves fast, even a minute delay can feel like an eternity. Sry for ramblings galore.
So your measuring the mg/dl not the mmol/l? I was gonna say a sugar level of 82 is a medical emergency! My father was a type 1 for forty years had to do the prick test a few times a day and inject himself, diabetes is no joke
For making the URL string, Python 3 supports multiple kinds of string interpolation, so you can instead write, e.g: ```Python url = f'{NIGHTSCOUT}/api/v1/entries.json?count=5&token={TOKEN}' ``` The `for _ in range(1)` loop seems like it can be eliminated since it will only run once. (list(range(1)) == [0]) The dictionary literal assignment in line 59 vs assigning one field at a time in lines 60-63 seems redundant but I could be misreading/misunderstanding. The CURRENTDIRECTION -> TEXTDIRECTION assignment block at lines 161-174 could be replaced with a dictionary and a lookup: ```Python current_to_text_direction = { 'Flat': RIGHTARROW, 'FourtyFiveUp': UPRIGHTARROW, ... } TEXTDIRECTION = current_to_text_direction[CURRENTDIRECTION] ``` And you'd want variables to be lower case with constants upper case. A style checker like black can flag these automatically. However, it doesn't really matter here. It's a small script and these issues are easily fixed. I can still see what the code is doing and why just fine. Making the device do something useful in a way that is hackable (can be modified/tinkered with) is much more important than style issues.
This is what practical use of Programming looks like. Not just building front-end and back-end apps and services but manifesting ideas into something real which can improve and help people's daily lives. Kudos.
Thank you so much for these videos. It's an enormous timesaver for me to just see how some things are set up. I love research, and often get lost in it, but sometimes I need to move along quickly.
Always enjoyed your newsletters. Chefs kiss to you providing video content as well.
Hi Scott.
I found your channel about a month ago when I was looking to learn C#. Love your videos. Thank you for explaining everything so clearly to us!🙂
I think inorder to change the colour you need, try to create a function with the group.append (line 95) and call it when your blood sugar is higher than 200. But remember to destroy the previous label created. This is one way to achieve this.
OR
By looking at this code it looks somewhat similar to tkinter python. There's a method called config in tkinter which lets you update labels, texts , canvas, frames on command. This might be useful if this type of method exists in circuit python or adafruit display library.
Nice of you to show how you're learning! Reminds me a lot of how I mess around with C# 🙂.
Hi Scott. I raised a PR some time ago suggesting VS Code put a serial terminal implementation into its core, but unfortunately I do not think the reviewer was an IOT type and did not get why we'd want such an antique! Some add-ins, including the CircuitPython one you mention here, add serial terminal functionality, but in my experience they are often problematic, perhaps because different implementations conflict. They work on some platforms but not others, or get broken when VS Code gets updated, or mysteriously fail when some other add-in is loaded. VS Code has other types of terminal/console implemented in its core and it seems natural to have the daddy of them all too!
Awesome video. I've been looking into those displays for messing around, too.
Here are three opportunities for cleaning up the code - for learning purposes. I'm no expert either, but I do use Python just about every day.
*First*, in the for loop where you're parsing the JSON, you create a dictionary "sugarDetails" and add the values to it, so you don't need the additional lines below - like setting sugarDetails["sgv"] = entry["svg"] because you already did it in the first line of the for loop. If you liked that style better, you could create an empty dictionary in the first line like sugarDetails = {} and then set each value below. But the real tip is you can use a list comprehension - it's a Python-specific thing (a bit more Pythonic) that'd replace the whole for loop and return a list from a list.
sugarDetails = [{"sgv": x.get("sgv"), "date": x.get("date"), "direction": x.get("direction")...} for x in full_data]
There are four parts of a list comprehension:
1. "x" - is just the element of the list (aka "entry" in your example).
2. full_data is the list you're looping over.
3. The first part is the transformation you're doing on "x" - in our case, making a new dictionary out of it.
4. There's also an optional part where you could say "[{x.get("date")} for x in full_data if x.get("date") == "2022-07-29")] - where you can add "if" after the list and then a conditional to pre-filter full_data any way you want.
Side note 1: The list comprehension is generally a bit faster in my experience.
Side note 2: I use x.get("key") in the list comprehension because it just returns None if the key doesn't exist. If you try to access the key with hard brackets - like x["key"], it'll throw an exception if the key doesn't exist - kind of like what you're trying to avoid later with the try/catch.
And then a *second* thing you could do to make this a bit nicer - for the if/elif statement mapping strings to those icon constants, you could use a dictionary for the definition:
# Mapping Strings to Icons
arrowdict = {"Flat": RIGHTARROW, "FortyFiveUp": UPRIGHTARROW, "FortyFiveDown": DOWNRIGHTARROW"... etc}
TEXTDIRECTION = arrowdict.get(SUGAR.sugarList[0]["direction"])
And the *third* thing... generally all-caps things are constants (and i referred to them as such). So, the "TEXTDIRECTION" would generally be lowercase or snake case - like "text_direction".
Hope that's helpful and again, great video. Love your stuff.
Thanks so much!
Great video - makes me want to try new things! Circuit Python is a great newbie-friendly environment - just yet another example of Adafruit's unwavering commitment to good out of the box learning experiences. When I retire, I want to work there. :)
They are just lovely folks all around. I visited them google “Scott Hanselman visits adafruit” to see inside their warehouse!
@@shanselman it was one of my favorite Ask an Engineer episodes...my two favorite tech heroes (and hobbies) collided!
Hi Scott,
Which device are you using for CGM?
Love this working on an idea stumbled into this. Creativity is great
Thanks, "The World Okeyest Programmer." Amazing video
I like using the Adafruit RPi adapter for that panel, so I can program it in C#.. Then use VSCode to remotely program it. But that is overkill, I also like using ESP32s on them.
Very nice overview Scott!! 👍🏽
I have the same chair. Love it ! Nice video too :)
Great Video, but why all of the vars are in uppercase?
This looks like fun. Any chance you could provide links to the hardware you are using?
Woah, Scott this is super useful
You could, for IoT’s sake just sleep 5 min every loop, but consider that you probably will end up with old data. Old as in up to 5 min. If you start the app just before your Dexcom uploads the new bg value, you will always be stuck out of sync. It’s imho better to calculate the timing based on the timestamp of the previous bg value. When the blood sugar moves fast, even a minute delay can feel like an eternity.
Sry for ramblings galore.
Great advice!
So your measuring the mg/dl not the mmol/l? I was gonna say a sugar level of 82 is a medical emergency! My father was a type 1 for forty years had to do the prick test a few times a day and inject himself, diabetes is no joke
Lol yes, this is in mg/dl and it’s perfect
thanks for wonderful content and experience sharing
If you enjoy playing around take a look at ESP32 and Picio Pi... so much you can do
Does this have bluetooth
For making the URL string, Python 3 supports multiple kinds of string interpolation, so you can instead write, e.g:
```Python
url = f'{NIGHTSCOUT}/api/v1/entries.json?count=5&token={TOKEN}'
```
The `for _ in range(1)` loop seems like it can be eliminated since it will only run once. (list(range(1)) == [0])
The dictionary literal assignment in line 59 vs assigning one field at a time in lines 60-63 seems redundant but I could be misreading/misunderstanding.
The CURRENTDIRECTION -> TEXTDIRECTION assignment block at lines 161-174 could be replaced with a dictionary and a lookup:
```Python
current_to_text_direction = {
'Flat': RIGHTARROW,
'FourtyFiveUp': UPRIGHTARROW,
...
}
TEXTDIRECTION = current_to_text_direction[CURRENTDIRECTION]
```
And you'd want variables to be lower case with constants upper case. A style checker like black can flag these automatically.
However, it doesn't really matter here. It's a small script and these issues are easily fixed. I can still see what the code is doing and why just fine. Making the device do something useful in a way that is hackable (can be modified/tinkered with) is much more important than style issues.