Optimize NSClient sync

This commit is contained in:
Milos Kozak 2021-10-12 23:54:04 +02:00
parent 252cc685a4
commit d5892a81f9
18 changed files with 674 additions and 345 deletions

View file

@ -14,7 +14,9 @@ import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.sharedPreferences.SP
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class DataSyncSelectorImplementation @Inject constructor(
private val sp: SP,
private val aapsLogger: AAPSLogger,
@ -26,6 +28,42 @@ class DataSyncSelectorImplementation @Inject constructor(
private val localProfilePlugin: LocalProfilePlugin
) : DataSyncSelector {
class QueueCounter (
var bolusesRemaining: Long = 0L,
var carbsRemaining: Long = 0L,
var bcrRemaining: Long = 0L,
var ttsRemaining: Long = 0L,
var foodsRemaining: Long = 0L,
var gvsRemaining: Long = 0L,
var tesRemaining: Long = 0L,
var dssRemaining: Long = 0L,
var tbrsRemaining: Long = 0L,
var ebsRemaining: Long = 0L,
var pssRemaining: Long = 0L,
var epssRemaining: Long = 0L,
var oesRemaining: Long = 0L
) {
fun size(): Long =
bolusesRemaining +
carbsRemaining +
bcrRemaining +
ttsRemaining +
foodsRemaining +
gvsRemaining +
tesRemaining +
dssRemaining +
tbrsRemaining +
ebsRemaining +
pssRemaining +
epssRemaining +
oesRemaining
}
private val queueCounter = QueueCounter()
override fun queueSize(): Long = queueCounter.size()
override fun doUpload() {
if (sp.getBoolean(R.string.key_ns_upload, true)) {
processChangedBolusesCompat()
@ -80,8 +118,8 @@ class DataSyncSelectorImplementation @Inject constructor(
}
}
@Volatile private var lastBolusId = -1L
@Volatile private var lastBolusTime = -1L
//private var lastBolusId = -1L
//private var lastBolusTime = -1L
override fun processChangedBolusesCompat(): Boolean {
val lastDbIdWrapped = appRepository.getLastBolusIdWrapped().blockingGet()
val lastDbId = if (lastDbIdWrapped is ValueWrapper.Existing) lastDbIdWrapped.value else 0L
@ -90,18 +128,27 @@ class DataSyncSelectorImplementation @Inject constructor(
sp.putLong(R.string.key_ns_bolus_last_synced_id, 0)
startId = 0
}
if (startId == lastBolusId && dateUtil.now() - lastBolusTime < 5000) return false
lastBolusId = startId
lastBolusTime = dateUtil.now()
//if (startId == lastBolusId && dateUtil.now() - lastBolusTime < 5000) return false
//lastBolusId = startId
//lastBolusTime = dateUtil.now()
queueCounter.bolusesRemaining = lastDbId - startId
appRepository.getNextSyncElementBolus(startId).blockingGet()?.let { bolus ->
aapsLogger.info(LTag.DATABASE, "Loading Bolus data Start: $startId ID: ${bolus.first.id} HistoryID: ${bolus.second} ")
aapsLogger.info(LTag.DATABASE, "Loading Bolus data Start: $startId ID: ${bolus.first.id} HistoryID: ${bolus.second.id} ")
when {
// only NsId changed, no need to upload
bolus.first.onlyNsIdAdded(bolus.second) -> {
confirmLastBolusIdIfGreater(bolus.second.id)
//lastBolusId = -1
processChangedBolusesCompat()
aapsLogger.info(LTag.DATABASE, "Ignoring Bolus. Only NS id changed ID: ${bolus.first.id} HistoryID: ${bolus.second.id} ")
return false
}
// without nsId = create new
bolus.first.interfaceIDs.nightscoutId == null ->
nsClientPlugin.nsClientService?.dbAdd("treatments", bolus.first.toJson(true, dateUtil), DataSyncSelector.PairBolus(bolus.first, bolus.second), "$startId/$lastDbId")
nsClientPlugin.nsClientService?.dbAdd("treatments", bolus.first.toJson(true, dateUtil), DataSyncSelector.PairBolus(bolus.first, bolus.second.id), "$startId/$lastDbId")
// with nsId = update
bolus.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbUpdate("treatments", bolus.first.interfaceIDs.nightscoutId, bolus.first.toJson(false, dateUtil), DataSyncSelector.PairBolus(bolus.first, bolus.second), "$startId/$lastDbId")
nsClientPlugin.nsClientService?.dbUpdate("treatments", bolus.first.interfaceIDs.nightscoutId, bolus.first.toJson(false, dateUtil), DataSyncSelector.PairBolus(bolus.first, bolus.second.id), "$startId/$lastDbId")
}
return true
}
@ -123,8 +170,8 @@ class DataSyncSelectorImplementation @Inject constructor(
}
}
@Volatile private var lastCarbsId = -1L
@Volatile private var lastCarbsTime = -1L
//private var lastCarbsId = -1L
//private var lastCarbsTime = -1L
override fun processChangedCarbsCompat(): Boolean {
val lastDbIdWrapped = appRepository.getLastCarbsIdWrapped().blockingGet()
val lastDbId = if (lastDbIdWrapped is ValueWrapper.Existing) lastDbIdWrapped.value else 0L
@ -133,18 +180,27 @@ class DataSyncSelectorImplementation @Inject constructor(
sp.putLong(R.string.key_ns_carbs_last_synced_id, 0)
startId = 0
}
if (startId == lastCarbsId && dateUtil.now() - lastCarbsTime < 5000) return false
lastCarbsId = startId
lastCarbsTime = dateUtil.now()
//if (startId == lastCarbsId && dateUtil.now() - lastCarbsTime < 5000) return false
//lastCarbsId = startId
//lastCarbsTime = dateUtil.now()
queueCounter.carbsRemaining = lastDbId - startId
appRepository.getNextSyncElementCarbs(startId).blockingGet()?.let { carb ->
aapsLogger.info(LTag.DATABASE, "Loading Carbs data Start: $startId ID: ${carb.first.id} HistoryID: ${carb.second} ")
aapsLogger.info(LTag.DATABASE, "Loading Carbs data Start: $startId ID: ${carb.first.id} HistoryID: ${carb.second.id} ")
when {
// only NsId changed, no need to upload
carb.first.onlyNsIdAdded(carb.second) -> {
confirmLastCarbsIdIfGreater(carb.second.id)
//lastCarbsId = -1
processChangedCarbsCompat()
aapsLogger.info(LTag.DATABASE, "Ignoring Carbs. Only NS id changed ID: ${carb.first.id} HistoryID: ${carb.second.id} ")
return false
}
// without nsId = create new
carb.first.interfaceIDs.nightscoutId == null ->
nsClientPlugin.nsClientService?.dbAdd("treatments", carb.first.toJson(true, dateUtil), DataSyncSelector.PairCarbs(carb.first, carb.second), "$startId/$lastDbId")
nsClientPlugin.nsClientService?.dbAdd("treatments", carb.first.toJson(true, dateUtil), DataSyncSelector.PairCarbs(carb.first, carb.second.id), "$startId/$lastDbId")
// with nsId = update
carb.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbUpdate("treatments", carb.first.interfaceIDs.nightscoutId, carb.first.toJson(false, dateUtil), DataSyncSelector.PairCarbs(carb.first, carb.second), "$startId/$lastDbId")
nsClientPlugin.nsClientService?.dbUpdate("treatments", carb.first.interfaceIDs.nightscoutId, carb.first.toJson(false, dateUtil), DataSyncSelector.PairCarbs(carb.first, carb.second.id), "$startId/$lastDbId")
}
return true
}
@ -166,8 +222,8 @@ class DataSyncSelectorImplementation @Inject constructor(
}
}
@Volatile private var lastBcrId = -1L
@Volatile private var lastBcrTime = -1L
//private var lastBcrId = -1L
//private var lastBcrTime = -1L
override fun processChangedBolusCalculatorResultsCompat(): Boolean {
val lastDbIdWrapped = appRepository.getLastBolusCalculatorResultIdWrapped().blockingGet()
val lastDbId = if (lastDbIdWrapped is ValueWrapper.Existing) lastDbIdWrapped.value else 0L
@ -176,18 +232,28 @@ class DataSyncSelectorImplementation @Inject constructor(
sp.putLong(R.string.key_ns_bolus_calculator_result_last_synced_id, 0)
startId = 0
}
if (startId == lastBcrId && dateUtil.now() - lastBcrTime < 5000) return false
lastBcrId = startId
lastBcrTime = dateUtil.now()
//if (startId == lastBcrId && dateUtil.now() - lastBcrTime < 5000) return false
//lastBcrId = startId
//lastBcrTime = dateUtil.now()
queueCounter.bcrRemaining = lastDbId - startId
appRepository.getNextSyncElementBolusCalculatorResult(startId).blockingGet()?.let { bolusCalculatorResult ->
aapsLogger.info(LTag.DATABASE, "Loading BolusCalculatorResult data Start: $startId ID: ${bolusCalculatorResult.first.id} HistoryID: ${bolusCalculatorResult.second} ")
aapsLogger.info(LTag.DATABASE, "Loading BolusCalculatorResult data Start: $startId ID: ${bolusCalculatorResult.first.id} HistoryID: ${bolusCalculatorResult.second.id} ")
when {
// only NsId changed, no need to upload
bolusCalculatorResult.first.onlyNsIdAdded(bolusCalculatorResult.second) -> {
confirmLastBolusCalculatorResultsIdIfGreater(bolusCalculatorResult.second.id)
//lastBcrId = -1
processChangedBolusCalculatorResultsCompat()
aapsLogger.info(LTag.DATABASE, "Ignoring BolusCalculatorResult. Only NS id changed ID: ${bolusCalculatorResult.first.id} HistoryID: ${bolusCalculatorResult.second.id} ")
return false
}
// without nsId = create new
bolusCalculatorResult.first.interfaceIDs.nightscoutId == null ->
nsClientPlugin.nsClientService?.dbAdd("treatments", bolusCalculatorResult.first.toJson(true, dateUtil), DataSyncSelector.PairBolusCalculatorResult(bolusCalculatorResult.first, bolusCalculatorResult.second), "$startId/$lastDbId")
nsClientPlugin.nsClientService?.dbAdd("treatments", bolusCalculatorResult.first.toJson(true, dateUtil), DataSyncSelector.PairBolusCalculatorResult(bolusCalculatorResult.first, bolusCalculatorResult.second.id), "$startId/$lastDbId")
// with nsId = update
bolusCalculatorResult.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbUpdate("treatments", bolusCalculatorResult.first.interfaceIDs.nightscoutId, bolusCalculatorResult.first.toJson(false, dateUtil), DataSyncSelector.PairBolusCalculatorResult(bolusCalculatorResult.first, bolusCalculatorResult.second), "$startId/$lastDbId")
nsClientPlugin.nsClientService?.dbUpdate("treatments", bolusCalculatorResult.first.interfaceIDs.nightscoutId, bolusCalculatorResult.first.toJson(false, dateUtil),
DataSyncSelector.PairBolusCalculatorResult(bolusCalculatorResult.first, bolusCalculatorResult.second.id), "$startId/$lastDbId")
}
return true
}
@ -209,8 +275,8 @@ class DataSyncSelectorImplementation @Inject constructor(
}
}
@Volatile private var lastTtId = -1L
@Volatile private var lastTtTime = -1L
//private var lastTtId = -1L
//private var lastTtTime = -1L
override fun processChangedTempTargetsCompat(): Boolean {
val lastDbIdWrapped = appRepository.getLastTempTargetIdWrapped().blockingGet()
val lastDbId = if (lastDbIdWrapped is ValueWrapper.Existing) lastDbIdWrapped.value else 0L
@ -219,18 +285,27 @@ class DataSyncSelectorImplementation @Inject constructor(
sp.putLong(R.string.key_ns_temporary_target_last_synced_id, 0)
startId = 0
}
if (startId == lastTtId && dateUtil.now() - lastTtTime < 5000) return false
lastTtId = startId
lastTtTime = dateUtil.now()
//if (startId == lastTtId && dateUtil.now() - lastTtTime < 5000) return false
//lastTtId = startId
//lastTtTime = dateUtil.now()
queueCounter.ttsRemaining = lastDbId - startId
appRepository.getNextSyncElementTemporaryTarget(startId).blockingGet()?.let { tt ->
aapsLogger.info(LTag.DATABASE, "Loading TemporaryTarget data Start: $startId ID: ${tt.first.id} HistoryID: ${tt.second} ")
aapsLogger.info(LTag.DATABASE, "Loading TemporaryTarget data Start: $startId ID: ${tt.first.id} HistoryID: ${tt.second.id} ")
when {
// only NsId changed, no need to upload
tt.first.onlyNsIdAdded(tt.second) -> {
confirmLastTempTargetsIdIfGreater(tt.second.id)
//lastTtId = -1
processChangedTempTargetsCompat()
aapsLogger.info(LTag.DATABASE, "Ignoring TemporaryTarget. Only NS id changed ID: ${tt.first.id} HistoryID: ${tt.second.id} ")
return false
}
// without nsId = create new
tt.first.interfaceIDs.nightscoutId == null ->
nsClientPlugin.nsClientService?.dbAdd("treatments", tt.first.toJson(true, profileFunction.getUnits(), dateUtil), DataSyncSelector.PairTemporaryTarget(tt.first, tt.second), "$startId/$lastDbId")
nsClientPlugin.nsClientService?.dbAdd("treatments", tt.first.toJson(true, profileFunction.getUnits(), dateUtil), DataSyncSelector.PairTemporaryTarget(tt.first, tt.second.id), "$startId/$lastDbId")
// existing with nsId = update
tt.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbUpdate("treatments", tt.first.interfaceIDs.nightscoutId, tt.first.toJson(false, profileFunction.getUnits(), dateUtil), DataSyncSelector.PairTemporaryTarget(tt.first, tt.second), "$startId/$lastDbId")
nsClientPlugin.nsClientService?.dbUpdate("treatments", tt.first.interfaceIDs.nightscoutId, tt.first.toJson(false, profileFunction.getUnits(), dateUtil), DataSyncSelector.PairTemporaryTarget(tt.first, tt.second.id), "$startId/$lastDbId")
}
return true
}
@ -252,8 +327,8 @@ class DataSyncSelectorImplementation @Inject constructor(
}
}
@Volatile private var lastFoodId = -1L
@Volatile private var lastFoodTime = -1L
//private var lastFoodId = -1L
//private var lastFoodTime = -1L
override fun processChangedFoodsCompat(): Boolean {
val lastDbIdWrapped = appRepository.getLastFoodIdWrapped().blockingGet()
val lastDbId = if (lastDbIdWrapped is ValueWrapper.Existing) lastDbIdWrapped.value else 0L
@ -262,18 +337,27 @@ class DataSyncSelectorImplementation @Inject constructor(
sp.putLong(R.string.key_ns_food_last_synced_id, 0)
startId = 0
}
if (startId == lastFoodId && dateUtil.now() - lastFoodTime < 5000) return false
lastFoodId = startId
lastFoodTime = dateUtil.now()
//if (startId == lastFoodId && dateUtil.now() - lastFoodTime < 5000) return false
//lastFoodId = startId
//lastFoodTime = dateUtil.now()
queueCounter.foodsRemaining = lastDbId - startId
appRepository.getNextSyncElementFood(startId).blockingGet()?.let { food ->
aapsLogger.info(LTag.DATABASE, "Loading Food data Start: $startId ID: ${food.first.id} HistoryID: ${food.second} ")
when {
// only NsId changed, no need to upload
food.first.onlyNsIdAdded(food.second) -> {
confirmLastFoodIdIfGreater(food.second.id)
//lastFoodId = -1
processChangedFoodsCompat()
aapsLogger.info(LTag.DATABASE, "Ignoring Food. Only NS id changed ID: ${food.first.id} HistoryID: ${food.second.id} ")
return false
}
// without nsId = create new
food.first.interfaceIDs.nightscoutId == null ->
nsClientPlugin.nsClientService?.dbAdd("food", food.first.toJson(true), DataSyncSelector.PairFood(food.first, food.second), "$startId/$lastDbId")
nsClientPlugin.nsClientService?.dbAdd("food", food.first.toJson(true), DataSyncSelector.PairFood(food.first, food.second.id), "$startId/$lastDbId")
// with nsId = update
food.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbUpdate("food", food.first.interfaceIDs.nightscoutId, food.first.toJson(false), DataSyncSelector.PairFood(food.first, food.second), "$startId/$lastDbId")
nsClientPlugin.nsClientService?.dbUpdate("food", food.first.interfaceIDs.nightscoutId, food.first.toJson(false), DataSyncSelector.PairFood(food.first, food.second.id), "$startId/$lastDbId")
}
return true
}
@ -295,8 +379,8 @@ class DataSyncSelectorImplementation @Inject constructor(
}
}
@Volatile private var lastGvId = -1L
@Volatile private var lastGvTime = -1L
//private var lastGvId = -1L
//private var lastGvTime = -1L
override fun processChangedGlucoseValuesCompat(): Boolean {
val lastDbIdWrapped = appRepository.getLastGlucoseValueIdWrapped().blockingGet()
val lastDbId = if (lastDbIdWrapped is ValueWrapper.Existing) lastDbIdWrapped.value else 0L
@ -305,24 +389,33 @@ class DataSyncSelectorImplementation @Inject constructor(
sp.putLong(R.string.key_ns_glucose_value_last_synced_id, 0)
startId = 0
}
if (startId == lastGvId && dateUtil.now() - lastGvTime < 5000) return false
lastGvId = startId
lastGvTime = dateUtil.now()
//if (startId == lastGvId && dateUtil.now() - lastGvTime < 5000) return false
//lastGvId = startId
//lastGvTime = dateUtil.now()
queueCounter.gvsRemaining = lastDbId - startId
appRepository.getNextSyncElementGlucoseValue(startId).blockingGet()?.let { gv ->
aapsLogger.info(LTag.DATABASE, "Loading GlucoseValue data Start: $startId ID: ${gv.first.id} HistoryID: ${gv.second} ")
aapsLogger.info(LTag.DATABASE, "Loading GlucoseValue data ID: ${gv.first.id} HistoryID: ${gv.second.id} ")
if (activePlugin.activeBgSource.shouldUploadToNs(gv.first)) {
when {
// only NsId changed, no need to upload
gv.first.onlyNsIdAdded(gv.second) -> {
confirmLastGlucoseValueIdIfGreater(gv.second.id)
//lastGvId = -1
processChangedGlucoseValuesCompat()
aapsLogger.info(LTag.DATABASE, "Ignoring GlucoseValue. Only NS id changed ID: ${gv.first.id} HistoryID: ${gv.second.id} ")
return false
}
// without nsId = create new
gv.first.interfaceIDs.nightscoutId == null ->
nsClientPlugin.nsClientService?.dbAdd("entries", gv.first.toJson(true, dateUtil), DataSyncSelector.PairGlucoseValue(gv.first, gv.second), "$startId/$lastDbId")
nsClientPlugin.nsClientService?.dbAdd("entries", gv.first.toJson(true, dateUtil), DataSyncSelector.PairGlucoseValue(gv.first, gv.second.id), "$startId/$lastDbId")
// with nsId = update
gv.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbUpdate("entries", gv.first.interfaceIDs.nightscoutId, gv.first.toJson(false, dateUtil), DataSyncSelector.PairGlucoseValue(gv.first, gv.second), "$startId/$lastDbId")
nsClientPlugin.nsClientService?.dbUpdate("entries", gv.first.interfaceIDs.nightscoutId, gv.first.toJson(false, dateUtil), DataSyncSelector.PairGlucoseValue(gv.first, gv.second.id), "$startId/$lastDbId")
}
return true
} else {
confirmLastGlucoseValueIdIfGreater(gv.second)
lastGvId = -1
confirmLastGlucoseValueIdIfGreater(gv.second.id)
//lastGvId = -1
processChangedGlucoseValuesCompat()
}
}
@ -344,8 +437,8 @@ class DataSyncSelectorImplementation @Inject constructor(
}
}
@Volatile private var lastTeId = -1L
@Volatile private var lastTeTime = -1L
//private var lastTeId = -1L
//private var lastTeTime = -1L
override fun processChangedTherapyEventsCompat(): Boolean {
val lastDbIdWrapped = appRepository.getLastTherapyEventIdWrapped().blockingGet()
val lastDbId = if (lastDbIdWrapped is ValueWrapper.Existing) lastDbIdWrapped.value else 0L
@ -354,18 +447,27 @@ class DataSyncSelectorImplementation @Inject constructor(
sp.putLong(R.string.key_ns_therapy_event_last_synced_id, 0)
startId = 0
}
if (startId == lastTeId && dateUtil.now() - lastTeTime < 5000) return false
lastTeId = startId
lastTeTime = dateUtil.now()
//if (startId == lastTeId && dateUtil.now() - lastTeTime < 5000) return false
//lastTeId = startId
//lastTeTime = dateUtil.now()
queueCounter.tesRemaining = lastDbId - startId
appRepository.getNextSyncElementTherapyEvent(startId).blockingGet()?.let { te ->
aapsLogger.info(LTag.DATABASE, "Loading TherapyEvents data Start: $startId ID: ${te.first.id} HistoryID: ${te.second} ")
when {
// only NsId changed, no need to upload
te.first.onlyNsIdAdded(te.second) -> {
confirmLastTherapyEventIdIfGreater(te.second.id)
//lastTeId = -1
processChangedTherapyEventsCompat()
aapsLogger.info(LTag.DATABASE, "Ignoring TherapyEvents. Only NS id changed ID: ${te.first.id} HistoryID: ${te.second.id} ")
return false
}
// without nsId = create new
te.first.interfaceIDs.nightscoutId == null ->
nsClientPlugin.nsClientService?.dbAdd("treatments", te.first.toJson(true, dateUtil), DataSyncSelector.PairTherapyEvent(te.first, te.second), "$startId/$lastDbId")
nsClientPlugin.nsClientService?.dbAdd("treatments", te.first.toJson(true, dateUtil), DataSyncSelector.PairTherapyEvent(te.first, te.second.id), "$startId/$lastDbId")
// nsId = update
te.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbUpdate("treatments", te.first.interfaceIDs.nightscoutId, te.first.toJson(false, dateUtil), DataSyncSelector.PairTherapyEvent(te.first, te.second), "$startId/$lastDbId")
nsClientPlugin.nsClientService?.dbUpdate("treatments", te.first.interfaceIDs.nightscoutId, te.first.toJson(false, dateUtil), DataSyncSelector.PairTherapyEvent(te.first, te.second.id), "$startId/$lastDbId")
}
return true
}
@ -386,8 +488,8 @@ class DataSyncSelectorImplementation @Inject constructor(
}
}
@Volatile private var lastDsId = -1L
@Volatile private var lastDsTime = -1L
//private var lastDsId = -1L
//private var lastDsTime = -1L
override fun processChangedDeviceStatusesCompat(): Boolean {
val lastDbIdWrapped = appRepository.getLastDeviceStatusIdWrapped().blockingGet()
val lastDbId = if (lastDbIdWrapped is ValueWrapper.Existing) lastDbIdWrapped.value else 0L
@ -396,9 +498,10 @@ class DataSyncSelectorImplementation @Inject constructor(
sp.putLong(R.string.key_ns_device_status_last_synced_id, 0)
startId = 0
}
if (startId == lastDsId && dateUtil.now() - lastDsTime < 5000) return false
lastDsId = startId
lastDsTime = dateUtil.now()
//if (startId == lastDsId && dateUtil.now() - lastDsTime < 5000) return false
//lastDsId = startId
//lastDsTime = dateUtil.now()
queueCounter.dssRemaining = lastDbId - startId
appRepository.getNextSyncElementDeviceStatus(startId).blockingGet()?.let { deviceStatus ->
aapsLogger.info(LTag.DATABASE, "Loading DeviceStatus data Start: $startId ID: ${deviceStatus.id}")
when {
@ -428,8 +531,8 @@ class DataSyncSelectorImplementation @Inject constructor(
}
}
@Volatile private var lastTbrId = -1L
@Volatile private var lastTbrTime = -1L
//private var lastTbrId = -1L
//private var lastTbrTime = -1L
override fun processChangedTemporaryBasalsCompat(): Boolean {
val useAbsolute = sp.getBoolean(R.string.key_ns_sync_use_absolute, false)
val lastDbIdWrapped = appRepository.getLastTemporaryBasalIdWrapped().blockingGet()
@ -439,25 +542,34 @@ class DataSyncSelectorImplementation @Inject constructor(
sp.putLong(R.string.key_ns_temporary_basal_last_synced_id, 0)
startId = 0
}
if (startId == lastTbrId && dateUtil.now() - lastTbrTime < 5000) return false
lastTbrId = startId
lastTbrTime = dateUtil.now()
//if (startId == lastTbrId && dateUtil.now() - lastTbrTime < 5000) return false
//lastTbrId = startId
//lastTbrTime = dateUtil.now()
queueCounter.tbrsRemaining = lastDbId - startId
appRepository.getNextSyncElementTemporaryBasal(startId).blockingGet()?.let { tb ->
aapsLogger.info(LTag.DATABASE, "Loading TemporaryBasal data Start: $startId ID: ${tb.first.id} HistoryID: ${tb.second} ")
val profile = profileFunction.getProfile(tb.first.timestamp)
if (profile != null) {
when {
// only NsId changed, no need to upload
tb.first.onlyNsIdAdded(tb.second) -> {
confirmLastTemporaryBasalIdIfGreater(tb.second.id)
//lastTbrId = -1
processChangedTemporaryBasalsCompat()
aapsLogger.info(LTag.DATABASE, "Ignoring TemporaryBasal. Only NS id changed ID: ${tb.first.id} HistoryID: ${tb.second.id} ")
return false
}
// without nsId = create new
tb.first.interfaceIDs.nightscoutId == null ->
nsClientPlugin.nsClientService?.dbAdd("treatments", tb.first.toJson(true, profile, dateUtil, useAbsolute), DataSyncSelector.PairTemporaryBasal(tb.first, tb.second), "$startId/$lastDbId")
nsClientPlugin.nsClientService?.dbAdd("treatments", tb.first.toJson(true, profile, dateUtil, useAbsolute), DataSyncSelector.PairTemporaryBasal(tb.first, tb.second.id), "$startId/$lastDbId")
// with nsId = update
tb.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbUpdate("treatments", tb.first.interfaceIDs.nightscoutId, tb.first.toJson(false, profile, dateUtil, useAbsolute), DataSyncSelector.PairTemporaryBasal(tb.first, tb.second), "$startId/$lastDbId")
nsClientPlugin.nsClientService?.dbUpdate("treatments", tb.first.interfaceIDs.nightscoutId, tb.first.toJson(false, profile, dateUtil, useAbsolute), DataSyncSelector.PairTemporaryBasal(tb.first, tb.second.id), "$startId/$lastDbId")
}
return true
} else {
confirmLastTemporaryBasalIdIfGreater(tb.second)
lastTbrId = -1
confirmLastTemporaryBasalIdIfGreater(tb.second.id)
//lastTbrId = -1
processChangedTemporaryBasalsCompat()
}
}
@ -479,8 +591,8 @@ class DataSyncSelectorImplementation @Inject constructor(
}
}
@Volatile private var lastEbId = -1L
@Volatile private var lastEbTime = -1L
//private var lastEbId = -1L
//private var lastEbTime = -1L
override fun processChangedExtendedBolusesCompat(): Boolean {
val useAbsolute = sp.getBoolean(R.string.key_ns_sync_use_absolute, false)
val lastDbIdWrapped = appRepository.getLastExtendedBolusIdWrapped().blockingGet()
@ -490,25 +602,34 @@ class DataSyncSelectorImplementation @Inject constructor(
sp.putLong(R.string.key_ns_extended_bolus_last_synced_id, 0)
startId = 0
}
if (startId == lastEbId && dateUtil.now() - lastEbTime < 5000) return false
lastEbId = startId
lastEbTime = dateUtil.now()
//if (startId == lastEbId && dateUtil.now() - lastEbTime < 5000) return false
//lastEbId = startId
//lastEbTime = dateUtil.now()
queueCounter.ebsRemaining = lastDbId - startId
appRepository.getNextSyncElementExtendedBolus(startId).blockingGet()?.let { eb ->
aapsLogger.info(LTag.DATABASE, "Loading ExtendedBolus data Start: $startId ID: ${eb.first.id} HistoryID: ${eb.second} ")
val profile = profileFunction.getProfile(eb.first.timestamp)
if (profile != null) {
when {
// only NsId changed, no need to upload
eb.first.onlyNsIdAdded(eb.second) -> {
confirmLastExtendedBolusIdIfGreater(eb.second.id)
//lastEbId = -1
processChangedExtendedBolusesCompat()
aapsLogger.info(LTag.DATABASE, "Ignoring ExtendedBolus. Only NS id changed ID: ${eb.first.id} HistoryID: ${eb.second.id} ")
return false
}
// without nsId = create new
eb.first.interfaceIDs.nightscoutId == null ->
nsClientPlugin.nsClientService?.dbAdd("treatments", eb.first.toJson(true, profile, dateUtil, useAbsolute), DataSyncSelector.PairExtendedBolus(eb.first, eb.second), "$startId/$lastDbId")
nsClientPlugin.nsClientService?.dbAdd("treatments", eb.first.toJson(true, profile, dateUtil, useAbsolute), DataSyncSelector.PairExtendedBolus(eb.first, eb.second.id), "$startId/$lastDbId")
// with nsId = update
eb.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbUpdate("treatments", eb.first.interfaceIDs.nightscoutId, eb.first.toJson(false, profile, dateUtil, useAbsolute), DataSyncSelector.PairExtendedBolus(eb.first, eb.second), "$startId/$lastDbId")
nsClientPlugin.nsClientService?.dbUpdate("treatments", eb.first.interfaceIDs.nightscoutId, eb.first.toJson(false, profile, dateUtil, useAbsolute), DataSyncSelector.PairExtendedBolus(eb.first, eb.second.id), "$startId/$lastDbId")
}
return true
} else {
confirmLastExtendedBolusIdIfGreater(eb.second)
lastEbId = -1
confirmLastExtendedBolusIdIfGreater(eb.second.id)
//lastEbId = -1
processChangedExtendedBolusesCompat()
}
}
@ -529,8 +650,8 @@ class DataSyncSelectorImplementation @Inject constructor(
}
}
@Volatile private var lastPsId = -1L
@Volatile private var lastPsTime = -1L
//private var lastPsId = -1L
//private var lastPsTime = -1L
override fun processChangedProfileSwitchesCompat(): Boolean {
val lastDbIdWrapped = appRepository.getLastProfileSwitchIdWrapped().blockingGet()
val lastDbId = if (lastDbIdWrapped is ValueWrapper.Existing) lastDbIdWrapped.value else 0L
@ -539,18 +660,27 @@ class DataSyncSelectorImplementation @Inject constructor(
sp.putLong(R.string.key_ns_profile_switch_last_synced_id, 0)
startId = 0
}
if (startId == lastPsId && dateUtil.now() - lastPsTime < 5000) return false
lastPsId = startId
lastPsTime = dateUtil.now()
//if (startId == lastPsId && dateUtil.now() - lastPsTime < 5000) return false
//lastPsId = startId
//lastPsTime = dateUtil.now()
queueCounter.pssRemaining = lastDbId - startId
appRepository.getNextSyncElementProfileSwitch(startId).blockingGet()?.let { ps ->
aapsLogger.info(LTag.DATABASE, "Loading ProfileSwitch data Start: $startId ID: ${ps.first.id} HistoryID: ${ps.second} ")
when {
// only NsId changed, no need to upload
ps.first.onlyNsIdAdded(ps.second) -> {
confirmLastProfileSwitchIdIfGreater(ps.second.id)
//lastPsId = -1
processChangedProfileSwitchesCompat()
aapsLogger.info(LTag.DATABASE, "Ignoring ProfileSwitch. Only NS id changed ID: ${ps.first.id} HistoryID: ${ps.second.id} ")
return false
}
// without nsId = create new
ps.first.interfaceIDs.nightscoutId == null ->
nsClientPlugin.nsClientService?.dbAdd("treatments", ps.first.toJson(true, dateUtil), DataSyncSelector.PairProfileSwitch(ps.first, ps.second), "$startId/$lastDbId")
nsClientPlugin.nsClientService?.dbAdd("treatments", ps.first.toJson(true, dateUtil), DataSyncSelector.PairProfileSwitch(ps.first, ps.second.id), "$startId/$lastDbId")
// with nsId = update
ps.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbUpdate("treatments", ps.first.interfaceIDs.nightscoutId, ps.first.toJson(false, dateUtil), DataSyncSelector.PairProfileSwitch(ps.first, ps.second), "$startId/$lastDbId")
nsClientPlugin.nsClientService?.dbUpdate("treatments", ps.first.interfaceIDs.nightscoutId, ps.first.toJson(false, dateUtil), DataSyncSelector.PairProfileSwitch(ps.first, ps.second.id), "$startId/$lastDbId")
}
return true
}
@ -571,8 +701,8 @@ class DataSyncSelectorImplementation @Inject constructor(
}
}
@Volatile private var lastEpsId = -1L
@Volatile private var lastEpsTime = -1L
//private var lastEpsId = -1L
//private var lastEpsTime = -1L
override fun processChangedEffectiveProfileSwitchesCompat(): Boolean {
val lastDbIdWrapped = appRepository.getLastEffectiveProfileSwitchIdWrapped().blockingGet()
val lastDbId = if (lastDbIdWrapped is ValueWrapper.Existing) lastDbIdWrapped.value else 0L
@ -581,18 +711,27 @@ class DataSyncSelectorImplementation @Inject constructor(
sp.putLong(R.string.key_ns_effective_profile_switch_last_synced_id, 0)
startId = 0
}
if (startId == lastEpsId && dateUtil.now() - lastEpsTime < 5000) return false
lastEpsId = startId
lastEpsTime = dateUtil.now()
//if (startId == lastEpsId && dateUtil.now() - lastEpsTime < 5000) return false
//lastEpsId = startId
//lastEpsTime = dateUtil.now()
queueCounter.epssRemaining = lastDbId - startId
appRepository.getNextSyncElementEffectiveProfileSwitch(startId).blockingGet()?.let { ps ->
aapsLogger.info(LTag.DATABASE, "Loading EffectiveProfileSwitch data Start: $startId ID: ${ps.first.id} HistoryID: ${ps.second} ")
when {
// only NsId changed, no need to upload
ps.first.onlyNsIdAdded(ps.second) -> {
confirmLastEffectiveProfileSwitchIdIfGreater(ps.second.id)
//lastEpsId = -1
processChangedEffectiveProfileSwitchesCompat()
aapsLogger.info(LTag.DATABASE, "Ignoring EffectiveProfileSwitch. Only NS id changed ID: ${ps.first.id} HistoryID: ${ps.second.id} ")
return false
}
// without nsId = create new
ps.first.interfaceIDs.nightscoutId == null ->
nsClientPlugin.nsClientService?.dbAdd("treatments", ps.first.toJson(true, dateUtil), DataSyncSelector.PairEffectiveProfileSwitch(ps.first, ps.second), "$startId/$lastDbId")
nsClientPlugin.nsClientService?.dbAdd("treatments", ps.first.toJson(true, dateUtil), DataSyncSelector.PairEffectiveProfileSwitch(ps.first, ps.second.id), "$startId/$lastDbId")
// with nsId = update
ps.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbUpdate("treatments", ps.first.interfaceIDs.nightscoutId, ps.first.toJson(false, dateUtil), DataSyncSelector.PairEffectiveProfileSwitch(ps.first, ps.second), "$startId/$lastDbId")
nsClientPlugin.nsClientService?.dbUpdate("treatments", ps.first.interfaceIDs.nightscoutId, ps.first.toJson(false, dateUtil), DataSyncSelector.PairEffectiveProfileSwitch(ps.first, ps.second.id), "$startId/$lastDbId")
}
return true
}
@ -614,8 +753,8 @@ class DataSyncSelectorImplementation @Inject constructor(
}
}
@Volatile private var lastOeId = -1L
@Volatile private var lastOeTime = -1L
//private var lastOeId = -1L
//private var lastOeTime = -1L
override fun processChangedOfflineEventsCompat(): Boolean {
val lastDbIdWrapped = appRepository.getLastOfflineEventIdWrapped().blockingGet()
val lastDbId = if (lastDbIdWrapped is ValueWrapper.Existing) lastDbIdWrapped.value else 0L
@ -624,18 +763,27 @@ class DataSyncSelectorImplementation @Inject constructor(
sp.putLong(R.string.key_ns_offline_event_last_synced_id, 0)
startId = 0
}
if (startId == lastOeId && dateUtil.now() - lastOeTime < 5000) return false
lastOeId = startId
lastOeTime = dateUtil.now()
//if (startId == lastOeId && dateUtil.now() - lastOeTime < 5000) return false
//lastOeId = startId
//lastOeTime = dateUtil.now()
queueCounter.oesRemaining = lastDbId - startId
appRepository.getNextSyncElementOfflineEvent(startId).blockingGet()?.let { oe ->
aapsLogger.info(LTag.DATABASE, "Loading OfflineEvent data Start: $startId ID: ${oe.first.id} HistoryID: ${oe.second} ")
when {
// only NsId changed, no need to upload
oe.first.onlyNsIdAdded(oe.second) -> {
confirmLastOfflineEventIdIfGreater(oe.second.id)
//lastOeId = -1
processChangedOfflineEventsCompat()
aapsLogger.info(LTag.DATABASE, "Ignoring OfflineEvent. Only NS id changed ID: ${oe.first.id} HistoryID: ${oe.second.id} ")
return false
}
// without nsId = create new
oe.first.interfaceIDs.nightscoutId == null ->
nsClientPlugin.nsClientService?.dbAdd("treatments", oe.first.toJson(true, dateUtil), DataSyncSelector.PairOfflineEvent(oe.first, oe.second), "$startId/$lastDbId")
nsClientPlugin.nsClientService?.dbAdd("treatments", oe.first.toJson(true, dateUtil), DataSyncSelector.PairOfflineEvent(oe.first, oe.second.id), "$startId/$lastDbId")
// existing with nsId = update
oe.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbUpdate("treatments", oe.first.interfaceIDs.nightscoutId, oe.first.toJson(false, dateUtil), DataSyncSelector.PairOfflineEvent(oe.first, oe.second), "$startId/$lastDbId")
nsClientPlugin.nsClientService?.dbUpdate("treatments", oe.first.interfaceIDs.nightscoutId, oe.first.toJson(false, dateUtil), DataSyncSelector.PairOfflineEvent(oe.first, oe.second.id), "$startId/$lastDbId")
}
return true
}

View file

@ -101,5 +101,6 @@ class NSClientFragment : DaggerFragment() {
if (nsClientPlugin.autoscroll) binding.logScrollview.fullScroll(ScrollView.FOCUS_DOWN)
binding.url.text = nsClientPlugin.url()
binding.status.text = nsClientPlugin.status
binding.queue.text = dataSyncSelector.queueSize().toString()
}
}

View file

@ -5,141 +5,159 @@
android:orientation="vertical"
tools:context=".plugins.general.nsclient.NSClientFragment">
<LinearLayout
android:layout_width="match_parent"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:gravity="center_horizontal"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:orientation="horizontal"
android:gravity="center_horizontal">
android:text="@string/nsclientinternal_url" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/nsclientinternal_url" />
<TextView
android:id="@+id/url"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:autoLink="web"
tools:ignore="RtlHardcoded" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:orientation="horizontal"
android:gravity="center_horizontal">
<CheckBox
android:id="@+id/paused"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/paused" />
<CheckBox
android:id="@+id/autoscroll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="10dp"
android:text="@string/nsclientinternal_autoscroll"
tools:ignore="RtlHardcoded" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
<TextView
android:id="@+id/url"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:autoLink="web"
tools:ignore="RtlHardcoded" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:gravity="center_horizontal"
android:orientation="horizontal">
<CheckBox
android:id="@+id/paused"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/paused" />
<CheckBox
android:id="@+id/autoscroll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="10dp"
android:text="@string/nsclientinternal_autoscroll"
tools:ignore="RtlHardcoded" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dp"
android:orientation="horizontal">
android:text="@string/status"
tools:ignore="RtlHardcoded" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dp"
android:text="@string/status"
tools:ignore="RtlHardcoded" />
<TextView
android:id="@+id/status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="normal|bold" />
<TextView
android:id="@+id/status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="normal|bold" />
<TextView
android:id="@+id/textView3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/queue" />
<LinearLayout
android:layout_width="match_parent"
<TextView
android:id="@+id/queue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:orientation="horizontal"
android:layout_marginBottom="10dp"
android:layout_marginTop="10dp">
android:layout_marginRight="5dp" />
<TextView
android:id="@+id/clear_log"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/clearlog"
android:textAlignment="center"
android:textColor="@android:color/holo_orange_light"
android:textStyle="normal|bold" />
</LinearLayout>
<TextView
android:id="@+id/restart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/restart"
android:textAlignment="center"
android:textColor="@android:color/holo_orange_light"
android:textStyle="normal|bold" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginTop="10dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="10dp"
android:orientation="horizontal">
<TextView
android:id="@+id/deliver_now"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/deliver_now"
android:textAlignment="center"
android:textColor="@android:color/holo_orange_light"
android:textStyle="normal|bold" />
<TextView
android:id="@+id/clear_log"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/clearlog"
android:textAlignment="center"
android:textColor="@android:color/holo_orange_light"
android:textStyle="normal|bold" />
<TextView
android:id="@+id/full_sync"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/full_sync"
android:textAlignment="center"
android:textColor="@android:color/holo_orange_light"
android:textStyle="normal|bold" />
<TextView
android:id="@+id/restart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/restart"
android:textAlignment="center"
android:textColor="@android:color/holo_orange_light"
android:textStyle="normal|bold" />
</LinearLayout>
<TextView
android:id="@+id/deliver_now"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/deliver_now"
android:textAlignment="center"
android:textColor="@android:color/holo_orange_light"
android:textStyle="normal|bold" />
<ScrollView
android:id="@+id/log_scrollview"
<TextView
android:id="@+id/full_sync"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/full_sync"
android:textAlignment="center"
android:textColor="@android:color/holo_orange_light"
android:textStyle="normal|bold" />
</LinearLayout>
<ScrollView
android:id="@+id/log_scrollview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp">
<TextView
android:id="@+id/log"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp">
<TextView
android:id="@+id/log"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="" />
</ScrollView>
android:layout_height="wrap_content"
android:text="" />
</ScrollView>
</LinearLayout>

View file

@ -20,6 +20,8 @@ interface DataSyncSelector {
data class PairOfflineEvent(val value: OfflineEvent, val updateRecordId: Long)
data class PairProfileStore(val value: JSONObject, val timestampSync: Long)
fun queueSize(): Long
fun doUpload()
fun resetToNextFullSync()

View file

@ -95,15 +95,15 @@ import kotlin.math.roundToInt
*
* It is a Maybe as there might be no next element.
* */
fun getNextSyncElementGlucoseValue(id: Long): Maybe<Pair<GlucoseValue, Long>> =
fun getNextSyncElementGlucoseValue(id: Long): Maybe<Pair<GlucoseValue, GlucoseValue>> =
database.glucoseValueDao.getNextModifiedOrNewAfter(id)
.flatMap { nextIdElement ->
val nextIdElemReferenceId = nextIdElement.referenceId
if (nextIdElemReferenceId == null) {
Maybe.just(nextIdElement to nextIdElement.id)
Maybe.just(nextIdElement to nextIdElement)
} else {
database.glucoseValueDao.getCurrentFromHistoric(nextIdElemReferenceId)
.map { it to nextIdElement.id }
.map { it to nextIdElement }
}
}
@ -123,15 +123,15 @@ import kotlin.math.roundToInt
*
* It is a Maybe as there might be no next element.
* */
fun getNextSyncElementTemporaryTarget(id: Long): Maybe<Pair<TemporaryTarget, Long>> =
fun getNextSyncElementTemporaryTarget(id: Long): Maybe<Pair<TemporaryTarget, TemporaryTarget>> =
database.temporaryTargetDao.getNextModifiedOrNewAfter(id)
.flatMap { nextIdElement ->
val nextIdElemReferenceId = nextIdElement.referenceId
if (nextIdElemReferenceId == null) {
Maybe.just(nextIdElement to nextIdElement.id)
Maybe.just(nextIdElement to nextIdElement)
} else {
database.temporaryTargetDao.getCurrentFromHistoric(nextIdElemReferenceId)
.map { it to nextIdElement.id }
.map { it to nextIdElement }
}
}
@ -185,15 +185,15 @@ import kotlin.math.roundToInt
// PROFILE SWITCH
fun getNextSyncElementProfileSwitch(id: Long): Maybe<Pair<ProfileSwitch, Long>> =
fun getNextSyncElementProfileSwitch(id: Long): Maybe<Pair<ProfileSwitch, ProfileSwitch>> =
database.profileSwitchDao.getNextModifiedOrNewAfter(id)
.flatMap { nextIdElement ->
val nextIdElemReferenceId = nextIdElement.referenceId
if (nextIdElemReferenceId == null) {
Maybe.just(nextIdElement to nextIdElement.id)
Maybe.just(nextIdElement to nextIdElement)
} else {
database.profileSwitchDao.getCurrentFromHistoric(nextIdElemReferenceId)
.map { it to nextIdElement.id }
.map { it to nextIdElement }
}
}
@ -250,15 +250,15 @@ import kotlin.math.roundToInt
*
* It is a Maybe as there might be no next element.
* */
fun getNextSyncElementEffectiveProfileSwitch(id: Long): Maybe<Pair<EffectiveProfileSwitch, Long>> =
fun getNextSyncElementEffectiveProfileSwitch(id: Long): Maybe<Pair<EffectiveProfileSwitch, EffectiveProfileSwitch>> =
database.effectiveProfileSwitchDao.getNextModifiedOrNewAfter(id)
.flatMap { nextIdElement ->
val nextIdElemReferenceId = nextIdElement.referenceId
if (nextIdElemReferenceId == null) {
Maybe.just(nextIdElement to nextIdElement.id)
Maybe.just(nextIdElement to nextIdElement)
} else {
database.effectiveProfileSwitchDao.getCurrentFromHistoric(nextIdElemReferenceId)
.map { it to nextIdElement.id }
.map { it to nextIdElement }
}
}
@ -309,15 +309,15 @@ import kotlin.math.roundToInt
*
* It is a Maybe as there might be no next element.
* */
fun getNextSyncElementTherapyEvent(id: Long): Maybe<Pair<TherapyEvent, Long>> =
fun getNextSyncElementTherapyEvent(id: Long): Maybe<Pair<TherapyEvent, TherapyEvent>> =
database.therapyEventDao.getNextModifiedOrNewAfter(id)
.flatMap { nextIdElement ->
val nextIdElemReferenceId = nextIdElement.referenceId
if (nextIdElemReferenceId == null) {
Maybe.just(nextIdElement to nextIdElement.id)
Maybe.just(nextIdElement to nextIdElement)
} else {
database.therapyEventDao.getCurrentFromHistoric(nextIdElemReferenceId)
.map { it to nextIdElement.id }
.map { it to nextIdElement }
}
}
@ -376,15 +376,15 @@ import kotlin.math.roundToInt
*
* It is a Maybe as there might be no next element.
* */
fun getNextSyncElementFood(id: Long): Maybe<Pair<Food, Long>> =
fun getNextSyncElementFood(id: Long): Maybe<Pair<Food, Food>> =
database.foodDao.getNextModifiedOrNewAfter(id)
.flatMap { nextIdElement ->
val nextIdElemReferenceId = nextIdElement.referenceId
if (nextIdElemReferenceId == null) {
Maybe.just(nextIdElement to nextIdElement.id)
Maybe.just(nextIdElement to nextIdElement)
} else {
database.foodDao.getCurrentFromHistoric(nextIdElemReferenceId)
.map { it to nextIdElement.id }
.map { it to nextIdElement }
}
}
@ -412,15 +412,15 @@ import kotlin.math.roundToInt
*
* It is a Maybe as there might be no next element.
* */
fun getNextSyncElementBolus(id: Long): Maybe<Pair<Bolus, Long>> =
fun getNextSyncElementBolus(id: Long): Maybe<Pair<Bolus, Bolus>> =
database.bolusDao.getNextModifiedOrNewAfterExclude(id, Bolus.Type.PRIMING)
.flatMap { nextIdElement ->
val nextIdElemReferenceId = nextIdElement.referenceId
if (nextIdElemReferenceId == null) {
Maybe.just(nextIdElement to nextIdElement.id)
Maybe.just(nextIdElement to nextIdElement)
} else {
database.bolusDao.getCurrentFromHistoric(nextIdElemReferenceId)
.map { it to nextIdElement.id }
.map { it to nextIdElement }
}
}
@ -499,15 +499,15 @@ import kotlin.math.roundToInt
*
* It is a Maybe as there might be no next element.
* */
fun getNextSyncElementCarbs(id: Long): Maybe<Pair<Carbs, Long>> =
fun getNextSyncElementCarbs(id: Long): Maybe<Pair<Carbs, Carbs>> =
database.carbsDao.getNextModifiedOrNewAfter(id)
.flatMap { nextIdElement ->
val nextIdElemReferenceId = nextIdElement.referenceId
if (nextIdElemReferenceId == null) {
Maybe.just(nextIdElement to nextIdElement.id)
Maybe.just(nextIdElement to nextIdElement)
} else {
database.carbsDao.getCurrentFromHistoric(nextIdElemReferenceId)
.map { it to nextIdElement.id }
.map { it to nextIdElement }
}
}
@ -590,15 +590,15 @@ import kotlin.math.roundToInt
*
* It is a Maybe as there might be no next element.
* */
fun getNextSyncElementBolusCalculatorResult(id: Long): Maybe<Pair<BolusCalculatorResult, Long>> =
fun getNextSyncElementBolusCalculatorResult(id: Long): Maybe<Pair<BolusCalculatorResult, BolusCalculatorResult>> =
database.bolusCalculatorResultDao.getNextModifiedOrNewAfter(id)
.flatMap { nextIdElement ->
val nextIdElemReferenceId = nextIdElement.referenceId
if (nextIdElemReferenceId == null) {
Maybe.just(nextIdElement to nextIdElement.id)
Maybe.just(nextIdElement to nextIdElement)
} else {
database.bolusCalculatorResultDao.getCurrentFromHistoric(nextIdElemReferenceId)
.map { it to nextIdElement.id }
.map { it to nextIdElement }
}
}
@ -658,15 +658,15 @@ import kotlin.math.roundToInt
* It is a Maybe as there might be no next element.
* */
fun getNextSyncElementTemporaryBasal(id: Long): Maybe<Pair<TemporaryBasal, Long>> =
fun getNextSyncElementTemporaryBasal(id: Long): Maybe<Pair<TemporaryBasal, TemporaryBasal>> =
database.temporaryBasalDao.getNextModifiedOrNewAfter(id)
.flatMap { nextIdElement ->
val nextIdElemReferenceId = nextIdElement.referenceId
if (nextIdElemReferenceId == null) {
Maybe.just(nextIdElement to nextIdElement.id)
Maybe.just(nextIdElement to nextIdElement)
} else {
database.temporaryBasalDao.getCurrentFromHistoric(nextIdElemReferenceId)
.map { it to nextIdElement.id }
.map { it to nextIdElement }
}
}
@ -720,15 +720,15 @@ import kotlin.math.roundToInt
* It is a Maybe as there might be no next element.
* */
fun getNextSyncElementExtendedBolus(id: Long): Maybe<Pair<ExtendedBolus, Long>> =
fun getNextSyncElementExtendedBolus(id: Long): Maybe<Pair<ExtendedBolus, ExtendedBolus>> =
database.extendedBolusDao.getNextModifiedOrNewAfter(id)
.flatMap { nextIdElement ->
val nextIdElemReferenceId = nextIdElement.referenceId
if (nextIdElemReferenceId == null) {
Maybe.just(nextIdElement to nextIdElement.id)
Maybe.just(nextIdElement to nextIdElement)
} else {
database.extendedBolusDao.getCurrentFromHistoric(nextIdElemReferenceId)
.map { it to nextIdElement.id }
.map { it to nextIdElement }
}
}
@ -788,15 +788,15 @@ import kotlin.math.roundToInt
*
* It is a Maybe as there might be no next element.
* */
fun getNextSyncElementOfflineEvent(id: Long): Maybe<Pair<OfflineEvent, Long>> =
fun getNextSyncElementOfflineEvent(id: Long): Maybe<Pair<OfflineEvent, OfflineEvent>> =
database.offlineEventDao.getNextModifiedOrNewAfter(id)
.flatMap { nextIdElement ->
val nextIdElemReferenceId = nextIdElement.referenceId
if (nextIdElemReferenceId == null) {
Maybe.just(nextIdElement to nextIdElement.id)
Maybe.just(nextIdElement to nextIdElement)
} else {
database.offlineEventDao.getCurrentFromHistoric(nextIdElemReferenceId)
.map { it to nextIdElement.id }
.map { it to nextIdElement }
}
}

View file

@ -12,12 +12,14 @@ import info.nightscout.androidaps.database.interfaces.DBEntryWithTime
import info.nightscout.androidaps.database.interfaces.TraceableDBEntry
import java.util.*
@Entity(tableName = TABLE_BOLUSES,
@Entity(
tableName = TABLE_BOLUSES,
foreignKeys = [
ForeignKey(
entity = Bolus::class,
parentColumns = ["id"],
childColumns = ["referenceId"])],
childColumns = ["referenceId"]
)],
indices = [
Index("id"),
Index("isValid"),
@ -27,7 +29,8 @@ import java.util.*
Index("pumpType"),
Index("referenceId"),
Index("timestamp")
])
]
)
data class Bolus(
@PrimaryKey(autoGenerate = true)
override var id: Long = 0,
@ -46,6 +49,20 @@ data class Bolus(
var insulinConfiguration: InsulinConfiguration? = null
) : TraceableDBEntry, DBEntryWithTime {
private fun contentEqualsTo(other: Bolus): Boolean =
isValid == other.isValid &&
timestamp == other.timestamp &&
utcOffset == other.utcOffset &&
amount == other.amount &&
type == other.type &&
isBasalInsulin == other.isBasalInsulin
fun onlyNsIdAdded(previous: Bolus): Boolean =
previous.id != id &&
contentEqualsTo(previous) &&
previous.interfaceIDs.nightscoutId == null &&
interfaceIDs.nightscoutId != null
enum class Type {
NORMAL,
SMB,

View file

@ -1,23 +1,30 @@
package info.nightscout.androidaps.database.entities
import androidx.room.*
import androidx.room.Embedded
import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.Index
import androidx.room.PrimaryKey
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
import java.util.*
@Entity(tableName = TABLE_BOLUS_CALCULATOR_RESULTS,
@Entity(
tableName = TABLE_BOLUS_CALCULATOR_RESULTS,
foreignKeys = [ForeignKey(
entity = BolusCalculatorResult::class,
parentColumns = ["id"],
childColumns = ["referenceId"])],
childColumns = ["referenceId"]
)],
indices = [
Index("referenceId"),
Index("timestamp"),
Index("id"),
Index("isValid")
])
]
)
data class BolusCalculatorResult(
@PrimaryKey(autoGenerate = true)
override var id: Long = 0,
@ -58,4 +65,45 @@ data class BolusCalculatorResult(
var percentageCorrection: Int,
var profileName: String,
var note: String
) : TraceableDBEntry, DBEntryWithTime
) : TraceableDBEntry, DBEntryWithTime {
private fun contentEqualsTo(other: BolusCalculatorResult): Boolean =
isValid == other.isValid &&
timestamp == other.timestamp &&
utcOffset == other.utcOffset &&
targetBGLow == other.targetBGLow &&
targetBGHigh == other.targetBGHigh &&
isf == other.isf &&
ic == other.ic &&
bolusIOB == other.bolusIOB &&
wasBolusIOBUsed == other.wasBolusIOBUsed &&
basalIOB == other.basalIOB &&
wasBasalIOBUsed == other.wasBasalIOBUsed &&
glucoseValue == other.glucoseValue &&
wasGlucoseUsed == other.wasGlucoseUsed &&
glucoseDifference == other.glucoseDifference &&
glucoseInsulin == other.glucoseInsulin &&
glucoseTrend == other.glucoseTrend &&
wasTrendUsed == other.wasTrendUsed &&
trendInsulin == other.trendInsulin &&
cob == other.cob &&
wasCOBUsed == other.wasCOBUsed &&
cobInsulin == other.cobInsulin &&
carbs == other.carbs &&
wereCarbsUsed == other.wereCarbsUsed &&
carbsInsulin == other.carbsInsulin &&
otherCorrection == other.otherCorrection &&
wasSuperbolusUsed == other.wasSuperbolusUsed &&
superbolusInsulin == other.superbolusInsulin &&
wasTempTargetUsed == other.wasTempTargetUsed &&
totalInsulin == other.totalInsulin &&
percentageCorrection == other.percentageCorrection &&
profileName == other.profileName &&
note == other.note
fun onlyNsIdAdded(previous: BolusCalculatorResult): Boolean =
previous.id != id &&
contentEqualsTo(previous) &&
previous.interfaceIDs.nightscoutId == null &&
interfaceIDs.nightscoutId != null
}

View file

@ -36,4 +36,18 @@ data class Carbs(
override var utcOffset: Long = TimeZone.getDefault().getOffset(timestamp).toLong(),
override var duration: Long, // in milliseconds
var amount: Double
) : TraceableDBEntry, DBEntryWithTimeAndDuration
) : TraceableDBEntry, DBEntryWithTimeAndDuration {
private fun contentEqualsTo(other: Carbs): Boolean =
isValid == other.isValid &&
timestamp == other.timestamp &&
utcOffset == other.utcOffset &&
amount == other.amount &&
duration == other.duration
fun onlyNsIdAdded(previous: Carbs): Boolean =
previous.id != id &&
contentEqualsTo(previous) &&
previous.interfaceIDs.nightscoutId == null &&
interfaceIDs.nightscoutId != null
}

View file

@ -14,17 +14,20 @@ import info.nightscout.androidaps.database.interfaces.DBEntryWithTime
import info.nightscout.androidaps.database.interfaces.TraceableDBEntry
import java.util.*
@Entity(tableName = TABLE_EFFECTIVE_PROFILE_SWITCHES,
@Entity(
tableName = TABLE_EFFECTIVE_PROFILE_SWITCHES,
foreignKeys = [ForeignKey(
entity = EffectiveProfileSwitch::class,
parentColumns = ["id"],
childColumns = ["referenceId"])],
childColumns = ["referenceId"]
)],
indices = [
Index("id"),
Index("referenceId"),
Index("timestamp"),
Index("isValid")
])
]
)
data class EffectiveProfileSwitch(
@PrimaryKey(autoGenerate = true)
override var id: Long = 0,
@ -52,6 +55,28 @@ data class EffectiveProfileSwitch(
var insulinConfiguration: InsulinConfiguration
) : TraceableDBEntry, DBEntryWithTime {
private fun contentEqualsTo(other: EffectiveProfileSwitch): Boolean =
isValid == other.isValid &&
timestamp == other.timestamp &&
utcOffset == other.utcOffset &&
basalBlocks == other.basalBlocks &&
isfBlocks == other.isfBlocks &&
icBlocks == other.icBlocks &&
targetBlocks == other.targetBlocks &&
glucoseUnit == other.glucoseUnit &&
originalProfileName == other.originalProfileName &&
originalCustomizedName == other.originalCustomizedName &&
originalTimeshift == other.originalTimeshift &&
originalPercentage == other.originalPercentage &&
originalDuration == other.originalDuration &&
originalEnd == other.originalEnd
fun onlyNsIdAdded(previous: EffectiveProfileSwitch): Boolean =
previous.id != id &&
contentEqualsTo(previous) &&
previous.interfaceIDs.nightscoutId == null &&
interfaceIDs.nightscoutId != null
enum class GlucoseUnit {
MGDL,
MMOL;

View file

@ -11,11 +11,13 @@ import info.nightscout.androidaps.database.interfaces.DBEntryWithTimeAndDuration
import info.nightscout.androidaps.database.interfaces.TraceableDBEntry
import java.util.*
@Entity(tableName = TABLE_EXTENDED_BOLUSES,
@Entity(
tableName = TABLE_EXTENDED_BOLUSES,
foreignKeys = [ForeignKey(
entity = ExtendedBolus::class,
parentColumns = ["id"],
childColumns = ["referenceId"])],
childColumns = ["referenceId"]
)],
indices = [
Index("id"),
Index("isValid"),
@ -25,7 +27,8 @@ import java.util.*
Index("pumpType"),
Index("referenceId"),
Index("timestamp")
])
]
)
data class ExtendedBolus(
@PrimaryKey(autoGenerate = true)
override var id: Long = 0,
@ -46,6 +49,20 @@ data class ExtendedBolus(
require(duration > 0)
}
private fun contentEqualsTo(other: ExtendedBolus): Boolean =
isValid == other.isValid &&
timestamp == other.timestamp &&
utcOffset == other.utcOffset &&
isEmulatingTempBasal == other.isEmulatingTempBasal &&
duration == other.duration &&
rate == other.rate
fun onlyNsIdAdded(previous: ExtendedBolus): Boolean =
previous.id != id &&
contentEqualsTo(previous) &&
previous.interfaceIDs.nightscoutId == null &&
interfaceIDs.nightscoutId != null
val rate: Double // in U/h
get() = amount * (60 * 60 * 1000.0) / duration
}

