database module
This commit is contained in:
parent
230cc943af
commit
b04862f602
|
@ -235,6 +235,7 @@ dependencies {
|
||||||
wearApp project(':wear')
|
wearApp project(':wear')
|
||||||
|
|
||||||
implementation project(':core')
|
implementation project(':core')
|
||||||
|
implementation project(':database')
|
||||||
implementation project(':dana')
|
implementation project(':dana')
|
||||||
implementation project(':danars')
|
implementation project(':danars')
|
||||||
implementation project(':danar')
|
implementation project(':danar')
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
ext {
|
ext {
|
||||||
kotlin_version = '1.4.21'
|
kotlin_version = '1.4.30'
|
||||||
coreVersion = '1.3.2'
|
coreVersion = '1.3.2'
|
||||||
rxjava_version = '2.2.19'
|
rxjava_version = '2.2.20'
|
||||||
rxandroid_version = '2.1.1'
|
rxandroid_version = '2.1.1'
|
||||||
rxkotlin_version = '2.4.0'
|
rxkotlin_version = '2.4.0'
|
||||||
room_version = '2.2.5'
|
room_version = '2.2.6'
|
||||||
lifecycle_version = '2.2.0'
|
lifecycle_version = '2.2.0'
|
||||||
dagger_version = '2.31.2'
|
dagger_version = '2.31.2'
|
||||||
coroutinesVersion = '1.3.7'
|
coroutinesVersion = '1.3.7'
|
||||||
|
|
1
database/.gitignore
vendored
Normal file
1
database/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/build
|
60
database/build.gradle
Normal file
60
database/build.gradle
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
apply plugin: 'com.android.library'
|
||||||
|
apply plugin: 'kotlin-android'
|
||||||
|
apply plugin: 'kotlin-kapt'
|
||||||
|
apply plugin: 'kotlin-android-extensions'
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion 28
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdkVersion 23
|
||||||
|
targetSdkVersion 28
|
||||||
|
versionCode 1
|
||||||
|
versionName "1.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
minifyEnabled false
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
|
}
|
||||||
|
debug {
|
||||||
|
}
|
||||||
|
firebaseDisable {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = '1.8'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation "androidx.core:core-ktx:$coreVersion"
|
||||||
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||||
|
|
||||||
|
implementation "io.reactivex.rxjava2:rxjava:$rxjava_version"
|
||||||
|
implementation "io.reactivex.rxjava2:rxandroid:$rxandroid_version"
|
||||||
|
implementation("io.reactivex.rxjava2:rxkotlin:$rxkotlin_version")
|
||||||
|
|
||||||
|
implementation "com.google.code.gson:gson:2.8.6"
|
||||||
|
|
||||||
|
api "androidx.room:room-runtime:$room_version"
|
||||||
|
kapt "androidx.room:room-compiler:$room_version"
|
||||||
|
implementation "androidx.room:room-ktx:$room_version"
|
||||||
|
implementation "androidx.room:room-rxjava2:$room_version"
|
||||||
|
|
||||||
|
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
|
||||||
|
|
||||||
|
implementation "com.google.dagger:dagger-android:$dagger_version"
|
||||||
|
implementation "com.google.dagger:dagger-android-support:$dagger_version"
|
||||||
|
annotationProcessor "com.google.dagger:dagger-compiler:$dagger_version"
|
||||||
|
annotationProcessor "com.google.dagger:dagger-android-processor:$dagger_version"
|
||||||
|
kapt "com.google.dagger:dagger-android-processor:$dagger_version"
|
||||||
|
kapt "com.google.dagger:dagger-compiler:$dagger_version"
|
||||||
|
}
|
0
database/consumer-rules.pro
Normal file
0
database/consumer-rules.pro
Normal file
21
database/proguard-rules.pro
vendored
Normal file
21
database/proguard-rules.pro
vendored
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# You can control the set of applied configuration files using the
|
||||||
|
# proguardFiles setting in build.gradle.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# If your project uses WebView with JS, uncomment the following
|
||||||
|
# and specify the fully qualified class name to the JavaScript interface
|
||||||
|
# class:
|
||||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
|
# public *;
|
||||||
|
#}
|
||||||
|
|
||||||
|
# Uncomment this to preserve the line number information for
|
||||||
|
# debugging stack traces.
|
||||||
|
#-keepattributes SourceFile,LineNumberTable
|
||||||
|
|
||||||
|
# If you keep the line number information, uncomment this to
|
||||||
|
# hide the original source file name.
|
||||||
|
#-renamesourcefileattribute SourceFile
|
|
@ -0,0 +1,25 @@
|
||||||
|
package info.nightscout.database
|
||||||
|
|
||||||
|
import androidx.test.platform.app.InstrumentationRegistry
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
|
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
|
import org.junit.Assert.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instrumented test, which will execute on an Android device.
|
||||||
|
*
|
||||||
|
* See [testing documentation](http://d.android.com/tools/testing).
|
||||||
|
*/
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
class ExampleInstrumentedTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun useAppContext() {
|
||||||
|
// Context of the app under test.
|
||||||
|
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||||
|
assertEquals("info.nightscout.database.test", appContext.packageName)
|
||||||
|
}
|
||||||
|
}
|
2
database/src/main/AndroidManifest.xml
Normal file
2
database/src/main/AndroidManifest.xml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="info.nightscout.androidaps.database" />
|
|
@ -0,0 +1,55 @@
|
||||||
|
package info.nightscout.androidaps.database
|
||||||
|
|
||||||
|
import androidx.room.Database
|
||||||
|
import androidx.room.RoomDatabase
|
||||||
|
import androidx.room.TypeConverters
|
||||||
|
import info.nightscout.androidaps.database.daos.*
|
||||||
|
import info.nightscout.androidaps.database.entities.*
|
||||||
|
import info.nightscout.androidaps.database.entities.APSResultLink
|
||||||
|
import info.nightscout.androidaps.database.entities.MealLink
|
||||||
|
import info.nightscout.androidaps.database.entities.MultiwaveBolusLink
|
||||||
|
|
||||||
|
const val DATABASE_VERSION = 1
|
||||||
|
|
||||||
|
@Database(version = DATABASE_VERSION, entities = arrayOf(APSResult::class, Bolus::class, BolusCalculatorResult::class, Carbs::class,
|
||||||
|
EffectiveProfileSwitch::class, ExtendedBolus::class, GlucoseValue::class, ProfileSwitch::class,
|
||||||
|
TemporaryBasal::class, TemporaryTarget::class, TherapyEvent::class, TotalDailyDose::class,
|
||||||
|
APSResultLink::class, MealLink::class, MultiwaveBolusLink::class, PreferenceChange::class, VersionChange::class))
|
||||||
|
@TypeConverters(Converters::class)
|
||||||
|
internal abstract class AppDatabase : RoomDatabase() {
|
||||||
|
|
||||||
|
abstract val glucoseValueDao: GlucoseValueDao
|
||||||
|
|
||||||
|
abstract val therapyEventDao: TherapyEventDao
|
||||||
|
|
||||||
|
abstract val temporaryBasalDao: TemporaryBasalDao
|
||||||
|
|
||||||
|
abstract val bolusDao: BolusDao
|
||||||
|
|
||||||
|
abstract val extendedBolusDao: ExtendedBolusDao
|
||||||
|
|
||||||
|
abstract val multiwaveBolusLinkDao: MultiwaveBolusLinkDao
|
||||||
|
|
||||||
|
abstract val totalDailyDoseDao: TotalDailyDoseDao
|
||||||
|
|
||||||
|
abstract val carbsDao: CarbsDao
|
||||||
|
|
||||||
|
abstract val mealLinkDao: MealLinkDao
|
||||||
|
|
||||||
|
abstract val temporaryTargetDao: TemporaryTargetDao
|
||||||
|
|
||||||
|
abstract val apsResultLinkDao: APSResultLinkDao
|
||||||
|
|
||||||
|
abstract val bolusCalculatorResultDao: BolusCalculatorResultDao
|
||||||
|
|
||||||
|
abstract val effectiveProfileSwitchDao: EffectiveProfileSwitchDao
|
||||||
|
|
||||||
|
abstract val profileSwitchDao: ProfileSwitchDao
|
||||||
|
|
||||||
|
abstract val apsResultDao: APSResultDao
|
||||||
|
|
||||||
|
abstract val versionChangeDao: VersionChangeDao
|
||||||
|
|
||||||
|
abstract val preferenceChangeDao: PreferenceChangeDao
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,118 @@
|
||||||
|
package info.nightscout.androidaps.database
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.database.entities.GlucoseValue
|
||||||
|
import info.nightscout.androidaps.database.entities.TemporaryTarget
|
||||||
|
import info.nightscout.androidaps.database.interfaces.DBEntry
|
||||||
|
import info.nightscout.androidaps.database.transactions.Transaction
|
||||||
|
import io.reactivex.Completable
|
||||||
|
import io.reactivex.Maybe
|
||||||
|
import io.reactivex.Observable
|
||||||
|
import io.reactivex.Single
|
||||||
|
import io.reactivex.schedulers.Schedulers
|
||||||
|
import io.reactivex.subjects.PublishSubject
|
||||||
|
import java.util.concurrent.Callable
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class AppRepository @Inject internal constructor(
|
||||||
|
internal val database: AppDatabase
|
||||||
|
) {
|
||||||
|
|
||||||
|
private val changeSubject = PublishSubject.create<List<DBEntry>>()
|
||||||
|
|
||||||
|
fun changeObservable(): Observable<List<DBEntry>> = changeSubject.subscribeOn(Schedulers.io())
|
||||||
|
|
||||||
|
val databaseVersion = DATABASE_VERSION
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes a transaction ignoring its result
|
||||||
|
* Runs on IO scheduler
|
||||||
|
*/
|
||||||
|
fun <T> runTransaction(transaction: Transaction<T>): Completable {
|
||||||
|
val changes = mutableListOf<DBEntry>()
|
||||||
|
return Completable.fromCallable {
|
||||||
|
database.runInTransaction {
|
||||||
|
transaction.database = DelegatedAppDatabase(changes, database)
|
||||||
|
transaction.run()
|
||||||
|
}
|
||||||
|
}.subscribeOn(Schedulers.io()).doOnComplete {
|
||||||
|
changeSubject.onNext(changes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes a transaction and returns its result
|
||||||
|
* Runs on IO scheduler
|
||||||
|
*/
|
||||||
|
fun <T> runTransactionForResult(transaction: Transaction<T>): Single<T> {
|
||||||
|
val changes = mutableListOf<DBEntry>()
|
||||||
|
return Single.fromCallable {
|
||||||
|
database.runInTransaction(Callable<T> {
|
||||||
|
transaction.database = DelegatedAppDatabase(changes, database)
|
||||||
|
transaction.run()
|
||||||
|
})
|
||||||
|
}.subscribeOn(Schedulers.io()).doOnSuccess {
|
||||||
|
changeSubject.onNext(changes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clearDatabases() = database.clearAllTables()
|
||||||
|
|
||||||
|
//BG READINGS -- only valid records
|
||||||
|
fun compatGetBgReadingsDataFromTime(timestamp: Long, ascending: Boolean) =
|
||||||
|
database.glucoseValueDao.compatGetBgReadingsDataFromTime(timestamp)
|
||||||
|
.map { if (!ascending) it.reversed() else it }
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
|
||||||
|
fun compatGetBgReadingsDataFromTime(start: Long, end: Long, ascending: Boolean) =
|
||||||
|
database.glucoseValueDao.compatGetBgReadingsDataFromTime(start, end)
|
||||||
|
.map { if (!ascending) it.reversed() else it }
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
|
||||||
|
//BG READINGS -- including invalid/history records
|
||||||
|
fun findBgReadingByNSIdSingle(nsId: String): Single<ValueWrapper<GlucoseValue>> =
|
||||||
|
database.glucoseValueDao.findByNSIdMaybe(nsId).toWrappedSingle()
|
||||||
|
|
||||||
|
fun getModifiedBgReadingsDataFromId(lastId: Long) =
|
||||||
|
database.glucoseValueDao.getModifiedFrom(lastId)
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
|
||||||
|
fun getBgReadingsCorrespondingLastHistoryRecord(lastId: Long) =
|
||||||
|
database.glucoseValueDao.getLastHistoryRecord(lastId)
|
||||||
|
|
||||||
|
@Suppress("unused") // debug purpose only
|
||||||
|
fun getAllBgReadingsStartingFrom(lastId: Long) =
|
||||||
|
database.glucoseValueDao.getAllStartingFrom(lastId)
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
|
||||||
|
// TEMP TARGETS
|
||||||
|
fun compatGetTemporaryTargetData() =
|
||||||
|
database.temporaryTargetDao.compatGetTemporaryTargetData()
|
||||||
|
|
||||||
|
fun compatGetTemporaryTargetDataFromTime(timestamp: Long, ascending: Boolean) =
|
||||||
|
database.temporaryTargetDao.compatGetTemporaryTargetDataFromTime(timestamp)
|
||||||
|
.map { if (!ascending) it.reversed() else it }
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
|
||||||
|
fun findTemporaryTargetByNSIdSingle(nsId: String): Single<ValueWrapper<TemporaryTarget>> =
|
||||||
|
database.temporaryTargetDao.findByNSIdMaybe(nsId).toWrappedSingle()
|
||||||
|
|
||||||
|
fun getModifiedTemporaryTargetsDataFromId(lastId: Long) =
|
||||||
|
database.temporaryTargetDao.getModifiedFrom(lastId)
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
|
||||||
|
fun getTemporaryTargetsCorrespondingLastHistoryRecord(lastId: Long) =
|
||||||
|
database.temporaryTargetDao.getLastHistoryRecord(lastId)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified T> Maybe<T>.toWrappedSingle(): Single<ValueWrapper<T>> =
|
||||||
|
this.map { ValueWrapper.Existing(it) as ValueWrapper<T> }
|
||||||
|
.switchIfEmpty(Maybe.just(ValueWrapper.Absent()))
|
||||||
|
.toSingle()
|
||||||
|
|
||||||
|
sealed class ValueWrapper<T> {
|
||||||
|
data class Existing<T>(val value: T) : ValueWrapper<T>()
|
||||||
|
class Absent<T> : ValueWrapper<T>()
|
||||||
|
}
|
|
@ -0,0 +1,142 @@
|
||||||
|
package info.nightscout.androidaps.database
|
||||||
|
|
||||||
|
import androidx.room.TypeConverter
|
||||||
|
import info.nightscout.androidaps.database.data.Block
|
||||||
|
import info.nightscout.androidaps.database.data.TargetBlock
|
||||||
|
import info.nightscout.androidaps.database.embedments.InterfaceIDs
|
||||||
|
import info.nightscout.androidaps.database.entities.*
|
||||||
|
import org.json.JSONArray
|
||||||
|
import org.json.JSONObject
|
||||||
|
|
||||||
|
class Converters {
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
fun fromBolusType(bolusType: Bolus.Type?) = bolusType?.name
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
fun toBolusType(bolusType: String?) = bolusType?.let { Bolus.Type.valueOf(it) }
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
fun fromTrendArrow(trendArrow: GlucoseValue.TrendArrow?) = trendArrow?.name
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
fun toTrendArrow(trendArrow: String?) = trendArrow?.let { GlucoseValue.TrendArrow.valueOf(it) }
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
fun fromSourceSensor(sourceSensor: GlucoseValue.SourceSensor?) = sourceSensor?.name
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
fun toSourceSensor(sourceSensor: String?) = sourceSensor?.let { GlucoseValue.SourceSensor.valueOf(it) }
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
fun fromTBRType(tbrType: TemporaryBasal.Type?) = tbrType?.name
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
fun toTBRType(tbrType: String?) = tbrType?.let { TemporaryBasal.Type.valueOf(it) }
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
fun fromTempTargetReason(tempTargetReason: TemporaryTarget.Reason?) = tempTargetReason?.name
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
fun toTempTargetReason(tempTargetReason: String?) = tempTargetReason?.let { TemporaryTarget.Reason.valueOf(it) }
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
fun fromTherapyEventType(therapyEventType: TherapyEvent.Type?) = therapyEventType?.name
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
fun toTherapyEventType(therapyEventType: String?) = therapyEventType?.let { TherapyEvent.Type.valueOf(it) }
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
fun fromGlucoseUnit(glucoseUnit: ProfileSwitch.GlucoseUnit?) = glucoseUnit?.name
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
fun toGlucoseUnit(glucoseUnit: String?) = glucoseUnit?.let { ProfileSwitch.GlucoseUnit.valueOf(it) }
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
fun fromPumpType(pumpType: InterfaceIDs.PumpType?) = pumpType?.name
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
fun toPumpType(pumpType: String?) = pumpType?.let { InterfaceIDs.PumpType.valueOf(it) }
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
fun fromAlgorithm(algorithm: APSResult.Algorithm?) = algorithm?.name
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
fun toAlgorithm(algorithm: String?) = algorithm?.let { APSResult.Algorithm.valueOf(it) }
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
fun fromListOfBlocks(blocks: List<Block>?): String? {
|
||||||
|
if (blocks == null) return null
|
||||||
|
val jsonArray = JSONArray()
|
||||||
|
blocks.forEach {
|
||||||
|
val jsonObject = JSONObject()
|
||||||
|
jsonObject.put("duration", it.duration)
|
||||||
|
jsonObject.put("amount", it.amount)
|
||||||
|
jsonArray.put(jsonObject)
|
||||||
|
}
|
||||||
|
return jsonArray.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
fun toListOfBlocks(jsonString: String?): List<Block>? {
|
||||||
|
if (jsonString == null) return null
|
||||||
|
val jsonArray = JSONArray(jsonString)
|
||||||
|
val list = mutableListOf<Block>()
|
||||||
|
for (i in 0 until jsonArray.length()) {
|
||||||
|
val jsonObject = jsonArray.getJSONObject(i)
|
||||||
|
list.add(Block(jsonObject.getLong("duration"), jsonObject.getDouble("amount")))
|
||||||
|
}
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
fun anyToString(value: Any?) = when (value) {
|
||||||
|
null -> null
|
||||||
|
is String -> "S$value"
|
||||||
|
is Int -> "I$value"
|
||||||
|
is Long -> "L$value"
|
||||||
|
is Boolean -> "B$value"
|
||||||
|
is Float -> "F$value"
|
||||||
|
else -> throw IllegalArgumentException("Type not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
fun stringToAny(value: String?): Any? = when {
|
||||||
|
value == null -> null
|
||||||
|
value.startsWith("S") -> value.substring(1)
|
||||||
|
value.startsWith("I") -> value.substring(1).toInt()
|
||||||
|
value.startsWith("L") -> value.substring(1).toLong()
|
||||||
|
value.startsWith("B") -> value.substring(1).toBoolean()
|
||||||
|
value.startsWith("F") -> value.substring(1).toFloat()
|
||||||
|
else -> throw IllegalArgumentException("Type not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
fun fromListOfTargetBlocks(blocks: List<TargetBlock>?): String? {
|
||||||
|
if (blocks == null) return null
|
||||||
|
val jsonArray = JSONArray()
|
||||||
|
blocks.forEach {
|
||||||
|
val jsonObject = JSONObject()
|
||||||
|
jsonObject.put("duration", it.duration)
|
||||||
|
jsonObject.put("lowTarget", it.lowTarget)
|
||||||
|
jsonObject.put("highTarget", it.highTarget)
|
||||||
|
jsonArray.put(jsonObject)
|
||||||
|
}
|
||||||
|
return jsonArray.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
fun toListOfTargetBlocks(jsonString: String?): List<TargetBlock>? {
|
||||||
|
if (jsonString == null) return null
|
||||||
|
val jsonArray = JSONArray(jsonString)
|
||||||
|
val list = mutableListOf<TargetBlock>()
|
||||||
|
for (i in 0 until jsonArray.length()) {
|
||||||
|
val jsonObject = jsonArray.getJSONObject(i)
|
||||||
|
list.add(TargetBlock(jsonObject.getLong("duration"),
|
||||||
|
jsonObject.getDouble("lowTarget"),
|
||||||
|
jsonObject.getDouble("highTarget")))
|
||||||
|
}
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package info.nightscout.androidaps.database
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.room.Room
|
||||||
|
import dagger.Module
|
||||||
|
import dagger.Provides
|
||||||
|
import javax.inject.Qualifier
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Module
|
||||||
|
open class DatabaseModule {
|
||||||
|
|
||||||
|
@DbFileName
|
||||||
|
@Provides
|
||||||
|
fun dbFileName() = "androidaps.db"
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
internal fun provideAppDatabase(context: Context, @DbFileName fileName: String) =
|
||||||
|
Room.databaseBuilder(context, AppDatabase::class.java, fileName).build()
|
||||||
|
|
||||||
|
@Qualifier
|
||||||
|
annotation class DbFileName
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package info.nightscout.androidaps.database
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.database.daos.*
|
||||||
|
import info.nightscout.androidaps.database.daos.delegated.*
|
||||||
|
import info.nightscout.androidaps.database.interfaces.DBEntry
|
||||||
|
|
||||||
|
internal class DelegatedAppDatabase(val changes: MutableList<DBEntry>, val database: AppDatabase) {
|
||||||
|
|
||||||
|
val glucoseValueDao: GlucoseValueDao = DelegatedGlucoseValueDao(changes, database.glucoseValueDao)
|
||||||
|
val therapyEventDao: TherapyEventDao = DelegatedTherapyEventDao(changes, database.therapyEventDao)
|
||||||
|
val temporaryBasalDao: TemporaryBasalDao = DelegatedTemporaryBasalDao(changes, database.temporaryBasalDao)
|
||||||
|
val bolusDao: BolusDao = DelegatedBolusDao(changes, database.bolusDao)
|
||||||
|
val extendedBolusDao: ExtendedBolusDao = DelegatedExtendedExtendedBolusDao(changes, database.extendedBolusDao)
|
||||||
|
val multiwaveBolusLinkDao: MultiwaveBolusLinkDao = DelegatedMultiwaveBolusLinkDao(changes, database.multiwaveBolusLinkDao)
|
||||||
|
val totalDailyDoseDao: TotalDailyDoseDao = DelegatedTotalDailyDoseDao(changes, database.totalDailyDoseDao)
|
||||||
|
val carbsDao: CarbsDao = DelegatedCarbsDao(changes, database.carbsDao)
|
||||||
|
val mealLinkDao: MealLinkDao = DelegatedMealLinkDao(changes, database.mealLinkDao)
|
||||||
|
val temporaryTargetDao: TemporaryTargetDao = DelegatedTemporaryTargetDao(changes, database.temporaryTargetDao)
|
||||||
|
val apsResultLinkDao: APSResultLinkDao = DelegatedAPSResultLinkLinkDao(changes, database.apsResultLinkDao)
|
||||||
|
val bolusCalculatorResultDao: BolusCalculatorResultDao = DelegatedBolusCalculatorResultDao(changes, database.bolusCalculatorResultDao)
|
||||||
|
val effectiveProfileSwitchDao: EffectiveProfileSwitchDao = DelegatedEffectiveProfileSwitchDao(changes, database.effectiveProfileSwitchDao)
|
||||||
|
val profileSwitchDao: ProfileSwitchDao = DelegatedProfileSwitchDao(changes, database.profileSwitchDao)
|
||||||
|
val apsResultDao: APSResultDao = DelegatedAPSResultDao(changes, database.apsResultDao)
|
||||||
|
val versionChangeDao: VersionChangeDao = DelegatedVersionChangeDao(changes, database.versionChangeDao)
|
||||||
|
val preferenceChangeDao: PreferenceChangeDao = DelegatedPreferenceChangeDao(changes, database.preferenceChangeDao)
|
||||||
|
fun clearAllTables() = database.clearAllTables()
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package info.nightscout.androidaps.database
|
||||||
|
|
||||||
|
const val TABLE_APS_RESULTS = "apsResults"
|
||||||
|
const val TABLE_APS_RESULT_LINKS = "apsResultLinks"
|
||||||
|
const val TABLE_BOLUSES = "boluses"
|
||||||
|
const val TABLE_BOLUS_CALCULATOR_RESULTS = "bolusCalculatorResults"
|
||||||
|
const val TABLE_CARBS = "carbs"
|
||||||
|
const val TABLE_EFFECTIVE_PROFILE_SWITCHES = "effectiveProfileSwitches"
|
||||||
|
const val TABLE_EXTENDED_BOLUSES = "extendedBoluses"
|
||||||
|
const val TABLE_GLUCOSE_VALUES = "glucoseValues"
|
||||||
|
const val TABLE_MEAL_LINKS = "mealLinks"
|
||||||
|
const val TABLE_MULTIWAVE_BOLUS_LINKS = "multiwaveBolusLinks"
|
||||||
|
const val TABLE_PROFILE_SWITCHES = "profileSwitches"
|
||||||
|
const val TABLE_TEMPORARY_BASALS = "temporaryBasals"
|
||||||
|
const val TABLE_TEMPORARY_TARGETS = "temporaryTargets"
|
||||||
|
const val TABLE_TOTAL_DAILY_DOSES = "totalDailyDoses"
|
||||||
|
const val TABLE_THERAPY_EVENTS = "therapyEvents"
|
||||||
|
const val TABLE_PREFERENCE_CHANGES = "preferenceChanges"
|
||||||
|
const val TABLE_VERSION_CHANGES = "versionChanges"
|
|
@ -0,0 +1,18 @@
|
||||||
|
package info.nightscout.androidaps.database.daos
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Query
|
||||||
|
import info.nightscout.androidaps.database.TABLE_APS_RESULTS
|
||||||
|
import info.nightscout.androidaps.database.entities.APSResult
|
||||||
|
import io.reactivex.Single
|
||||||
|
|
||||||
|
@Suppress("FunctionName")
|
||||||
|
@Dao
|
||||||
|
internal interface APSResultDao : TraceableDao<APSResult> {
|
||||||
|
|
||||||
|
@Query("SELECT * FROM $TABLE_APS_RESULTS WHERE id = :id")
|
||||||
|
override fun findById(id: Long): APSResult?
|
||||||
|
|
||||||
|
@Query("DELETE FROM $TABLE_APS_RESULTS")
|
||||||
|
override fun deleteAllEntries()
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package info.nightscout.androidaps.database.daos
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Query
|
||||||
|
import info.nightscout.androidaps.database.TABLE_APS_RESULTS
|
||||||
|
import info.nightscout.androidaps.database.TABLE_APS_RESULT_LINKS
|
||||||
|
import info.nightscout.androidaps.database.entities.APSResultLink
|
||||||
|
import io.reactivex.Single
|
||||||
|
|
||||||
|
@Suppress("FunctionName")
|
||||||
|
@Dao
|
||||||
|
internal interface APSResultLinkDao : TraceableDao<APSResultLink> {
|
||||||
|
|
||||||
|
@Query("SELECT * FROM $TABLE_APS_RESULT_LINKS WHERE id = :id")
|
||||||
|
override fun findById(id: Long): APSResultLink?
|
||||||
|
|
||||||
|
@Query("DELETE FROM $TABLE_APS_RESULTS")
|
||||||
|
override fun deleteAllEntries()
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package info.nightscout.androidaps.database.daos
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Query
|
||||||
|
import info.nightscout.androidaps.database.TABLE_BOLUS_CALCULATOR_RESULTS
|
||||||
|
import info.nightscout.androidaps.database.entities.BolusCalculatorResult
|
||||||
|
import io.reactivex.Single
|
||||||
|
|
||||||
|
@Suppress("FunctionName")
|
||||||
|
@Dao
|
||||||
|
internal interface BolusCalculatorResultDao : TraceableDao<BolusCalculatorResult> {
|
||||||
|
|
||||||
|
@Query("SELECT * FROM $TABLE_BOLUS_CALCULATOR_RESULTS WHERE id = :id")
|
||||||
|
override fun findById(id: Long): BolusCalculatorResult?
|
||||||
|
|
||||||
|
@Query("DELETE FROM $TABLE_BOLUS_CALCULATOR_RESULTS")
|
||||||
|
override fun deleteAllEntries()
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package info.nightscout.androidaps.database.daos
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Query
|
||||||
|
import info.nightscout.androidaps.database.TABLE_BOLUSES
|
||||||
|
import info.nightscout.androidaps.database.embedments.InterfaceIDs
|
||||||
|
import info.nightscout.androidaps.database.entities.Bolus
|
||||||
|
import io.reactivex.Single
|
||||||
|
|
||||||
|
@Suppress("FunctionName")
|
||||||
|
@Dao
|
||||||
|
internal interface BolusDao : TraceableDao<Bolus> {
|
||||||
|
|
||||||
|
@Query("SELECT * FROM $TABLE_BOLUSES WHERE id = :id")
|
||||||
|
override fun findById(id: Long): Bolus?
|
||||||
|
|
||||||
|
@Query("DELETE FROM $TABLE_BOLUSES")
|
||||||
|
override fun deleteAllEntries()
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package info.nightscout.androidaps.database.daos
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Query
|
||||||
|
import info.nightscout.androidaps.database.TABLE_CARBS
|
||||||
|
import info.nightscout.androidaps.database.entities.Carbs
|
||||||
|
import io.reactivex.Single
|
||||||
|
|
||||||
|
@Suppress("FunctionName")
|
||||||
|
@Dao
|
||||||
|
internal interface CarbsDao : TraceableDao<Carbs> {
|
||||||
|
|
||||||
|
@Query("SELECT * FROM $TABLE_CARBS WHERE id = :id")
|
||||||
|
override fun findById(id: Long): Carbs?
|
||||||
|
|
||||||
|
@Query("DELETE FROM $TABLE_CARBS")
|
||||||
|
override fun deleteAllEntries()
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package info.nightscout.androidaps.database.daos
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Query
|
||||||
|
import info.nightscout.androidaps.database.TABLE_EFFECTIVE_PROFILE_SWITCHES
|
||||||
|
import info.nightscout.androidaps.database.entities.EffectiveProfileSwitch
|
||||||
|
import io.reactivex.Single
|
||||||
|
|
||||||
|
@Suppress("FunctionName")
|
||||||
|
@Dao
|
||||||
|
internal interface EffectiveProfileSwitchDao : TraceableDao<EffectiveProfileSwitch> {
|
||||||
|
|
||||||
|
@Query("SELECT * FROM $TABLE_EFFECTIVE_PROFILE_SWITCHES WHERE id = :id")
|
||||||
|
override fun findById(id: Long): EffectiveProfileSwitch?
|
||||||
|
|
||||||
|
@Query("DELETE FROM $TABLE_EFFECTIVE_PROFILE_SWITCHES")
|
||||||
|
override fun deleteAllEntries()
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
package info.nightscout.androidaps.database.daos
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Query
|
||||||
|
import info.nightscout.androidaps.database.TABLE_EXTENDED_BOLUSES
|
||||||
|
import info.nightscout.androidaps.database.embedments.InterfaceIDs
|
||||||
|
import info.nightscout.androidaps.database.entities.ExtendedBolus
|
||||||
|
import io.reactivex.Flowable
|
||||||
|
import io.reactivex.Single
|
||||||
|
|
||||||
|
@Suppress("FunctionName")
|
||||||
|
@Dao
|
||||||
|
internal interface ExtendedBolusDao : TraceableDao<ExtendedBolus> {
|
||||||
|
|
||||||
|
@Query("SELECT * FROM $TABLE_EXTENDED_BOLUSES WHERE id = :id")
|
||||||
|
override fun findById(id: Long): ExtendedBolus?
|
||||||
|
|
||||||
|
@Query("DELETE FROM $TABLE_EXTENDED_BOLUSES")
|
||||||
|
override fun deleteAllEntries()
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package info.nightscout.androidaps.database.daos
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Query
|
||||||
|
import info.nightscout.androidaps.database.TABLE_GLUCOSE_VALUES
|
||||||
|
import info.nightscout.androidaps.database.entities.GlucoseValue
|
||||||
|
import io.reactivex.Maybe
|
||||||
|
import io.reactivex.Single
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
internal interface GlucoseValueDao : TraceableDao<GlucoseValue> {
|
||||||
|
|
||||||
|
@Query("SELECT * FROM $TABLE_GLUCOSE_VALUES WHERE id = :id")
|
||||||
|
override fun findById(id: Long): GlucoseValue?
|
||||||
|
|
||||||
|
@Query("DELETE FROM $TABLE_GLUCOSE_VALUES")
|
||||||
|
override fun deleteAllEntries()
|
||||||
|
|
||||||
|
@Query("SELECT * FROM $TABLE_GLUCOSE_VALUES WHERE nightscoutId = :nsId AND referenceId IS NULL")
|
||||||
|
fun findByNSIdMaybe(nsId: String): Maybe<GlucoseValue>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM $TABLE_GLUCOSE_VALUES WHERE timestamp = :timestamp AND sourceSensor = :sourceSensor AND referenceId IS NULL")
|
||||||
|
fun findByTimestampAndSensor(timestamp: Long, sourceSensor: GlucoseValue.SourceSensor): GlucoseValue?
|
||||||
|
|
||||||
|
@Query("SELECT * FROM $TABLE_GLUCOSE_VALUES WHERE timestamp >= :timestamp AND isValid = 1 AND referenceId IS NULL AND value >= 39 ORDER BY timestamp ASC")
|
||||||
|
fun compatGetBgReadingsDataFromTime(timestamp: Long): Single<List<GlucoseValue>>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM $TABLE_GLUCOSE_VALUES WHERE timestamp BETWEEN :start AND :end AND isValid = 1 AND referenceId IS NULL AND value >= 39 ORDER BY timestamp ASC")
|
||||||
|
fun compatGetBgReadingsDataFromTime(start: Long, end: Long): Single<List<GlucoseValue>>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM $TABLE_GLUCOSE_VALUES WHERE id > :lastId AND referenceId IS NULL ORDER BY timestamp ASC")
|
||||||
|
fun getDataFromId(lastId: Long): Single<List<GlucoseValue>>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM $TABLE_GLUCOSE_VALUES WHERE id >= :id")
|
||||||
|
fun getAllStartingFrom(id: Long): Single<List<GlucoseValue>>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM $TABLE_GLUCOSE_VALUES WHERE referenceId = :id ORDER BY id DESC LIMIT 1")
|
||||||
|
fun getLastHistoryRecord(id: Long): GlucoseValue?
|
||||||
|
|
||||||
|
@Query("SELECT * FROM $TABLE_GLUCOSE_VALUES WHERE id > :id AND referenceId IS NULL OR id IN (SELECT DISTINCT referenceId FROM $TABLE_GLUCOSE_VALUES WHERE id > :id) ORDER BY id ASC")
|
||||||
|
fun getModifiedFrom(id: Long): Single<List<GlucoseValue>>
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package info.nightscout.androidaps.database.daos
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Query
|
||||||
|
import info.nightscout.androidaps.database.TABLE_MEAL_LINKS
|
||||||
|
import info.nightscout.androidaps.database.entities.MealLink
|
||||||
|
import io.reactivex.Single
|
||||||
|
|
||||||
|
@Suppress("FunctionName")
|
||||||
|
@Dao
|
||||||
|
internal interface MealLinkDao : TraceableDao<MealLink> {
|
||||||
|
|
||||||
|
@Query("SELECT * FROM $TABLE_MEAL_LINKS WHERE id = :id")
|
||||||
|
override fun findById(id: Long): MealLink?
|
||||||
|
|
||||||
|
@Query("DELETE FROM $TABLE_MEAL_LINKS")
|
||||||
|
override fun deleteAllEntries()
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package info.nightscout.androidaps.database.daos
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Query
|
||||||
|
import info.nightscout.androidaps.database.TABLE_MEAL_LINKS
|
||||||
|
import info.nightscout.androidaps.database.TABLE_MULTIWAVE_BOLUS_LINKS
|
||||||
|
import info.nightscout.androidaps.database.entities.MultiwaveBolusLink
|
||||||
|
import io.reactivex.Single
|
||||||
|
|
||||||
|
@Suppress("FunctionName")
|
||||||
|
@Dao
|
||||||
|
internal interface MultiwaveBolusLinkDao : TraceableDao<MultiwaveBolusLink> {
|
||||||
|
|
||||||
|
@Query("SELECT * FROM $TABLE_MULTIWAVE_BOLUS_LINKS WHERE id = :id")
|
||||||
|
override fun findById(id: Long): MultiwaveBolusLink?
|
||||||
|
|
||||||
|
@Query("DELETE FROM $TABLE_MEAL_LINKS")
|
||||||
|
override fun deleteAllEntries()
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package info.nightscout.androidaps.database.daos
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Insert
|
||||||
|
import androidx.room.Query
|
||||||
|
import info.nightscout.androidaps.database.TABLE_PREFERENCE_CHANGES
|
||||||
|
import info.nightscout.androidaps.database.entities.PreferenceChange
|
||||||
|
import io.reactivex.Single
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface PreferenceChangeDao {
|
||||||
|
|
||||||
|
@Insert
|
||||||
|
fun insert(preferenceChange: PreferenceChange)
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package info.nightscout.androidaps.database.daos
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Query
|
||||||
|
import info.nightscout.androidaps.database.TABLE_PROFILE_SWITCHES
|
||||||
|
import info.nightscout.androidaps.database.data.checkSanity
|
||||||
|
import info.nightscout.androidaps.database.daos.workaround.ProfileSwitchDaoWorkaround
|
||||||
|
import info.nightscout.androidaps.database.entities.ProfileSwitch
|
||||||
|
import io.reactivex.Flowable
|
||||||
|
import io.reactivex.Single
|
||||||
|
|
||||||
|
@Suppress("FunctionName")
|
||||||
|
@Dao
|
||||||
|
internal interface ProfileSwitchDao : ProfileSwitchDaoWorkaround {
|
||||||
|
|
||||||
|
@Query("SELECT * FROM $TABLE_PROFILE_SWITCHES WHERE id = :id")
|
||||||
|
override fun findById(id: Long): ProfileSwitch?
|
||||||
|
|
||||||
|
@Query("DELETE FROM $TABLE_PROFILE_SWITCHES")
|
||||||
|
override fun deleteAllEntries()
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun ProfileSwitchDao.insertNewEntryImpl(entry: ProfileSwitch): Long {
|
||||||
|
if (!entry.basalBlocks.checkSanity()) throw IllegalArgumentException("Sanity check failed for basal blocks.")
|
||||||
|
if (!entry.icBlocks.checkSanity()) throw IllegalArgumentException("Sanity check failed for IC blocks.")
|
||||||
|
if (!entry.isfBlocks.checkSanity()) throw IllegalArgumentException("Sanity check failed for ISF blocks.")
|
||||||
|
if (!entry.targetBlocks.checkSanity()) throw IllegalArgumentException("Sanity check failed for target blocks.")
|
||||||
|
return (this as TraceableDao<ProfileSwitch>).insertNewEntryImpl(entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun ProfileSwitchDao.updateExistingEntryImpl(entry: ProfileSwitch): Long {
|
||||||
|
if (!entry.basalBlocks.checkSanity()) throw IllegalArgumentException("Sanity check failed for basal blocks.")
|
||||||
|
if (!entry.icBlocks.checkSanity()) throw IllegalArgumentException("Sanity check failed for IC blocks.")
|
||||||
|
if (!entry.isfBlocks.checkSanity()) throw IllegalArgumentException("Sanity check failed for ISF blocks.")
|
||||||
|
if (!entry.targetBlocks.checkSanity()) throw IllegalArgumentException("Sanity check failed for target blocks.")
|
||||||
|
return (this as TraceableDao<ProfileSwitch>).updateExistingEntryImpl(entry)
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package info.nightscout.androidaps.database.daos
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Query
|
||||||
|
import info.nightscout.androidaps.database.TABLE_TEMPORARY_BASALS
|
||||||
|
import info.nightscout.androidaps.database.embedments.InterfaceIDs
|
||||||
|
import info.nightscout.androidaps.database.entities.TemporaryBasal
|
||||||
|
import io.reactivex.Flowable
|
||||||
|
import io.reactivex.Maybe
|
||||||
|
import io.reactivex.Single
|
||||||
|
|
||||||
|
@Suppress("FunctionName")
|
||||||
|
@Dao
|
||||||
|
internal interface TemporaryBasalDao : TraceableDao<TemporaryBasal> {
|
||||||
|
|
||||||
|
@Query("SELECT * FROM $TABLE_TEMPORARY_BASALS WHERE id = :id")
|
||||||
|
override fun findById(id: Long): TemporaryBasal?
|
||||||
|
|
||||||
|
@Query("DELETE FROM $TABLE_TEMPORARY_BASALS")
|
||||||
|
override fun deleteAllEntries()
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package info.nightscout.androidaps.database.daos
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Query
|
||||||
|
import info.nightscout.androidaps.database.TABLE_TEMPORARY_TARGETS
|
||||||
|
import info.nightscout.androidaps.database.entities.TemporaryTarget
|
||||||
|
import io.reactivex.Maybe
|
||||||
|
import io.reactivex.Observable
|
||||||
|
import io.reactivex.Single
|
||||||
|
|
||||||
|
@Suppress("FunctionName")
|
||||||
|
@Dao
|
||||||
|
internal interface TemporaryTargetDao : TraceableDao<TemporaryTarget> {
|
||||||
|
|
||||||
|
@Query("SELECT * FROM $TABLE_TEMPORARY_TARGETS WHERE id = :id")
|
||||||
|
override fun findById(id: Long): TemporaryTarget?
|
||||||
|
|
||||||
|
@Query("DELETE FROM $TABLE_TEMPORARY_TARGETS")
|
||||||
|
override fun deleteAllEntries()
|
||||||
|
|
||||||
|
@Query("SELECT * FROM $TABLE_TEMPORARY_TARGETS WHERE nightscoutId = :nsId AND referenceId IS NULL")
|
||||||
|
fun findByNSIdMaybe(nsId: String): Maybe<TemporaryTarget>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM $TABLE_TEMPORARY_TARGETS WHERE timestamp <= :timestamp AND (timestamp + duration) > :timestamp AND referenceId IS NULL AND isValid = 1 ORDER BY timestamp DESC LIMIT 1")
|
||||||
|
fun getTemporaryTargetActiveAt(timestamp: Long): TemporaryTarget?
|
||||||
|
|
||||||
|
@Query("SELECT * FROM $TABLE_TEMPORARY_TARGETS WHERE timestamp >= :timestamp AND isValid = 1 AND referenceId IS NULL ORDER BY timestamp ASC")
|
||||||
|
fun compatGetTemporaryTargetDataFromTime(timestamp: Long): Single<List<TemporaryTarget>>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM $TABLE_TEMPORARY_TARGETS WHERE isValid = 1 AND referenceId IS NULL ORDER BY timestamp ASC")
|
||||||
|
fun compatGetTemporaryTargetData(): List<TemporaryTarget>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM $TABLE_TEMPORARY_TARGETS WHERE referenceId = :id ORDER BY id DESC LIMIT 1")
|
||||||
|
fun getLastHistoryRecord(id: Long): TemporaryTarget?
|
||||||
|
|
||||||
|
@Query("SELECT * FROM $TABLE_TEMPORARY_TARGETS WHERE id > :id AND referenceId IS NULL OR id IN (SELECT DISTINCT referenceId FROM $TABLE_TEMPORARY_TARGETS WHERE id > :id) ORDER BY id ASC")
|
||||||
|
fun getModifiedFrom(id: Long): Single<List<TemporaryTarget>>
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package info.nightscout.androidaps.database.daos
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Query
|
||||||
|
import info.nightscout.androidaps.database.TABLE_THERAPY_EVENTS
|
||||||
|
import info.nightscout.androidaps.database.embedments.InterfaceIDs
|
||||||
|
import info.nightscout.androidaps.database.entities.TherapyEvent
|
||||||
|
import io.reactivex.Flowable
|
||||||
|
import io.reactivex.Maybe
|
||||||
|
import io.reactivex.Single
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
internal interface TherapyEventDao : TraceableDao<TherapyEvent> {
|
||||||
|
|
||||||
|
@Query("SELECT * FROM $TABLE_THERAPY_EVENTS WHERE id = :id")
|
||||||
|
override fun findById(id: Long): TherapyEvent?
|
||||||
|
|
||||||
|
@Query("DELETE FROM $TABLE_THERAPY_EVENTS")
|
||||||
|
override fun deleteAllEntries()
|
||||||
|
|
||||||
|
@Query("SELECT * FROM $TABLE_THERAPY_EVENTS WHERE type = :type AND timestamp = :timestamp AND referenceId IS NULL")
|
||||||
|
fun findByTimestamp(type: TherapyEvent.Type, timestamp: Long): TherapyEvent?
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package info.nightscout.androidaps.database.daos
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Query
|
||||||
|
import info.nightscout.androidaps.database.TABLE_TOTAL_DAILY_DOSES
|
||||||
|
import info.nightscout.androidaps.database.entities.TotalDailyDose
|
||||||
|
import io.reactivex.Single
|
||||||
|
|
||||||
|
@Suppress("FunctionName")
|
||||||
|
@Dao
|
||||||
|
internal interface TotalDailyDoseDao : TraceableDao<TotalDailyDose> {
|
||||||
|
|
||||||
|
@Query("SELECT * FROM $TABLE_TOTAL_DAILY_DOSES WHERE id = :id")
|
||||||
|
override fun findById(id: Long): TotalDailyDose?
|
||||||
|
|
||||||
|
@Query("DELETE FROM $TABLE_TOTAL_DAILY_DOSES")
|
||||||
|
override fun deleteAllEntries()
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
package info.nightscout.androidaps.database.daos
|
||||||
|
|
||||||
|
import androidx.room.Insert
|
||||||
|
import androidx.room.Update
|
||||||
|
import info.nightscout.androidaps.database.daos.workaround.TraceableDaoWorkaround
|
||||||
|
import info.nightscout.androidaps.database.interfaces.TraceableDBEntry
|
||||||
|
import io.reactivex.Single
|
||||||
|
|
||||||
|
internal interface TraceableDao<T : TraceableDBEntry> : TraceableDaoWorkaround<T> {
|
||||||
|
|
||||||
|
fun findById(id: Long): T?
|
||||||
|
|
||||||
|
fun deleteAllEntries()
|
||||||
|
|
||||||
|
//fun getAllStartingFrom(id: Long): Single<List<T>>
|
||||||
|
|
||||||
|
@Insert
|
||||||
|
fun insert(entry: T): Long
|
||||||
|
|
||||||
|
@Update
|
||||||
|
fun update(entry: T)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts a new entry
|
||||||
|
* @return The ID of the newly generated entry
|
||||||
|
*/
|
||||||
|
//@Transaction
|
||||||
|
internal fun <T : TraceableDBEntry> TraceableDao<T>.insertNewEntryImpl(entry: T): Long {
|
||||||
|
if (entry.id != 0L) throw IllegalArgumentException("ID must be 0.")
|
||||||
|
if (entry.version != 0) throw IllegalArgumentException("Version must be 0.")
|
||||||
|
if (entry.referenceId != null) throw IllegalArgumentException("Reference ID must be null.")
|
||||||
|
if (!entry.foreignKeysValid) throw IllegalArgumentException("One or more foreign keys are invalid (e.g. 0 value).")
|
||||||
|
val lastModified = System.currentTimeMillis()
|
||||||
|
entry.dateCreated = lastModified
|
||||||
|
val id = insert(entry)
|
||||||
|
entry.id = id
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates an existing entry
|
||||||
|
* @return The ID of the newly generated HISTORIC entry
|
||||||
|
*/
|
||||||
|
//@Transaction
|
||||||
|
internal fun <T : TraceableDBEntry> TraceableDao<T>.updateExistingEntryImpl(entry: T): Long {
|
||||||
|
if (entry.id == 0L) throw IllegalArgumentException("ID must not be 0.")
|
||||||
|
if (entry.referenceId != null) throw IllegalArgumentException("Reference ID must be null.")
|
||||||
|
if (!entry.foreignKeysValid) throw IllegalArgumentException("One or more foreign keys are invalid (e.g. 0 value).")
|
||||||
|
val lastModified = System.currentTimeMillis()
|
||||||
|
entry.dateCreated = lastModified
|
||||||
|
val current = findById(entry.id)
|
||||||
|
?: throw IllegalArgumentException("The entry with the specified ID does not exist.")
|
||||||
|
if (current.referenceId != null) throw IllegalArgumentException("The entry with the specified ID is historic and cannot be updated.")
|
||||||
|
entry.version = current.version + 1
|
||||||
|
update(entry)
|
||||||
|
current.referenceId = entry.id
|
||||||
|
current.id = 0
|
||||||
|
return insert(current)
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package info.nightscout.androidaps.database.daos
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Insert
|
||||||
|
import androidx.room.Query
|
||||||
|
import info.nightscout.androidaps.database.TABLE_VERSION_CHANGES
|
||||||
|
import info.nightscout.androidaps.database.entities.VersionChange
|
||||||
|
import io.reactivex.Single
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface VersionChangeDao {
|
||||||
|
|
||||||
|
@Insert
|
||||||
|
fun insert(versionChange: VersionChange)
|
||||||
|
|
||||||
|
@Query("SELECT * FROM $TABLE_VERSION_CHANGES ORDER BY id DESC LIMIT 1")
|
||||||
|
fun getMostRecentVersionChange(): VersionChange?
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package info.nightscout.androidaps.database.daos.delegated
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.database.daos.APSResultDao
|
||||||
|
import info.nightscout.androidaps.database.entities.APSResult
|
||||||
|
import info.nightscout.androidaps.database.interfaces.DBEntry
|
||||||
|
|
||||||
|
internal class DelegatedAPSResultDao(changes: MutableList<DBEntry>, private val dao: APSResultDao) : DelegatedDao(changes), APSResultDao by dao {
|
||||||
|
|
||||||
|
override fun insertNewEntry(entry: APSResult): Long {
|
||||||
|
changes.add(entry)
|
||||||
|
return dao.insertNewEntry(entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateExistingEntry(entry: APSResult): Long {
|
||||||
|
changes.add(entry)
|
||||||
|
return dao.updateExistingEntry(entry)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package info.nightscout.androidaps.database.daos.delegated
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.database.daos.APSResultLinkDao
|
||||||
|
import info.nightscout.androidaps.database.entities.APSResultLink
|
||||||
|
import info.nightscout.androidaps.database.interfaces.DBEntry
|
||||||
|
|
||||||
|
internal class DelegatedAPSResultLinkLinkDao(changes: MutableList<DBEntry>, private val dao: APSResultLinkDao) : DelegatedDao(changes), APSResultLinkDao by dao {
|
||||||
|
|
||||||
|
override fun insertNewEntry(entry: APSResultLink): Long {
|
||||||
|
changes.add(entry)
|
||||||
|
return dao.insertNewEntry(entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateExistingEntry(entry: APSResultLink): Long {
|
||||||
|
changes.add(entry)
|
||||||
|
return dao.updateExistingEntry(entry)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package info.nightscout.androidaps.database.daos.delegated
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.database.daos.BolusCalculatorResultDao
|
||||||
|
import info.nightscout.androidaps.database.entities.BolusCalculatorResult
|
||||||
|
import info.nightscout.androidaps.database.interfaces.DBEntry
|
||||||
|
|
||||||
|
internal class DelegatedBolusCalculatorResultDao(changes: MutableList<DBEntry>, private val dao: BolusCalculatorResultDao) : DelegatedDao(changes), BolusCalculatorResultDao by dao {
|
||||||
|
|
||||||
|
override fun insertNewEntry(entry: BolusCalculatorResult): Long {
|
||||||
|
changes.add(entry)
|
||||||
|
return dao.insertNewEntry(entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateExistingEntry(entry: BolusCalculatorResult): Long {
|
||||||
|
changes.add(entry)
|
||||||
|
return dao.updateExistingEntry(entry)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package info.nightscout.androidaps.database.daos.delegated
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.database.daos.BolusDao
|
||||||
|
import info.nightscout.androidaps.database.entities.Bolus
|
||||||
|
import info.nightscout.androidaps.database.interfaces.DBEntry
|
||||||
|
|
||||||
|
internal class DelegatedBolusDao(changes: MutableList<DBEntry>, private val dao: BolusDao) : DelegatedDao(changes), BolusDao by dao {
|
||||||
|
|
||||||
|
override fun insertNewEntry(entry: Bolus): Long {
|
||||||
|
changes.add(entry)
|
||||||
|
return dao.insertNewEntry(entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateExistingEntry(entry: Bolus): Long {
|
||||||
|
changes.add(entry)
|
||||||
|
return dao.updateExistingEntry(entry)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package info.nightscout.androidaps.database.daos.delegated
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.database.daos.CarbsDao
|
||||||
|
import info.nightscout.androidaps.database.entities.Carbs
|
||||||
|
import info.nightscout.androidaps.database.interfaces.DBEntry
|
||||||
|
|
||||||
|
internal class DelegatedCarbsDao(changes: MutableList<DBEntry>, private val dao: CarbsDao) : DelegatedDao(changes), CarbsDao by dao {
|
||||||
|
|
||||||
|
override fun insertNewEntry(entry: Carbs): Long {
|
||||||
|
changes.add(entry)
|
||||||
|
return dao.insertNewEntry(entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateExistingEntry(entry: Carbs): Long {
|
||||||
|
changes.add(entry)
|
||||||
|
return dao.updateExistingEntry(entry)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package info.nightscout.androidaps.database.daos.delegated
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.database.interfaces.DBEntry
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A DAO that adds updated or inserted entries to a list
|
||||||
|
*/
|
||||||
|
internal abstract class DelegatedDao(protected val changes: MutableList<DBEntry>)
|
|
@ -0,0 +1,18 @@
|
||||||
|
package info.nightscout.androidaps.database.daos.delegated
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.database.daos.EffectiveProfileSwitchDao
|
||||||
|
import info.nightscout.androidaps.database.entities.EffectiveProfileSwitch
|
||||||
|
import info.nightscout.androidaps.database.interfaces.DBEntry
|
||||||
|
|
||||||
|
internal class DelegatedEffectiveProfileSwitchDao(changes: MutableList<DBEntry>, private val dao: EffectiveProfileSwitchDao) : DelegatedDao(changes), EffectiveProfileSwitchDao by dao {
|
||||||
|
|
||||||
|
override fun insertNewEntry(entry: EffectiveProfileSwitch): Long {
|
||||||
|
changes.add(entry)
|
||||||
|
return super.insertNewEntry(entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateExistingEntry(entry: EffectiveProfileSwitch): Long {
|
||||||
|
changes.add(entry)
|
||||||
|
return super.updateExistingEntry(entry)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package info.nightscout.androidaps.database.daos.delegated
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.database.daos.ExtendedBolusDao
|
||||||
|
import info.nightscout.androidaps.database.entities.ExtendedBolus
|
||||||
|
import info.nightscout.androidaps.database.interfaces.DBEntry
|
||||||
|
|
||||||
|
internal class DelegatedExtendedExtendedBolusDao(changes: MutableList<DBEntry>, private val dao: ExtendedBolusDao) : DelegatedDao(changes), ExtendedBolusDao by dao {
|
||||||
|
|
||||||
|
override fun insertNewEntry(entry: ExtendedBolus): Long {
|
||||||
|
changes.add(entry)
|
||||||
|
return dao.insertNewEntry(entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateExistingEntry(entry: ExtendedBolus): Long {
|
||||||
|
changes.add(entry)
|
||||||
|
return dao.updateExistingEntry(entry)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package info.nightscout.androidaps.database.daos.delegated
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.database.daos.GlucoseValueDao
|
||||||
|
import info.nightscout.androidaps.database.entities.GlucoseValue
|
||||||
|
import info.nightscout.androidaps.database.interfaces.DBEntry
|
||||||
|
|
||||||
|
internal class DelegatedGlucoseValueDao(changes: MutableList<DBEntry>, private val dao: GlucoseValueDao) : DelegatedDao(changes), GlucoseValueDao by dao {
|
||||||
|
|
||||||
|
override fun insertNewEntry(entry: GlucoseValue): Long {
|
||||||
|
changes.add(entry)
|
||||||
|
return dao.insertNewEntry(entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateExistingEntry(entry: GlucoseValue): Long {
|
||||||
|
changes.add(entry)
|
||||||
|
return dao.updateExistingEntry(entry)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package info.nightscout.androidaps.database.daos.delegated
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.database.daos.MealLinkDao
|
||||||
|
import info.nightscout.androidaps.database.entities.MealLink
|
||||||
|
import info.nightscout.androidaps.database.interfaces.DBEntry
|
||||||
|
|
||||||
|
internal class DelegatedMealLinkDao(changes: MutableList<DBEntry>, private val dao: MealLinkDao) : DelegatedDao(changes), MealLinkDao by dao {
|
||||||
|
|
||||||
|
override fun insertNewEntry(entry: MealLink): Long {
|
||||||
|
changes.add(entry)
|
||||||
|
return dao.insertNewEntry(entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateExistingEntry(entry: MealLink): Long {
|
||||||
|
changes.add(entry)
|
||||||
|
return dao.updateExistingEntry(entry)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package info.nightscout.androidaps.database.daos.delegated
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.database.daos.MultiwaveBolusLinkDao
|
||||||
|
import info.nightscout.androidaps.database.entities.MultiwaveBolusLink
|
||||||
|
import info.nightscout.androidaps.database.interfaces.DBEntry
|
||||||
|
|
||||||
|
internal class DelegatedMultiwaveBolusLinkDao(changes: MutableList<DBEntry>, private val dao: MultiwaveBolusLinkDao) : DelegatedDao(changes), MultiwaveBolusLinkDao by dao {
|
||||||
|
|
||||||
|
override fun insertNewEntry(entry: MultiwaveBolusLink): Long {
|
||||||
|
changes.add(entry)
|
||||||
|
return dao.insertNewEntry(entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateExistingEntry(entry: MultiwaveBolusLink): Long {
|
||||||
|
changes.add(entry)
|
||||||
|
return dao.updateExistingEntry(entry)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package info.nightscout.androidaps.database.daos.delegated
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.database.daos.PreferenceChangeDao
|
||||||
|
import info.nightscout.androidaps.database.entities.PreferenceChange
|
||||||
|
import info.nightscout.androidaps.database.interfaces.DBEntry
|
||||||
|
|
||||||
|
internal class DelegatedPreferenceChangeDao(changes: MutableList<DBEntry>, private val dao: PreferenceChangeDao) : DelegatedDao(changes), PreferenceChangeDao by dao {
|
||||||
|
|
||||||
|
override fun insert(preferenceChange: PreferenceChange) {
|
||||||
|
changes.add(preferenceChange)
|
||||||
|
return dao.insert(preferenceChange)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package info.nightscout.androidaps.database.daos.delegated
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.database.daos.ProfileSwitchDao
|
||||||
|
import info.nightscout.androidaps.database.entities.ProfileSwitch
|
||||||
|
import info.nightscout.androidaps.database.interfaces.DBEntry
|
||||||
|
|
||||||
|
internal class DelegatedProfileSwitchDao(changes: MutableList<DBEntry>, private val dao: ProfileSwitchDao) : DelegatedDao(changes), ProfileSwitchDao by dao {
|
||||||
|
|
||||||
|
override fun insertNewEntry(entry: ProfileSwitch): Long {
|
||||||
|
changes.add(entry)
|
||||||
|
return dao.insertNewEntry(entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateExistingEntry(entry: ProfileSwitch): Long {
|
||||||
|
changes.add(entry)
|
||||||
|
return dao.updateExistingEntry(entry)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package info.nightscout.androidaps.database.daos.delegated
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.database.daos.TemporaryBasalDao
|
||||||
|
import info.nightscout.androidaps.database.entities.TemporaryBasal
|
||||||
|
import info.nightscout.androidaps.database.interfaces.DBEntry
|
||||||
|
|
||||||
|
internal class DelegatedTemporaryBasalDao(changes: MutableList<DBEntry>, private val dao: TemporaryBasalDao) : DelegatedDao(changes), TemporaryBasalDao by dao {
|
||||||
|
|
||||||
|
override fun insertNewEntry(entry: TemporaryBasal): Long {
|
||||||
|
changes.add(entry)
|
||||||
|
return dao.insertNewEntry(entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateExistingEntry(entry: TemporaryBasal): Long {
|
||||||
|
changes.add(entry)
|
||||||
|
return dao.updateExistingEntry(entry)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package info.nightscout.androidaps.database.daos.delegated
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.database.daos.TemporaryTargetDao
|
||||||
|
import info.nightscout.androidaps.database.entities.TemporaryTarget
|
||||||
|
import info.nightscout.androidaps.database.interfaces.DBEntry
|
||||||
|
|
||||||
|
internal class DelegatedTemporaryTargetDao(changes: MutableList<DBEntry>, private val dao: TemporaryTargetDao) : DelegatedDao(changes), TemporaryTargetDao by dao {
|
||||||
|
|
||||||
|
override fun insertNewEntry(entry: TemporaryTarget): Long {
|
||||||
|
changes.add(entry)
|
||||||
|
return dao.insertNewEntry(entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateExistingEntry(entry: TemporaryTarget): Long {
|
||||||
|
changes.add(entry)
|
||||||
|
return dao.updateExistingEntry(entry)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package info.nightscout.androidaps.database.daos.delegated
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.database.daos.TherapyEventDao
|
||||||
|
import info.nightscout.androidaps.database.entities.TherapyEvent
|
||||||
|
import info.nightscout.androidaps.database.interfaces.DBEntry
|
||||||
|
|
||||||
|
internal class DelegatedTherapyEventDao(changes: MutableList<DBEntry>, private val dao: TherapyEventDao) : DelegatedDao(changes), TherapyEventDao by dao {
|
||||||
|
|
||||||
|
override fun insertNewEntry(entry: TherapyEvent): Long {
|
||||||
|
changes.add(entry)
|
||||||
|
return dao.insertNewEntry(entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateExistingEntry(entry: TherapyEvent): Long {
|
||||||
|
changes.add(entry)
|
||||||
|
return dao.updateExistingEntry(entry)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package info.nightscout.androidaps.database.daos.delegated
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.database.daos.TotalDailyDoseDao
|
||||||
|
import info.nightscout.androidaps.database.entities.TotalDailyDose
|
||||||
|
import info.nightscout.androidaps.database.interfaces.DBEntry
|
||||||
|
|
||||||
|
internal class DelegatedTotalDailyDoseDao(changes: MutableList<DBEntry>, private val dao: TotalDailyDoseDao) : DelegatedDao(changes), TotalDailyDoseDao by dao {
|
||||||
|
|
||||||
|
override fun insertNewEntry(entry: TotalDailyDose): Long {
|
||||||
|
changes.add(entry)
|
||||||
|
return dao.insertNewEntry(entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateExistingEntry(entry: TotalDailyDose): Long {
|
||||||
|
changes.add(entry)
|
||||||
|
return dao.updateExistingEntry(entry)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package info.nightscout.androidaps.database.daos.delegated
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.database.daos.VersionChangeDao
|
||||||
|
import info.nightscout.androidaps.database.entities.VersionChange
|
||||||
|
import info.nightscout.androidaps.database.interfaces.DBEntry
|
||||||
|
|
||||||
|
internal class DelegatedVersionChangeDao(changes: MutableList<DBEntry>, private val dao: VersionChangeDao) : DelegatedDao(changes), VersionChangeDao by dao {
|
||||||
|
|
||||||
|
override fun insert(versionChange: VersionChange) {
|
||||||
|
changes.add(versionChange)
|
||||||
|
return dao.insert(versionChange)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package info.nightscout.androidaps.database.daos.workaround;
|
||||||
|
|
||||||
|
import androidx.room.Transaction;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.database.daos.ProfileSwitchDao;
|
||||||
|
import info.nightscout.androidaps.database.daos.ProfileSwitchDaoKt;
|
||||||
|
import info.nightscout.androidaps.database.daos.TraceableDao;
|
||||||
|
import info.nightscout.androidaps.database.entities.ProfileSwitch;
|
||||||
|
|
||||||
|
public interface ProfileSwitchDaoWorkaround extends TraceableDao<ProfileSwitch> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transaction
|
||||||
|
default long insertNewEntry(ProfileSwitch entry) {
|
||||||
|
return ProfileSwitchDaoKt.insertNewEntryImpl((ProfileSwitchDao) this, entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transaction
|
||||||
|
default long updateExistingEntry(ProfileSwitch entry) {
|
||||||
|
return ProfileSwitchDaoKt.updateExistingEntryImpl((ProfileSwitchDao) this, entry);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package info.nightscout.androidaps.database.daos.workaround;
|
||||||
|
|
||||||
|
import androidx.room.Transaction;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.database.daos.TraceableDao;
|
||||||
|
import info.nightscout.androidaps.database.daos.TraceableDaoKt;
|
||||||
|
import info.nightscout.androidaps.database.interfaces.TraceableDBEntry;
|
||||||
|
|
||||||
|
public interface TraceableDaoWorkaround<T extends TraceableDBEntry> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts a new entry
|
||||||
|
*
|
||||||
|
* @return The ID of the newly generated entry
|
||||||
|
*/
|
||||||
|
@Transaction
|
||||||
|
default long insertNewEntry(T entry) {
|
||||||
|
return TraceableDaoKt.insertNewEntryImpl((TraceableDao<T>) this, entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates an existing entry
|
||||||
|
*
|
||||||
|
* @return The ID of the newly generated HISTORIC entry
|
||||||
|
*/
|
||||||
|
@Transaction
|
||||||
|
default long updateExistingEntry(T entry) {
|
||||||
|
return TraceableDaoKt.updateExistingEntryImpl((TraceableDao<T>) this, entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
/**
|
||||||
|
* Workarounds until Kotlin is able to properly translate interface default methods while annotation processing.
|
||||||
|
* See https://youtrack.jetbrains.com/issue/KT-25960
|
||||||
|
*/
|
||||||
|
package info.nightscout.androidaps.database.daos.workaround;
|
|
@ -0,0 +1,11 @@
|
||||||
|
package info.nightscout.androidaps.database.data
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
data class Block(var duration: Long, var amount: Double)
|
||||||
|
|
||||||
|
fun List<Block>.checkSanity(): Boolean {
|
||||||
|
var sum = 0L
|
||||||
|
forEach { sum += it.duration }
|
||||||
|
return sum == TimeUnit.DAYS.toMillis(1)
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
package info.nightscout.androidaps.database.data
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
data class TargetBlock(var duration: Long, var lowTarget: Double, var highTarget: Double)
|
||||||
|
|
||||||
|
fun List<TargetBlock>.checkSanity(): Boolean {
|
||||||
|
var sum = 0L
|
||||||
|
forEach { sum += it.duration }
|
||||||
|
return sum == TimeUnit.DAYS.toMillis(1)
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package info.nightscout.androidaps.database.embedments
|
||||||
|
|
||||||
|
data class InsulinConfiguration(
|
||||||
|
var insulinLabel: String,
|
||||||
|
var insulinEndTime: Long,
|
||||||
|
var peak: Long
|
||||||
|
)
|
|
@ -0,0 +1,20 @@
|
||||||
|
package info.nightscout.androidaps.database.embedments
|
||||||
|
|
||||||
|
data class InterfaceIDs(
|
||||||
|
var nightscoutSystemId: String? = null,
|
||||||
|
var nightscoutId: String? = null,
|
||||||
|
var pumpType: PumpType? = null,
|
||||||
|
var pumpSerial: String? = null,
|
||||||
|
var pumpId: Long? = null,
|
||||||
|
var startId: Long? = null,
|
||||||
|
var endId: Long? = null
|
||||||
|
) {
|
||||||
|
enum class PumpType {
|
||||||
|
ACCU_CHEK_INSIGHT,
|
||||||
|
ACCU_CHEK_COMBO,
|
||||||
|
DANA_R,
|
||||||
|
DANA_RS,
|
||||||
|
MEDTRONIC,
|
||||||
|
OMNIPOD
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package info.nightscout.androidaps.database.entities
|
||||||
|
|
||||||
|
import androidx.room.*
|
||||||
|
import info.nightscout.androidaps.database.TABLE_APS_RESULTS
|
||||||
|
import info.nightscout.androidaps.database.embedments.InterfaceIDs
|
||||||
|
import info.nightscout.androidaps.database.interfaces.DBEntryWithTime
|
||||||
|
import info.nightscout.androidaps.database.interfaces.TraceableDBEntry
|
||||||
|
import java.util.TimeZone
|
||||||
|
|
||||||
|
@Entity(tableName = TABLE_APS_RESULTS,
|
||||||
|
foreignKeys = [ForeignKey(
|
||||||
|
entity = APSResult::class,
|
||||||
|
parentColumns = ["id"],
|
||||||
|
childColumns = ["referenceId"])],
|
||||||
|
indices = [Index("referenceId"), Index("timestamp")])
|
||||||
|
data class APSResult(
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
override var id: Long = 0,
|
||||||
|
override var version: Int = 0,
|
||||||
|
override var dateCreated: Long = -1,
|
||||||
|
override var isValid: Boolean = true,
|
||||||
|
override var referenceId: Long? = null,
|
||||||
|
@Embedded
|
||||||
|
override var interfaceIDs_backing: InterfaceIDs? = null,
|
||||||
|
override var timestamp: Long,
|
||||||
|
override var utcOffset: Long = TimeZone.getDefault().getOffset(timestamp).toLong(),
|
||||||
|
var algorithm: Algorithm,
|
||||||
|
var glucoseStatusJson: String,
|
||||||
|
var currentTempJson: String,
|
||||||
|
var iobDataJson: String,
|
||||||
|
var profileJson: String,
|
||||||
|
var autosensDataJson: String?,
|
||||||
|
var mealDataJson: String,
|
||||||
|
var isMicroBolusAllowed: Boolean?,
|
||||||
|
var resultJson: String
|
||||||
|
) : TraceableDBEntry, DBEntryWithTime {
|
||||||
|
enum class Algorithm {
|
||||||
|
MA,
|
||||||
|
AMA,
|
||||||
|
SMB
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package info.nightscout.androidaps.database.entities
|
||||||
|
|
||||||
|
import androidx.room.*
|
||||||
|
import info.nightscout.androidaps.database.TABLE_APS_RESULT_LINKS
|
||||||
|
import info.nightscout.androidaps.database.embedments.InterfaceIDs
|
||||||
|
import info.nightscout.androidaps.database.interfaces.TraceableDBEntry
|
||||||
|
|
||||||
|
@Entity(tableName = TABLE_APS_RESULT_LINKS,
|
||||||
|
foreignKeys = [ForeignKey(
|
||||||
|
entity = APSResult::class,
|
||||||
|
parentColumns = arrayOf("id"),
|
||||||
|
childColumns = arrayOf("apsResultId")), ForeignKey(
|
||||||
|
|
||||||
|
entity = Bolus::class,
|
||||||
|
parentColumns = arrayOf("id"),
|
||||||
|
childColumns = arrayOf("smbId")), ForeignKey(
|
||||||
|
|
||||||
|
entity = TemporaryBasal::class,
|
||||||
|
parentColumns = arrayOf("id"),
|
||||||
|
childColumns = arrayOf("tbrId")), ForeignKey(
|
||||||
|
|
||||||
|
entity = APSResultLink::class,
|
||||||
|
parentColumns = arrayOf("id"),
|
||||||
|
childColumns = arrayOf("referenceId"))],
|
||||||
|
indices = [Index("referenceId"), Index("apsResultId"),
|
||||||
|
Index("smbId"), Index("tbrId")])
|
||||||
|
data class APSResultLink(
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
override var id: Long = 0,
|
||||||
|
override var version: Int = 0,
|
||||||
|
override var dateCreated: Long = -1,
|
||||||
|
override var isValid: Boolean = true,
|
||||||
|
override var referenceId: Long? = null,
|
||||||
|
@Embedded
|
||||||
|
override var interfaceIDs_backing: InterfaceIDs? = null,
|
||||||
|
var apsResultId: Long,
|
||||||
|
var smbId: Long? = null,
|
||||||
|
var tbrId: Long? = null
|
||||||
|
) : TraceableDBEntry {
|
||||||
|
override val foreignKeysValid: Boolean
|
||||||
|
get() = super.foreignKeysValid && apsResultId != 0L && smbId != 0L && tbrId != 0L
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package info.nightscout.androidaps.database.entities
|
||||||
|
|
||||||
|
import androidx.room.*
|
||||||
|
import info.nightscout.androidaps.database.TABLE_BOLUSES
|
||||||
|
import info.nightscout.androidaps.database.embedments.InsulinConfiguration
|
||||||
|
import info.nightscout.androidaps.database.embedments.InterfaceIDs
|
||||||
|
import info.nightscout.androidaps.database.interfaces.DBEntryWithTime
|
||||||
|
import info.nightscout.androidaps.database.interfaces.TraceableDBEntry
|
||||||
|
import java.util.TimeZone
|
||||||
|
|
||||||
|
@Entity(tableName = TABLE_BOLUSES,
|
||||||
|
foreignKeys = [ForeignKey(
|
||||||
|
entity = Bolus::class,
|
||||||
|
parentColumns = ["id"],
|
||||||
|
childColumns = ["referenceId"])],
|
||||||
|
indices = [Index("referenceId"), Index("timestamp")])
|
||||||
|
data class Bolus(
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
override var id: Long = 0,
|
||||||
|
override var version: Int = 0,
|
||||||
|
override var dateCreated: Long = -1,
|
||||||
|
override var isValid: Boolean = true,
|
||||||
|
override var referenceId: Long? = null,
|
||||||
|
@Embedded
|
||||||
|
override var interfaceIDs_backing: InterfaceIDs? = null,
|
||||||
|
override var timestamp: Long,
|
||||||
|
override var utcOffset: Long = TimeZone.getDefault().getOffset(timestamp).toLong(),
|
||||||
|
var amount: Double,
|
||||||
|
var type: Type,
|
||||||
|
var isBasalInsulin: Boolean,
|
||||||
|
@Embedded
|
||||||
|
var insulinConfiguration: InsulinConfiguration? = null
|
||||||
|
) : TraceableDBEntry, DBEntryWithTime {
|
||||||
|
enum class Type {
|
||||||
|
NORMAL,
|
||||||
|
SMB,
|
||||||
|
PRIMING
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
package info.nightscout.androidaps.database.entities
|
||||||
|
|
||||||
|
import androidx.room.*
|
||||||
|
import info.nightscout.androidaps.database.TABLE_BOLUS_CALCULATOR_RESULTS
|
||||||
|
import info.nightscout.androidaps.database.embedments.InterfaceIDs
|
||||||
|
import info.nightscout.androidaps.database.interfaces.DBEntryWithTime
|
||||||
|
import info.nightscout.androidaps.database.interfaces.TraceableDBEntry
|
||||||
|
import java.util.TimeZone
|
||||||
|
|
||||||
|
@Entity(tableName = TABLE_BOLUS_CALCULATOR_RESULTS,
|
||||||
|
foreignKeys = [ForeignKey(
|
||||||
|
entity = BolusCalculatorResult::class,
|
||||||
|
parentColumns = ["id"],
|
||||||
|
childColumns = ["referenceId"])],
|
||||||
|
indices = [Index("referenceId"), Index("timestamp")])
|
||||||
|
data class BolusCalculatorResult(
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
override var id: Long = 0,
|
||||||
|
override var version: Int = 0,
|
||||||
|
override var dateCreated: Long = -1,
|
||||||
|
override var isValid: Boolean = true,
|
||||||
|
override var referenceId: Long? = null,
|
||||||
|
@Embedded
|
||||||
|
override var interfaceIDs_backing: InterfaceIDs? = null,
|
||||||
|
override var timestamp: Long,
|
||||||
|
override var utcOffset: Long = TimeZone.getDefault().getOffset(timestamp).toLong(),
|
||||||
|
var targetBGLow: Double,
|
||||||
|
var targetBGHigh: Double,
|
||||||
|
var isf: Double,
|
||||||
|
var ic: Double,
|
||||||
|
var bolusIOB: Double,
|
||||||
|
var wasBolusIOBUsed: Boolean,
|
||||||
|
var basalIOB: Double,
|
||||||
|
var wasBasalIOBUsed: Boolean,
|
||||||
|
var glucoseValue: Double,
|
||||||
|
var wasGlucoseUsed: Boolean,
|
||||||
|
var glucoseDifference: Double,
|
||||||
|
var glucoseInsulin: Double,
|
||||||
|
var glucoseTrend: Double,
|
||||||
|
var wasTrendUsed: Boolean,
|
||||||
|
var trendInsulin: Double,
|
||||||
|
var cob: Double,
|
||||||
|
var wasCOBUsed: Boolean,
|
||||||
|
var cobInsulin: Double,
|
||||||
|
var carbs: Double,
|
||||||
|
var wereCarbsUsed: Boolean,
|
||||||
|
var carbsInsulin: Double,
|
||||||
|
var otherCorrection: Double,
|
||||||
|
var wasSuperbolusUsed: Boolean,
|
||||||
|
var superbolusInsulin: Double,
|
||||||
|
var wasTempTargetUsed: Boolean,
|
||||||
|
var totalInsulin: Double
|
||||||
|
) : TraceableDBEntry, DBEntryWithTime
|
|
@ -0,0 +1,29 @@
|
||||||
|
package info.nightscout.androidaps.database.entities
|
||||||
|
|
||||||
|
import androidx.room.*
|
||||||
|
import info.nightscout.androidaps.database.TABLE_CARBS
|
||||||
|
import info.nightscout.androidaps.database.embedments.InterfaceIDs
|
||||||
|
import info.nightscout.androidaps.database.interfaces.DBEntryWithTimeAndDuration
|
||||||
|
import info.nightscout.androidaps.database.interfaces.TraceableDBEntry
|
||||||
|
import java.util.TimeZone
|
||||||
|
|
||||||
|
@Entity(tableName = TABLE_CARBS,
|
||||||
|
foreignKeys = [ForeignKey(
|
||||||
|
entity = Carbs::class,
|
||||||
|
parentColumns = ["id"],
|
||||||
|
childColumns = ["referenceId"])],
|
||||||
|
indices = [Index("referenceId"), Index("timestamp")])
|
||||||
|
data class Carbs(
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
override var id: Long = 0,
|
||||||
|
override var version: Int = 0,
|
||||||
|
override var dateCreated: Long = -1,
|
||||||
|
override var isValid: Boolean = true,
|
||||||
|
override var referenceId: Long? = null,
|
||||||
|
@Embedded
|
||||||
|
override var interfaceIDs_backing: InterfaceIDs? = null,
|
||||||
|
override var timestamp: Long,
|
||||||
|
override var utcOffset: Long = TimeZone.getDefault().getOffset(timestamp).toLong(),
|
||||||
|
override var duration: Long,
|
||||||
|
var amount: Double
|
||||||
|
) : TraceableDBEntry, DBEntryWithTimeAndDuration
|
|
@ -0,0 +1,30 @@
|
||||||
|
package info.nightscout.androidaps.database.entities
|
||||||
|
|
||||||
|
import androidx.room.*
|
||||||
|
import info.nightscout.androidaps.database.data.Block
|
||||||
|
import info.nightscout.androidaps.database.TABLE_EFFECTIVE_PROFILE_SWITCHES
|
||||||
|
import info.nightscout.androidaps.database.embedments.InterfaceIDs
|
||||||
|
import info.nightscout.androidaps.database.interfaces.DBEntryWithTimeAndDuration
|
||||||
|
import info.nightscout.androidaps.database.interfaces.TraceableDBEntry
|
||||||
|
import java.util.TimeZone
|
||||||
|
|
||||||
|
@Entity(tableName = TABLE_EFFECTIVE_PROFILE_SWITCHES,
|
||||||
|
foreignKeys = [ForeignKey(
|
||||||
|
entity = EffectiveProfileSwitch::class,
|
||||||
|
parentColumns = ["id"],
|
||||||
|
childColumns = ["referenceId"])],
|
||||||
|
indices = [Index("referenceId"), Index("timestamp")])
|
||||||
|
data class EffectiveProfileSwitch(
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
override var id: Long = 0,
|
||||||
|
override var version: Int = 0,
|
||||||
|
override var dateCreated: Long = -1,
|
||||||
|
override var isValid: Boolean = true,
|
||||||
|
override var referenceId: Long? = null,
|
||||||
|
@Embedded
|
||||||
|
override var interfaceIDs_backing: InterfaceIDs? = null,
|
||||||
|
override var timestamp: Long,
|
||||||
|
override var utcOffset: Long = TimeZone.getDefault().getOffset(timestamp).toLong(),
|
||||||
|
override var duration: Long,
|
||||||
|
var basalBlocks: List<Block>
|
||||||
|
) : TraceableDBEntry, DBEntryWithTimeAndDuration
|
|
@ -0,0 +1,30 @@
|
||||||
|
package info.nightscout.androidaps.database.entities
|
||||||
|
|
||||||
|
import androidx.room.*
|
||||||
|
import info.nightscout.androidaps.database.TABLE_EXTENDED_BOLUSES
|
||||||
|
import info.nightscout.androidaps.database.embedments.InterfaceIDs
|
||||||
|
import info.nightscout.androidaps.database.interfaces.DBEntryWithTimeAndDuration
|
||||||
|
import info.nightscout.androidaps.database.interfaces.TraceableDBEntry
|
||||||
|
import java.util.TimeZone
|
||||||
|
|
||||||
|
@Entity(tableName = TABLE_EXTENDED_BOLUSES,
|
||||||
|
foreignKeys = [ForeignKey(
|
||||||
|
entity = ExtendedBolus::class,
|
||||||
|
parentColumns = ["id"],
|
||||||
|
childColumns = ["referenceId"])],
|
||||||
|
indices = [Index("referenceId"), Index("timestamp")])
|
||||||
|
data class ExtendedBolus(
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
override var id: Long = 0,
|
||||||
|
override var version: Int = 0,
|
||||||
|
override var dateCreated: Long = -1,
|
||||||
|
override var isValid: Boolean = true,
|
||||||
|
override var referenceId: Long? = null,
|
||||||
|
@Embedded
|
||||||
|
override var interfaceIDs_backing: InterfaceIDs? = InterfaceIDs(),
|
||||||
|
override var timestamp: Long,
|
||||||
|
override var utcOffset: Long = TimeZone.getDefault().getOffset(timestamp).toLong(),
|
||||||
|
override var duration: Long,
|
||||||
|
var amount: Double,
|
||||||
|
var isEmulatingTempBasal: Boolean
|
||||||
|
) : TraceableDBEntry, DBEntryWithTimeAndDuration
|
|
@ -0,0 +1,100 @@
|
||||||
|
package info.nightscout.androidaps.database.entities
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName
|
||||||
|
import androidx.room.*
|
||||||
|
import info.nightscout.androidaps.database.TABLE_GLUCOSE_VALUES
|
||||||
|
import info.nightscout.androidaps.database.embedments.InterfaceIDs
|
||||||
|
import info.nightscout.androidaps.database.interfaces.DBEntryWithTime
|
||||||
|
import info.nightscout.androidaps.database.interfaces.TraceableDBEntry
|
||||||
|
import java.util.TimeZone
|
||||||
|
|
||||||
|
@Entity(tableName = TABLE_GLUCOSE_VALUES,
|
||||||
|
foreignKeys = [ForeignKey(
|
||||||
|
entity = GlucoseValue::class,
|
||||||
|
parentColumns = ["id"],
|
||||||
|
childColumns = ["referenceId"])],
|
||||||
|
indices = [Index("referenceId"), Index("timestamp")])
|
||||||
|
data class GlucoseValue(
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
override var id: Long = 0,
|
||||||
|
override var version: Int = 0,
|
||||||
|
override var dateCreated: Long = -1,
|
||||||
|
override var isValid: Boolean = true,
|
||||||
|
override var referenceId: Long? = null,
|
||||||
|
@Embedded
|
||||||
|
override var interfaceIDs_backing: InterfaceIDs? = InterfaceIDs(),
|
||||||
|
override var timestamp: Long,
|
||||||
|
override var utcOffset: Long = TimeZone.getDefault().getOffset(timestamp).toLong(),
|
||||||
|
var raw: Double?,
|
||||||
|
var value: Double,
|
||||||
|
var trendArrow: TrendArrow,
|
||||||
|
var noise: Double?,
|
||||||
|
var sourceSensor: SourceSensor
|
||||||
|
) : TraceableDBEntry, DBEntryWithTime {
|
||||||
|
|
||||||
|
fun contentEqualsTo(other: GlucoseValue): Boolean =
|
||||||
|
timestamp == other.timestamp &&
|
||||||
|
utcOffset == other.utcOffset &&
|
||||||
|
raw == other.raw &&
|
||||||
|
value == other.value &&
|
||||||
|
trendArrow == other.trendArrow &&
|
||||||
|
noise == other.noise &&
|
||||||
|
sourceSensor == other.sourceSensor &&
|
||||||
|
isValid == other.isValid
|
||||||
|
|
||||||
|
fun isRecordDeleted(other: GlucoseValue): Boolean =
|
||||||
|
isValid && !other.isValid
|
||||||
|
|
||||||
|
enum class TrendArrow (val text:String, val symbol:String){
|
||||||
|
@SerializedName("NONE") NONE("NONE", "??"),
|
||||||
|
@SerializedName("TripleUp")TRIPLE_UP("TripleUp", "X"),
|
||||||
|
@SerializedName("DoubleUp")DOUBLE_UP("DoubleUp", "\u21c8"),
|
||||||
|
@SerializedName("SingleUp")SINGLE_UP("SingleUp", "\u2191"),
|
||||||
|
@SerializedName("FortyFiveUp")FORTY_FIVE_UP("FortyFiveUp", "\u2197"),
|
||||||
|
@SerializedName("Flat")FLAT("Flat", "\u2192"),
|
||||||
|
@SerializedName("FortyFiveDown")FORTY_FIVE_DOWN("FortyFiveDown", "\u2198"),
|
||||||
|
@SerializedName("SingleDown")SINGLE_DOWN("SingleDown", "\u2193"),
|
||||||
|
@SerializedName("DoubleDown")DOUBLE_DOWN("DoubleDown", "\u21ca"),
|
||||||
|
@SerializedName("TripleDown")TRIPLE_DOWN("TripleDown", "X")
|
||||||
|
;
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun fromString(direction : String?) = values().firstOrNull {it.text == direction} ?: NONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class SourceSensor(val text : String) {
|
||||||
|
@SerializedName("AndroidAPS-Dexcom") DEXCOM_NATIVE_UNKNOWN("AndroidAPS-Dexcom"),
|
||||||
|
@SerializedName("AndroidAPS-DexcomG6") DEXCOM_G6_NATIVE("AndroidAPS-DexcomG6"),
|
||||||
|
@SerializedName("AndroidAPS-DexcomG5") DEXCOM_G5_NATIVE("AndroidAPS-DexcomG5"),
|
||||||
|
@SerializedName("Bluetooth Wixel") DEXCOM_G4_WIXEL("Bluetooth Wixel"),
|
||||||
|
@SerializedName("xBridge Wixel") DEXCOM_G4_XBRIDGE("xBridge Wixel"),
|
||||||
|
@SerializedName("G4 Share Receiver") DEXCOM_G4_NATIVE("G4 Share Receiver"),
|
||||||
|
@SerializedName("Medtrum A6") MEDTRUM_A6("Medtrum A6"),
|
||||||
|
@SerializedName("Network G4") DEXCOM_G4_NET("Network G4"),
|
||||||
|
@SerializedName("Network G4 and xBridge") DEXCOM_G4_NET_XBRIDGE("Network G4 and xBridge"),
|
||||||
|
@SerializedName("Network G4 and Classic xDrip") DEXCOM_G4_NET_CLASSIC("Network G4 and Classic xDrip"),
|
||||||
|
@SerializedName("DexcomG5") DEXCOM_G5_XDRIP("DexcomG5"),
|
||||||
|
@SerializedName("G6 Native") DEXCOM_G6_NATIVE_XDRIP("G6 Native"),
|
||||||
|
@SerializedName("G5 Native") DEXCOM_G5_NATIVE_XDRIP("G5 Native"),
|
||||||
|
@SerializedName("Network libre") LIBRE_1_NET("Network libre"),
|
||||||
|
@SerializedName("BlueReader") LIBRE_1_BLUE("BlueReader"),
|
||||||
|
@SerializedName("Transmiter PL") LIBRE_1_PL("Transmiter PL"),
|
||||||
|
@SerializedName("Blucon") LIBRE_1_BLUCON("Blucon"),
|
||||||
|
@SerializedName("Tomato") LIBRE_1_TOMATO("Tomato"),
|
||||||
|
@SerializedName("Rfduino") LIBRE_1_RF("Rfduino"),
|
||||||
|
@SerializedName("LimiTTer") LIBRE_1_LIMITTER("LimiTTer"),
|
||||||
|
@SerializedName("Glimp") GLIMP("Glimp"),
|
||||||
|
@SerializedName("Libre2") LIBRE_2_NATIVE("Libre2"),
|
||||||
|
@SerializedName("Poctech") POCTECH_NATIVE("Poctech"),
|
||||||
|
@SerializedName("MM600Series") MM_600_SERIES("MM600Series"),
|
||||||
|
@SerializedName("Eversense") EVERSENSE("Eversense"),
|
||||||
|
@SerializedName("Random") RANDOM("Random"),
|
||||||
|
@SerializedName("Unknown") UNKNOWN("Unknown")
|
||||||
|
;
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun fromString(source : String?) = values().firstOrNull {it.text == source} ?: UNKNOWN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
package info.nightscout.androidaps.database.entities
|
||||||
|
|
||||||
|
import androidx.room.*
|
||||||
|
import info.nightscout.androidaps.database.TABLE_MEAL_LINKS
|
||||||
|
import info.nightscout.androidaps.database.embedments.InterfaceIDs
|
||||||
|
import info.nightscout.androidaps.database.interfaces.TraceableDBEntry
|
||||||
|
|
||||||
|
@Entity(tableName = TABLE_MEAL_LINKS,
|
||||||
|
foreignKeys = [ForeignKey(
|
||||||
|
entity = Bolus::class,
|
||||||
|
parentColumns = arrayOf("id"),
|
||||||
|
childColumns = arrayOf("bolusId")), ForeignKey(
|
||||||
|
|
||||||
|
entity = Carbs::class,
|
||||||
|
parentColumns = arrayOf("id"),
|
||||||
|
childColumns = arrayOf("carbsId")), ForeignKey(
|
||||||
|
|
||||||
|
entity = BolusCalculatorResult::class,
|
||||||
|
parentColumns = arrayOf("id"),
|
||||||
|
childColumns = arrayOf("bolusCalcResultId")), ForeignKey(
|
||||||
|
|
||||||
|
entity = TemporaryBasal::class,
|
||||||
|
parentColumns = arrayOf("id"),
|
||||||
|
childColumns = arrayOf("superbolusTempBasalId")), ForeignKey(
|
||||||
|
|
||||||
|
entity = TherapyEvent::class,
|
||||||
|
parentColumns = arrayOf("id"),
|
||||||
|
childColumns = arrayOf("noteId")), ForeignKey(
|
||||||
|
|
||||||
|
entity = MealLink::class,
|
||||||
|
parentColumns = ["id"],
|
||||||
|
childColumns = ["referenceId"])],
|
||||||
|
indices = [Index("referenceId"), Index("bolusId"),
|
||||||
|
Index("carbsId"), Index("bolusCalcResultId"),
|
||||||
|
Index("superbolusTempBasalId"), Index("noteId")])
|
||||||
|
data class MealLink(
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
override var id: Long = 0,
|
||||||
|
override var version: Int = 0,
|
||||||
|
override var dateCreated: Long = -1,
|
||||||
|
override var isValid: Boolean = true,
|
||||||
|
override var referenceId: Long? = null,
|
||||||
|
@Embedded
|
||||||
|
override var interfaceIDs_backing: InterfaceIDs? = null,
|
||||||
|
var bolusId: Long? = null,
|
||||||
|
var carbsId: Long? = null,
|
||||||
|
var bolusCalcResultId: Long? = null,
|
||||||
|
var superbolusTempBasalId: Long? = null,
|
||||||
|
var noteId: Long? = null
|
||||||
|
) : TraceableDBEntry {
|
||||||
|
override val foreignKeysValid: Boolean
|
||||||
|
get() = super.foreignKeysValid && bolusId != 0L && carbsId != 0L &&
|
||||||
|
bolusCalcResultId != 0L && superbolusTempBasalId != 0L && noteId != 0L
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package info.nightscout.androidaps.database.entities
|
||||||
|
|
||||||
|
import androidx.room.*
|
||||||
|
import info.nightscout.androidaps.database.TABLE_MULTIWAVE_BOLUS_LINKS
|
||||||
|
import info.nightscout.androidaps.database.embedments.InterfaceIDs
|
||||||
|
import info.nightscout.androidaps.database.interfaces.TraceableDBEntry
|
||||||
|
|
||||||
|
@Entity(tableName = TABLE_MULTIWAVE_BOLUS_LINKS,
|
||||||
|
foreignKeys = [ForeignKey(
|
||||||
|
entity = Bolus::class,
|
||||||
|
parentColumns = arrayOf("id"),
|
||||||
|
childColumns = arrayOf("bolusId")), ForeignKey(
|
||||||
|
|
||||||
|
entity = ExtendedBolus::class,
|
||||||
|
parentColumns = arrayOf("id"),
|
||||||
|
childColumns = arrayOf("extendedBolusId")), ForeignKey(
|
||||||
|
|
||||||
|
entity = MultiwaveBolusLink::class,
|
||||||
|
parentColumns = ["id"],
|
||||||
|
childColumns = ["referenceId"])],
|
||||||
|
indices = [Index("referenceId"), Index("bolusId"),
|
||||||
|
Index("extendedBolusId")])
|
||||||
|
data class MultiwaveBolusLink(
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
override var id: Long = 0,
|
||||||
|
override var version: Int = 0,
|
||||||
|
override var dateCreated: Long = -1,
|
||||||
|
override var isValid: Boolean = true,
|
||||||
|
override var referenceId: Long? = null,
|
||||||
|
@Embedded
|
||||||
|
override var interfaceIDs_backing: InterfaceIDs? = null,
|
||||||
|
var bolusId: Long,
|
||||||
|
var extendedBolusId: Long
|
||||||
|
) : TraceableDBEntry {
|
||||||
|
override val foreignKeysValid: Boolean
|
||||||
|
get() = super.foreignKeysValid && bolusId != 0L && bolusId != 0L && extendedBolusId != 0L
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package info.nightscout.androidaps.database.entities
|
||||||
|
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
import info.nightscout.androidaps.database.TABLE_PREFERENCE_CHANGES
|
||||||
|
import info.nightscout.androidaps.database.interfaces.DBEntry
|
||||||
|
import info.nightscout.androidaps.database.interfaces.DBEntryWithTime
|
||||||
|
import java.util.TimeZone
|
||||||
|
|
||||||
|
@Entity(tableName = TABLE_PREFERENCE_CHANGES)
|
||||||
|
data class PreferenceChange(
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
override var id: Long = 0L,
|
||||||
|
override var timestamp: Long,
|
||||||
|
override var utcOffset: Long = TimeZone.getDefault().getOffset(timestamp).toLong(),
|
||||||
|
var key: String,
|
||||||
|
var value: Any?
|
||||||
|
) : DBEntry, DBEntryWithTime
|
|
@ -0,0 +1,46 @@
|
||||||
|
package info.nightscout.androidaps.database.entities
|
||||||
|
|
||||||
|
import androidx.room.*
|
||||||
|
import info.nightscout.androidaps.database.data.Block
|
||||||
|
import info.nightscout.androidaps.database.TABLE_PROFILE_SWITCHES
|
||||||
|
import info.nightscout.androidaps.database.data.TargetBlock
|
||||||
|
import info.nightscout.androidaps.database.embedments.InsulinConfiguration
|
||||||
|
import info.nightscout.androidaps.database.embedments.InterfaceIDs
|
||||||
|
import info.nightscout.androidaps.database.interfaces.DBEntryWithTimeAndDuration
|
||||||
|
import info.nightscout.androidaps.database.interfaces.TraceableDBEntry
|
||||||
|
import java.util.TimeZone
|
||||||
|
|
||||||
|
@Entity(tableName = TABLE_PROFILE_SWITCHES,
|
||||||
|
foreignKeys = [ForeignKey(
|
||||||
|
entity = ProfileSwitch::class,
|
||||||
|
parentColumns = ["id"],
|
||||||
|
childColumns = ["referenceId"])],
|
||||||
|
indices = [Index("referenceId"), Index("timestamp")])
|
||||||
|
data class ProfileSwitch(
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
override var id: Long = 0,
|
||||||
|
override var version: Int = 0,
|
||||||
|
override var dateCreated: Long = -1,
|
||||||
|
override var isValid: Boolean = true,
|
||||||
|
override var referenceId: Long? = null,
|
||||||
|
@Embedded
|
||||||
|
override var interfaceIDs_backing: InterfaceIDs? = InterfaceIDs(),
|
||||||
|
override var timestamp: Long,
|
||||||
|
override var utcOffset: Long = TimeZone.getDefault().getOffset(timestamp).toLong(),
|
||||||
|
var profileName: String,
|
||||||
|
var glucoseUnit: GlucoseUnit,
|
||||||
|
var basalBlocks: List<Block>,
|
||||||
|
var isfBlocks: List<Block>,
|
||||||
|
var icBlocks: List<Block>,
|
||||||
|
var targetBlocks: List<TargetBlock>,
|
||||||
|
@Embedded
|
||||||
|
var insulinConfiguration: InsulinConfiguration,
|
||||||
|
var timeshift: Int,
|
||||||
|
var percentage: Int,
|
||||||
|
override var duration: Long
|
||||||
|
) : TraceableDBEntry, DBEntryWithTimeAndDuration {
|
||||||
|
enum class GlucoseUnit {
|
||||||
|
MGDL,
|
||||||
|
MMOL
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package info.nightscout.androidaps.database.entities
|
||||||
|
|
||||||
|
import androidx.room.*
|
||||||
|
import info.nightscout.androidaps.database.TABLE_TEMPORARY_BASALS
|
||||||
|
import info.nightscout.androidaps.database.embedments.InterfaceIDs
|
||||||
|
import info.nightscout.androidaps.database.interfaces.DBEntryWithTimeAndDuration
|
||||||
|
import info.nightscout.androidaps.database.interfaces.TraceableDBEntry
|
||||||
|
import java.util.TimeZone
|
||||||
|
|
||||||
|
@Entity(tableName = TABLE_TEMPORARY_BASALS,
|
||||||
|
foreignKeys = [ForeignKey(
|
||||||
|
entity = TemporaryBasal::class,
|
||||||
|
parentColumns = ["id"],
|
||||||
|
childColumns = ["referenceId"])],
|
||||||
|
indices = [Index("referenceId"), Index("timestamp")])
|
||||||
|
data class TemporaryBasal(
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
override var id: Long = 0,
|
||||||
|
override var version: Int = 0,
|
||||||
|
override var dateCreated: Long = -1,
|
||||||
|
override var isValid: Boolean = true,
|
||||||
|
override var referenceId: Long? = null,
|
||||||
|
@Embedded
|
||||||
|
override var interfaceIDs_backing: InterfaceIDs? = InterfaceIDs(),
|
||||||
|
override var timestamp: Long,
|
||||||
|
override var utcOffset: Long = TimeZone.getDefault().getOffset(timestamp).toLong(),
|
||||||
|
var type: Type,
|
||||||
|
var isAbsolute: Boolean,
|
||||||
|
var rate: Double,
|
||||||
|
override var duration: Long
|
||||||
|
) : TraceableDBEntry, DBEntryWithTimeAndDuration {
|
||||||
|
enum class Type {
|
||||||
|
NORMAL,
|
||||||
|
EMULATED_PUMP_SUSPEND,
|
||||||
|
PUMP_SUSPEND,
|
||||||
|
SUPERBOLUS
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
package info.nightscout.androidaps.database.entities
|
||||||
|
|
||||||
|
import androidx.room.Embedded
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.ForeignKey
|
||||||
|
import androidx.room.Index
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
import com.google.gson.annotations.SerializedName
|
||||||
|
import info.nightscout.androidaps.database.TABLE_TEMPORARY_TARGETS
|
||||||
|
import info.nightscout.androidaps.database.embedments.InterfaceIDs
|
||||||
|
import info.nightscout.androidaps.database.interfaces.DBEntryWithTimeAndDuration
|
||||||
|
import info.nightscout.androidaps.database.interfaces.TraceableDBEntry
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
@Entity(tableName = TABLE_TEMPORARY_TARGETS,
|
||||||
|
foreignKeys = [ForeignKey(
|
||||||
|
entity = TemporaryTarget::class,
|
||||||
|
parentColumns = ["id"],
|
||||||
|
childColumns = ["referenceId"])],
|
||||||
|
indices = [Index("referenceId"), Index("timestamp")])
|
||||||
|
data class TemporaryTarget(
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
override var id: Long = 0,
|
||||||
|
override var version: Int = 0,
|
||||||
|
override var dateCreated: Long = -1,
|
||||||
|
override var isValid: Boolean = true,
|
||||||
|
override var referenceId: Long? = null,
|
||||||
|
@Embedded
|
||||||
|
override var interfaceIDs_backing: InterfaceIDs? = InterfaceIDs(),
|
||||||
|
override var timestamp: Long,
|
||||||
|
override var utcOffset: Long = TimeZone.getDefault().getOffset(timestamp).toLong(),
|
||||||
|
var reason: Reason,
|
||||||
|
var highTarget: Double, // in mgdl
|
||||||
|
var lowTarget: Double, // in mgdl
|
||||||
|
override var duration: Long // in millis
|
||||||
|
) : TraceableDBEntry, DBEntryWithTimeAndDuration {
|
||||||
|
|
||||||
|
fun contentEqualsTo(other: TemporaryTarget): Boolean =
|
||||||
|
timestamp == other.timestamp &&
|
||||||
|
utcOffset == other.utcOffset &&
|
||||||
|
reason == other.reason &&
|
||||||
|
highTarget == other.highTarget &&
|
||||||
|
lowTarget == other.lowTarget &&
|
||||||
|
duration == other.duration &&
|
||||||
|
isValid == other.isValid
|
||||||
|
|
||||||
|
fun isRecordDeleted(other: TemporaryTarget): Boolean =
|
||||||
|
isValid && !other.isValid
|
||||||
|
|
||||||
|
enum class Reason(val text: String) {
|
||||||
|
@SerializedName("Custom")
|
||||||
|
CUSTOM("Custom"),
|
||||||
|
@SerializedName("Hypo")
|
||||||
|
HYPOGLYCEMIA("Hypo"),
|
||||||
|
@SerializedName("Activity")
|
||||||
|
ACTIVITY("Activity"),
|
||||||
|
@SerializedName("Eating Soon")
|
||||||
|
EATING_SOON("Eating Soon"),
|
||||||
|
@SerializedName("Automation")
|
||||||
|
AUTOMATION("Automation")
|
||||||
|
;
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun fromString(direction: String?) = values().firstOrNull { it.text == direction }
|
||||||
|
?: CUSTOM
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
package info.nightscout.androidaps.database.entities
|
||||||
|
|
||||||
|
import androidx.room.*
|
||||||
|
import info.nightscout.androidaps.database.TABLE_THERAPY_EVENTS
|
||||||
|
import info.nightscout.androidaps.database.embedments.InterfaceIDs
|
||||||
|
import info.nightscout.androidaps.database.interfaces.DBEntryWithTimeAndDuration
|
||||||
|
import info.nightscout.androidaps.database.interfaces.TraceableDBEntry
|
||||||
|
import java.util.TimeZone
|
||||||
|
|
||||||
|
@Entity(tableName = TABLE_THERAPY_EVENTS,
|
||||||
|
foreignKeys = [ForeignKey(
|
||||||
|
entity = TherapyEvent::class,
|
||||||
|
parentColumns = ["id"],
|
||||||
|
childColumns = ["referenceId"])],
|
||||||
|
indices = [Index("referenceId"), Index("timestamp")])
|
||||||
|
data class TherapyEvent(
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
override var id: Long = 0,
|
||||||
|
override var version: Int = 0,
|
||||||
|
override var dateCreated: Long = -1,
|
||||||
|
override var isValid: Boolean = true,
|
||||||
|
override var referenceId: Long? = null,
|
||||||
|
@Embedded
|
||||||
|
override var interfaceIDs_backing: InterfaceIDs? = InterfaceIDs(),
|
||||||
|
override var timestamp: Long,
|
||||||
|
override var utcOffset: Long = TimeZone.getDefault().getOffset(timestamp).toLong(),
|
||||||
|
override var duration: Long = 0,
|
||||||
|
var type: Type,
|
||||||
|
var note: String? = null,
|
||||||
|
var amount: Double? = null
|
||||||
|
) : TraceableDBEntry, DBEntryWithTimeAndDuration {
|
||||||
|
enum class Type {
|
||||||
|
CANNULA_CHANGED,
|
||||||
|
TUBE_CHANGED,
|
||||||
|
RESERVOIR_CHANGED,
|
||||||
|
BATTERY_CHANGED,
|
||||||
|
LEAKING_INFUSION_SET,
|
||||||
|
SENSOR_INSERTED,
|
||||||
|
SENSOR_STARTED,
|
||||||
|
SENSOR_STOPPED,
|
||||||
|
FINGER_STICK_BG_VALUE,
|
||||||
|
ACTIVITY,
|
||||||
|
FALLING_ASLEEP,
|
||||||
|
WAKING_UP,
|
||||||
|
SICKNESS,
|
||||||
|
STRESS,
|
||||||
|
PRE_PERIOD,
|
||||||
|
ALCOHOL,
|
||||||
|
CORTISON,
|
||||||
|
FEELING_LOW,
|
||||||
|
FEELING_HIGH,
|
||||||
|
ANNOUNCEMENT,
|
||||||
|
QUESTION,
|
||||||
|
NOTE,
|
||||||
|
APS_OFFLINE,
|
||||||
|
BATTERY_EMPTY,
|
||||||
|
RESERVOIR_EMPTY,
|
||||||
|
OCCLUSION,
|
||||||
|
PUMP_STOPPED,
|
||||||
|
PUMP_STARTED,
|
||||||
|
PUMP_PAUSED
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
package info.nightscout.androidaps.database.entities
|
||||||
|
|
||||||
|
import androidx.room.*
|
||||||
|
import info.nightscout.androidaps.database.TABLE_TOTAL_DAILY_DOSES
|
||||||
|
import info.nightscout.androidaps.database.embedments.InterfaceIDs
|
||||||
|
import info.nightscout.androidaps.database.interfaces.DBEntryWithTime
|
||||||
|
import info.nightscout.androidaps.database.interfaces.TraceableDBEntry
|
||||||
|
import java.util.TimeZone
|
||||||
|
|
||||||
|
@Entity(tableName = TABLE_TOTAL_DAILY_DOSES,
|
||||||
|
foreignKeys = [ForeignKey(
|
||||||
|
entity = TotalDailyDose::class,
|
||||||
|
parentColumns = ["id"],
|
||||||
|
childColumns = ["referenceId"])],
|
||||||
|
indices = [Index("referenceId"), Index("timestamp")])
|
||||||
|
data class TotalDailyDose(
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
override var id: Long = 0,
|
||||||
|
override var version: Int = 0,
|
||||||
|
override var dateCreated: Long = -1,
|
||||||
|
override var isValid: Boolean = true,
|
||||||
|
override var referenceId: Long? = null,
|
||||||
|
@Embedded
|
||||||
|
override var interfaceIDs_backing: InterfaceIDs? = InterfaceIDs(),
|
||||||
|
override var timestamp: Long,
|
||||||
|
override var utcOffset: Long = TimeZone.getDefault().getOffset(timestamp).toLong(),
|
||||||
|
var basalAmount: Double?,
|
||||||
|
var bolusAmount: Double?,
|
||||||
|
var totalAmount: Double?
|
||||||
|
) : TraceableDBEntry, DBEntryWithTime
|
|
@ -0,0 +1,20 @@
|
||||||
|
package info.nightscout.androidaps.database.entities
|
||||||
|
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
import info.nightscout.androidaps.database.TABLE_VERSION_CHANGES
|
||||||
|
import info.nightscout.androidaps.database.interfaces.DBEntry
|
||||||
|
import info.nightscout.androidaps.database.interfaces.DBEntryWithTime
|
||||||
|
import java.util.TimeZone
|
||||||
|
|
||||||
|
@Entity(tableName = TABLE_VERSION_CHANGES)
|
||||||
|
data class VersionChange(
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
override var id: Long = 0L,
|
||||||
|
override var timestamp: Long,
|
||||||
|
override var utcOffset: Long = TimeZone.getDefault().getOffset(timestamp).toLong(),
|
||||||
|
var versionCode: Int,
|
||||||
|
var versionName: String,
|
||||||
|
var gitRemote: String?,
|
||||||
|
var commitHash: String?
|
||||||
|
) : DBEntry, DBEntryWithTime
|
|
@ -0,0 +1,5 @@
|
||||||
|
package info.nightscout.androidaps.database.interfaces
|
||||||
|
|
||||||
|
interface DBEntry {
|
||||||
|
var id: Long
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package info.nightscout.androidaps.database.interfaces
|
||||||
|
|
||||||
|
interface DBEntryWithDuration {
|
||||||
|
var duration: Long
|
||||||
|
|
||||||
|
val durationUnknown get() = duration == Long.MAX_VALUE
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
package info.nightscout.androidaps.database.interfaces
|
||||||
|
|
||||||
|
interface DBEntryWithTime {
|
||||||
|
var timestamp: Long
|
||||||
|
var utcOffset: Long
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package info.nightscout.androidaps.database.interfaces
|
||||||
|
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
|
interface DBEntryWithTimeAndDuration : DBEntryWithTime, DBEntryWithDuration
|
||||||
|
|
||||||
|
var DBEntryWithTimeAndDuration.end
|
||||||
|
get() = timestamp + duration
|
||||||
|
set(value) {
|
||||||
|
duration = value - timestamp
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmOverloads
|
||||||
|
fun DBEntryWithTimeAndDuration.getRemainingDuration(current: Long = System.currentTimeMillis()) = min(0L, end - current)
|
|
@ -0,0 +1,28 @@
|
||||||
|
package info.nightscout.androidaps.database.interfaces
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.database.embedments.InterfaceIDs
|
||||||
|
|
||||||
|
interface TraceableDBEntry: DBEntry {
|
||||||
|
var version: Int
|
||||||
|
var dateCreated: Long
|
||||||
|
var isValid: Boolean
|
||||||
|
var referenceId: Long?
|
||||||
|
var interfaceIDs_backing: InterfaceIDs?
|
||||||
|
|
||||||
|
val historic: Boolean get() = referenceId != null
|
||||||
|
|
||||||
|
val foreignKeysValid: Boolean get() = referenceId != 0L
|
||||||
|
|
||||||
|
var interfaceIDs: InterfaceIDs
|
||||||
|
get() {
|
||||||
|
var value = this.interfaceIDs_backing
|
||||||
|
if (value == null) {
|
||||||
|
value = InterfaceIDs()
|
||||||
|
interfaceIDs_backing = value
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
set(value) {
|
||||||
|
interfaceIDs_backing = value
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package info.nightscout.androidaps.database.transactions
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.database.entities.TemporaryTarget
|
||||||
|
import info.nightscout.androidaps.database.interfaces.end
|
||||||
|
|
||||||
|
class CancelCurrentTemporaryTargetIfAnyTransaction(
|
||||||
|
val timestamp: Long
|
||||||
|
) : Transaction<Unit>() {
|
||||||
|
override fun run() {
|
||||||
|
val current = database.temporaryTargetDao.getTemporaryTargetActiveAt(timestamp)
|
||||||
|
if (current != null) {
|
||||||
|
current.end = timestamp
|
||||||
|
database.temporaryTargetDao.updateExistingEntry(current)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
package info.nightscout.androidaps.database.transactions
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.database.entities.GlucoseValue
|
||||||
|
import info.nightscout.androidaps.database.entities.TherapyEvent
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts data from a CGM source into the database
|
||||||
|
*/
|
||||||
|
class CgmSourceTransaction(
|
||||||
|
private val glucoseValues: List<TransactionGlucoseValue>,
|
||||||
|
private val calibrations: List<Calibration>,
|
||||||
|
private val sensorInsertionTime: Long?
|
||||||
|
) : Transaction<List<GlucoseValue>>() {
|
||||||
|
|
||||||
|
override fun run(): List<GlucoseValue> {
|
||||||
|
val insertedGlucoseValues = mutableListOf<GlucoseValue>()
|
||||||
|
glucoseValues.forEach {
|
||||||
|
val current = database.glucoseValueDao.findByTimestampAndSensor(it.timestamp, it.sourceSensor)
|
||||||
|
val glucoseValue = GlucoseValue(
|
||||||
|
timestamp = it.timestamp,
|
||||||
|
raw = it.raw,
|
||||||
|
value = it.value,
|
||||||
|
noise = it.noise,
|
||||||
|
trendArrow = it.trendArrow,
|
||||||
|
sourceSensor = it.sourceSensor
|
||||||
|
)
|
||||||
|
glucoseValue.interfaceIDs.nightscoutId = it.nightscoutId
|
||||||
|
when {
|
||||||
|
current == null -> {
|
||||||
|
database.glucoseValueDao.insertNewEntry(glucoseValue)
|
||||||
|
insertedGlucoseValues.add(glucoseValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
!current.contentEqualsTo(glucoseValue) -> {
|
||||||
|
glucoseValue.id = current.id
|
||||||
|
database.glucoseValueDao.updateExistingEntry(glucoseValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
calibrations.forEach {
|
||||||
|
if (database.therapyEventDao.findByTimestamp(TherapyEvent.Type.FINGER_STICK_BG_VALUE, it.timestamp) == null) {
|
||||||
|
database.therapyEventDao.insertNewEntry(TherapyEvent(
|
||||||
|
timestamp = it.timestamp,
|
||||||
|
type = TherapyEvent.Type.FINGER_STICK_BG_VALUE,
|
||||||
|
amount = it.value
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sensorInsertionTime?.let {
|
||||||
|
if (database.therapyEventDao.findByTimestamp(TherapyEvent.Type.SENSOR_INSERTED, it) == null) {
|
||||||
|
database.therapyEventDao.insertNewEntry(TherapyEvent(
|
||||||
|
timestamp = it,
|
||||||
|
type = TherapyEvent.Type.SENSOR_INSERTED
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return insertedGlucoseValues
|
||||||
|
}
|
||||||
|
|
||||||
|
data class TransactionGlucoseValue(
|
||||||
|
val timestamp: Long,
|
||||||
|
val value: Double,
|
||||||
|
val raw: Double?,
|
||||||
|
val noise: Double?,
|
||||||
|
val trendArrow: GlucoseValue.TrendArrow,
|
||||||
|
val nightscoutId: String? = null,
|
||||||
|
val sourceSensor: GlucoseValue.SourceSensor
|
||||||
|
)
|
||||||
|
|
||||||
|
data class Calibration(
|
||||||
|
val timestamp: Long,
|
||||||
|
val value: Double
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package info.nightscout.androidaps.database.transactions
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.database.entities.GlucoseValue
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the GlucoseValue
|
||||||
|
*/
|
||||||
|
class InsertGlucoseValueTransaction(val glucoseValue: GlucoseValue) : Transaction<Unit>() {
|
||||||
|
|
||||||
|
override fun run() {
|
||||||
|
database.glucoseValueDao.insert(glucoseValue)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package info.nightscout.androidaps.database.transactions
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.database.entities.TemporaryTarget
|
||||||
|
import info.nightscout.androidaps.database.interfaces.end
|
||||||
|
|
||||||
|
class InsertTemporaryTargetAndCancelCurrentTransaction(
|
||||||
|
private val temporaryTarget: TemporaryTarget
|
||||||
|
) : Transaction<Unit>() {
|
||||||
|
|
||||||
|
constructor(timestamp: Long, duration: Long, reason: TemporaryTarget.Reason, lowTarget: Double, highTarget: Double) :
|
||||||
|
this(TemporaryTarget(timestamp = timestamp, reason = reason, lowTarget = lowTarget, highTarget = highTarget, duration = duration))
|
||||||
|
|
||||||
|
override fun run() {
|
||||||
|
val current = database.temporaryTargetDao.getTemporaryTargetActiveAt(temporaryTarget.timestamp)
|
||||||
|
if (current != null) {
|
||||||
|
current.end = temporaryTarget.timestamp
|
||||||
|
database.temporaryTargetDao.updateExistingEntry(current)
|
||||||
|
}
|
||||||
|
database.temporaryTargetDao.insertNewEntry(temporaryTarget)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package info.nightscout.androidaps.database.transactions
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.database.transactions.Transaction
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalidates the GlucoseValue with the specified id
|
||||||
|
*/
|
||||||
|
class InvalidateGlucoseValueTransaction(val id: Long) : Transaction<Unit>() {
|
||||||
|
override fun run() {
|
||||||
|
val glucoseValue = database.glucoseValueDao.findById(id)
|
||||||
|
?: throw IllegalArgumentException("There is no such GlucoseValue with the specified ID.")
|
||||||
|
glucoseValue.isValid = false
|
||||||
|
database.glucoseValueDao.updateExistingEntry(glucoseValue)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package info.nightscout.androidaps.database.transactions
|
||||||
|
|
||||||
|
class InvalidateTemporaryTargetTransaction(val id: Long) : Transaction<Unit>() {
|
||||||
|
override fun run() {
|
||||||
|
val temporaryTarget = database.temporaryTargetDao.findById(id)
|
||||||
|
?: throw IllegalArgumentException("There is no such TemporaryTarget with the specified ID.")
|
||||||
|
temporaryTarget.isValid = false
|
||||||
|
database.temporaryTargetDao.updateExistingEntry(temporaryTarget)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package info.nightscout.androidaps.database.transactions
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.database.DelegatedAppDatabase
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for database transactions
|
||||||
|
* @param T The return type of the Transaction
|
||||||
|
*/
|
||||||
|
abstract class Transaction<T> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the Transaction
|
||||||
|
*/
|
||||||
|
internal abstract fun run(): T
|
||||||
|
|
||||||
|
internal lateinit var database: DelegatedAppDatabase
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package info.nightscout.androidaps.database.transactions
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.database.entities.GlucoseValue
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the GlucoseValue
|
||||||
|
*/
|
||||||
|
class UpdateGlucoseValueTransaction(val glucoseValue: GlucoseValue) : Transaction<Unit>() {
|
||||||
|
|
||||||
|
override fun run() {
|
||||||
|
database.glucoseValueDao.updateExistingEntry(glucoseValue)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package info.nightscout.androidaps.database.transactions
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.database.entities.TemporaryTarget
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the TemporaryTarget
|
||||||
|
*/
|
||||||
|
class UpdateTemporaryTargetTransaction(private val temporaryTarget: TemporaryTarget) : Transaction<Unit>() {
|
||||||
|
|
||||||
|
override fun run() {
|
||||||
|
database.temporaryTargetDao.updateExistingEntry(temporaryTarget)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
package info.nightscout.androidaps.database.transactions
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.database.entities.VersionChange
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class VersionChangeTransaction(
|
||||||
|
private val versionName: String,
|
||||||
|
private val versionCode: Int,
|
||||||
|
private val gitRemote: String?,
|
||||||
|
private val commitHash: String?) : Transaction<Unit>() {
|
||||||
|
|
||||||
|
override fun run() {
|
||||||
|
val current = database.versionChangeDao.getMostRecentVersionChange()
|
||||||
|
if (current == null
|
||||||
|
|| current.versionName != versionName
|
||||||
|
|| current.versionCode != versionCode
|
||||||
|
|| current.gitRemote != gitRemote
|
||||||
|
|| current.commitHash != commitHash) {
|
||||||
|
val currentTime = System.currentTimeMillis()
|
||||||
|
database.versionChangeDao.insert(VersionChange(
|
||||||
|
timestamp = System.currentTimeMillis(),
|
||||||
|
versionCode = versionCode,
|
||||||
|
versionName = versionName,
|
||||||
|
gitRemote = gitRemote,
|
||||||
|
commitHash = commitHash
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package info.nightscout.database
|
||||||
|
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
import org.junit.Assert.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Example local unit test, which will execute on the development machine (host).
|
||||||
|
*
|
||||||
|
* See [testing documentation](http://d.android.com/tools/testing).
|
||||||
|
*/
|
||||||
|
class ExampleUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun addition_isCorrect() {
|
||||||
|
assertEquals(4, 2 + 2)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,2 +1,3 @@
|
||||||
|
include ':database'
|
||||||
include ':app', ':wear', ':core', ':dana', ':danar', ':danars', ':rileylink', ':medtronic', ':omnipod'
|
include ':app', ':wear', ':core', ':dana', ':danar', ':danars', ':rileylink', ':medtronic', ':omnipod'
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue