Skip to content

Commit

Permalink
Merge pull request #574 from paulplant/staging-5.4
Browse files Browse the repository at this point in the history
Staging 5.4
  • Loading branch information
paulplant authored Oct 14, 2024
2 parents 364324f + 8c0e7b7 commit 2117f5c
Show file tree
Hide file tree
Showing 52 changed files with 230 additions and 167 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1287,7 +1287,7 @@ class CGMG5Transmitter:BluetoothTransmitter, CGMTransmitter {

var forceNewSensor = false

if let sensorStartDate = self.sensorStartDate, let activeSensorStartDate = UserDefaults.standard.activeSensorStartDate, activeSensorStartDate < sensorStartDate.addingTimeInterval(-15.0) {
if let sensorStartDate = self.sensorStartDate, let activeSensorStartDate = UserDefaults.standard.activeSensorStartDate, activeSensorStartDate < sensorStartDate.addingTimeInterval(-15.0) || activeSensorStartDate > sensorStartDate.addingTimeInterval(15.0) {
forceNewSensor = true
}

Expand Down Expand Up @@ -1327,7 +1327,7 @@ class CGMG5Transmitter:BluetoothTransmitter, CGMTransmitter {

var forceNewSensor = false

if let sensorStartDate = self.sensorStartDate, let activeSensorStartDate = UserDefaults.standard.activeSensorStartDate, activeSensorStartDate < sensorStartDate.addingTimeInterval(-15.0) {
if let sensorStartDate = self.sensorStartDate, let activeSensorStartDate = UserDefaults.standard.activeSensorStartDate, activeSensorStartDate < sensorStartDate.addingTimeInterval(-15.0) || activeSensorStartDate > sensorStartDate.addingTimeInterval(15.0) {
forceNewSensor = true
}

Expand Down
20 changes: 16 additions & 4 deletions xdrip/BluetoothTransmitter/CGM/Dexcom/G7/CGMG7Transmitter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ class CGMG7Transmitter: BluetoothTransmitter, CGMTransmitter {
init(address:String?, name: String?, bluetoothTransmitterDelegate: BluetoothTransmitterDelegate, cGMG7TransmitterDelegate: CGMG7TransmitterDelegate, cGMTransmitterDelegate:CGMTransmitterDelegate) {

// assign addressname and name or expected devicename
// For G7 we don't listen for a specific device name. Dexcom uses an advertising id, which already filters out all other devices (like tv's etc. We will verify in another way that we have the current active G7, and not an old one, which is still near
// For G7/ONE+ we don't listen for a specific device name. Dexcom uses an advertising id, which already filters out all other devices (like tv's etc. We will verify in another way that we have the current active G7/ONE+, and not an old one, which is still near
var newAddressAndName: BluetoothTransmitter.DeviceAddressAndName = BluetoothTransmitter.DeviceAddressAndName.notYetConnected(expectedName: "DX")

if let name = name {
Expand Down Expand Up @@ -209,8 +209,20 @@ class CGMG7Transmitter: BluetoothTransmitter, CGMTransmitter {
trace(" failed to create G7GlucoseMessage", log: log, category: ConstantsLog.categoryCGMG7, type: .error )
return
}

trace(" received g7GlucoseMessage mesage, calculatedValue = %{public}@, timeStamp = %{public}@", log: log, category: ConstantsLog.categoryCGMG7, type: .info, g7GlucoseMessage.calculatedValue.description, g7GlucoseMessage.timeStamp.description(with: .current))

let maxSensorAgeInDays = ConstantsDexcomG7.maxSensorAgeInDays
let sensorAgeInDays = Double(round((g7GlucoseMessage.sensorAge / 3600 / 24) * 10) / 10)

// G7/ONE+ has the peculiarity that it will keep sending/repeating the same BG value (without ever changing) via BLE even after the session officially ends.
// to avoid this, let's check if the sensor is still within maxSensorAge before we continue
guard sensorAgeInDays < maxSensorAgeInDays else {
trace(" G7 is expired so will not process reading. sensorAge: %{public}@ / maxSensorAgeInDays: %{public}@", log: log, category: ConstantsLog.categoryCGMG7, type: .error, sensorAgeInDays.description, maxSensorAgeInDays.description)
return
}

trace(" received g7GlucoseMessage mesage, calculatedValue = %{public}@, timeStamp = %{public}@, sensorAge = %{public}@ / %{public}@", log: log, category: ConstantsLog.categoryCGMG7, type: .info, g7GlucoseMessage.calculatedValue.description, g7GlucoseMessage.timeStamp.description(with: .current))

trace(" received g7GlucoseMessage mesage, sensorAge = %{public}@ / %{public}@", log: log, category: ConstantsLog.categoryCGMG7, type: .info, sensorAgeInDays.description, maxSensorAgeInDays.description)

sensorAge = g7GlucoseMessage.sensorAge

Expand Down Expand Up @@ -253,7 +265,7 @@ class CGMG7Transmitter: BluetoothTransmitter, CGMTransmitter {
return
}

if let sensorAge = sensorAge, let dexcomG7BackfillMessage = DexcomG7BackfillMessage(data: value, sensorAge: sensorAge) {
if let sensorAge = sensorAge, sensorAge < (ConstantsDexcomG7.maxSensorAgeInDays * 24 * 3600), let dexcomG7BackfillMessage = DexcomG7BackfillMessage(data: value, sensorAge: sensorAge) {
trace(" received backfill mesage, calculatedValue = %{public}@, timeStamp = %{public}@", log: log, category: ConstantsLog.categoryCGMG7, type: .info, dexcomG7BackfillMessage.calculatedValue.description, dexcomG7BackfillMessage.timeStamp.description(with: .current))

backfill.append(GlucoseData(timeStamp: dexcomG7BackfillMessage.timeStamp, glucoseLevelRaw: dexcomG7BackfillMessage.calculatedValue))
Expand Down
4 changes: 2 additions & 2 deletions xdrip/BluetoothTransmitter/CGM/Generic/CGMTransmitter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,10 @@ enum CGMTransmitterType:String, CaseIterable {
case dexcomG4 = "Dexcom G4"

/// dexcom G5, G6
case dexcom = "Dexcom"
case dexcom = "Dexcom G5/G6/ONE"

/// dexcom G7
case dexcomG7 = "Dexcom G7"
case dexcomG7 = "Dexcom G7/ONE+"

/// miaomiao
case miaomiao = "MiaoMiao"
Expand Down
4 changes: 2 additions & 2 deletions xdrip/Constants/ConstantsDexcomG7.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ enum ConstantsDexcomG7 {
/// if there's a new connect within this period, but latest reading was less than this interval ago, then no need to request new reading
static let minimumTimeBetweenTwoReadings = TimeInterval(minutes: 2.1)

/// how many days the sensor session lasts
static let maxSensorAgeInDays: Double = 10.0
/// how many days the sensor session lasts. In the case of G7/ONE+ it is 10 days + a 12 hour grace period = 10.5 days
static let maxSensorAgeInDays: Double = 10.5

}
8 changes: 4 additions & 4 deletions xdrip/Constants/ConstantsHomeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ enum ConstantsHomeView {

/// urgent time left / colour
static let sensorProgressViewUrgentInMinutes: Double = 60 * 12.0 // 12 hours before the sensor reaches max age
static let sensorProgressViewProgressColorUrgent: UIColor = .red
static let sensorProgressViewProgressColorUrgentSwiftUI: Color = .red
static let sensorProgressViewProgressColorUrgent: UIColor = .orange
static let sensorProgressViewProgressColorUrgentSwiftUI: Color = .orange

/// colour for an expired sensor
static let sensorProgressExpired: UIColor = .purple
static let sensorProgressExpiredSwiftUI: Color = .purple
static let sensorProgressExpired: UIColor = .red
static let sensorProgressExpiredSwiftUI: Color = .red

/// colour for an normal text
static let sensorProgressNormalTextColor: UIColor = .lightGray
Expand Down
4 changes: 2 additions & 2 deletions xdrip/Managers/Alerts/AlertManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -822,8 +822,8 @@ public class AlertManager:NSObject {
return true

} else {
if !UserDefaults.standard.isMaster && !UserDefaults.standard.followerBackgroundKeepAliveType.shouldKeepAlive {
trace("in checkAlert, there's no need to raise alert %{public}@ because we're in follower mode and keep-alive is: %{public}@", log: self.log, category: ConstantsLog.categoryAlertManager, type: .info, alertKind.descriptionForLogging(), UserDefaults.standard.followerBackgroundKeepAliveType.description)
if !UserDefaults.standard.isMaster && UserDefaults.standard.followerBackgroundKeepAliveType == .disabled {
trace("in checkAlert, there's no need to raise alert '%{public}@' because we're in follower mode and keep-alive is disabled", log: self.log, category: ConstantsLog.categoryAlertManager, type: .info, alertKind.descriptionForLogging())
} else {
trace("in checkAlert, there's no need to raise alert %{public}@", log: self.log, category: ConstantsLog.categoryAlertManager, type: .info, alertKind.descriptionForLogging())
}
Expand Down
12 changes: 4 additions & 8 deletions xdrip/Managers/BluetoothPeripheral/AlgorithmType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,15 @@

import Foundation

/// types of live activity, namely when we should show the live activities
/// types of algorithms available to use
public enum AlgorithmType: Int, CaseIterable {

// when adding to LiveActivityType, add new cases at the end (ie 3, ...)
// if this is done in the middle then a database migration would be required, because the rawvalue is stored as Int16 in the coredata

case transmitterAlgorithm = 0
case nativeAlgorithm = 0
case xDripAlgorithm = 1

var description: String {
switch self {
case .transmitterAlgorithm:
return Texts_BluetoothPeripheralView.transmitterAlgorithm
case .nativeAlgorithm:
return Texts_BluetoothPeripheralView.nativeAlgorithm
case .xDripAlgorithm:
return Texts_BluetoothPeripheralView.xDripAlgorithm
}
Expand Down
31 changes: 9 additions & 22 deletions xdrip/Managers/ContactImage/ContactImageManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ class ContactImageManager: NSObject {
UserDefaults.standard.addObserver(self, forKeyPath: UserDefaults.Key.displayTrendInContactImage.rawValue, options: .new, context: nil)
UserDefaults.standard.addObserver(self, forKeyPath: UserDefaults.Key.useHighContrastContactImage.rawValue, options: .new, context: nil)
UserDefaults.standard.addObserver(self, forKeyPath: UserDefaults.Key.bloodGlucoseUnitIsMgDl.rawValue, options: .new, context: nil)
UserDefaults.standard.addObserver(self, forKeyPath: UserDefaults.Key.isMaster.rawValue, options: .new, context: nil)
UserDefaults.standard.addObserver(self, forKeyPath: UserDefaults.Key.followerBackgroundKeepAliveType.rawValue, options: .new, context: nil)


}
Expand Down Expand Up @@ -63,24 +65,7 @@ class ContactImageManager: NSObject {

/// used by observevalue for UserDefaults.Key
private func evaluateUserDefaultsChange(keyPathEnum: UserDefaults.Key) {
switch keyPathEnum {

case UserDefaults.Key.enableContactImage:
// if the user has enabled the option, then update the existing contact or add a new one if it doesn't exist
// this isn't really the best way to do it as we should delete the contact if
// not required to "clean up", but too many users didn't re-select the new contact after
// re-enabling in the Watch complication and assumed that the app wasn't working
if UserDefaults.standard.enableContactImage {
updateContact()
}

case UserDefaults.Key.displayTrendInContactImage, UserDefaults.Key.useHighContrastContactImage, UserDefaults.Key.bloodGlucoseUnitIsMgDl:
updateContact()

default:
break

}
updateContact()
}

/// this function will perform the following actions:
Expand All @@ -94,8 +79,6 @@ class ContactImageManager: NSObject {
self.workItem?.cancel()
self.workItem = nil

guard UserDefaults.standard.enableContactImage else { return }

// check that access to contacts is authorized by the user
guard CNContactStore.authorizationStatus(for: .contacts) == .authorized else {
trace("in updateContact, access to contacts is not authorized, setting enableContactImage to false", log: self.log, category: ConstantsLog.categoryContactImageManager, type: .info)
Expand All @@ -109,10 +92,14 @@ class ContactImageManager: NSObject {
let lastReading = self.bgReadingsAccessor.get2LatestBgReadings(minimumTimeIntervalInMinutes: 4.0)
var contactImageView: ContactImageView

// disable the image (show "OFF") if the function is disabled or if the user is in follower mode with background keep-alive disabled
// as otherwise it would always be out of date
let disableContactImage: Bool = !UserDefaults.standard.enableContactImage || (!UserDefaults.standard.isMaster && UserDefaults.standard.followerBackgroundKeepAliveType == .disabled)

if lastReading.count > 0 {
let valueIsUpToDate = abs(lastReading[0].timeStamp.timeIntervalSinceNow) < 7 * 60

contactImageView = ContactImageView(bgValue: lastReading[0].calculatedValue, isMgDl: UserDefaults.standard.bloodGlucoseUnitIsMgDl, slopeArrow: UserDefaults.standard.displayTrendInContactImage ? lastReading[0].slopeArrow() : "", bgRangeDescription: lastReading[0].bgRangeDescription(), valueIsUpToDate: valueIsUpToDate, useHighContrastContactImage: UserDefaults.standard.useHighContrastContactImage)
contactImageView = ContactImageView(bgValue: lastReading[0].calculatedValue, isMgDl: UserDefaults.standard.bloodGlucoseUnitIsMgDl, slopeArrow: UserDefaults.standard.displayTrendInContactImage ? lastReading[0].slopeArrow() : "", bgRangeDescription: lastReading[0].bgRangeDescription(), valueIsUpToDate: valueIsUpToDate, useHighContrastContactImage: UserDefaults.standard.useHighContrastContactImage, disableContactImage: disableContactImage)

// schedule an update in 5 min 15 seconds - if no new data is received until then, the empty value will get rendered into the contact (this update will be canceled if new data is received)
self.workItem = DispatchWorkItem(block: {
Expand All @@ -123,7 +110,7 @@ class ContactImageManager: NSObject {
DispatchQueue.main.asyncAfter(deadline: .now() + (5 * 60) + 15, execute: self.workItem!)
} else {
// create an 'empty' image view if there is no BG data to show
contactImageView = ContactImageView(bgValue: 0, isMgDl: UserDefaults.standard.bloodGlucoseUnitIsMgDl, slopeArrow: "", bgRangeDescription: .inRange, valueIsUpToDate: false, useHighContrastContactImage: false)
contactImageView = ContactImageView(bgValue: 0, isMgDl: UserDefaults.standard.bloodGlucoseUnitIsMgDl, slopeArrow: "", bgRangeDescription: .inRange, valueIsUpToDate: false, useHighContrastContactImage: false, disableContactImage: disableContactImage)
}

// we're going to use the app name as the given name of the contact we want to use/create/update
Expand Down
13 changes: 7 additions & 6 deletions xdrip/Managers/LibreLinkUp/LibreLinkUpFollowManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ class LibreLinkUpFollowManager: NSObject {
let graphResponse = try await requestGraph(patientId: patientId)

// before processing the glucoseMeasurement values, let's set up the sensor info in coredata so that we can show it to the user in the settings screen
// starting with LLU 4.12.0 this data sometimes isn't sent for some users so we'll try and use it if available and if not, just continue as normal without throwing an error
if let startDate = graphResponse.data?.activeSensors?.first?.sensor?.a,
let serialNumber = graphResponse.data?.activeSensors?.first?.sensor?.sn {

Expand All @@ -266,12 +267,12 @@ class LibreLinkUpFollowManager: NSObject {
if serialNumber.range(of: #"^MH"#, options: .regularExpression) != nil {

// MHxxxxxxxx
// must be a L2 sensor
// must be a L2 (or Libre 2 Plus) sensor
activeSensorDescription = "Libre 2"

} else if serialNumber.range(of: #"^0D"#, options: .regularExpression) != nil || serialNumber.range(of: #"^0E"#, options: .regularExpression) != nil || serialNumber.range(of: #"^0F"#, options: .regularExpression) != nil{

// must be a Libre 3 sensor
// must be a Libre 3 (or Libre 3 Plus) sensor
activeSensorDescription = "Libre 3"

}
Expand All @@ -281,9 +282,12 @@ class LibreLinkUpFollowManager: NSObject {
} else {

// this will only happen if the account doesn't have an active sensor connected
// reset the data just in case it was previously stored
resetActiveSensorData()

throw LibreLinkUpFollowError.generalError
// for some reason no active sensor data was sent by the server. This seems to sometimes happen since LLU v4.12.0 for some users and for some (unknown) reason.
// instead of throwing an error, we'll just continue as normal and hide later (in the UI) the sensor information
trace(" in download, no active sensor data was returned by the server so just process the values if any", log: self.log, category: ConstantsLog.categoryLibreLinkUpFollowManager, type: .info)

}

Expand All @@ -305,9 +309,6 @@ class LibreLinkUpFollowManager: NSObject {
followerDelegate.followerInfoReceived(followGlucoseDataArray: &followGlucoseDataArray)
}

// schedule new download
//self.scheduleNewDownload()

}

}
Expand Down
Loading

0 comments on commit 2117f5c

Please sign in to comment.