pydexcom
A simple Python API to interact with Dexcom Share service. Used to get real-time Dexcom CGM sensor data.
Quickstart
- Download the Dexcom G6 / G5 / G4 mobile app and enable the Share service.
The Dexcom Share service requires setup of at least one follower to enable the share service, but pydexcom
will use your credentials, not the follower's
Install the
pydexcom
package.pip3 install pydexcom
Profit.
>>> from pydexcom import Dexcom
>>> dexcom = Dexcom("username", "password") # `ous=True` if outside of US
>>> glucose_reading = dexcom.get_current_glucose_reading()
>>> print(glucose_reading)
85
>>> glucose_reading.value
85
>>> glucose_reading.mmol_l
4.7
>>> glucose_reading.trend
4
>>> glucose_reading.trend_direction
'Flat'
>>> glucose_reading.trend_description
'steady'
>>> glucose_reading.trend_arrow
'→'
>>> print(bg.datetime)
2023-08-07 20:40:58
>>> glucose_reading.json
{'WT': 'Date(1691455258000)', 'ST': 'Date(1691455258000)', 'DT': 'Date(1691455258000-0400)', 'Value': 85, 'Trend': 'Flat'}
Documentation
https://gagebenne.github.io/pydexcom/pydexcom.html
Frequently Asked Questions
Why is my password not working?
The Dexcom Share API understandably reports limited information during account validation. If anything is incorrect, the API simply reports back invalid password (pydexcom.errors.AccountErrorEnum
). However, there could be many reasons you are getting this error:
- Use the correct Dexcom Share API instance.
If you are located outside of the United States, be sure to set ous=True
when intializing Dexcom
.
- Use your Dexcom Share credentials, not the follower's credentials.
Use the same credentials used to login to the Dexcom mobile application publishing the glucose readings.
- Ensure you have at least one follower on Dexcom Share.
The Dexcom Share service requires setup of at least one follower to enable the service, as does this package.
- Check whether your account credentials involve usernames or emails.
There are two account types the Dexcom Share API uses: legacy username-based accounts, and newer email-based accounts. Be sure to use the correct authentication method.
- Use alpha-numeric passwords.
Some individuals have had problems with connecting when their Dexcom Share passwords are entirely numeric. If you have connection issues, try changing your password to something with a mix of numbers and letters.
- Report it!
The Dexcom Share API sometimes changes. If you believe there is an issue with pydexcom
, feel free to create an issue if one has not been created yet already.
Why not use the official Dexcom Developer API?
The official Dexcom API is a great tool to view trends, statistics, and day-by-day data, but is not suitable for real time fetching of glucose readings as it is a retrospective API.
How can I let you know of suggestions or issues?
By all means submit a pull request if you have a feature you would like to see in the next release. Alternatively, you may create an issue if you have a suggestion or bug you'd like to report.
Where is this package being used?
Primarily this package is used in the Home Assistant Dexcom integration, but it's fantastic to see community projects involving pydexcom
:
1""" 2.. include:: ../README.md 3""" 4import logging 5import re 6from datetime import datetime 7from typing import Any, Dict, List, Optional 8 9import requests 10 11from .const import ( 12 DEFAULT_UUID, 13 DEXCOM_APPLICATION_ID, 14 DEXCOM_AUTHENTICATE_ENDPOINT, 15 DEXCOM_BASE_URL, 16 DEXCOM_BASE_URL_OUS, 17 DEXCOM_GLUCOSE_READINGS_ENDPOINT, 18 DEXCOM_LOGIN_ID_ENDPOINT, 19 DEXCOM_TREND_DIRECTIONS, 20 MAX_MAX_COUNT, 21 MAX_MINUTES, 22 MMOL_L_CONVERSION_FACTOR, 23 TREND_ARROWS, 24 TREND_DESCRIPTIONS, 25) 26from .errors import ( 27 AccountError, 28 AccountErrorEnum, 29 ArgumentError, 30 ArgumentErrorEnum, 31 DexcomError, 32 SessionError, 33 SessionErrorEnum, 34) 35 36_LOGGER = logging.getLogger("pydexcom") 37 38 39class GlucoseReading: 40 """Class for parsing glucose reading from Dexcom Share API.""" 41 42 def __init__(self, json_glucose_reading: Dict[str, Any]): 43 """Initialize `GlucoseReading` with JSON glucose reading from Dexcom Share API. 44 45 :param json_glucose_reading: JSON glucose reading from Dexcom Share API 46 """ 47 self._json = json_glucose_reading 48 try: 49 self._value = int(json_glucose_reading["Value"]) 50 self._trend_direction: str = json_glucose_reading["Trend"] 51 # Dexcom Share API returns `str` direction now, previously `int` trend 52 self._trend: int = DEXCOM_TREND_DIRECTIONS[self._trend_direction] 53 self._datetime = datetime.fromtimestamp( 54 int(re.sub("[^0-9]", "", json_glucose_reading["WT"])) / 1000.0 55 ) 56 except (KeyError, TypeError, ValueError): 57 raise ArgumentError(ArgumentErrorEnum.GLUCOSE_READING_INVALID) 58 59 @property 60 def value(self) -> int: 61 """Blood glucose value in mg/dL.""" 62 return self._value 63 64 @property 65 def mg_dl(self) -> int: 66 """Blood glucose value in mg/dL.""" 67 return self._value 68 69 @property 70 def mmol_l(self) -> float: 71 """Blood glucose value in mmol/L.""" 72 return round(self.value * MMOL_L_CONVERSION_FACTOR, 1) 73 74 @property 75 def trend(self) -> int: 76 """Blood glucose trend information 77 (value of `pydexcom.const.DEXCOM_TREND_DIRECTIONS`).""" 78 return self._trend 79 80 @property 81 def trend_direction(self) -> str: 82 """Blood glucose trend direction 83 (key of `pydexcom.const.DEXCOM_TREND_DIRECTIONS`).""" 84 return self._trend_direction 85 86 @property 87 def trend_description(self) -> Optional[str]: 88 """Blood glucose trend information description 89 (`pydexcom.const.TREND_DESCRIPTIONS`). 90 """ 91 return TREND_DESCRIPTIONS[self._trend] 92 93 @property 94 def trend_arrow(self) -> str: 95 """Blood glucose trend as unicode arrow (`pydexcom.const.TREND_ARROWS`).""" 96 return TREND_ARROWS[self._trend] 97 98 @property 99 def datetime(self) -> datetime: 100 """Glucose reading recorded time as datetime.""" 101 return self._datetime 102 103 @property 104 def json(self) -> Dict[str, Any]: 105 """JSON glucose reading from Dexcom Share API.""" 106 return self._json 107 108 def __str__(self) -> str: 109 return str(self._value) 110 111 112class Dexcom: 113 """Class for communicating with Dexcom Share API.""" 114 115 def __init__(self, username: str, password: str, ous: bool = False): 116 """ 117 Initialize `Dexcom` with Dexcom Share credentials. 118 119 :param username: username for the Dexcom Share user, *not follower*. 120 :param password: password for the Dexcom Share user. 121 :param ous: whether the Dexcom Share user is outside of the US. 122 """ 123 self._base_url = DEXCOM_BASE_URL_OUS if ous else DEXCOM_BASE_URL 124 self._username = username 125 self._password = password 126 self._account_id: Optional[str] = None 127 self._session_id: Optional[str] = None 128 self.__session = requests.Session() 129 self._session() 130 131 def _post( 132 self, 133 endpoint: str, 134 params: Optional[Dict[str, Any]] = None, 135 json: Optional[Dict[str, Any]] = None, 136 ) -> Any: 137 """Send post request to Dexcom Share API. 138 139 :param endpoint: URL of the post request 140 :param params: `dict` to send in the query string of the post request 141 :param json: JSON to send in the body of the post request 142 """ 143 response = self.__session.post( 144 f"{self._base_url}/{endpoint}", 145 headers={"Accept-Encoding": "application/json"}, 146 params=params, 147 json={} if json is None else json, 148 ) 149 150 try: 151 response.raise_for_status() 152 return response.json() 153 except requests.HTTPError as http_error: 154 error = self._handle_response(response) 155 if error: 156 raise error from http_error 157 _LOGGER.error("%s", response.text) 158 raise http_error 159 160 def _handle_response(self, response: requests.Response) -> Optional[DexcomError]: 161 error: Optional[DexcomError] = None 162 """ 163 Parse `requests.Response` for `pydexcom.errors.DexcomError`. 164 165 :param response: `requests.Response` to parse 166 """ 167 if response.json(): 168 _LOGGER.debug("%s", response.json()) 169 code = response.json().get("Code", None) 170 message = response.json().get("Message", None) 171 if code == "SessionIdNotFound": 172 error = SessionError(SessionErrorEnum.NOT_FOUND) 173 elif code == "SessionNotValid": 174 error = SessionError(SessionErrorEnum.INVALID) 175 elif code == "AccountPasswordInvalid": 176 error = AccountError(AccountErrorEnum.PASSWORD_INVALID) 177 elif code == "SSO_AuthenticateMaxAttemptsExceeed": 178 error = AccountError(AccountErrorEnum.MAX_ATTEMPTS) 179 elif code == "InvalidArgument": 180 if message and "accountName" in message: 181 error = ArgumentError(ArgumentErrorEnum.USERNAME_INVALID) 182 elif message and "password" in message: 183 error = ArgumentError(ArgumentErrorEnum.PASSWORD_INVALID) 184 elif message and "UUID" in message: 185 error = ArgumentError(ArgumentErrorEnum.ACCOUNT_ID_INVALID) 186 elif code and message: 187 _LOGGER.debug("%s: %s", code, message) 188 return error 189 190 def _validate_session_id(self) -> None: 191 """Validate session ID.""" 192 if any([not isinstance(self._session_id, str), not self._session_id]): 193 raise ArgumentError(ArgumentErrorEnum.SESSION_ID_INVALID) 194 if self._session_id == DEFAULT_UUID: 195 raise ArgumentError(ArgumentErrorEnum.SESSION_ID_DEFAULT) 196 197 def _validate_credentials(self) -> None: 198 """Validate credentials.""" 199 if any([not isinstance(self._username, str), not self._username]): 200 raise ArgumentError(ArgumentErrorEnum.USERNAME_INVALID) 201 if any([not isinstance(self._password, str), not self._password]): 202 raise ArgumentError(ArgumentErrorEnum.PASSWORD_INVALID) 203 204 def _validate_account_id(self) -> None: 205 """Validate account ID.""" 206 if any([not isinstance(self._account_id, str), not self._account_id]): 207 raise ArgumentError(ArgumentErrorEnum.ACCOUNT_ID_INVALID) 208 if self._account_id == DEFAULT_UUID: 209 raise ArgumentError(ArgumentErrorEnum.ACCOUNT_ID_DEFAULT) 210 211 def _get_account_id(self) -> str: 212 """Retrieve account ID from the authentication endpoint 213 (`pydexcom.const.DEXCOM_AUTHENTICATE_ENDPOINT`).""" 214 _LOGGER.debug("Retrieve account ID from the authentication endpoint") 215 return self._post( 216 DEXCOM_AUTHENTICATE_ENDPOINT, 217 json={ 218 "accountName": self._username, 219 "password": self._password, 220 "applicationId": DEXCOM_APPLICATION_ID, 221 }, 222 ) 223 224 def _get_session_id(self) -> str: 225 """Retrieve session ID from the login endpoint 226 (`pydexcom.const.DEXCOM_LOGIN_ID_ENDPOINT`).""" 227 _LOGGER.debug("Retrieve session ID from the login endpoint") 228 return self._post( 229 DEXCOM_LOGIN_ID_ENDPOINT, 230 json={ 231 "accountId": self._account_id, 232 "password": self._password, 233 "applicationId": DEXCOM_APPLICATION_ID, 234 }, 235 ) 236 237 def _session(self) -> None: 238 """Create Dexcom Share API session.""" 239 self._validate_credentials() 240 241 if self._account_id is None: 242 self._account_id = self._get_account_id() 243 self._validate_account_id() 244 245 self._session_id = self._get_session_id() 246 self._validate_session_id() 247 248 def _get_glucose_readings( 249 self, minutes: int = MAX_MINUTES, max_count: int = MAX_MAX_COUNT 250 ) -> List[Dict[str, Any]]: 251 """Retrieve glucose readings from the glucose readings endpoint 252 (`pydexcom.const.DEXCOM_GLUCOSE_READINGS_ENDPOINT`).""" 253 if not isinstance(minutes, int) or any([minutes < 0, minutes > MAX_MINUTES]): 254 raise ArgumentError(ArgumentErrorEnum.MINUTES_INVALID) 255 if not isinstance(max_count, int) or any( 256 [max_count < 0, max_count > MAX_MAX_COUNT] 257 ): 258 raise ArgumentError(ArgumentErrorEnum.MAX_COUNT_INVALID) 259 260 _LOGGER.debug("Retrieve glucose readings from the glucose readings endpoint") 261 return self._post( 262 DEXCOM_GLUCOSE_READINGS_ENDPOINT, 263 params={ 264 "sessionId": self._session_id, 265 "minutes": minutes, 266 "maxCount": max_count, 267 }, 268 ) 269 270 def get_glucose_readings( 271 self, minutes: int = MAX_MINUTES, max_count: int = MAX_MAX_COUNT 272 ) -> List[GlucoseReading]: 273 """Get `max_count` glucose readings within specified number of `minutes`. 274 275 Catches one instance of a thrown `pydexcom.errors.SessionError` if session ID 276 expired, attempts to get a new session ID and retries. 277 278 :param minutes: Number of minutes to retrieve glucose readings from (1-1440) 279 :param max_count: Maximum number of glucose readings to retrieve (1-288) 280 """ 281 282 json_glucose_readings: List[Dict[str, Any]] = [] 283 284 try: 285 # Requesting glucose reading with DEFAULT_UUID returns non-JSON empty string 286 self._validate_session_id() 287 288 json_glucose_readings = self._get_glucose_readings(minutes, max_count) 289 except SessionError: 290 # Attempt to update expired session ID 291 self._session() 292 293 json_glucose_readings = self._get_glucose_readings(minutes, max_count) 294 295 return [GlucoseReading(json_reading) for json_reading in json_glucose_readings] 296 297 def get_latest_glucose_reading(self) -> Optional[GlucoseReading]: 298 """Get latest available glucose reading, within the last 24 hours.""" 299 glucose_readings = self.get_glucose_readings(max_count=1) 300 return glucose_readings[0] if glucose_readings else None 301 302 def get_current_glucose_reading(self) -> Optional[GlucoseReading]: 303 """Get current available glucose reading, within the last 10 minutes.""" 304 glucose_readings = self.get_glucose_readings(minutes=10, max_count=1) 305 return glucose_readings[0] if glucose_readings else None
40class GlucoseReading: 41 """Class for parsing glucose reading from Dexcom Share API.""" 42 43 def __init__(self, json_glucose_reading: Dict[str, Any]): 44 """Initialize `GlucoseReading` with JSON glucose reading from Dexcom Share API. 45 46 :param json_glucose_reading: JSON glucose reading from Dexcom Share API 47 """ 48 self._json = json_glucose_reading 49 try: 50 self._value = int(json_glucose_reading["Value"]) 51 self._trend_direction: str = json_glucose_reading["Trend"] 52 # Dexcom Share API returns `str` direction now, previously `int` trend 53 self._trend: int = DEXCOM_TREND_DIRECTIONS[self._trend_direction] 54 self._datetime = datetime.fromtimestamp( 55 int(re.sub("[^0-9]", "", json_glucose_reading["WT"])) / 1000.0 56 ) 57 except (KeyError, TypeError, ValueError): 58 raise ArgumentError(ArgumentErrorEnum.GLUCOSE_READING_INVALID) 59 60 @property 61 def value(self) -> int: 62 """Blood glucose value in mg/dL.""" 63 return self._value 64 65 @property 66 def mg_dl(self) -> int: 67 """Blood glucose value in mg/dL.""" 68 return self._value 69 70 @property 71 def mmol_l(self) -> float: 72 """Blood glucose value in mmol/L.""" 73 return round(self.value * MMOL_L_CONVERSION_FACTOR, 1) 74 75 @property 76 def trend(self) -> int: 77 """Blood glucose trend information 78 (value of `pydexcom.const.DEXCOM_TREND_DIRECTIONS`).""" 79 return self._trend 80 81 @property 82 def trend_direction(self) -> str: 83 """Blood glucose trend direction 84 (key of `pydexcom.const.DEXCOM_TREND_DIRECTIONS`).""" 85 return self._trend_direction 86 87 @property 88 def trend_description(self) -> Optional[str]: 89 """Blood glucose trend information description 90 (`pydexcom.const.TREND_DESCRIPTIONS`). 91 """ 92 return TREND_DESCRIPTIONS[self._trend] 93 94 @property 95 def trend_arrow(self) -> str: 96 """Blood glucose trend as unicode arrow (`pydexcom.const.TREND_ARROWS`).""" 97 return TREND_ARROWS[self._trend] 98 99 @property 100 def datetime(self) -> datetime: 101 """Glucose reading recorded time as datetime.""" 102 return self._datetime 103 104 @property 105 def json(self) -> Dict[str, Any]: 106 """JSON glucose reading from Dexcom Share API.""" 107 return self._json 108 109 def __str__(self) -> str: 110 return str(self._value)
Class for parsing glucose reading from Dexcom Share API.
43 def __init__(self, json_glucose_reading: Dict[str, Any]): 44 """Initialize `GlucoseReading` with JSON glucose reading from Dexcom Share API. 45 46 :param json_glucose_reading: JSON glucose reading from Dexcom Share API 47 """ 48 self._json = json_glucose_reading 49 try: 50 self._value = int(json_glucose_reading["Value"]) 51 self._trend_direction: str = json_glucose_reading["Trend"] 52 # Dexcom Share API returns `str` direction now, previously `int` trend 53 self._trend: int = DEXCOM_TREND_DIRECTIONS[self._trend_direction] 54 self._datetime = datetime.fromtimestamp( 55 int(re.sub("[^0-9]", "", json_glucose_reading["WT"])) / 1000.0 56 ) 57 except (KeyError, TypeError, ValueError): 58 raise ArgumentError(ArgumentErrorEnum.GLUCOSE_READING_INVALID)
Initialize GlucoseReading
with JSON glucose reading from Dexcom Share API.
Parameters
- json_glucose_reading: JSON glucose reading from Dexcom Share API
Blood glucose trend information description
(pydexcom.const.TREND_DESCRIPTIONS
).
113class Dexcom: 114 """Class for communicating with Dexcom Share API.""" 115 116 def __init__(self, username: str, password: str, ous: bool = False): 117 """ 118 Initialize `Dexcom` with Dexcom Share credentials. 119 120 :param username: username for the Dexcom Share user, *not follower*. 121 :param password: password for the Dexcom Share user. 122 :param ous: whether the Dexcom Share user is outside of the US. 123 """ 124 self._base_url = DEXCOM_BASE_URL_OUS if ous else DEXCOM_BASE_URL 125 self._username = username 126 self._password = password 127 self._account_id: Optional[str] = None 128 self._session_id: Optional[str] = None 129 self.__session = requests.Session() 130 self._session() 131 132 def _post( 133 self, 134 endpoint: str, 135 params: Optional[Dict[str, Any]] = None, 136 json: Optional[Dict[str, Any]] = None, 137 ) -> Any: 138 """Send post request to Dexcom Share API. 139 140 :param endpoint: URL of the post request 141 :param params: `dict` to send in the query string of the post request 142 :param json: JSON to send in the body of the post request 143 """ 144 response = self.__session.post( 145 f"{self._base_url}/{endpoint}", 146 headers={"Accept-Encoding": "application/json"}, 147 params=params, 148 json={} if json is None else json, 149 ) 150 151 try: 152 response.raise_for_status() 153 return response.json() 154 except requests.HTTPError as http_error: 155 error = self._handle_response(response) 156 if error: 157 raise error from http_error 158 _LOGGER.error("%s", response.text) 159 raise http_error 160 161 def _handle_response(self, response: requests.Response) -> Optional[DexcomError]: 162 error: Optional[DexcomError] = None 163 """ 164 Parse `requests.Response` for `pydexcom.errors.DexcomError`. 165 166 :param response: `requests.Response` to parse 167 """ 168 if response.json(): 169 _LOGGER.debug("%s", response.json()) 170 code = response.json().get("Code", None) 171 message = response.json().get("Message", None) 172 if code == "SessionIdNotFound": 173 error = SessionError(SessionErrorEnum.NOT_FOUND) 174 elif code == "SessionNotValid": 175 error = SessionError(SessionErrorEnum.INVALID) 176 elif code == "AccountPasswordInvalid": 177 error = AccountError(AccountErrorEnum.PASSWORD_INVALID) 178 elif code == "SSO_AuthenticateMaxAttemptsExceeed": 179 error = AccountError(AccountErrorEnum.MAX_ATTEMPTS) 180 elif code == "InvalidArgument": 181 if message and "accountName" in message: 182 error = ArgumentError(ArgumentErrorEnum.USERNAME_INVALID) 183 elif message and "password" in message: 184 error = ArgumentError(ArgumentErrorEnum.PASSWORD_INVALID) 185 elif message and "UUID" in message: 186 error = ArgumentError(ArgumentErrorEnum.ACCOUNT_ID_INVALID) 187 elif code and message: 188 _LOGGER.debug("%s: %s", code, message) 189 return error 190 191 def _validate_session_id(self) -> None: 192 """Validate session ID.""" 193 if any([not isinstance(self._session_id, str), not self._session_id]): 194 raise ArgumentError(ArgumentErrorEnum.SESSION_ID_INVALID) 195 if self._session_id == DEFAULT_UUID: 196 raise ArgumentError(ArgumentErrorEnum.SESSION_ID_DEFAULT) 197 198 def _validate_credentials(self) -> None: 199 """Validate credentials.""" 200 if any([not isinstance(self._username, str), not self._username]): 201 raise ArgumentError(ArgumentErrorEnum.USERNAME_INVALID) 202 if any([not isinstance(self._password, str), not self._password]): 203 raise ArgumentError(ArgumentErrorEnum.PASSWORD_INVALID) 204 205 def _validate_account_id(self) -> None: 206 """Validate account ID.""" 207 if any([not isinstance(self._account_id, str), not self._account_id]): 208 raise ArgumentError(ArgumentErrorEnum.ACCOUNT_ID_INVALID) 209 if self._account_id == DEFAULT_UUID: 210 raise ArgumentError(ArgumentErrorEnum.ACCOUNT_ID_DEFAULT) 211 212 def _get_account_id(self) -> str: 213 """Retrieve account ID from the authentication endpoint 214 (`pydexcom.const.DEXCOM_AUTHENTICATE_ENDPOINT`).""" 215 _LOGGER.debug("Retrieve account ID from the authentication endpoint") 216 return self._post( 217 DEXCOM_AUTHENTICATE_ENDPOINT, 218 json={ 219 "accountName": self._username, 220 "password": self._password, 221 "applicationId": DEXCOM_APPLICATION_ID, 222 }, 223 ) 224 225 def _get_session_id(self) -> str: 226 """Retrieve session ID from the login endpoint 227 (`pydexcom.const.DEXCOM_LOGIN_ID_ENDPOINT`).""" 228 _LOGGER.debug("Retrieve session ID from the login endpoint") 229 return self._post( 230 DEXCOM_LOGIN_ID_ENDPOINT, 231 json={ 232 "accountId": self._account_id, 233 "password": self._password, 234 "applicationId": DEXCOM_APPLICATION_ID, 235 }, 236 ) 237 238 def _session(self) -> None: 239 """Create Dexcom Share API session.""" 240 self._validate_credentials() 241 242 if self._account_id is None: 243 self._account_id = self._get_account_id() 244 self._validate_account_id() 245 246 self._session_id = self._get_session_id() 247 self._validate_session_id() 248 249 def _get_glucose_readings( 250 self, minutes: int = MAX_MINUTES, max_count: int = MAX_MAX_COUNT 251 ) -> List[Dict[str, Any]]: 252 """Retrieve glucose readings from the glucose readings endpoint 253 (`pydexcom.const.DEXCOM_GLUCOSE_READINGS_ENDPOINT`).""" 254 if not isinstance(minutes, int) or any([minutes < 0, minutes > MAX_MINUTES]): 255 raise ArgumentError(ArgumentErrorEnum.MINUTES_INVALID) 256 if not isinstance(max_count, int) or any( 257 [max_count < 0, max_count > MAX_MAX_COUNT] 258 ): 259 raise ArgumentError(ArgumentErrorEnum.MAX_COUNT_INVALID) 260 261 _LOGGER.debug("Retrieve glucose readings from the glucose readings endpoint") 262 return self._post( 263 DEXCOM_GLUCOSE_READINGS_ENDPOINT, 264 params={ 265 "sessionId": self._session_id, 266 "minutes": minutes, 267 "maxCount": max_count, 268 }, 269 ) 270 271 def get_glucose_readings( 272 self, minutes: int = MAX_MINUTES, max_count: int = MAX_MAX_COUNT 273 ) -> List[GlucoseReading]: 274 """Get `max_count` glucose readings within specified number of `minutes`. 275 276 Catches one instance of a thrown `pydexcom.errors.SessionError` if session ID 277 expired, attempts to get a new session ID and retries. 278 279 :param minutes: Number of minutes to retrieve glucose readings from (1-1440) 280 :param max_count: Maximum number of glucose readings to retrieve (1-288) 281 """ 282 283 json_glucose_readings: List[Dict[str, Any]] = [] 284 285 try: 286 # Requesting glucose reading with DEFAULT_UUID returns non-JSON empty string 287 self._validate_session_id() 288 289 json_glucose_readings = self._get_glucose_readings(minutes, max_count) 290 except SessionError: 291 # Attempt to update expired session ID 292 self._session() 293 294 json_glucose_readings = self._get_glucose_readings(minutes, max_count) 295 296 return [GlucoseReading(json_reading) for json_reading in json_glucose_readings] 297 298 def get_latest_glucose_reading(self) -> Optional[GlucoseReading]: 299 """Get latest available glucose reading, within the last 24 hours.""" 300 glucose_readings = self.get_glucose_readings(max_count=1) 301 return glucose_readings[0] if glucose_readings else None 302 303 def get_current_glucose_reading(self) -> Optional[GlucoseReading]: 304 """Get current available glucose reading, within the last 10 minutes.""" 305 glucose_readings = self.get_glucose_readings(minutes=10, max_count=1) 306 return glucose_readings[0] if glucose_readings else None
Class for communicating with Dexcom Share API.
116 def __init__(self, username: str, password: str, ous: bool = False): 117 """ 118 Initialize `Dexcom` with Dexcom Share credentials. 119 120 :param username: username for the Dexcom Share user, *not follower*. 121 :param password: password for the Dexcom Share user. 122 :param ous: whether the Dexcom Share user is outside of the US. 123 """ 124 self._base_url = DEXCOM_BASE_URL_OUS if ous else DEXCOM_BASE_URL 125 self._username = username 126 self._password = password 127 self._account_id: Optional[str] = None 128 self._session_id: Optional[str] = None 129 self.__session = requests.Session() 130 self._session()
Initialize Dexcom
with Dexcom Share credentials.
Parameters
- username: username for the Dexcom Share user, not follower.
- password: password for the Dexcom Share user.
- ous: whether the Dexcom Share user is outside of the US.
271 def get_glucose_readings( 272 self, minutes: int = MAX_MINUTES, max_count: int = MAX_MAX_COUNT 273 ) -> List[GlucoseReading]: 274 """Get `max_count` glucose readings within specified number of `minutes`. 275 276 Catches one instance of a thrown `pydexcom.errors.SessionError` if session ID 277 expired, attempts to get a new session ID and retries. 278 279 :param minutes: Number of minutes to retrieve glucose readings from (1-1440) 280 :param max_count: Maximum number of glucose readings to retrieve (1-288) 281 """ 282 283 json_glucose_readings: List[Dict[str, Any]] = [] 284 285 try: 286 # Requesting glucose reading with DEFAULT_UUID returns non-JSON empty string 287 self._validate_session_id() 288 289 json_glucose_readings = self._get_glucose_readings(minutes, max_count) 290 except SessionError: 291 # Attempt to update expired session ID 292 self._session() 293 294 json_glucose_readings = self._get_glucose_readings(minutes, max_count) 295 296 return [GlucoseReading(json_reading) for json_reading in json_glucose_readings]
Get max_count
glucose readings within specified number of minutes
.
Catches one instance of a thrown pydexcom.errors.SessionError
if session ID
expired, attempts to get a new session ID and retries.
Parameters
- minutes: Number of minutes to retrieve glucose readings from (1-1440)
- max_count: Maximum number of glucose readings to retrieve (1-288)
298 def get_latest_glucose_reading(self) -> Optional[GlucoseReading]: 299 """Get latest available glucose reading, within the last 24 hours.""" 300 glucose_readings = self.get_glucose_readings(max_count=1) 301 return glucose_readings[0] if glucose_readings else None
Get latest available glucose reading, within the last 24 hours.
303 def get_current_glucose_reading(self) -> Optional[GlucoseReading]: 304 """Get current available glucose reading, within the last 10 minutes.""" 305 glucose_readings = self.get_glucose_readings(minutes=10, max_count=1) 306 return glucose_readings[0] if glucose_readings else None
Get current available glucose reading, within the last 10 minutes.