View file

@ -9,17 +9,20 @@ import info.nightscout.androidaps.database.TABLE_FOODS
import info.nightscout.androidaps.database.embedments.InterfaceIDs
import info.nightscout.androidaps.database.interfaces.TraceableDBEntry
@Entity(tableName = TABLE_FOODS,
@Entity(
tableName = TABLE_FOODS,
foreignKeys = [ForeignKey(
entity = Food::class,
parentColumns = ["id"],
childColumns = ["referenceId"])],
childColumns = ["referenceId"]
)],
indices = [
Index("id"),
Index("nightscoutId"),
Index("referenceId"),
Index("isValid")
])
]
)
data class Food(
@PrimaryKey(autoGenerate = true)
override var id: Long = 0,
@ -46,7 +49,7 @@ data class Food(
) : TraceableDBEntry {
fun isEqual(other: Food): Boolean {
fun contentEqualsTo(other: Food): Boolean {
if (isValid != other.isValid) return false
if (portion != other.portion) return false
if (carbs != other.carbs) return false
@ -60,6 +63,12 @@ data class Food(
return unit == other.unit
}
fun onlyNsIdAdded(previous: Food): Boolean =
previous.id != id &&
contentEqualsTo(previous) &&
previous.interfaceIDs.nightscoutId == null &&
interfaceIDs.nightscoutId != null
fun copyFrom(other: Food) {
isValid = other.isValid
name = other.name

View file

@ -45,14 +45,20 @@ data class GlucoseValue(
) : TraceableDBEntry, DBEntryWithTime {
fun contentEqualsTo(other: GlucoseValue): Boolean =
timestamp == other.timestamp &&
isValid == other.isValid &&
timestamp == other.timestamp &&
utcOffset == other.utcOffset &&
raw == other.raw &&
value == other.value &&
trendArrow == other.trendArrow &&
noise == other.noise &&
sourceSensor == other.sourceSensor &&
isValid == other.isValid
sourceSensor == other.sourceSensor
fun onlyNsIdAdded(previous: GlucoseValue): Boolean =
previous.id != id &&
contentEqualsTo(previous) &&
previous.interfaceIDs.nightscoutId == null &&
interfaceIDs.nightscoutId != null
fun isRecordDeleted(other: GlucoseValue): Boolean =
isValid && !other.isValid

View file

@ -11,18 +11,21 @@ import info.nightscout.androidaps.database.interfaces.DBEntryWithTimeAndDuration
import info.nightscout.androidaps.database.interfaces.TraceableDBEntry
import java.util.*
@Entity(tableName = TABLE_OFFLINE_EVENTS,
@Entity(
tableName = TABLE_OFFLINE_EVENTS,
foreignKeys = [ForeignKey(
entity = OfflineEvent::class,
parentColumns = ["id"],
childColumns = ["referenceId"])],
childColumns = ["referenceId"]
)],
indices = [
Index("id"),
Index("isValid"),
Index("nightscoutId"),
Index("referenceId"),
Index("timestamp")
])
]
)
data class OfflineEvent(
@PrimaryKey(autoGenerate = true)
override var id: Long = 0,
@ -45,6 +48,12 @@ data class OfflineEvent(
duration == other.duration &&
isValid == other.isValid
fun onlyNsIdAdded(previous: OfflineEvent): Boolean =
previous.id != id &&
contentEqualsTo(previous) &&
previous.interfaceIDs.nightscoutId == null &&
interfaceIDs.nightscoutId != null
fun isRecordDeleted(other: OfflineEvent): Boolean =
isValid && !other.isValid

View file

@ -14,18 +14,21 @@ import info.nightscout.androidaps.database.interfaces.DBEntryWithTimeAndDuration
import info.nightscout.androidaps.database.interfaces.TraceableDBEntry
import java.util.*
@Entity(tableName = TABLE_PROFILE_SWITCHES,
@Entity(
tableName = TABLE_PROFILE_SWITCHES,
foreignKeys = [ForeignKey(
entity = ProfileSwitch::class,
parentColumns = ["id"],
childColumns = ["referenceId"])],
childColumns = ["referenceId"]
)],
indices = [
Index("referenceId"),
Index("timestamp"),
Index("isValid"),
Index("id"),
Index("nightscoutId")
])
]
)
data class ProfileSwitch(
@PrimaryKey(autoGenerate = true)
override var id: Long = 0,
@ -50,6 +53,26 @@ data class ProfileSwitch(
var insulinConfiguration: InsulinConfiguration
) : TraceableDBEntry, DBEntryWithTimeAndDuration {
private fun contentEqualsTo(other: ProfileSwitch): Boolean =
isValid == other.isValid &&
timestamp == other.timestamp &&
utcOffset == other.utcOffset &&
basalBlocks == other.basalBlocks &&
isfBlocks == other.isfBlocks &&
icBlocks == other.icBlocks &&
targetBlocks == other.targetBlocks &&
glucoseUnit == other.glucoseUnit &&
profileName == other.profileName &&
timeshift == other.timeshift &&
percentage == other.percentage &&
duration == other.duration
fun onlyNsIdAdded(previous: ProfileSwitch): Boolean =
previous.id != id &&
contentEqualsTo(previous) &&
previous.interfaceIDs.nightscoutId == null &&
interfaceIDs.nightscoutId != null
enum class GlucoseUnit {
MGDL,
MMOL;

View file

@ -48,6 +48,21 @@ data class TemporaryBasal(
require(duration > 0)
}
private fun contentEqualsTo(other: TemporaryBasal): Boolean =
isValid == other.isValid &&
timestamp == other.timestamp &&
utcOffset == other.utcOffset &&
isAbsolute == other.isAbsolute &&
type == other.type &&
duration == other.duration &&
rate == other.rate
fun onlyNsIdAdded(previous: TemporaryBasal): Boolean =
previous.id != id &&
contentEqualsTo(previous) &&
previous.interfaceIDs.nightscoutId == null &&
interfaceIDs.nightscoutId != null
enum class Type {
NORMAL,
EMULATED_PUMP_SUSPEND,

View file

@ -5,25 +5,27 @@ 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,
@Entity(
tableName = TABLE_TEMPORARY_TARGETS,
foreignKeys = [ForeignKey(
entity = TemporaryTarget::class,
parentColumns = ["id"],
childColumns = ["referenceId"])],
childColumns = ["referenceId"]
)],
indices = [
Index("id"),
Index("isValid"),
Index("nightscoutId"),
Index("referenceId"),
Index("timestamp")
])
]
)
data class TemporaryTarget(
@PrimaryKey(autoGenerate = true)
override var id: Long = 0,
@ -53,22 +55,23 @@ data class TemporaryTarget(
fun isRecordDeleted(other: TemporaryTarget): Boolean =
isValid && !other.isValid
fun onlyNsIdAdded(previous: TemporaryTarget): Boolean =
previous.id != id &&
contentEqualsTo(previous) &&
previous.interfaceIDs.nightscoutId == null &&
interfaceIDs.nightscoutId != null
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"),
@SerializedName("Wear")
WEAR("Wear")
;
companion object {
fun fromString(reason: String?) = values().firstOrNull { it.text == reason }
?: CUSTOM
}

View file

@ -5,18 +5,19 @@ 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_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.*
@Entity(tableName = TABLE_THERAPY_EVENTS,
@Entity(
tableName = TABLE_THERAPY_EVENTS,
foreignKeys = [ForeignKey(
entity = TherapyEvent::class,
parentColumns = ["id"],
childColumns = ["referenceId"])],
childColumns = ["referenceId"]
)],
indices = [
Index("id"),
Index("type"),
@ -24,7 +25,8 @@ import java.util.*
Index("isValid"),
Index("referenceId"),
Index("timestamp")
])
]
)
data class TherapyEvent(
@PrimaryKey(autoGenerate = true)
override var id: Long = 0,
@ -45,18 +47,34 @@ data class TherapyEvent(
var glucoseUnit: GlucoseUnit,
) : TraceableDBEntry, DBEntryWithTimeAndDuration {
private fun contentEqualsTo(other: TherapyEvent): Boolean =
isValid == other.isValid &&
timestamp == other.timestamp &&
utcOffset == other.utcOffset &&
duration == other.duration &&
type == other.type &&
note == other.note &&
enteredBy == other.enteredBy &&
glucose == other.glucose &&
glucoseType == other.glucoseType &&
glucoseUnit == other.glucoseUnit
fun onlyNsIdAdded(previous: TherapyEvent): Boolean =
previous.id != id &&
contentEqualsTo(previous) &&
previous.interfaceIDs.nightscoutId == null &&
interfaceIDs.nightscoutId != null
enum class GlucoseUnit {
MGDL,
MMOL;
companion object
}
enum class MeterType(val text: String) {
@SerializedName("Finger")
FINGER("Finger"),
@SerializedName("Sensor")
SENSOR("Sensor"),
@SerializedName("Manual")
MANUAL("Manual")
;
@ -69,99 +87,55 @@ data class TherapyEvent(
@Suppress("unused")
enum class Type(val text: String, val nsNative: Boolean = false) {
@SerializedName("Site Change")
CANNULA_CHANGE("Site Change", nsNative = true),
@SerializedName("Insulin Change")
INSULIN_CHANGE("Insulin Change", nsNative = true),
@SerializedName("Pump Battery Change")
PUMP_BATTERY_CHANGE("Pump Battery Change", nsNative = true),
@SerializedName("Sensor Change")
SENSOR_CHANGE("Sensor Change", nsNative = true),
@SerializedName("Sensor Start")
SENSOR_STARTED("Sensor Start", nsNative = true),
@SerializedName("Sensor Stop")
SENSOR_STOPPED("Sensor Stop", nsNative = true),
@SerializedName("BG Check")
FINGER_STICK_BG_VALUE("BG Check", nsNative = true),
@SerializedName("Exercise")
EXERCISE("Exercise", nsNative = true),
@SerializedName("Announcement")
ANNOUNCEMENT("Announcement", nsNative = true),
@SerializedName("Question")
QUESTION("Question", nsNative = true),
@SerializedName("Note")
NOTE("Note", nsNative = true),
@SerializedName("OpenAPS Offline")
APS_OFFLINE("OpenAPS Offline", nsNative = true),
@SerializedName("D.A.D. Alert")
DAD_ALERT("D.A.D. Alert", nsNative = true),
@SerializedName("Mbg")
NS_MBG("Mbg", nsNative = true),
// Used but not as a Therapy Event (use constants only)
@SerializedName("Carb Correction")
CARBS_CORRECTION("Carb Correction", nsNative = true),
@SerializedName("Bolus Wizard")
BOLUS_WIZARD("Bolus Wizard", nsNative = true),
@SerializedName("Correction Bolus")
CORRECTION_BOLUS("Correction Bolus", nsNative = true),
@SerializedName("Meal Bolus")
MEAL_BOLUS("Meal Bolus", nsNative = true),
@SerializedName("Combo Bolus")
COMBO_BOLUS("Combo Bolus", nsNative = true),
@SerializedName("Temporary Target")
TEMPORARY_TARGET("Temporary Target", nsNative = true),
@SerializedName("Temporary Target Cancel")
TEMPORARY_TARGET_CANCEL("Temporary Target Cancel", nsNative = true),
@SerializedName("Profile Switch")
PROFILE_SWITCH("Profile Switch", nsNative = true),
@SerializedName("Snack Bolus")
SNACK_BOLUS("Snack Bolus", nsNative = true),
@SerializedName("Temp Basal")
TEMPORARY_BASAL("Temp Basal", nsNative = true),
@SerializedName("Temp Basal Start")
TEMPORARY_BASAL_START("Temp Basal Start", nsNative = true),
@SerializedName("Temp Basal End")
TEMPORARY_BASAL_END("Temp Basal End", nsNative = true),
// Not supported by NS
@SerializedName("Tube Change")
TUBE_CHANGE("Tube Change"),
@SerializedName("Falling Asleep")
FALLING_ASLEEP("Falling Asleep"),
@SerializedName("Battery Empty")
BATTERY_EMPTY("Battery Empty"),
@SerializedName("Reservoir Empty")
RESERVOIR_EMPTY("Reservoir Empty"),
@SerializedName("Occlusion")
OCCLUSION("Occlusion"),
@SerializedName("Pump Stopped")
PUMP_STOPPED("Pump Stopped"),
@SerializedName("Pump Started")
PUMP_STARTED("Pump Started"),
@SerializedName("Pump Paused")
PUMP_PAUSED("Pump Paused"),
@SerializedName("Waking Up")
WAKING_UP("Waking Up"),
@SerializedName("Sickness")
SICKNESS("Sickness"),
@SerializedName("Stress")
STRESS("Stress"),
@SerializedName("Pre Period")
PRE_PERIOD("Pre Period"),
@SerializedName("Alcohol")
ALCOHOL("Alcohol"),
@SerializedName("Cortisone")
CORTISONE("Cortisone"),
@SerializedName("Feeling Low")
FEELING_LOW("Feeling Low"),
@SerializedName("Feeling High")
FEELING_HIGH("Feeling High"),
@SerializedName("Leaking Infusion Set")
LEAKING_INFUSION_SET("Leaking Infusion Set"),
// Default
@SerializedName("<none>")
NONE("<none>")
;

View file

@ -17,7 +17,7 @@ class SyncNsFoodTransaction(private val food: Food) : Transaction<SyncNsFoodTran
if (current != null) {
// nsId exists, update if different
if (!current.isEqual(food)) {
if (!current.contentEqualsTo(food)) {
current.copyFrom(food)
database.foodDao.updateExistingEntry(current)
if (food.isValid && current.isValid) result.updated.add(current)