snooze parameters being stored in core data

This commit is contained in:
Johan Degraeve 2020-10-10 22:01:47 +02:00
parent b1fc7c3ffe
commit 03381e60cb
10 changed files with 345 additions and 27 deletions

View File

@ -239,6 +239,9 @@
F85DC2F521CFE3D400B9F74A /* BgReading+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = F85DC2F221CFE3D400B9F74A /* BgReading+CoreDataClass.swift */; };
F85FF39125288870004E6FF1 /* HouseKeeper.swift in Sources */ = {isa = PBXBuildFile; fileRef = F85FF39025288870004E6FF1 /* HouseKeeper.swift */; };
F85FF3C4252D0C32004E6FF1 /* xdrip.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = F85FF3C2252D0C32004E6FF1 /* xdrip.xcdatamodeld */; };
F85FF3CD252F9FD7004E6FF1 /* SnoozeParameters+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = F85FF3CC252F9FD7004E6FF1 /* SnoozeParameters+CoreDataProperties.swift */; };
F85FF3D1252F9FF9004E6FF1 /* SnoozeParameters+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = F85FF3D0252F9FF9004E6FF1 /* SnoozeParameters+CoreDataClass.swift */; };
F85FF3D7252FB1C0004E6FF1 /* SnoozeParametersAccessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = F85FF3D6252FB1C0004E6FF1 /* SnoozeParametersAccessor.swift */; };
F867E2612252ADAB000FD265 /* Calibration+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = F867E25D2252ADAB000FD265 /* Calibration+CoreDataProperties.swift */; };
F8691888239CEEFA0065B607 /* BluetoothPeripheralViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8691887239CEEFA0065B607 /* BluetoothPeripheralViewModel.swift */; };
F869188C23A044340065B607 /* TextsM5StackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F869188B23A044340065B607 /* TextsM5StackView.swift */; };
@ -746,6 +749,10 @@
F85DC2F221CFE3D400B9F74A /* BgReading+CoreDataClass.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "BgReading+CoreDataClass.swift"; sourceTree = "<group>"; };
F85FF39025288870004E6FF1 /* HouseKeeper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HouseKeeper.swift; sourceTree = "<group>"; };
F85FF3C3252D0C32004E6FF1 /* xdrip v12.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "xdrip v12.xcdatamodel"; sourceTree = "<group>"; };
F85FF3CB252F9C9A004E6FF1 /* xdrip v13.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "xdrip v13.xcdatamodel"; sourceTree = "<group>"; };
F85FF3CC252F9FD7004E6FF1 /* SnoozeParameters+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SnoozeParameters+CoreDataProperties.swift"; sourceTree = "<group>"; };
F85FF3D0252F9FF9004E6FF1 /* SnoozeParameters+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SnoozeParameters+CoreDataClass.swift"; sourceTree = "<group>"; };
F85FF3D6252FB1C0004E6FF1 /* SnoozeParametersAccessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnoozeParametersAccessor.swift; sourceTree = "<group>"; };
F867E25D2252ADAB000FD265 /* Calibration+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "Calibration+CoreDataProperties.swift"; path = "xdrip/Core Data/extensions/Calibration+CoreDataProperties.swift"; sourceTree = SOURCE_ROOT; };
F8691887239CEEFA0065B607 /* BluetoothPeripheralViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BluetoothPeripheralViewModel.swift; sourceTree = "<group>"; };
F869188B23A044340065B607 /* TextsM5StackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextsM5StackView.swift; sourceTree = "<group>"; };
@ -1869,6 +1876,7 @@
F8B3A819227DEC92004BA588 /* README.md */,
F8B3A815227DEC91004BA588 /* SensorsAccessor.swift */,
F8DF766323E781C100063910 /* BLEPeripheralAccessor.swift */,
F85FF3D6252FB1C0004E6FF1 /* SnoozeParametersAccessor.swift */,
);
path = accessors;
sourceTree = "<group>";
@ -2167,6 +2175,8 @@
F8C97852242AA70C00A09483 /* MiaoMiao+CoreDataProperties.swift */,
F85DC2F121CFE3D400B9F74A /* Sensor+CoreDataClass.swift */,
F85DC2E921CFE2F500B9F74A /* Sensor+CoreDataProperties.swift */,
F85FF3D0252F9FF9004E6FF1 /* SnoozeParameters+CoreDataClass.swift */,
F85FF3CC252F9FD7004E6FF1 /* SnoozeParameters+CoreDataProperties.swift */,
F830991A23C2909E005741DF /* Watlaa+CoreDataClass.swift */,
F830991B23C2909E005741DF /* Watlaa+CoreDataProperties.swift */,
);
@ -2863,6 +2873,7 @@
F816E1002436734C009EE65B /* CGMGNSEntryTransmitterDelegate.swift in Sources */,
F8C97853242AA70D00A09483 /* MiaoMiao+CoreDataClass.swift in Sources */,
F8F9720D23A5915900C3F17D /* ResetMessage.swift in Sources */,
F85FF3D7252FB1C0004E6FF1 /* SnoozeParametersAccessor.swift in Sources */,
F8C97856242AA86B00A09483 /* CGMMiaoMiaoTransmitterDelegate.swift in Sources */,
F898EDF6234A8A5700BFB79B /* UInt32.swift in Sources */,
F816E0F32433DAA9009EE65B /* BluetoothPeripheralManager+CGMBluconTransmitterDelegate.swift in Sources */,
@ -2988,6 +2999,7 @@
F8F9720A23A5915900C3F17D /* DexcomTransmitterOpCode.swift in Sources */,
F8AC425E21ADEBD60078C348 /* AppDelegate.swift in Sources */,
F804870D2336D90200EBDDB7 /* M5Stack+CoreDataProperties.swift in Sources */,
F85FF3CD252F9FD7004E6FF1 /* SnoozeParameters+CoreDataProperties.swift in Sources */,
F8F9722F23A5915900C3F17D /* M5StackPacket.swift in Sources */,
F897E25223FC871C0075E0E8 /* BluetoothPeripheralManager+BluetoothTransmitterDelegate.swift in Sources */,
F821CF8E22AB090C005C1E43 /* DatePickerViewController.swift in Sources */,
@ -3133,6 +3145,7 @@
F816E0ED2432A55F009EE65B /* BluconBluetoothPeripheralViewModel.swift in Sources */,
F8F9722923A5915900C3F17D /* CGMTransmitter.swift in Sources */,
F8A389ED23342EB10010F405 /* ConstantsNightScout.swift in Sources */,
F85FF3D1252F9FF9004E6FF1 /* SnoozeParameters+CoreDataClass.swift in Sources */,
F890E07A247687AE008FB2EC /* URL.swift in Sources */,
F8B3A856227F28DC004BA588 /* AlertTypeSettingsViewController.swift in Sources */,
F8A1584F22ECB281007F5B5D /* SettingsViewInfoViewModel.swift in Sources */,
@ -3691,9 +3704,10 @@
F85FF3C2252D0C32004E6FF1 /* xdrip.xcdatamodeld */ = {
isa = XCVersionGroup;
children = (
F85FF3CB252F9C9A004E6FF1 /* xdrip v13.xcdatamodel */,
F85FF3C3252D0C32004E6FF1 /* xdrip v12.xcdatamodel */,
);
currentVersion = F85FF3C3252D0C32004E6FF1 /* xdrip v12.xcdatamodel */;
currentVersion = F85FF3CB252F9C9A004E6FF1 /* xdrip v13.xcdatamodel */;
path = xdrip.xcdatamodeld;
sourceTree = "<group>";
versionGroupType = wrapper.xcdatamodel;

View File

@ -139,5 +139,8 @@ enum ConstantsLog {
/// housekeeping
static let categoryHouseKeeper = "HouseKeeper "
/// soonzeParameter accessor
static let categoryApplicationDataSnoozeParameter = "ApplicationDataSnoozeParameter"
}

View File

@ -0,0 +1,65 @@
import Foundation
import CoreData
import os
class SnoozeParametersAccessor {
// MARK: - Properties
/// CoreDataManager to use
private let coreDataManager:CoreDataManager
/// for logging
private var log = OSLog(subsystem: ConstantsLog.subSystem, category: ConstantsLog.categoryApplicationDataSnoozeParameter)
// MARK: - initializer
init(coreDataManager:CoreDataManager) {
self.coreDataManager = coreDataManager
}
// MARK: Public functions
/// - gets all SnoozeParameters instances from coredata
/// - if this the first call to this function (ie no SnoozeParameters stored yet in coredata), then they will be created for every AlertKind
/// - sorts them by AlertKind.rawvalue (from low to high), ie from 0 to (verylow) to 8 (fastrise)
func getSnoozeParameters() -> [SnoozeParameters] {
// create fetchRequest to get SnoozeParameters's as SnoozeParameters classes
let snoozeParametersFetchRequest: NSFetchRequest<SnoozeParameters> = SnoozeParameters.fetchRequest()
// sort by alertkind from low to high
snoozeParametersFetchRequest.sortDescriptors = [NSSortDescriptor(key: #keyPath(SnoozeParameters.alertKind), ascending: true)]
// fetch the SnoozeParameterss
var snoozeParameterArray = [SnoozeParameters]()
coreDataManager.mainManagedObjectContext.performAndWait {
do {
// Execute Fetch Request
snoozeParameterArray = try snoozeParametersFetchRequest.execute()
} catch {
let fetchError = error as NSError
trace("in getSnoozeParameterss, Unable to Execute SnoozeParameterss Fetch Request : %{public}@", log: self.log, category: ConstantsLog.categoryApplicationDataSnoozeParameter, type: .error, fetchError.localizedDescription)
}
}
// snoozeParameters are ordered by alertKind so goes from 0 to highest value
// but maybe some (or all) are missing
// if some are missing, then it's either because it's the first time this app runs
// or it's because new alertKind's have been added, in which case it's at the end of the range they are added
for index in snoozeParameterArray.count..<AlertKind.allCases.count {
if let alertKind = AlertKind(rawValue: index) {
snoozeParameterArray.append(SnoozeParameters(alertKind: alertKind, snoozePeriodInMinutes: 0, snoozeTimeStamp: nil, nsManagedObjectContext: coreDataManager.mainManagedObjectContext))
}
}
return snoozeParameterArray
}
}

View File

@ -0,0 +1,25 @@
import Foundation
import CoreData
/// maps to SnoozeParameters
public class SnoozeParameters: NSManagedObject {
init(
alertKind:AlertKind,
snoozePeriodInMinutes: Int16,
snoozeTimeStamp: Date?,
nsManagedObjectContext:NSManagedObjectContext
) {
let entity = NSEntityDescription.entity(forEntityName: "SnoozeParameters", in: nsManagedObjectContext)!
super.init(entity: entity, insertInto: nsManagedObjectContext)
self.snoozePeriodInMinutes = snoozePeriodInMinutes
self.alertKind = Int16(alertKind.rawValue)
self.snoozeTimeStamp = snoozeTimeStamp
}
private override init(entity: NSEntityDescription, insertInto context: NSManagedObjectContext?) {
super.init(entity: entity, insertInto: context)
}
}

View File

@ -0,0 +1,29 @@
//
// SnoozeParameters+CoreDataProperties.swift
// xdrip
//
// Created by Johan Degraeve on 14/04/2019.
// Copyright © 2019 Johan Degraeve. All rights reserved.
//
//
import Foundation
import CoreData
extension SnoozeParameters {
@nonobjc public class func fetchRequest() -> NSFetchRequest<SnoozeParameters> {
return NSFetchRequest<SnoozeParameters>(entityName: "SnoozeParameters")
}
/// the alertKind for which these snooze parameters are applicable
@NSManaged public var alertKind: Int16
/// this is snooze period chosen by user, nil value is not snoozed
@NSManaged public var snoozePeriodInMinutes:Int16
/// when was the alert snoozed, nil is not snoozed
@NSManaged public var snoozeTimeStamp:Date?
}

View File

@ -3,6 +3,6 @@
<plist version="1.0">
<dict>
<key>_XCCurrentVersionName</key>
<string>xdrip v12.xcdatamodel</string>
<string>xdrip v13.xcdatamodel</string>
</dict>
</plist>

View File

@ -0,0 +1,178 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="17192" systemVersion="19H2" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<entity name="AlertEntry" representedClassName=".AlertEntry" syncable="YES">
<attribute name="alertkind" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="start" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="value" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/>
<relationship name="alertType" maxCount="1" deletionRule="Nullify" destinationEntity="AlertType" inverseName="alertEntries" inverseEntity="AlertType"/>
</entity>
<entity name="AlertType" representedClassName=".AlertType" syncable="YES">
<attribute name="enabled" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="name" attributeType="String"/>
<attribute name="overridemute" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="snooze" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="snoozeperiod" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="soundname" optional="YES" attributeType="String"/>
<attribute name="vibrate" attributeType="Boolean" usesScalarValueType="YES"/>
<relationship name="alertEntries" optional="YES" toMany="YES" deletionRule="Deny" destinationEntity="AlertEntry" inverseName="alertType" inverseEntity="AlertEntry"/>
</entity>
<entity name="BgReading" representedClassName=".BgReading" syncable="YES">
<attribute name="a" attributeType="Double" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="ageAdjustedRawValue" attributeType="Double" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="b" attributeType="Double" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="c" attributeType="Double" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="calculatedValue" attributeType="Double" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="calculatedValueSlope" attributeType="Double" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="calibrationFlag" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="deviceName" optional="YES" attributeType="String"/>
<attribute name="filteredCalculatedValue" attributeType="Double" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="filteredData" attributeType="Double" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="hideSlope" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="id" attributeType="String"/>
<attribute name="ra" attributeType="Double" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="rawData" attributeType="Double" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="rb" attributeType="Double" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="rc" attributeType="Double" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="timeStamp" attributeType="Date" usesScalarValueType="NO"/>
<relationship name="calibration" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Calibration" inverseName="bgreadings" inverseEntity="Calibration"/>
<relationship name="sensor" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Sensor" inverseName="readings" inverseEntity="Sensor"/>
</entity>
<entity name="BLEPeripheral" representedClassName=".BLEPeripheral" syncable="YES">
<attribute name="address" attributeType="String"/>
<attribute name="alias" optional="YES" attributeType="String"/>
<attribute name="lastConnectionStatusChangeTimeStamp" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="name" attributeType="String"/>
<attribute name="nonFixedSlopeEnabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="parameterUpdateNeededAtNextConnect" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="sensorSerialNumber" optional="YES" attributeType="String"/>
<attribute name="shouldconnect" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="transmitterId" optional="YES" attributeType="String"/>
<attribute name="webOOPEnabled" attributeType="Boolean" usesScalarValueType="YES"/>
<relationship name="blucon" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="Blucon" inverseName="blePeripheral" inverseEntity="Blucon"/>
<relationship name="blueReader" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="BlueReader" inverseName="blePeripheral" inverseEntity="BlueReader"/>
<relationship name="bubble" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="Bubble" inverseName="blePeripheral" inverseEntity="Bubble"/>
<relationship name="dexcomG4" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="DexcomG4" inverseName="blePeripheral" inverseEntity="DexcomG4"/>
<relationship name="dexcomG5" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="DexcomG5" inverseName="blePeripheral" inverseEntity="DexcomG5"/>
<relationship name="droplet" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Droplet" inverseName="blePeripheral" inverseEntity="Droplet"/>
<relationship name="gNSEntry" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="GNSEntry" inverseName="blePeripheral" inverseEntity="GNSEntry"/>
<relationship name="libre2" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="Libre2" inverseName="blePeripheral" inverseEntity="Libre2"/>
<relationship name="m5Stack" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="M5Stack" inverseName="blePeripheral" inverseEntity="M5Stack"/>
<relationship name="miaoMiao" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="MiaoMiao" inverseName="blePeripheral" inverseEntity="MiaoMiao"/>
<relationship name="watlaa" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="Watlaa" inverseName="blePeripheral" inverseEntity="Watlaa"/>
</entity>
<entity name="Blucon" representedClassName=".Blucon" syncable="YES">
<attribute name="timeStampLastBgReading" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<relationship name="blePeripheral" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="BLEPeripheral" inverseName="blucon" inverseEntity="BLEPeripheral"/>
</entity>
<entity name="BlueReader" representedClassName=".BlueReader" syncable="YES">
<relationship name="blePeripheral" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="BLEPeripheral" inverseName="blueReader" inverseEntity="BLEPeripheral"/>
</entity>
<entity name="Bubble" representedClassName=".Bubble" syncable="YES">
<attribute name="firmware" optional="YES" attributeType="String"/>
<attribute name="hardware" optional="YES" attributeType="String"/>
<attribute name="timeStampLastBgReading" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<relationship name="blePeripheral" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="BLEPeripheral" inverseName="bubble" inverseEntity="BLEPeripheral"/>
</entity>
<entity name="Calibration" representedClassName=".Calibration" syncable="YES">
<attribute name="adjustedRawValue" attributeType="Double" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="bg" attributeType="Double" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="deviceName" optional="YES" attributeType="String"/>
<attribute name="distanceFromEstimate" attributeType="Double" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="estimateRawAtTimeOfCalibration" attributeType="Double" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="id" attributeType="String"/>
<attribute name="intercept" attributeType="Double" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="possibleBad" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="rawTimeStamp" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="rawValue" attributeType="Double" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="sensorConfidence" attributeType="Double" usesScalarValueType="YES"/>
<attribute name="slope" attributeType="Double" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="slopeConfidence" attributeType="Double" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="timeStamp" attributeType="Date" usesScalarValueType="NO"/>
<relationship name="bgreadings" toMany="YES" deletionRule="Deny" destinationEntity="BgReading" inverseName="calibration" inverseEntity="BgReading"/>
<relationship name="sensor" maxCount="1" deletionRule="Nullify" destinationEntity="Sensor" inverseName="calibrations" inverseEntity="Sensor"/>
</entity>
<entity name="DexcomG4" representedClassName=".DexcomG4" syncable="YES">
<relationship name="blePeripheral" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="BLEPeripheral" inverseName="dexcomG4" inverseEntity="BLEPeripheral"/>
</entity>
<entity name="DexcomG5" representedClassName=".DexcomG5" syncable="YES">
<attribute name="batteryResist" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="batteryRuntime" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="batteryStatus" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="batteryTemperature" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="firmwareVersion" optional="YES" attributeType="String"/>
<attribute name="isDexcomG6" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="lastResetTimeStamp" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="voltageA" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="voltageB" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<relationship name="blePeripheral" maxCount="1" deletionRule="Cascade" destinationEntity="BLEPeripheral" inverseName="dexcomG5" inverseEntity="BLEPeripheral"/>
</entity>
<entity name="Droplet" representedClassName=".Droplet" syncable="YES">
<relationship name="blePeripheral" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="BLEPeripheral" inverseName="droplet" inverseEntity="BLEPeripheral"/>
</entity>
<entity name="GNSEntry" representedClassName=".GNSEntry" syncable="YES">
<attribute name="bootLoader" optional="YES" attributeType="String"/>
<attribute name="firmwareVersion" optional="YES" attributeType="String"/>
<attribute name="serialNumber" optional="YES" attributeType="String"/>
<attribute name="timeStampLastBgReading" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<relationship name="blePeripheral" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="BLEPeripheral" inverseName="gNSEntry" inverseEntity="BLEPeripheral"/>
</entity>
<entity name="Libre2" representedClassName=".Libre2" syncable="YES">
<attribute name="timeStampLastBgReading" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<relationship name="blePeripheral" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="BLEPeripheral" inverseName="libre2" inverseEntity="BLEPeripheral"/>
</entity>
<entity name="M5Stack" representedClassName=".M5Stack" syncable="YES">
<attribute name="backGroundColor" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="blepassword" optional="YES" attributeType="String"/>
<attribute name="brightness" optional="YES" attributeType="Integer 16" defaultValueString="100" usesScalarValueType="YES"/>
<attribute name="connectToWiFi" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="isM5StickC" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="rotation" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="textcolor" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<relationship name="blePeripheral" maxCount="1" deletionRule="Cascade" destinationEntity="BLEPeripheral" inverseName="m5Stack" inverseEntity="BLEPeripheral"/>
</entity>
<entity name="MiaoMiao" representedClassName=".MiaoMiao" syncable="YES">
<attribute name="firmware" optional="YES" attributeType="String"/>
<attribute name="hardware" optional="YES" attributeType="String"/>
<attribute name="timeStampLastBgReading" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<relationship name="blePeripheral" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="BLEPeripheral" inverseName="miaoMiao" inverseEntity="BLEPeripheral"/>
</entity>
<entity name="Sensor" representedClassName=".Sensor" syncable="YES">
<attribute name="endDate" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="id" attributeType="String"/>
<attribute name="startDate" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="uploadedToNS" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<relationship name="calibrations" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Calibration" inverseName="sensor" inverseEntity="Calibration"/>
<relationship name="readings" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="BgReading" inverseName="sensor" inverseEntity="BgReading"/>
</entity>
<entity name="SnoozeParameters" representedClassName=".SnoozeParameters" syncable="YES">
<attribute name="alertKind" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="snoozePeriodInMinutes" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="snoozeTimeStamp" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
</entity>
<entity name="Watlaa" representedClassName=".Watlaa" syncable="YES">
<attribute name="firmware" optional="YES" attributeType="String"/>
<attribute name="hardware" optional="YES" attributeType="String"/>
<attribute name="timeStampLastBgReading" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<relationship name="blePeripheral" maxCount="1" deletionRule="Cascade" destinationEntity="BLEPeripheral" inverseName="watlaa" inverseEntity="BLEPeripheral"/>
</entity>
<elements>
<element name="AlertEntry" positionX="-648" positionY="189" width="128" height="28"/>
<element name="AlertType" positionX="-657" positionY="180" width="128" height="28"/>
<element name="BgReading" positionX="-285.87109375" positionY="31.9921875" width="128" height="330"/>
<element name="BLEPeripheral" positionX="-630" positionY="216" width="128" height="358"/>
<element name="Blucon" positionX="-657" positionY="189" width="128" height="73"/>
<element name="BlueReader" positionX="-639" positionY="207" width="128" height="58"/>
<element name="Bubble" positionX="-657" positionY="189" width="128" height="103"/>
<element name="Calibration" positionX="-859.21484375" positionY="46.21484375" width="128" height="285"/>
<element name="DexcomG4" positionX="-621" positionY="225" width="128" height="58"/>
<element name="DexcomG5" positionX="-648" positionY="198" width="128" height="193"/>
<element name="Droplet" positionX="-630" positionY="216" width="128" height="58"/>
<element name="GNSEntry" positionX="-648" positionY="198" width="128" height="118"/>
<element name="Libre2" positionX="-648" positionY="198" width="128" height="73"/>
<element name="M5Stack" positionX="-657" positionY="180" width="128" height="163"/>
<element name="MiaoMiao" positionX="-657" positionY="189" width="128" height="103"/>
<element name="Sensor" positionX="-603.0859375" positionY="482.2890625" width="128" height="133"/>
<element name="Watlaa" positionX="-639" positionY="207" width="128" height="103"/>
<element name="SnoozeParameters" positionX="-648" positionY="198" width="128" height="28"/>
</elements>
</model>

View File

@ -4,7 +4,7 @@ import Foundation
public enum AlertKind:Int, CaseIterable {
// when adding alertkinds, add new cases at the end (ie 9, ...)
// if this is done in the middle ((eg rapid rise alert might seem better positioned after veryhigh), then a database migration would be required, because the rawvalue is stored as Int16 in the coredata, namely the alertkind
// if this is done in the middle ((eg rapid rise alert might seem better positioned after veryhigh), then a database migration would be required, because the rawvalue is stored as Int16 in the coredata, namely the alertkind - and also in SnoozeParameters
// the order of the alerts will in the uiview is determined by the initializer init(forRowAt row: Int)
case verylow = 0

View File

@ -39,7 +39,7 @@ public class AlertManager:NSObject {
private var soundPlayer:SoundPlayer?
/// snooze parameters
private var snoozeParameters = [Int: SnoozeParameters]()
private var snoozeParameters = [SnoozeParameters]()
/// helper array with all alert notification identifiers
private var alertNotificationIdentifers = [String]()
@ -47,6 +47,9 @@ public class AlertManager:NSObject {
/// permanent reference to notificationcenter
private let uNUserNotificationCenter:UNUserNotificationCenter
// coredataManager instance
private var coreDataManager: CoreDataManager
/// snooze times in minutes
private let snoozeValueMinutes = [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 75, 90, 120, 150, 180, 240, 300, 360, 420, 480, 540, 600, 1440, 10080]
@ -69,14 +72,13 @@ public class AlertManager:NSObject {
self.sensorsAccessor = SensorsAccessor(coreDataManager: coreDataManager)
self.soundPlayer = soundPlayer
self.uNUserNotificationCenter = UNUserNotificationCenter.current()
self.coreDataManager = coreDataManager
// call super.init
super.init()
// initialize snoozeparameters
for alertKind in AlertKind.allCases {
snoozeParameters[alertKind.rawValue] = SnoozeParameters()
}
snoozeParameters = SnoozeParametersAccessor(coreDataManager: coreDataManager).getSnoozeParameters()
// in snoozeValueStrings, replace all occurrences of minutes, minute, etc... by language dependent value
for (index, _) in snoozeValueStrings.enumerated() {
@ -215,6 +217,9 @@ public class AlertManager:NSObject {
snooze(alertKind: alertKind, snoozePeriodInMinutes: Int(currentAlertEntry.alertType.snoozeperiod), response: response)
// save changes in coredata
coreDataManager.saveChanges()
case UNNotificationDefaultActionIdentifier:
trace("in userNotificationCenter, received actionIdentifier : UNNotificationDefaultActionIdentifier (user clicked the notification which opens the app, but not the snooze action in this notification)", log: self.log, category: ConstantsLog.categoryAlertManager, type: .info)
@ -230,6 +235,8 @@ public class AlertManager:NSObject {
// if it's a missed reading alert, let's replan it in 5 minutes
if alertKind == .missedreading {
snooze(alertKind: .missedreading, snoozePeriodInMinutes: 5, response: response)
// save changes in coredata
coreDataManager.saveChanges()
}
default:
@ -247,11 +254,7 @@ public class AlertManager:NSObject {
/// get the snoozeParameter for the alertKind
public func getSnoozeParameters(alertKind: AlertKind) -> SnoozeParameters {
if let snoozeParameters = snoozeParameters[alertKind.rawValue] {
return snoozeParameters
} else {
fatalError("in snoozeParameters(alertKind: AlertKind) -> SnoozeParameters, failed to get snoozeparameters for alertKind")
}
return snoozeParameters[alertKind.rawValue]
}
/// Function to be called that receives the notification actions. Will handle the response. completionHandler will not necessarily be called. Only if the identifier (response.notification.request.identifier) is one of the alert notification identifers, then it will handle the response and also call completionhandler.
@ -287,6 +290,9 @@ public class AlertManager:NSObject {
// unsnooze
getSnoozeParameters(alertKind: alertKind).unSnooze()
// save changes in coredata
coreDataManager.saveChanges()
}
/// creates PickerViewData which allows user to snooze an alert.
@ -324,7 +330,10 @@ public class AlertManager:NSObject {
// snooze
trace(" snoozing alert %{public}@ for %{public}@ minutes (1)", log: self.log, category: ConstantsLog.categoryAlertManager, type: .info, alertKind.descriptionForLogging(), snoozePeriod.description)
self.getSnoozeParameters(alertKind: alertKind).snooze(snoozePeriodInMinutes: snoozePeriod)
// save changes in coredata
self.coreDataManager.saveChanges()
// if it's a missed reading alert, then cancel any planned missed reading alerts and reschedule
// if content is not nil, then it means a missed reading alert went off, the user clicked it, app opens, user clicks snooze, snoozing must be set
// if content is nil, then this is an alert snoozed via presnooze button, missed reading alert needs to recalculated.
@ -470,9 +479,9 @@ public class AlertManager:NSObject {
switch alertKind {
case .missedreading: // any alert type that would be configured with a delay
if let snoozePeriodInMinutes = getSnoozeParameters(alertKind: alertKind).snoozePeriodInMinutes, let snoozeTimeStamp = getSnoozeParameters(alertKind: alertKind).snoozeTimeStamp {
if getSnoozeParameters(alertKind: alertKind).snoozePeriodInMinutes > 0, let snoozeTimeStamp = getSnoozeParameters(alertKind: alertKind).snoozeTimeStamp {
minimumDelayInSecondsToUse = -Int(Date().timeIntervalSince(Date(timeInterval: TimeInterval(snoozePeriodInMinutes * 60), since: snoozeTimeStamp)).rawValue)
minimumDelayInSecondsToUse = -Int(Date().timeIntervalSince(Date(timeInterval: TimeInterval(getSnoozeParameters(alertKind: alertKind).snoozePeriodInMinutes * 60), since: snoozeTimeStamp)).rawValue)
trace("in checkAlertAndFire, minimumDelayInSecondsToUse = %{public}@" , log: log, category: ConstantsLog.categoryAlertManager, type: .info, minimumDelayInSecondsToUse!.description)
} // if snoozePeriodInMinutes or snoozeTimeStamp is nil (which shouldn't be the case) continue without taking into account the snooze status
@ -681,6 +690,9 @@ public class AlertManager:NSObject {
getSnoozeParameters(alertKind: alertKind).snooze(snoozePeriodInMinutes: snoozePeriodInMinutes)
trace("Snoozing alert %{public}@ for %{public}@ minutes (2)", log: log, category: ConstantsLog.categoryAlertManager, type: .info, alertKind.descriptionForLogging(), snoozePeriodInMinutes.description)
// save changes in coredata
coreDataManager.saveChanges()
}
}

View File

@ -1,27 +1,19 @@
import Foundation
public class SnoozeParameters {
// MARK: private properties
/// this is snooze period chosen by user, nil value is not snoozed
private(set) var snoozePeriodInMinutes:Int?
/// when was the alert snoozed, nil is not snoozed
private(set) var snoozeTimeStamp:Date?
extension SnoozeParameters {
// MARK: public functions
/// store snoozeperiod in minutes, snoozetimestamp = now,
public func snooze(snoozePeriodInMinutes:Int) {
self.snoozePeriodInMinutes = snoozePeriodInMinutes
self.snoozePeriodInMinutes = Int16(snoozePeriodInMinutes)
snoozeTimeStamp = Date()
}
/// reset snooze, ie not snoozed
public func unSnooze() {
snoozePeriodInMinutes = nil
snoozePeriodInMinutes = 0
snoozeTimeStamp = nil
}
@ -30,7 +22,7 @@ public class SnoozeParameters {
/// - isSnoozed : is the alert snoozed
/// - remainingSeconds : if the alert is snoozed, then this says how many seconds remaining
public func getSnoozeValue() -> (isSnoozed:Bool, remainingSeconds:Int?) {
if let snoozeTimeStamp = snoozeTimeStamp, let snoozePeriodInMinutes = snoozePeriodInMinutes {
if let snoozeTimeStamp = snoozeTimeStamp, snoozePeriodInMinutes > 0 {
if Date(timeInterval: TimeInterval(snoozePeriodInMinutes * 60), since: snoozeTimeStamp) < Date() {
// snooze attributes are set, however they are expired
unSnooze() // set attributes to nil