diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/DataSyncSelectorImplementation.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/DataSyncSelectorImplementation.kt index 8776dceef0..99b9febf03 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/DataSyncSelectorImplementation.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/DataSyncSelectorImplementation.kt @@ -35,6 +35,7 @@ class DataSyncSelectorImplementation @Inject constructor( sp.remove(R.string.key_ns_temporary_basal_last_synced_id) sp.remove(R.string.key_ns_extended_bolus_last_synced_id) sp.remove(R.string.key_ns_therapy_event_last_synced_id) + sp.remove(R.string.key_ns_profile_switch_last_synced_id) } override fun confirmLastBolusIdIfGreater(lastSynced: Long) { @@ -321,11 +322,11 @@ class DataSyncSelectorImplementation @Inject constructor( aapsLogger.info(LTag.DATABASE, "Loading DeviceStatus data Start: $startId ID: ${deviceStatus.id}") when { // without nsId = create new - deviceStatus.interfaceIDs.nightscoutId == null -> + deviceStatus.interfaceIDs.nightscoutId == null -> nsClientPlugin.nsClientService?.dbAdd("devicestatus", deviceStatus.toJson(dateUtil), deviceStatus) // with nsId = ignore - deviceStatus.interfaceIDs.nightscoutId != null -> Any() - } + deviceStatus.interfaceIDs.nightscoutId != null -> Any() + } return true } return false @@ -408,4 +409,40 @@ class DataSyncSelectorImplementation @Inject constructor( } return false } + + override fun confirmLastProfileSwitchIdIfGreater(lastSynced: Long) { + if (lastSynced > sp.getLong(R.string.key_ns_profile_switch_last_synced_id, 0)) { + aapsLogger.debug(LTag.NSCLIENT, "Setting ProfileSwitch data sync from $lastSynced") + sp.putLong(R.string.key_ns_profile_switch_last_synced_id, lastSynced) + } + } + + override fun changedProfileSwitch(): List { + val startId = sp.getLong(R.string.key_ns_profile_switch_last_synced_id, 0) + return appRepository.getModifiedProfileSwitchDataFromId(startId).blockingGet().also { + aapsLogger.debug(LTag.NSCLIENT, "Loading ProfileSwitch data for sync from $startId. Records ${it.size}") + } + } + + override fun processChangedProfileSwitchesCompat(): Boolean { + val startId = sp.getLong(R.string.key_ns_profile_switch_last_synced_id, 0) + appRepository.getNextSyncElementProfileSwitch(startId).blockingGet()?.let { eb -> + aapsLogger.info(LTag.DATABASE, "Loading ProfileSwitch data Start: $startId ID: ${eb.first.id} HistoryID: ${eb.second} ") + when { + // removed and not uploaded yet = ignore + !eb.first.isValid && eb.first.interfaceIDs.nightscoutId == null -> Any() + // removed and already uploaded = send for removal + !eb.first.isValid && eb.first.interfaceIDs.nightscoutId != null -> + nsClientPlugin.nsClientService?.dbRemove("treatments", eb.first.interfaceIDs.nightscoutId, DataSyncSelector.PairProfileSwitch(eb.first, eb.second)) + // existing without nsId = create new + eb.first.isValid && eb.first.interfaceIDs.nightscoutId == null -> + nsClientPlugin.nsClientService?.dbAdd("treatments", eb.first.toJson(dateUtil), DataSyncSelector.PairProfileSwitch(eb.first, eb.second)) + // existing with nsId = update + eb.first.isValid && eb.first.interfaceIDs.nightscoutId != null -> + nsClientPlugin.nsClientService?.dbUpdate("treatments", eb.first.interfaceIDs.nightscoutId, eb.first.toJson(dateUtil), DataSyncSelector.PairProfileSwitch(eb.first, eb.second)) + } + return true + } + return false + } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientAddAckWorker.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientAddAckWorker.kt index 4b89e51d0b..39c20b00e3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientAddAckWorker.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientAddAckWorker.kt @@ -209,6 +209,25 @@ class NSClientAddAckWorker( dataSyncSelector.processChangedTemporaryBasalsCompat() } + is PairProfileSwitch -> { + val pair = ack.originalObject + pair.value.interfaceIDs.nightscoutId = ack.id + repository.runTransactionForResult(UpdateNsIdProfileSwitchTransaction(pair.value)) + .doOnError { error -> + aapsLogger.error(LTag.DATABASE, "Updated ns id of ProfileSwitch failed", error) + ret = Result.failure((workDataOf("Error" to error.toString()))) + } + .doOnSuccess { + ret = Result.success(workDataOf("ProcessedData" to pair.toString())) + aapsLogger.debug(LTag.DATABASE, "Updated ns id of ProfileSwitch " + pair.value) + dataSyncSelector.confirmLastProfileSwitchIdIfGreater(pair.updateRecordId) + } + .blockingGet() + rxBus.send(EventNSClientNewLog("DBADD", "Acked ProfileSwitch" + pair.value.interfaceIDs.nightscoutId)) + // Send new if waiting + dataSyncSelector.processChangedTemporaryBasalsCompat() + } + is DeviceStatus -> { val deviceStatus = ack.originalObject deviceStatus.interfaceIDs.nightscoutId = ack.id diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientAddUpdateWorker.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientAddUpdateWorker.kt index d0cd0e8a41..83b19b2a16 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientAddUpdateWorker.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientAddUpdateWorker.kt @@ -15,7 +15,6 @@ import info.nightscout.androidaps.database.entities.ValueWithUnit import info.nightscout.androidaps.database.transactions.* import info.nightscout.androidaps.extensions.* import info.nightscout.androidaps.interfaces.Config -import info.nightscout.androidaps.interfaces.DatabaseHelperInterface import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.UserEntryLogger @@ -44,7 +43,6 @@ class NSClientAddUpdateWorker( @Inject lateinit var dateUtil: DateUtil @Inject lateinit var config: Config @Inject lateinit var repository: AppRepository - @Inject lateinit var databaseHelper: DatabaseHelperInterface @Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var uel: UserEntryLogger @@ -305,8 +303,30 @@ class NSClientAddUpdateWorker( } } } ?: aapsLogger.error("Error parsing TemporaryBasal json $json") - eventType == TherapyEvent.Type.PROFILE_SWITCH.text -> Any() -// TODO("databaseHelper.createProfileSwitchFromJsonIfNotExists(json)") + eventType == TherapyEvent.Type.PROFILE_SWITCH.text -> + profileSwitchFromJson(json, dateUtil)?.let { profileSwitch -> + repository.runTransactionForResult(SyncNsProfileSwitchTransaction(profileSwitch, invalidateByNsOnly = false)) + .doOnError { + aapsLogger.error(LTag.DATABASE, "Error while saving ProfileSwitch", it) + ret = Result.failure(workDataOf("Error" to it.toString())) + } + .blockingGet() + .also { result -> + result.inserted.forEach { + uel.log(Action.PROFILE_SWITCH, Sources.NSClient, + ValueWithUnit.Timestamp(it.timestamp)) + aapsLogger.debug(LTag.DATABASE, "Inserted ProfileSwitch $it") + } + result.invalidated.forEach { + uel.log(Action.PROFILE_SWITCH_REMOVED, Sources.NSClient, + ValueWithUnit.Timestamp(it.timestamp)) + aapsLogger.debug(LTag.DATABASE, "Invalidated ProfileSwitch $it") + } + result.updatedNsId.forEach { + aapsLogger.debug(LTag.DATABASE, "Updated nsId ProfileSwitch $it") + } + } + } ?: aapsLogger.error("Error parsing TemporaryBasal json $json") } if (eventType == TherapyEvent.Type.ANNOUNCEMENT.text) { val date = safeGetLong(json, "mills") diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientRemoveWorker.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientRemoveWorker.kt index 3c002f0b80..a2423de9ce 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientRemoveWorker.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientRemoveWorker.kt @@ -156,8 +156,20 @@ class NSClientRemoveWorker( } } - // old DB model - //databaseHelper.deleteProfileSwitchById(nsId) + // room ProfileSwitch + repository.runTransactionForResult(InvalidateNsIdProfileSwitchTransaction(nsId)) + .doOnError { + aapsLogger.error(LTag.DATABASE, "Error while invalidating ProfileSwitch", it) + ret = Result.failure(workDataOf("Error" to it.toString())) + } + .blockingGet() + .also { result -> + result.invalidated.forEach { + uel.log( + Action.CAREPORTAL_REMOVED, Sources.NSClient, + ValueWithUnit.Timestamp(it.timestamp)) + } + } } return ret diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientUpdateRemoveAckWorker.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientUpdateRemoveAckWorker.kt index b061350786..cd818d4461 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientUpdateRemoveAckWorker.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientUpdateRemoveAckWorker.kt @@ -116,6 +116,15 @@ class NSClientUpdateRemoveAckWorker( dataSyncSelector.processChangedExtendedBolusesCompat() ret = Result.success(workDataOf("ProcessedData" to pair.toString())) } + + is PairProfileSwitch -> { + val pair = ack.originalObject + dataSyncSelector.confirmLastProfileSwitchIdIfGreater(pair.updateRecordId) + rxBus.send(EventNSClientNewLog("DBUPDATE/DBREMOVE", "Acked ProfileSwitch " + ack._id)) + // Send new if waiting + dataSyncSelector.processChangedProfileSwitchesCompat() + ret = Result.success(workDataOf("ProcessedData" to pair.toString())) + } } return ret } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/UploadQueue.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/UploadQueue.java index f7ba9c3c0a..f7669b182d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/UploadQueue.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/UploadQueue.java @@ -86,28 +86,6 @@ public class UploadQueue implements UploadQueueAdminInterface { } } - @Override - public void removeByNsClientIdIfExists(final JSONObject record) { - startService(); - if (NSClientService.handler != null) { - NSClientService.handler.post(() -> { - try { - String id; - if (record.has("NSCLIENT_ID")) { - id = record.getString("NSCLIENT_ID"); - } else { - return; - } - if (databaseHelper.deleteDbRequest(id) == 1) { - aapsLogger.debug(LTag.NSCLIENT, "Removed item from UploadQueue. " + status()); - } - } catch (JSONException e) { - aapsLogger.error("Unhandled exception", e); - } - }); - } - } - @Override public void removeByMongoId(final String action, final String _id) { if (_id == null || _id.equals("")) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/services/NSClientService.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/services/NSClientService.java index b63e31feec..078d56943e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/services/NSClientService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/services/NSClientService.java @@ -220,36 +220,18 @@ public class NSClientService extends DaggerService { public void processAddAck(NSAddAck ack) { lastAckTime = dateUtil.now(); - // new room way dataWorker.enqueue( new OneTimeWorkRequest.Builder(NSClientAddAckWorker.class) .setInputData(dataWorker.storeInputData(ack, null)) .build()); - - // old way - if (ack.nsClientID != null) { - uploadQueue.removeByNsClientIdIfExists(ack.json); - rxBus.send(new EventNSClientNewLog("DBADD", "Acked " + ack.nsClientID)); - } else { - rxBus.send(new EventNSClientNewLog("ERROR", "DBADD Unknown response")); - } } public void processUpdateAck(NSUpdateAck ack) { lastAckTime = dateUtil.now(); - // new room way dataWorker.enqueue( new OneTimeWorkRequest.Builder(NSClientUpdateRemoveAckWorker.class) .setInputData(dataWorker.storeInputData(ack, null)) .build()); - - // old way - if (ack.getResult()) { - uploadQueue.removeByMongoId(ack.getAction(), ack.get_id()); - rxBus.send(new EventNSClientNewLog("DBUPDATE/DBREMOVE", "Acked " + ack.get_id())); - } else { - rxBus.send(new EventNSClientNewLog("ERROR", "DBUPDATE/DBREMOVE Unknown response")); - } } public void processAuthAck(NSAuthAck ack) { @@ -811,6 +793,7 @@ public class NSClientService extends DaggerService { dataSyncSelector.processChangedBolusCalculatorResultsCompat(); dataSyncSelector.processChangedTemporaryBasalsCompat(); dataSyncSelector.processChangedExtendedBolusesCompat(); + dataSyncSelector.processChangedProfileSwitchesCompat(); dataSyncSelector.processChangedGlucoseValuesCompat(); dataSyncSelector.processChangedTempTargetsCompat(); dataSyncSelector.processChangedFoodsCompat(); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a523ed73cb..e7dc848158 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -46,6 +46,7 @@ ns_device_status_last_synced_id ns_temporary_basal_last_synced_id ns_extended_bolus_last_synced_id + profile_switch_last_synced_id Treatments safety Max allowed bolus [U] diff --git a/core/src/main/java/info/nightscout/androidaps/extensions/ProfileSwitchExtension.kt b/core/src/main/java/info/nightscout/androidaps/extensions/ProfileSwitchExtension.kt index d320c95ccf..806e1b47f3 100644 --- a/core/src/main/java/info/nightscout/androidaps/extensions/ProfileSwitchExtension.kt +++ b/core/src/main/java/info/nightscout/androidaps/extensions/ProfileSwitchExtension.kt @@ -5,29 +5,70 @@ import info.nightscout.androidaps.data.ProfileSealed import info.nightscout.androidaps.data.PureProfile import info.nightscout.androidaps.database.embedments.InterfaceIDs import info.nightscout.androidaps.database.entities.ProfileSwitch +import info.nightscout.androidaps.database.entities.TemporaryBasal +import info.nightscout.androidaps.database.entities.TherapyEvent import info.nightscout.androidaps.interfaces.GlucoseUnit +import info.nightscout.androidaps.interfaces.Profile import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DecimalFormatter.to2Decimal import info.nightscout.androidaps.utils.JsonHelper import info.nightscout.androidaps.utils.T import org.json.JSONObject -import java.lang.Exception import java.util.* -fun profileSwitchFromProfileSwitchJson(jsonObject: JSONObject): ProfileSwitch? { +fun ProfileSwitch.toJson(dateUtil: DateUtil): JSONObject = + JSONObject() + .put("created_at", dateUtil.toISOString(timestamp)) + .put("enteredBy", "openaps://" + "AndroidAPS") + .put("eventType", TherapyEvent.Type.PROFILE_SWITCH.text) + .put("duration", T.msecs(duration).mins()) + .put("profile", getCustomizedName()) + .put("profileJson", ProfileSealed.PS(this).toPureNsJson(dateUtil)) + .put("timeshift", T.msecs(timeshift).hours()) + .put("percentage", percentage) + .also { + if (interfaceIDs.pumpId != null) it.put("pumpId", interfaceIDs.pumpId) + if (interfaceIDs.pumpType != null) it.put("pumpType", interfaceIDs.pumpType!!.name) + if (interfaceIDs.pumpSerial != null) it.put("pumpSerial", interfaceIDs.pumpSerial) + if (interfaceIDs.nightscoutId != null) it.put("_id", interfaceIDs.nightscoutId) + } + +fun profileSwitchFromJson(jsonObject: JSONObject, dateUtil: DateUtil): ProfileSwitch? { val timestamp = JsonHelper.safeGetLongAllowNull(jsonObject, "mills", null) ?: return null val duration = JsonHelper.safeGetLong(jsonObject, "duration") - val timeshift = JsonHelper.safeGetInt(jsonObject, "timeshift", 0) - val percentage = JsonHelper.safeGetInt(jsonObject, "duration", 100) + val timeshift = JsonHelper.safeGetLong(jsonObject, "timeshift") + val percentage = JsonHelper.safeGetInt(jsonObject, "percentage", 100) val isValid = JsonHelper.safeGetBoolean(jsonObject, "isValid", true) val id = JsonHelper.safeGetStringAllowNull(jsonObject, "_id", null) + val profileName = JsonHelper.safeGetStringAllowNull(jsonObject, "profile", null) ?: return null + val profileJson = JsonHelper.safeGetStringAllowNull(jsonObject, "profileJson", null) ?: return null val pumpId = JsonHelper.safeGetLongAllowNull(jsonObject, "pumpId", null) val pumpType = InterfaceIDs.PumpType.fromString(JsonHelper.safeGetStringAllowNull(jsonObject, "pumpType", null)) val pumpSerial = JsonHelper.safeGetStringAllowNull(jsonObject, "pumpSerial", null) if (timestamp == 0L) return null + val pureProfile = pureProfileFromJson(JSONObject(profileJson), dateUtil) ?: return null + val profileSealed = ProfileSealed.Pure(pureProfile) - return null + return ProfileSwitch( + timestamp = timestamp, + basalBlocks = profileSealed.basalBlocks, + isfBlocks = profileSealed.isfBlocks, + icBlocks = profileSealed.icBlocks, + targetBlocks = profileSealed.targetBlocks, + glucoseUnit = ProfileSwitch.GlucoseUnit.fromConstant(profileSealed.units), + profileName = profileName, + timeshift = T.hours(timeshift).msecs(), + percentage = percentage, + duration = T.mins(duration).msecs(), + insulinConfiguration = profileSealed.insulinConfiguration, + isValid = isValid + ).also { + it.interfaceIDs.nightscoutId = id + it.interfaceIDs.pumpId = pumpId + it.interfaceIDs.pumpType = pumpType + it.interfaceIDs.pumpSerial = pumpSerial + } } /** diff --git a/core/src/main/java/info/nightscout/androidaps/interfaces/DataSyncSelector.kt b/core/src/main/java/info/nightscout/androidaps/interfaces/DataSyncSelector.kt index 1e1911b75e..b4221f79bb 100644 --- a/core/src/main/java/info/nightscout/androidaps/interfaces/DataSyncSelector.kt +++ b/core/src/main/java/info/nightscout/androidaps/interfaces/DataSyncSelector.kt @@ -14,6 +14,7 @@ interface DataSyncSelector { data class PairBolusCalculatorResult(val value: BolusCalculatorResult, val updateRecordId: Long) data class PairTemporaryBasal(val value: TemporaryBasal, val updateRecordId: Long) data class PairExtendedBolus(val value: ExtendedBolus, val updateRecordId: Long) + data class PairProfileSwitch(val value: ProfileSwitch, val updateRecordId: Long) fun resetToNextFullSync() @@ -66,4 +67,9 @@ interface DataSyncSelector { fun changedExtendedBoluses() : List // Until NS v3 fun processChangedExtendedBolusesCompat(): Boolean + + fun confirmLastProfileSwitchIdIfGreater(lastSynced: Long) + fun changedProfileSwitch() : List + // Until NS v3 + fun processChangedProfileSwitchesCompat(): Boolean } \ No newline at end of file diff --git a/core/src/main/java/info/nightscout/androidaps/interfaces/UploadQueueInterface.java b/core/src/main/java/info/nightscout/androidaps/interfaces/UploadQueueInterface.java index e8d5b187f1..65e02dcdb8 100644 --- a/core/src/main/java/info/nightscout/androidaps/interfaces/UploadQueueInterface.java +++ b/core/src/main/java/info/nightscout/androidaps/interfaces/UploadQueueInterface.java @@ -10,8 +10,6 @@ public interface UploadQueueInterface { void add(DbRequest dbRequest); - void removeByNsClientIdIfExists(JSONObject record); - void removeByMongoId(final String action, final String _id); String textList(); diff --git a/database/src/main/java/info/nightscout/androidaps/database/AppRepository.kt b/database/src/main/java/info/nightscout/androidaps/database/AppRepository.kt index 0237a36754..d2150de8bc 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/AppRepository.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/AppRepository.kt @@ -170,6 +170,22 @@ open class AppRepository @Inject internal constructor( // PROFILE SWITCH + fun getNextSyncElementProfileSwitch(id: Long): Maybe> = + database.profileSwitchDao.getNextModifiedOrNewAfter(id) + .flatMap { nextIdElement -> + val nextIdElemReferenceId = nextIdElement.referenceId + if (nextIdElemReferenceId == null) { + Maybe.just(nextIdElement to nextIdElement.id) + } else { + database.profileSwitchDao.getCurrentFromHistoric(nextIdElemReferenceId) + .map { it to nextIdElement.id } + } + } + + fun getModifiedProfileSwitchDataFromId(lastId: Long): Single> = + database.profileSwitchDao.getModifiedFrom(lastId) + .subscribeOn(Schedulers.io()) + fun getActiveProfileSwitch(timestamp: Long): ProfileSwitch? { val tps = database.profileSwitchDao.getTemporaryProfileSwitchActiveAt(timestamp) .subscribeOn(Schedulers.io()) diff --git a/database/src/main/java/info/nightscout/androidaps/database/daos/ProfileSwitchDao.kt b/database/src/main/java/info/nightscout/androidaps/database/daos/ProfileSwitchDao.kt index 221eff8eff..c992e592be 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/daos/ProfileSwitchDao.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/daos/ProfileSwitchDao.kt @@ -19,6 +19,12 @@ internal interface ProfileSwitchDao : ProfileSwitchDaoWorkaround { @Query("DELETE FROM $TABLE_PROFILE_SWITCHES") override fun deleteAllEntries() + @Query("SELECT * FROM $TABLE_PROFILE_SWITCHES WHERE timestamp = :timestamp AND referenceId IS NULL") + fun findByTimestamp(timestamp: Long): ProfileSwitch? + + @Query("SELECT * FROM $TABLE_PROFILE_SWITCHES WHERE nightscoutId = :nsId AND referenceId IS NULL") + fun findByNSId(nsId: String): ProfileSwitch? + @Query("SELECT * FROM $TABLE_PROFILE_SWITCHES WHERE timestamp <= :timestamp AND (timestamp + duration) > :timestamp AND referenceId IS NULL AND isValid = 1 ORDER BY timestamp DESC LIMIT 1") fun getTemporaryProfileSwitchActiveAt(timestamp: Long): Maybe @@ -34,6 +40,16 @@ internal interface ProfileSwitchDao : ProfileSwitchDaoWorkaround { @Query("SELECT * FROM $TABLE_PROFILE_SWITCHES WHERE timestamp >= :timestamp AND isValid = 1 AND referenceId IS NULL ORDER BY timestamp ASC") fun getProfileSwitchDataFromTime(timestamp: Long): Single> + // This query will be used with v3 to get all changed records + @Query("SELECT * FROM $TABLE_PROFILE_SWITCHES WHERE id > :id AND referenceId IS NULL OR id IN (SELECT DISTINCT referenceId FROM $TABLE_PROFILE_SWITCHES WHERE id > :id) ORDER BY id ASC") + fun getModifiedFrom(id: Long): Single> + + // for WS we need 1 record only + @Query("SELECT * FROM $TABLE_PROFILE_SWITCHES WHERE id > :id ORDER BY id ASC limit 1") + fun getNextModifiedOrNewAfter(id: Long): Maybe + + @Query("SELECT * FROM $TABLE_PROFILE_SWITCHES WHERE id = :referenceId") + fun getCurrentFromHistoric(referenceId: Long): Maybe } internal fun ProfileSwitchDao.insertNewEntryImpl(entry: ProfileSwitch): Long { diff --git a/database/src/main/java/info/nightscout/androidaps/database/transactions/InvalidateNsIdProfileSwitchTransaction.kt b/database/src/main/java/info/nightscout/androidaps/database/transactions/InvalidateNsIdProfileSwitchTransaction.kt new file mode 100644 index 0000000000..67cb703cc6 --- /dev/null +++ b/database/src/main/java/info/nightscout/androidaps/database/transactions/InvalidateNsIdProfileSwitchTransaction.kt @@ -0,0 +1,23 @@ +package info.nightscout.androidaps.database.transactions + +import info.nightscout.androidaps.database.entities.Food +import info.nightscout.androidaps.database.entities.ProfileSwitch + +class InvalidateNsIdProfileSwitchTransaction(val nsId: String) : Transaction() { + + override fun run() : TransactionResult{ + val result = TransactionResult() + val current = database.profileSwitchDao.findByNSId(nsId) + if (current != null) { + current.isValid = false + database.profileSwitchDao.updateExistingEntry(current) + result.invalidated.add(current) + } + return result + } + + class TransactionResult { + val invalidated = mutableListOf() + } + +} \ No newline at end of file diff --git a/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncNsProfileSwitchTransaction.kt b/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncNsProfileSwitchTransaction.kt new file mode 100644 index 0000000000..40e1ff0aa0 --- /dev/null +++ b/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncNsProfileSwitchTransaction.kt @@ -0,0 +1,51 @@ +package info.nightscout.androidaps.database.transactions + +import info.nightscout.androidaps.database.entities.ProfileSwitch + +/** + * Sync the ProfileSwitch from NS + */ +class SyncNsProfileSwitchTransaction(private val profileSwitch: ProfileSwitch, private val invalidateByNsOnly: Boolean) : Transaction() { + + override fun run(): TransactionResult { + val result = TransactionResult() + + val current: ProfileSwitch? = + profileSwitch.interfaceIDs.nightscoutId?.let { + database.profileSwitchDao.findByNSId(it) + } + + if (current != null) { + // nsId exists, allow only invalidation + if (current.isValid && !profileSwitch.isValid) { + current.isValid = false + database.profileSwitchDao.updateExistingEntry(current) + result.invalidated.add(current) + } + return result + } + + if (invalidateByNsOnly) return result + + // not known nsId + val existing = database.profileSwitchDao.findByTimestamp(profileSwitch.timestamp) + if (existing != null && existing.interfaceIDs.nightscoutId == null) { + // the same record, update nsId only + existing.interfaceIDs.nightscoutId = profileSwitch.interfaceIDs.nightscoutId + existing.isValid = profileSwitch.isValid + database.profileSwitchDao.updateExistingEntry(existing) + result.updatedNsId.add(existing) + } else { + database.profileSwitchDao.insertNewEntry(profileSwitch) + result.inserted.add(profileSwitch) + } + return result + } + + class TransactionResult { + + val updatedNsId = mutableListOf() + val inserted = mutableListOf() + val invalidated = mutableListOf() + } +} \ No newline at end of file diff --git a/database/src/main/java/info/nightscout/androidaps/database/transactions/UpdateNsIdProfileSwitchTransaction.kt b/database/src/main/java/info/nightscout/androidaps/database/transactions/UpdateNsIdProfileSwitchTransaction.kt new file mode 100644 index 0000000000..63a589db51 --- /dev/null +++ b/database/src/main/java/info/nightscout/androidaps/database/transactions/UpdateNsIdProfileSwitchTransaction.kt @@ -0,0 +1,12 @@ +package info.nightscout.androidaps.database.transactions + +import info.nightscout.androidaps.database.entities.ProfileSwitch + +class UpdateNsIdProfileSwitchTransaction(val profileSwitch: ProfileSwitch) : Transaction() { + + override fun run() { + val current = database.profileSwitchDao.findById(profileSwitch.id) + if (current != null && current.interfaceIDs.nightscoutId != profileSwitch.interfaceIDs.nightscoutId) + database.profileSwitchDao.updateExistingEntry(profileSwitch) + } +} \ No newline at end of file