-
-
Notifications
You must be signed in to change notification settings - Fork 263
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
150 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
r""" | ||
Display glucose readings from your Dexcom CGM system. | ||
Dexcom CGM systems provide glucose readings up to every five minutes, all with | ||
zero fingersticks required for calibration or mealtime dosing. Designed to help | ||
diabetes patients keep track of their blood glucose levels with ease. | ||
Configuration parameters: | ||
format: display format for this module | ||
*(default "Dexcom [\?color=mg_dl {mg_dl} mg/dL {trend_arrow}] [\?color=darkgrey {datetime}]")* | ||
format_datetime: specify strftime characters to format (default {"datetime": "%-I:%M %p"}) | ||
ous: specify whether if the Dexcom Share user is outside of the US (default False) | ||
password: specify password for the Dexcom Share user (default None) | ||
user: specify username for the Dexcom Share user, not follower (default None) | ||
thresholds: specify color thresholds to use | ||
*(default { | ||
"mg_dl": [(55, "bad"), (70, "degraded"), (80, "good"), (130, "degraded"), (180, "bad")], | ||
"mmol_l": [(3.1, "bad"), (3.9, "degraded"), (4.4, "good"), (7.2, "degraded"), (10.0, "bad")], | ||
})* | ||
Format placeholders: | ||
{mg_dl} blood glucose value in mg/dL, eg 80 | ||
{mmol_l} blood glucose value in mmol/L, eg 4.4 | ||
{trend} blood glucose trend information, eg 4 | ||
{trend_direction} blood glucose trend direction, eg Flat | ||
{trend_description} blood glucose trend information description, eg steady | ||
{trend_arrow} blood glucose trend as unicode arrow, eg → | ||
{datetime} glucose reading recorded time as datetime | ||
format_datetime placeholders: | ||
key: epoch_placeholder, eg {datetime} | ||
value: % strftime characters to be translated, eg '%b %d' ----> 'Jan 1' | ||
Color thresholds: | ||
xxx: print a color based on the value of `xxx` placeholder | ||
Requires: | ||
pydexcom: A simple Python API to interact with Dexcom Share service | ||
Note: | ||
IF GLUCOSE ALERTS AND CGM READINGS DO NOT MATCH SYMPTOMS OR EXPECTATIONS, | ||
USE A BLOOD GLUCOSE METER TO MAKE DIABETES TREATMENT DECISIONS. | ||
Examples: | ||
``` | ||
# compact | ||
dexcom { | ||
format = "\?color=darkgrey [\?color=mg_dl {mg_dl} {trend_arrow}] {datetime}" | ||
format_datetime = {"datetime": "%-I:%M"} | ||
} | ||
``` | ||
@author lasers | ||
SAMPLE OUTPUT | ||
[ | ||
{"full_text": "Dexcom "}, | ||
{"full_text": "80 mg/dL →", "color": "#00FF00"}, | ||
{"full_text": "7:15 PM", "color": "#A9A9A9"} | ||
] | ||
""" | ||
|
||
from pydexcom import Dexcom | ||
from datetime import datetime as dt, timedelta as td | ||
|
||
|
||
class Py3status: | ||
""" """ | ||
|
||
# available configuration parameters | ||
format = r"Dexcom [\?color=mg_dl {mg_dl} mg/dL {trend_arrow}] [\?color=darkgrey {datetime}]" | ||
format_datetime = {"datetime": "%-I:%M %p"} | ||
ous = False | ||
password = None | ||
thresholds = { | ||
"mg_dl": [ | ||
(55, "bad"), | ||
(70, "degraded"), | ||
(80, "good"), | ||
(130, "degraded"), | ||
(180, "bad"), | ||
], | ||
"mmol_l": [ | ||
(3.1, "bad"), | ||
(3.9, "degraded"), | ||
(4.4, "good"), | ||
(7.2, "degraded"), | ||
(10.0, "bad"), | ||
], | ||
} | ||
user = None | ||
|
||
def post_config_hook(self): | ||
for x in ["user", "password"]: | ||
if not getattr(self, x): | ||
raise Exception(f"missing {x}") | ||
|
||
# fmt: off | ||
self.placeholders = [ | ||
"datetime", "mg_dl", "mmol_l", "trend", "trend_arrow", "trend_description", "trend_direction", | ||
] | ||
# fmt: on | ||
|
||
self.init = {"datetimes": []} | ||
for word in ["datetime"]: | ||
if self.py3.format_contains(self.format, word) and word in self.format_datetime: | ||
self.init["datetimes"].append(word) | ||
|
||
self.thresholds_init = self.py3.get_color_names_list(self.format) | ||
self.dexcom_class = Dexcom(self.user, self.password, ous=self.ous) | ||
|
||
def _get_dexcom_data(self): | ||
glucose_reading = self.dexcom_class.get_current_glucose_reading() | ||
data = {x: getattr(glucose_reading, x) for x in self.placeholders} | ||
data["datetime"] = data["datetime"].isoformat() | ||
return data | ||
|
||
def _get_cached_until(self, data): | ||
timestamp = dt.fromisoformat(data["datetime"]) | ||
return ((timestamp + td(minutes=5, seconds=5)) - dt.today()).total_seconds() | ||
|
||
def dexcom(self): | ||
dexcom_data = self._get_dexcom_data() | ||
cached_until = self._get_cached_until(dexcom_data) | ||
|
||
for word in self.init["datetimes"]: | ||
if word in dexcom_data: | ||
tmp_str = dt.strftime( | ||
dt.fromisoformat(dexcom_data[word]), self.format_datetime[word] | ||
) | ||
dexcom_data[word] = self.py3.safe_format(tmp_str) | ||
|
||
for x in self.thresholds_init: | ||
if x in dexcom_data: | ||
self.py3.threshold_get_color(dexcom_data[x], x) | ||
|
||
return { | ||
"cached_until": self.py3.time_in(cached_until), | ||
"full_text": self.py3.safe_format(self.format, dexcom_data), | ||
} | ||
|
||
|
||
if __name__ == "__main__": | ||
""" | ||
Run module in test mode. | ||
""" | ||
from py3status.module_test import module_test | ||
|
||
module_test(Py3status) |