pydexcom

repository·main·Indexed 42 days ago

https://github.com/gagebenne/pydexcom

A Python library to interface with the Dexcom Share API for retrieving real-time glucose readings and trend information. It provides the Dexcom client for authentication across US, OUS, and JP regions, and the GlucoseReading class to parse data into mg/dL and mmol/L units with associated trend descriptions and arrows.

Tokens
4.8K
Snippets
16
Records
22
Agent score
54%

What's inside pydexcom

  1. Install pydexcom

    main

    Install the pydexcom package using pip to interact with the Dexcom Share service for real-time CGM sensor data.

    Prerequisites:

    1. Download a compatible Dexcom mobile app (G7, G6, G5, G4, or ONE+).
    2. Enable the Share service in the app. Note that the Share service requires at least one follower to be set up to be active.
    pip install pydexcom
  2. Troubleshoot AccountErrorEnum (Invalid Password)

    main

    If you receive a pydexcom.errors.AccountErrorEnum, the Dexcom Share API is reporting an authentication failure. Check the following:

    1. Credentials: Verify your login works on the Dexcom Account Management website for your region (uam1.dexcom.com for US, uam2.dexcom.com for non-US, uam.dexcom.jp for Japan).
    2. Region: Ensure you have set the correct region parameter ("us", "ous", or "jp") when initializing the Dexcom object.
    3. Username Format: Phone numbers must include the + and country code (e.g., +11234567890).
    4. Credential Type: Use the credentials of the user publishing the readings (the sensor user), not the follower's credentials.
    5. Share Service Status: Ensure you have at least one follower configured in the Dexcom app; the service may not be active without one.
    6. Account ID: If username/password fails, try using your hyphenated UUID account_id found in the URL of the Dexcom Account Management dashboard.
  3. Get current glucose readings

    main

    The get_current_glucose_reading() method retrieves the most recent glucose data from the Dexcom Share service. It returns a glucose reading object containing several attributes.

    Available Attributes on the reading object:

    • value: The glucose reading in mg/dL.
    • mmol_l: The glucose reading in mmol/L.
    • trend: An integer representing the trend.
    • trend_direction: A string describing the direction (e.g., 'Flat').
    • trend_description: A string describing the trend (e.g., 'steady').
    • trend_arrow: A visual representation of the trend (e.g., '→').
    • datetime: The timestamp of the reading.
    • json: A dictionary representation of the reading data.

    Note: This package is designed for real-time data. The official Dexcom Developer API is retrospective and not suitable for real-time fetching.

    from pydexcom import Dexcom
    
    dexcom = Dexcom(username="username", password="password")
    glucose_reading = dexcom.get_current_glucose_reading()
    
    print(glucose_reading.value)           # e.g., 85
    print(glucose_reading.mmol_l)          # e.g., 4.7
    print(glucose_reading.trend_direction) # e.g., 'Flat'
    print(glucose_reading.trend_arrow)      # e.g., '→'
    print(glucose_reading.datetime)       # e.g., 2023-08-07 20:40:58
    print(glucose_reading.json)           # Returns a dict of the reading
  4. Initialize the Dexcom client

    main

    Use the Dexcom class to authenticate with the Dexcom Share service. You can authenticate using a username (email or phone number) or an advanced account_id (UUID).

    Region Configuration: By default, the client uses the US region. You must specify the region parameter if you are outside the US or in Japan:

    • US: region="us" (default)
    • Outside US: region="ous"
    • Japan: region="jp"

    Username Formats:

    • Email address: user@email.com
    • Phone number: Must include the + and country code (e.g., +11234567890)
    • Account ID: A hyphenated UUID (e.g., 12345678-90ab-cdef-1234-567890abcdef)
    from pydexcom import Dexcom
    
    # Using email
    dexcom = Dexcom(username="user@email.com", password="password")
    
    # Using phone number
    dexcom = Dexcom(username="+11234567890", password="password")
    
    # Using account ID (advanced)
    dexcom = Dexcom(account_id="12345678-90ab-cdef-1234-567890abcdef", password="password")
    
    # Specifying region (e.g., outside US)
    dexcom = Dexcom(username="user@email.com", password="password", region="ous")
  5. Use the GlucoseReading class to parse Dexcom readings

    main

    The GlucoseReading class is used to parse and represent a single glucose reading retrieved from the Dexcom Share API. You initialize it by passing the raw JSON dictionary received from the API.

    If the JSON structure is invalid or missing required keys (like Value, Trend, or DT), it will raise an ArgumentError with ArgumentErrorEnum.GLUCOSE_READING_INVALID.

    from pydexcom.glucose_reading import GlucoseReading
    
    # Example JSON structure expected from Dexcom Share API
    raw_json = {
        "Value": 120,
        "Trend": "Steady",
        "DT": "Date(1672531200000+0000)"
    }
    
    reading = GlucoseReading(raw_json)
    print(f"Value: {reading.mg_dl} mg/dL")
  6. Handle Dexcom errors using DexcomError and its subclasses

    main

    All errors in pydexcom inherit from the DexcomError base class. You can catch specific error types to handle different failure scenarios (e.g., authentication issues vs. invalid arguments). Each error can optionally be associated with a DexcomErrorEnum value, which provides a machine-readable error string via the .enum property.

    from pydexcom.errors import DexcomError, AccountError, ArgumentError
    
    try:
        # Perform Dexcom operations
        pass
    except AccountError as e:
        print(f"Authentication failed: {e}")
        if e.enum:
            print(f"Error code: {e.enum.value}")
    except ArgumentError as e:
        print(f"Invalid argument provided: {e}")
    except DexcomError as e:
        print(f"An unexpected Dexcom error occurred: {e}")
  7. Get the latest or current glucose reading

    main

    If you only need a single data point, use these convenience methods:

    • get_latest_glucose_reading(): Returns the most recent GlucoseReading available within the last 24 hours. Returns None if no reading is found.
    • get_current_glucose_reading(): Returns the most recent GlucoseReading available within the last 10 minutes. Returns None if no reading is found.
    # Get the single most recent reading
    latest = client.get_latest_glucose_reading()
    if latest:
        print(f"Latest value: {latest.value}")
    
    # Get the reading from the last 10 minutes
    current = client.get_current_glucose_reading()
  8. Get glucose readings with get_glucose_readings()

    main

    Retrieve a list of GlucoseReading objects from the Dexcom Share service. The method allows you to limit the scope of the data retrieved using minutes and max_count.

    Parameters:

    • minutes (int, optional): The number of minutes to look back (range: 1-1440). Defaults to MAX_MINUTES.
    • max_count (int, optional): The maximum number of readings to return (range: 1-288). Defaults to MAX_MAX_COUNT.

    Behavior: This method automatically handles session expiration. If a SessionError occurs, it attempts to refresh the session ID and retries the request once.

    # Get up to 50 readings from the last 60 minutes
    readings = client.get_glucose_readings(minutes=60, max_count=50)
    
    for reading in readings:
        print(reading.value)
  9. Initialize the Dexcom client

    main

    The primary entry point for the library is the Dexcom class. You use it to authenticate and interact with the Dexcom API. It requires credentials and a Region to specify which Dexcom server to connect to.

    from pydexcom import Dexcom, Region
    
    # Example initialization
    client = Dexcom(username='your_username', password='your_password', region=Region.US)
  10. Interpret Dexcom trend directions

    main

    Dexcom returns trend directions as integers. The package provides mappings to convert these integers into human-readable descriptions and visual arrows. The following three collections are ordered identically and correspond to the same integer values:

    1. DEXCOM_TREND_DIRECTIONS: The integer values returned by the API.
    2. TREND_DESCRIPTIONS: Human-readable text (e.g., "rising quickly").
    3. TREND_ARROWS: Visual arrow symbols (e.g., "↑↑").
    IntegerDescriptionArrow
    0None (unconfirmed)''
    1rising quickly↑↑
    2rising↑
    3rising slightly↗
    4steady→
    5falling slightly↘
    6falling↓
    7falling quickly↓↓
    8NotComputable (unconfirmed)?
    9RateOutOfRange (unconfirmed)-
    from pydexcom.const import DEXCOM_TREND_DIRECTIONS, TREND_DESCRIPTIONS, TREND_ARROWS
    
    # Example: converting an API integer value to a description
    api_value = 1
    
    # Find the index of the direction to look up description/arrow
    # Note: In practice, you would use the integer directly as an index
    description = TREND_DESCRIPTIONS[api_value]
    arrow = TREND_ARROWS[api_value]
    
    print(f"{arrow} {description}") # Output: ↑↑ rising quickly
  11. Handle Dexcom authentication and session errors

    main

    The pydexcom library raises specific exceptions to help you diagnose issues with credentials or connectivity:

    • AccountError: Raised when authentication fails (e.g., AccountErrorEnum.FAILED_AUTHENTICATION due to invalid password or AccountErrorEnum.MAX_ATTEMPTS due to too many failed attempts).
    • SessionError: Raised when the session is invalid or not found (e.g., SessionErrorEnum.INVALID). The client attempts to recover from this automatically during get_glucose_readings().
    • ArgumentError: Raised when provided parameters are invalid (e.g., ArgumentErrorEnum.REGION_INVALID, ArgumentErrorEnum.USERNAME_INVALID, or ArgumentErrorEnum.ACCOUNT_ID_INVALID).
    • ServerError: Raised when the Dexcom API returns an unexpected error or invalid JSON.
  12. Map Regions to Application IDs and Base URLs

    main

    The package provides lookup dictionaries to resolve configuration details based on a Region instance. Use these to programmatically determine the correct API settings:

    • DEXCOM_APPLICATION_IDS: Maps a Region to its corresponding Dexcom application ID string.
    • DEXCOM_BASE_URLS: Maps a Region to its corresponding Dexcom Share API base URL.
    from pydexcom.const import Region, DEXCOM_APPLICATION_IDS, DEXCOM_BASE_URLS
    
    region = Region.JP
    app_id = DEXCOM_APPLICATION_IDS[region]
    base_url = DEXCOM_BASE_URLS[region]