Skip to content

spamsch/glooko-reader-swift

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

glooko-reader-swift

Swift package for reading data from the Glooko diabetes data platform. Retrieves insulin pump data (Omnipod 5), CGM readings, and statistics via Glooko's internal web API.

Important: Glooko data is not real-time. The Omnipod 5 app syncs data to Glooko periodically — typically once every few hours, and only when the phone has connectivity. This means bolus entries, IOB values, and pump mode data can lag behind actual pump activity by 1-4 hours. Do not rely on this library for time-critical insulin dosing decisions. It is best suited for retrospective analysis, trend monitoring, and enriching recommendation systems with historical pump context.

Note: Glooko does not provide a public API. This library authenticates by replicating the browser login flow (CSRF token extraction, cookie-based sessions). It may break if Glooko changes their web application.

See also: glooko-reader (Python version)

Installation

Add to your Package.swift:

dependencies: [
    .package(url: "https://github.com/spamsch/glooko-reader-swift.git", from: "0.1.0"),
],
targets: [
    .target(
        name: "YourTarget",
        dependencies: [
            .product(name: "GlookoReader", package: "glooko-reader-swift"),
        ]
    ),
]

Quick Start

import GlookoReader

let client = GlookoClient(email: "you@example.com", password: "your_password")
try await client.authenticate()

// Fetch insulin delivery data
let data = try await client.getGraphData(dateRange: .lastDays(1))

// Parse into structured objects
if let data {
    let boluses = parseBolusEntries(from: data)
    for b in boluses {
        print("\(b.timestamp)\(b.units)u (IOB: \(b.insulinOnBoard ?? 0), carbs: \(b.carbsInput ?? 0)g)")
    }
}

// Pump mode and statistics
let stats = try await client.getStatistics(dateRange: .lastDays(1))
if let stats, let pump = parsePumpMode(from: stats) {
    print("Pump: \(pump.mode ?? .auto) mode, \(pump.totalInsulinPerDay ?? 0) units/day")
}

// Connected devices
let deviceData = try await client.getDeviceSettings()
if let deviceData {
    let devices = parseDevices(from: deviceData)
    for d in devices {
        print("\(d.name) — last sync: \(d.lastSync?.description ?? "unknown")")
    }
}

API Reference

GlookoClient

let client = GlookoClient(email: String, password: String, sessionTimeoutMinutes: Int = 55)

All API methods are async throws.

Method Returns Description
authenticate() Void Perform browser-based login flow
ensureAuthenticated() Void Re-authenticate if session expired
getGraphData(dateRange:) [String: Any]? CGM readings + delivered bolus insulin
getStatistics(dateRange:) [String: Any]? Overall stats, pump modes, insulin totals
getDailyData(dateRange:) [String: Any]? Daily CGM averages and percentile bands
getDeviceSettings() [String: Any]? Connected devices and configuration
testConnection() Bool Verify authentication works

DateRange

DateRange.today                          // Today
DateRange.lastDays(7)                    // Last 7 days
DateRange(from: startDate, to: endDate)  // Custom range

Parsers

Function Returns Description
parseBolusEntries(from:) [BolusEntry] Insulin bolus deliveries
parseIOBFromBolus(from:maxAgeMinutes:) Double? IOB from most recent bolus
parsePumpMode(from:) PumpStatistics? Pump mode and insulin stats
parseDevices(from:) [DeviceInfo] Connected device info
parseTimestamp(_:) Date? Parse Glooko timestamp formats

Models

BolusEntry — A single insulin bolus delivery

Property Type Description
timestamp Date When the bolus was delivered
units Double Insulin units delivered
carbsInput Double? Carbs entered at bolus time
insulinOnBoard Double? IOB reported by pump
bloodGlucoseInput Int? BG reading at bolus time
bloodGlucoseSource String? Source ("CGM", etc.)
correctionUnits Double? Insulin for correction
carbUnits Double? Insulin for carbs
isManual Bool Whether manually entered
deviceName String? Delivering device

PumpStatistics — Pump mode and insulin statistics

Property Type Description
mode PumpMode? .auto, .manual, or .limited
autoPercentage Double Time in auto mode (%)
manualPercentage Double Time in manual mode (%)
totalInsulinPerDay Double? Average daily insulin
inRangePercentage Double? Time in range (%)
carbsPerDay Double? Average daily carbs (g)

DeviceInfo — Connected device

Property Type Description
name String Display name
brand String? Manufacturer
model String? Model name
deviceType String? "pump", "cgm", etc.
lastSync Date? Last data sync

Authentication Details

Glooko uses a multi-step browser login flow:

  1. GET https://my.glooko.com/users/sign_in — follows redirect to regional server
  2. Extracts CSRF token from HTML
  3. POST login form with credentials and CSRF token
  4. Extracts patient_id and apiUrl from dashboard JavaScript
  5. Subsequent API calls use cookie-based authentication with CORS headers

API Quirks

  • Date format: Full ISO datetime required (2026-03-29T00:00:00.000Z), not YYYY-MM-DD
  • CORS headers: Graph/statistics endpoints require Origin and Referer headers
  • URL encoding: series[] must use literal brackets, not percent-encoded %5B%5D
  • Regional routing: Users are routed to regional servers (e.g., de-fr.api.glooko.com)

Testing

A mock client is included:

let mock = MockGlookoClient(scenario: .normal)
// Also: .highBasal, .manualMode, .podChange, .noData

let data = mock.getGraphData(dateRange: .today)
let boluses = parseBolusEntries(from: data!)

Tested With

  • Insulet Omnipod 5 System
  • Dexcom G7 (via Omnipod 5 integration)
  • Glooko EU region (de-fr.api.glooko.com)

Requirements

  • Swift 5.9+
  • macOS 13+ / iOS 16+
  • No external dependencies

License

MIT

About

Swift package for reading data from the Glooko diabetes platform. Retrieves Omnipod 5 insulin pump data, CGM readings, and statistics. Zero external dependencies.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages