Fix Nightscout API Query Using Unreliable `dateString` Field by imbercal · Pull Request #506 · loopandlearn/LoopFollow
Fix Nightscout API Query Using Unreliable dateString Field
Summary
This PR fixes a bug where Nightscout BG data queries could return empty results when data was slightly stale, causing the log message "No bg data received. Skipping processing."
The root cause was using the dateString field for date filtering, which is not reliably populated across all CGM uploaders and Nightscout configurations. The fix switches to using the numeric date field (milliseconds since epoch), which is always present and consistently formatted.
Problem
Symptoms
- I was experiencing "No bg data received. Skipping processing." in logs and no values for BG shown on the home page
- This occurred even when Nightscout had valid BG data that was only slightly stale (a few minutes old)
Root Cause
The previous code queried Nightscout entries using the dateString field:
let utcISODateFormatter = ISO8601DateFormatter() let date = Calendar.current.date(byAdding: .day, value: -1 * Storage.shared.downloadDays.value, to: Date())! parameters["find[dateString][$gte]"] = utcISODateFormatter.string(from: date)
However, the dateString field in Nightscout entries Is not always populated - Some CGM uploaders (xDrip+, various Dexcom integrations) don't consistently set this field
Solution
Changed the query to use the numeric date field (milliseconds since epoch), which is:
- Always present in Nightscout entries
- The primary timestamp field used for sorting, deduplication, and Last-Modified headers
- Consistently formatted across all uploaders
- The approach used by other Nightscout apps like Nightguard
Code Change
Before:
var parameters: [String: String] = [:] let utcISODateFormatter = ISO8601DateFormatter() let date = Calendar.current.date(byAdding: .day, value: -1 * Storage.shared.downloadDays.value, to: Date())! parameters["count"] = "\(Storage.shared.downloadDays.value * 2 * 24 * 60 / 5)" parameters["find[dateString][$gte]"] = utcISODateFormatter.string(from: date)
After:
var parameters: [String: String] = [:] let date = Calendar.current.date(byAdding: .day, value: -1 * Storage.shared.downloadDays.value, to: Date())! parameters["count"] = "\(Storage.shared.downloadDays.value * 2 * 24 * 60 / 5)" parameters["find[date][$gte]"] = "\(Int(date.timeIntervalSince1970 * 1000))"
Test Plan
- Verify BG data loads correctly on fresh app launch
- Verify BG data continues to update when CGM data is slightly delayed (5-10 minutes)
- Verify historical data (multiple days) loads correctly
- Test with different Nightscout configurations:
- Nightscout with xDrip+ uploader
- Nightscout with Dexcom Share bridge
- Nightscout with Loop uploader
- Verify no "No bg data received" errors when valid data exists in Nightscout
Research References
- Nightscout API Documentation - Documents both
dateanddateStringas valid query parameters - Nightscout Issue #7910 - Documents bug with entries missing
dateString - Nightguard Query Implementation - Shows official Nightscout app uses
find[date][$gt]with milliseconds
Files Changed
| File | Change |
|---|---|
LoopFollow/Controllers/Nightscout/BGData.swift |
Changed find[dateString][$gte] to find[date][$gte] with milliseconds |