From 2463f8fc474077e1cc703254b4b3fa2c899d8594 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Mon, 5 Apr 2021 22:41:28 +0200 Subject: [PATCH] ExtendedBolus, TemporaryBasal -> room, DanaRS working --- .../info/nightscout/androidaps/MainApp.kt | 2 - .../activities/ProfileHelperActivity.kt | 2 +- .../androidaps/db/DatabaseHelper.java | 373 +-- .../androidaps/db/DatabaseHelperProvider.java | 38 +- .../androidaps/dialogs/CarbsDialog.kt | 2 +- .../androidaps/dialogs/CareDialog.kt | 2 +- .../androidaps/dialogs/ExtendedBolusDialog.kt | 2 +- .../androidaps/dialogs/FillDialog.kt | 2 +- .../androidaps/dialogs/InsulinDialog.kt | 6 +- .../androidaps/dialogs/LoopDialog.kt | 2 +- .../androidaps/dialogs/TempBasalDialog.kt | 2 +- .../androidaps/dialogs/TreatmentDialog.kt | 4 +- .../androidaps/dialogs/WizardDialog.kt | 8 +- .../historyBrowser/HistoryBrowseActivity.kt | 2 +- .../IobCobCalculatorPluginHistory.kt | 3 +- .../historyBrowser/TreatmentsPluginHistory.kt | 4 +- .../androidaps/plugins/aps/loop/LoopPlugin.kt | 26 +- .../openAPSAMA/DetermineBasalAdapterAMAJS.kt | 18 +- .../aps/openAPSAMA/OpenAPSAMAPlugin.kt | 5 +- .../openAPSSMB/DetermineBasalAdapterSMBJS.kt | 18 +- .../aps/openAPSSMB/OpenAPSSMBPlugin.kt | 5 +- .../configBuilder/ConfigBuilderFragment.kt | 2 +- .../constraints/safety/SafetyPlugin.kt | 8 +- .../general/actions/ActionsFragment.kt | 23 +- .../dataBroadcaster/DataBroadcastPlugin.kt | 21 +- .../plugins/general/food/FoodFragment.kt | 2 +- .../plugins/general/food/FoodPlugin.kt | 2 +- .../DataSyncSelectorImplementation.kt | 81 +- .../nsclient/NSClientAddUpdateWorker.kt | 103 +- .../general/nsclient/NSClientMbgWorker.kt | 2 +- .../general/nsclient/NSClientRemoveWorker.kt | 49 +- .../nsclient/services/NSClientService.java | 58 +- .../general/openhumans/OpenHumansUploader.kt | 14 +- .../general/overview/OverviewFragment.kt | 50 +- .../general/overview/OverviewPlugin.kt | 1 + .../general/overview/StatusLightHandler.kt | 2 +- .../general/overview/graphData/GraphData.kt | 10 +- .../graphExtensions/ExtendedBolusDataPoint.kt | 25 + .../PersistentNotificationPlugin.kt | 9 +- .../smsCommunicator/SmsCommunicatorPlugin.kt | 4 +- .../general/tidepool/comm/UploadChunk.kt | 16 +- .../general/tidepool/elements/BasalElement.kt | 20 +- .../tidepool/elements/BloodGlucoseElement.kt | 2 +- .../general/wear/ActionStringHandler.kt | 2 +- .../wearintegration/WatchUpdaterService.java | 43 +- .../xdripStatusline/StatusLinePlugin.kt | 5 +- .../insulin/InsulinOrefFreePeakPlugin.kt | 4 +- .../IobCobCalculatorPlugin.kt | 231 +- .../iob/iobCobCalculator/IobCobOref1Thread.kt | 2 +- .../pump/virtual/VirtualPumpFragment.kt | 16 +- .../plugins/pump/virtual/VirtualPumpPlugin.kt | 89 +- .../sensitivity/SensitivityAAPSPlugin.kt | 2 +- .../sensitivity/SensitivityOref1Plugin.kt | 2 +- .../SensitivityWeightedAveragePlugin.kt | 2 +- .../plugins/source/BGSourceFragment.kt | 6 +- .../androidaps/plugins/source/DexcomPlugin.kt | 7 - .../plugins/source/RandomBgPlugin.kt | 7 +- .../androidaps/plugins/source/TomatoPlugin.kt | 2 - .../plugins/treatments/TreatmentsFragment.kt | 9 +- .../plugins/treatments/TreatmentsPlugin.java | 342 +- .../fragments/TreatmentsBolusCarbsFragment.kt | 15 +- .../fragments/TreatmentsCareportalFragment.kt | 2 +- .../TreatmentsExtendedBolusesFragment.kt | 166 +- .../TreatmentsProfileSwitchFragment.kt | 2 +- .../fragments/TreatmentsTempTargetFragment.kt | 10 +- .../TreatmentsTemporaryBasalsFragment.kt | 138 +- .../fragments/TreatmentsUserEntryFragment.kt | 1 + .../androidaps/receivers/KeepAliveReceiver.kt | 2 +- .../alertDialogs/PrefImportSummaryDialog.kt | 2 +- .../alertDialogs/TwoMessagesAlertDialog.kt | 2 +- .../androidaps/utils/stats/TddCalculator.kt | 59 +- .../androidaps/utils/wizard/BolusWizard.kt | 6 +- .../utils/wizard/QuickWizardEntry.kt | 12 +- app/src/main/res/layout/dialog_temptarget.xml | 2 - .../treatments_extendedbolus_fragment.xml | 24 + .../layout/treatments_extendedbolus_item.xml | 107 +- .../layout/treatments_tempbasals_fragment.xml | 25 +- .../res/layout/treatments_tempbasals_item.xml | 141 +- .../layout/treatments_temptarget_fragment.xml | 1 - app/src/main/res/values/strings.xml | 2 + .../androidaps/TestBaseWithProfile.kt | 7 +- .../nightscout/androidaps/TestPumpPlugin.kt | 5 +- .../androidaps/data/QuickWizardTest.kt | 5 +- .../interfaces/ConstraintsCheckerTest.kt | 15 +- .../plugins/aps/loop/LoopPluginTest.kt | 6 +- .../constraints/safety/SafetyPluginTest.kt | 2 +- .../SmsCommunicatorPluginTest.kt | 9 +- .../IobCobCalculatorPluginTest.kt | 4 +- .../pump/virtual/VirtualPumpPluginUTest.kt | 6 +- .../treatments/TreatmentsPluginTest.kt | 6 +- .../androidaps/queue/CommandQueueTest.kt | 7 +- .../androidaps/queue/QueueThreadTest.kt | 4 +- .../utils/wizard/BolusWizardTest.kt | 2 +- .../general/automation/AutomationFragment.kt | 2 +- .../actions/ActionStartTempTarget.kt | 2 +- .../automation/dialogs/EditEventDialog.kt | 2 +- .../general/automation/TestPumpPlugin.kt | 5 +- .../plugins/pump/combo/ComboPlugin.java | 186 +- .../plugins/pump/combo/ComboPluginTest.kt | 4 +- .../info/nightscout/androidaps/Constants.java | 2 +- .../nightscout/androidaps/data/Profile.java | 2 +- .../androidaps/db/ExtendedBolus.java | 5 +- .../androidaps/db/TemporaryBasal.java | 38 +- .../dialogs/DialogFragmentWithDate.kt | 2 +- .../BolusCalculatorResultExtension.kt | 4 +- .../{utils => }/extensions/BolusExtension.kt | 4 +- .../{utils => }/extensions/CarbsExtension.kt | 4 +- .../{utils => }/extensions/Concurrency.kt | 2 +- .../extensions/DeviceStatusExtension.kt | 2 +- .../extensions/ExtendedBolusExtension.kt | 190 ++ .../{utils => }/extensions/FoodExtension.kt | 2 +- .../extensions/GlucoseValueExtension.kt | 2 +- .../extensions/HexByteArrayConversion.kt | 2 +- .../{utils => }/extensions/HtmlString.kt | 2 +- .../{utils => }/extensions/JSONObjectExt.kt | 2 +- .../extensions/PumpStateExtension.kt | 62 + .../extensions/TemporaryBasalExtension.kt | 224 ++ .../extensions/TemporaryTargetExtension.kt | 2 +- .../extensions/TherapyEventExtension.kt | 2 +- .../{utils => }/extensions/TrendArrowIcon.kt | 2 +- .../{utils => }/extensions/UIUtils.kt | 2 +- .../{utils => }/extensions/UserEntryExt.kt | 2 +- .../androidaps/interfaces/DataSyncSelector.kt | 12 + .../interfaces/DatabaseHelperInterface.kt | 12 +- .../androidaps/interfaces/IobCobCalculator.kt | 54 +- .../androidaps/interfaces/PumpSync.kt | 118 +- .../interfaces/TreatmentsInterface.java | 28 - .../androidaps/plugins/aps/loop/APSResult.kt | 16 +- .../activities/PrefImportListActivity.kt | 2 +- .../formats/EncryptedPrefsFormat.kt | 4 +- .../plugins/general/nsclient/NSUpload.java | 150 +- .../overview/notifications/Notification.kt | 1 + .../plugins/pump/PumpSyncImplementation.kt | 107 +- .../bolusInfo/DetailedBolusInfoStorage.kt | 4 +- .../common/bolusInfo/TemporaryBasalStorage.kt | 59 + .../nightscout/androidaps/utils/CryptoUtil.kt | 2 +- .../nightscout/androidaps/utils/DateUtil.java | 2 +- .../info/nightscout/androidaps/utils/T.java | 79 - .../info/nightscout/androidaps/utils/T.kt | 25 + .../nightscout/androidaps/utils/WarnColors.kt | 2 +- .../androidaps/utils/alertDialogs/OKDialog.kt | 2 +- .../utils/alertDialogs/WarningDialog.kt | 2 +- .../utils/protection/BiometricCheck.kt | 2 +- .../androidaps/utils/ui/UIRunnable.kt | 2 +- .../androidaps/utils/ui/WeekdayPicker.kt | 2 +- core/src/main/res/values/strings.xml | 1 - .../nightscout/androidaps/TestPumpPlugin.kt | 5 +- .../plugins/aps/loop/APSResultTest.kt | 48 +- .../bolusInfo/DetailedBolusInfoStorageTest.kt | 3 - .../bolusInfo/TemporaryBasalStorageTest.kt | 79 + .../androidaps/dana/DanaFragment.kt | 16 +- .../nightscout/androidaps/dana/DanaPump.kt | 122 +- dana/src/main/res/values/strings.xml | 1 - .../androidaps/dana/DanaPumpTest.kt | 2 +- .../danaRKorean/DanaRKoreanPlugin.java | 41 +- .../danaRKorean/comm/MsgStatus_k.kt | 12 +- .../services/DanaRKoreanExecutionService.java | 6 +- .../androidaps/danaRv2/DanaRv2Plugin.java | 30 +- .../danaRv2/comm/MessageHashTableRv2.kt | 4 +- .../danaRv2/comm/MsgHistoryEvents_v2.kt | 107 +- .../danaRv2/comm/MsgStatusBolusExtended_v2.kt | 49 - .../danaRv2/comm/MsgStatusTempBasal_v2.kt | 42 - .../services/DanaRv2ExecutionService.java | 49 +- .../androidaps/danar/AbstractDanaRPlugin.java | 100 +- .../androidaps/danar/DanaRPlugin.java | 41 +- .../androidaps/danar/comm/MessageBase.java | 2 + .../androidaps/danar/comm/MsgStatus.kt | 12 +- .../danar/comm/MsgStatusBolusExtended.kt | 47 +- .../danar/comm/MsgStatusTempBasal.kt | 50 +- .../androidaps/danar/di/DanaRCommModule.kt | 8 +- .../AbstractDanaRExecutionService.java | 107 +- .../danar/services/DanaRExecutionService.java | 2 + danar/src/main/res/values/strings.xml | 1 + danar/src/main/res/xml/pref_danar.xml | 6 - danar/src/main/res/xml/pref_danarkorean.xml | 6 - .../nightscout/androidaps/TestPumpPlugin.kt | 5 +- .../plugins/pump/danaR/DanaRPluginTest.kt | 2 +- .../plugins/pump/danaR/comm/DanaRTestBase.kt | 12 +- .../danaR/comm/MsgStatusBolusExtendedTest.kt | 5 +- .../pump/danaRKorean/DanaRKoreanPluginTest.kt | 2 +- .../plugins/pump/danaRv2/DanaRv2PluginTest.kt | 9 +- .../danaRv2/comm/MsgHistoryEventsRv2Test.kt | 4 +- .../comm/MsgStatusBolusExtendedRv2Test.kt | 20 - .../danaRv2/comm/MsgStatusTempBasalRv2Test.kt | 22 - .../androidaps/danars/DanaRSPlugin.kt | 83 +- .../danars/activities/EnterPinActivity.kt | 2 +- .../comm/DanaRS_Packet_APS_History_Events.kt | 133 +- ..._Packet_Basal_Get_Temporary_Basal_State.kt | 18 +- .../DanaRS_Packet_Bolus_Get_Dual_Bolus.kt | 4 +- .../DanaRS_Packet_Bolus_Get_Extended_Bolus.kt | 4 +- ...S_Packet_Bolus_Get_Extended_Bolus_State.kt | 21 +- ...aRS_Packet_General_Get_More_Information.kt | 8 +- ...cket_General_Initial_Screen_Information.kt | 20 +- .../androidaps/danars/services/BLEComm.kt | 4 +- .../danars/services/DanaRSService.kt | 39 +- .../androidaps/danars/DanaRSPluginTest.kt | 11 +- .../androidaps/danars/DanaRSTestBase.kt | 2 +- .../comm/DanaRsPacketApsHistoryEventsTest.kt | 9 +- .../DanaRsPacketBolusSetStepBolusStartTest.kt | 6 +- ...naRsPacketNotifyDeliveryRateDisplayTest.kt | 6 +- .../11.json | 2943 +++++++++++++++++ .../12.json | 2931 ++++++++++++++++ .../androidaps/database/AppDatabase.kt | 2 +- .../androidaps/database/AppRepository.kt | 112 +- .../database/daos/ExtendedBolusDao.kt | 47 +- .../database/daos/TemporaryBasalDao.kt | 13 +- .../database/entities/ExtendedBolus.kt | 30 +- .../database/entities/TemporaryBasal.kt | 36 +- .../androidaps/database/entities/UserEntry.kt | 1 + .../InvalidateExtendedBolusTransaction.kt | 21 + .../InvalidateTemporaryBasalTransaction.kt | 21 + .../SyncNsExtendedBolusTransaction.kt | 71 + .../SyncNsTemporaryBasalTransaction.kt | 62 + .../transactions/SyncPumpBolusTransaction.kt | 16 +- ...PumpCancelExtendedBolusIfAnyTransaction.kt | 32 + ...umpCancelTemporaryBasalIfAnyTransaction.kt | 4 +- .../SyncPumpExtendedBolusTransaction.kt | 49 + .../SyncPumpTemporaryBasalTransaction.kt | 24 +- .../UpdateNsIdExtendedBolusTransaction.kt | 12 + .../UpdateNsIdTemporaryBasalTransaction.kt | 12 + .../pump/insight/LocalInsightPlugin.java | 19 +- .../pump/common/PumpPluginAbstract.java | 39 +- .../pump/medtronic/MedtronicFragment.kt | 11 +- .../pump/medtronic/MedtronicPumpPlugin.java | 5 +- .../common/fragment/ActionFragmentBase.kt | 2 +- .../omnipod/eros/OmnipodErosPumpPlugin.java | 78 +- .../eros/manager/AapsOmnipodErosManager.java | 114 +- .../eros/ui/ErosPodManagementActivity.kt | 2 +- .../eros/OmnipodErosPumpPluginTest.java | 40 +- 229 files changed, 9493 insertions(+), 2753 deletions(-) create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphExtensions/ExtendedBolusDataPoint.kt rename core/src/main/java/info/nightscout/androidaps/{utils => }/extensions/BolusCalculatorResultExtension.kt (86%) rename core/src/main/java/info/nightscout/androidaps/{utils => }/extensions/BolusExtension.kt (96%) rename core/src/main/java/info/nightscout/androidaps/{utils => }/extensions/CarbsExtension.kt (95%) rename core/src/main/java/info/nightscout/androidaps/{utils => }/extensions/Concurrency.kt (93%) rename core/src/main/java/info/nightscout/androidaps/{utils => }/extensions/DeviceStatusExtension.kt (99%) create mode 100644 core/src/main/java/info/nightscout/androidaps/extensions/ExtendedBolusExtension.kt rename core/src/main/java/info/nightscout/androidaps/{utils => }/extensions/FoodExtension.kt (97%) rename core/src/main/java/info/nightscout/androidaps/{utils => }/extensions/GlucoseValueExtension.kt (94%) rename core/src/main/java/info/nightscout/androidaps/{utils => }/extensions/HexByteArrayConversion.kt (94%) rename core/src/main/java/info/nightscout/androidaps/{utils => }/extensions/HtmlString.kt (86%) rename core/src/main/java/info/nightscout/androidaps/{utils => }/extensions/JSONObjectExt.kt (97%) create mode 100644 core/src/main/java/info/nightscout/androidaps/extensions/PumpStateExtension.kt create mode 100644 core/src/main/java/info/nightscout/androidaps/extensions/TemporaryBasalExtension.kt rename core/src/main/java/info/nightscout/androidaps/{utils => }/extensions/TemporaryTargetExtension.kt (98%) rename core/src/main/java/info/nightscout/androidaps/{utils => }/extensions/TherapyEventExtension.kt (98%) rename core/src/main/java/info/nightscout/androidaps/{utils => }/extensions/TrendArrowIcon.kt (94%) rename core/src/main/java/info/nightscout/androidaps/{utils => }/extensions/UIUtils.kt (83%) rename core/src/main/java/info/nightscout/androidaps/{utils => }/extensions/UserEntryExt.kt (92%) create mode 100644 core/src/main/java/info/nightscout/androidaps/plugins/pump/common/bolusInfo/TemporaryBasalStorage.kt delete mode 100644 core/src/main/java/info/nightscout/androidaps/utils/T.java create mode 100644 core/src/main/java/info/nightscout/androidaps/utils/T.kt create mode 100644 core/src/test/java/info/nightscout/androidaps/pump/bolusInfo/TemporaryBasalStorageTest.kt delete mode 100644 danar/src/main/java/info/nightscout/androidaps/danaRv2/comm/MsgStatusBolusExtended_v2.kt delete mode 100644 danar/src/main/java/info/nightscout/androidaps/danaRv2/comm/MsgStatusTempBasal_v2.kt delete mode 100644 danar/src/test/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgStatusBolusExtendedRv2Test.kt delete mode 100644 danar/src/test/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgStatusTempBasalRv2Test.kt create mode 100644 database/schemas/info.nightscout.androidaps.database.AppDatabase/11.json create mode 100644 database/schemas/info.nightscout.androidaps.database.AppDatabase/12.json create mode 100644 database/src/main/java/info/nightscout/androidaps/database/transactions/InvalidateExtendedBolusTransaction.kt create mode 100644 database/src/main/java/info/nightscout/androidaps/database/transactions/InvalidateTemporaryBasalTransaction.kt create mode 100644 database/src/main/java/info/nightscout/androidaps/database/transactions/SyncNsExtendedBolusTransaction.kt create mode 100644 database/src/main/java/info/nightscout/androidaps/database/transactions/SyncNsTemporaryBasalTransaction.kt create mode 100644 database/src/main/java/info/nightscout/androidaps/database/transactions/SyncPumpCancelExtendedBolusIfAnyTransaction.kt create mode 100644 database/src/main/java/info/nightscout/androidaps/database/transactions/SyncPumpExtendedBolusTransaction.kt create mode 100644 database/src/main/java/info/nightscout/androidaps/database/transactions/UpdateNsIdExtendedBolusTransaction.kt create mode 100644 database/src/main/java/info/nightscout/androidaps/database/transactions/UpdateNsIdTemporaryBasalTransaction.kt diff --git a/app/src/main/java/info/nightscout/androidaps/MainApp.kt b/app/src/main/java/info/nightscout/androidaps/MainApp.kt index 784980d894..db3e97d199 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainApp.kt +++ b/app/src/main/java/info/nightscout/androidaps/MainApp.kt @@ -23,7 +23,6 @@ import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin import info.nightscout.androidaps.plugins.configBuilder.PluginStore import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtils -import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.receivers.BTReceiver import info.nightscout.androidaps.receivers.ChargingStateReceiver import info.nightscout.androidaps.receivers.KeepAliveReceiver.KeepAliveManager @@ -47,7 +46,6 @@ class MainApp : DaggerApplication() { @Inject lateinit var activityMonitor: ActivityMonitor @Inject lateinit var versionCheckersUtils: VersionCheckerUtils @Inject lateinit var sp: SP - @Inject lateinit var nsUpload: NSUpload @Inject lateinit var config: Config @Inject lateinit var configBuilderPlugin: ConfigBuilderPlugin @Inject lateinit var keepAliveManager: KeepAliveManager diff --git a/app/src/main/java/info/nightscout/androidaps/activities/ProfileHelperActivity.kt b/app/src/main/java/info/nightscout/androidaps/activities/ProfileHelperActivity.kt index 34978739b6..6d8fffd160 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/ProfileHelperActivity.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/ProfileHelperActivity.kt @@ -24,7 +24,7 @@ import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.ToastUtils import info.nightscout.androidaps.utils.alertDialogs.OKDialog -import info.nightscout.androidaps.utils.extensions.toVisibility +import info.nightscout.androidaps.extensions.toVisibility import info.nightscout.androidaps.utils.stats.TddCalculator import java.text.DecimalFormat import javax.inject.Inject diff --git a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java index 3e4f21c330..e780600aa0 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java +++ b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java @@ -80,12 +80,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { public static Long earliestDataChange = null; - private static final ScheduledExecutorService tempBasalsWorker = Executors.newSingleThreadScheduledExecutor(); - private static ScheduledFuture scheduledTemBasalsPost = null; - - private static final ScheduledExecutorService extendedBolusWorker = Executors.newSingleThreadScheduledExecutor(); - private static ScheduledFuture scheduledExtendedBolusPost = null; - private static final ScheduledExecutorService profileSwitchEventWorker = Executors.newSingleThreadScheduledExecutor(); private static ScheduledFuture scheduledProfileSwitchEventPost = null; @@ -198,8 +192,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { aapsLogger.error("Unhandled exception", e); } virtualPumpPlugin.setFakingStatus(true); - scheduleTemporaryBasalChange(); - scheduleExtendedBolusChange(); scheduleProfileSwitchChange(); new java.util.Timer().schedule( new java.util.TimerTask() { @@ -212,29 +204,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { ); } - public void resetTemporaryBasals() { - try { - TableUtils.dropTable(connectionSource, TemporaryBasal.class, true); - TableUtils.createTableIfNotExists(connectionSource, TemporaryBasal.class); - updateEarliestDataChange(0); - } catch (SQLException e) { - aapsLogger.error("Unhandled exception", e); - } - virtualPumpPlugin.setFakingStatus(false); - scheduleTemporaryBasalChange(); - } - - public void resetExtededBoluses() { - try { - TableUtils.dropTable(connectionSource, ExtendedBolus.class, true); - TableUtils.createTableIfNotExists(connectionSource, ExtendedBolus.class); - updateEarliestDataChange(0); - } catch (SQLException e) { - aapsLogger.error("Unhandled exception", e); - } - scheduleExtendedBolusChange(); - } - public void resetProfileSwitch() { try { TableUtils.dropTable(connectionSource, ProfileSwitch.class, true); @@ -507,7 +476,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { openHumansUploader.enqueueTemporaryBasal(old); updateEarliestDataChange(tempBasal.date); - scheduleTemporaryBasalChange(); +// scheduleTemporaryBasalChange(); return false; } @@ -516,7 +485,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { openHumansUploader.enqueueTemporaryBasal(tempBasal); aapsLogger.debug(LTag.DATABASE, "TEMPBASAL: New record from: " + Source.getString(tempBasal.source) + " " + tempBasal.toString()); updateEarliestDataChange(tempBasal.date); - scheduleTemporaryBasalChange(); +// scheduleTemporaryBasalChange(); return true; } if (tempBasal.source == Source.NIGHTSCOUT) { @@ -535,7 +504,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { aapsLogger.debug(LTag.DATABASE, "TEMPBASAL: Updating record by date from: " + Source.getString(tempBasal.source) + " " + old.toString()); updateEarliestDataChange(oldDate); updateEarliestDataChange(old.date); - scheduleTemporaryBasalChange(); +// scheduleTemporaryBasalChange(); return true; } return false; @@ -558,7 +527,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { aapsLogger.debug(LTag.DATABASE, "TEMPBASAL: Updating record by _id from: " + Source.getString(tempBasal.source) + " " + old.toString()); updateEarliestDataChange(oldDate); updateEarliestDataChange(old.date); - scheduleTemporaryBasalChange(); +// scheduleTemporaryBasalChange(); return true; } } @@ -567,7 +536,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { openHumansUploader.enqueueTemporaryBasal(tempBasal); aapsLogger.debug(LTag.DATABASE, "TEMPBASAL: New record from: " + Source.getString(tempBasal.source) + " " + tempBasal.toString()); updateEarliestDataChange(tempBasal.date); - scheduleTemporaryBasalChange(); +// scheduleTemporaryBasalChange(); return true; } if (tempBasal.source == Source.USER) { @@ -575,7 +544,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { openHumansUploader.enqueueTemporaryBasal(tempBasal); aapsLogger.debug(LTag.DATABASE, "TEMPBASAL: New record from: " + Source.getString(tempBasal.source) + " " + tempBasal.toString()); updateEarliestDataChange(tempBasal.date); - scheduleTemporaryBasalChange(); +// scheduleTemporaryBasalChange(); return true; } } catch (SQLException e) { @@ -592,16 +561,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { } catch (SQLException e) { aapsLogger.error("Unhandled exception", e); } - scheduleTemporaryBasalChange(); - } - - public List getAllTemporaryBasals() { - try { - return getDaoTemporaryBasal().queryForAll(); - } catch (SQLException e) { - aapsLogger.error("Unhandled exception", e); - } - return Collections.emptyList(); +// scheduleTemporaryBasalChange(); } public List getTemporaryBasalsDataFromTime(long mills, boolean ascending) { @@ -620,44 +580,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { return new ArrayList(); } - public List getTemporaryBasalsDataFromTime(long from, long to, boolean ascending) { - try { - List tempbasals; - QueryBuilder queryBuilder = getDaoTemporaryBasal().queryBuilder(); - queryBuilder.orderBy("date", ascending); - Where where = queryBuilder.where(); - where.between("date", from, to); - PreparedQuery preparedQuery = queryBuilder.prepare(); - tempbasals = getDaoTemporaryBasal().query(preparedQuery); - return tempbasals; - } catch (SQLException e) { - aapsLogger.error("Unhandled exception", e); - } - return new ArrayList(); - } - - private void scheduleTemporaryBasalChange() { - class PostRunnable implements Runnable { - public void run() { - aapsLogger.debug(LTag.DATABASE, "Firing EventTempBasalChange"); - rxBus.send(new EventReloadTempBasalData()); - rxBus.send(new EventTempBasalChange()); - if (earliestDataChange != null) - rxBus.send(new EventNewHistoryData(earliestDataChange)); - earliestDataChange = null; - scheduledTemBasalsPost = null; - } - } - // prepare task for execution in 1 sec - // cancel waiting task to prevent sending multiple posts - if (scheduledTemBasalsPost != null) - scheduledTemBasalsPost.cancel(false); - Runnable task = new PostRunnable(); - final int sec = 1; - scheduledTemBasalsPost = tempBasalsWorker.schedule(task, sec, TimeUnit.SECONDS); - - } - /* { "_id": "59232e1ddd032d04218dab00", @@ -674,93 +596,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { } */ - public void createTempBasalFromJsonIfNotExists(JSONObject trJson) { - try { - if (trJson.has("originalExtendedAmount")) { // extended bolus uploaded as temp basal - ExtendedBolus extendedBolus = new ExtendedBolus(StaticInjector.Companion.getInstance()) - .source(Source.NIGHTSCOUT) - .date(trJson.getLong("mills")) - .pumpId(trJson.has("pumpId") ? trJson.getLong("pumpId") : 0) - .durationInMinutes(trJson.getInt("duration")) - .insulin(trJson.getDouble("originalExtendedAmount")) - ._id(trJson.getString("_id")); - // if faking found in NS, adapt AAPS to use it too - if (!virtualPumpPlugin.getFakingStatus()) { - virtualPumpPlugin.setFakingStatus(true); - updateEarliestDataChange(0); - scheduleTemporaryBasalChange(); - } - createOrUpdate(extendedBolus); - } else if (trJson.has("isFakedTempBasal")) { // extended bolus end uploaded as temp basal end - ExtendedBolus extendedBolus = new ExtendedBolus(StaticInjector.Companion.getInstance()); - extendedBolus.source = Source.NIGHTSCOUT; - extendedBolus.date = trJson.getLong("mills"); - extendedBolus.pumpId = trJson.has("pumpId") ? trJson.getLong("pumpId") : 0; - extendedBolus.durationInMinutes = 0; - extendedBolus.insulin = 0; - extendedBolus._id = trJson.getString("_id"); - // if faking found in NS, adapt AAPS to use it too - if (!virtualPumpPlugin.getFakingStatus()) { - virtualPumpPlugin.setFakingStatus(true); - updateEarliestDataChange(0); - scheduleTemporaryBasalChange(); - } - createOrUpdate(extendedBolus); - } else { - TemporaryBasal tempBasal = new TemporaryBasal(StaticInjector.Companion.getInstance()) - .date(trJson.getLong("mills")) - .source(Source.NIGHTSCOUT) - .pumpId(trJson.has("pumpId") ? trJson.getLong("pumpId") : 0); - if (trJson.has("duration")) { - tempBasal.durationInMinutes = trJson.getInt("duration"); - } - if (trJson.has("percent")) { - tempBasal.percentRate = trJson.getInt("percent") + 100; - tempBasal.isAbsolute = false; - } - if (trJson.has("absolute")) { - tempBasal.absoluteRate = trJson.getDouble("absolute"); - tempBasal.isAbsolute = true; - } - tempBasal._id = trJson.getString("_id"); - createOrUpdate(tempBasal); - } - } catch (JSONException e) { - aapsLogger.error("Unhandled exception: " + trJson.toString(), e); - } - } - - public void deleteTempBasalById(String _id) { - TemporaryBasal stored = findTempBasalById(_id); - if (stored != null) { - aapsLogger.debug(LTag.DATABASE, "TEMPBASAL: Removing TempBasal record from database: " + stored.toString()); - delete(stored); - updateEarliestDataChange(stored.date); - scheduleTemporaryBasalChange(); - } - } - - public TemporaryBasal findTempBasalById(String _id) { - try { - QueryBuilder queryBuilder = null; - queryBuilder = getDaoTemporaryBasal().queryBuilder(); - Where where = queryBuilder.where(); - where.eq("_id", _id); - PreparedQuery preparedQuery = queryBuilder.prepare(); - List list = getDaoTemporaryBasal().query(preparedQuery); - - if (list.size() != 1) { - return null; - } else { - return list.get(0); - } - } catch (SQLException e) { - aapsLogger.error("Unhandled exception", e); - } - return null; - } - - public TemporaryBasal findTempBasalByPumpId(Long pumpId) { try { QueryBuilder queryBuilder = null; @@ -785,109 +620,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { // ------------ ExtendedBolus handling --------------- - public boolean createOrUpdate(ExtendedBolus extendedBolus) { - try { - aapsLogger.debug(LTag.DATABASE, "EXTENDEDBOLUS: createOrUpdate: " + Source.getString(extendedBolus.source) + " " + extendedBolus.log()); - - ExtendedBolus old; - extendedBolus.date = roundDateToSec(extendedBolus.date); - - if (extendedBolus.source == Source.PUMP) { - // if pumpId == 0 do not check for existing pumpId - // used with pumps without history - // and insight where record as added first without pumpId - // and then is record updated with pumpId - if (extendedBolus.pumpId == 0) { - getDaoExtendedBolus().createOrUpdate(extendedBolus); - openHumansUploader.enqueueExtendedBolus(extendedBolus); - } else { - QueryBuilder queryBuilder = getDaoExtendedBolus().queryBuilder(); - Where where = queryBuilder.where(); - where.eq("pumpId", extendedBolus.pumpId); - PreparedQuery preparedQuery = queryBuilder.prepare(); - List trList = getDaoExtendedBolus().query(preparedQuery); - if (trList.size() > 1) { - aapsLogger.error("EXTENDEDBOLUS: Multiple records found for pumpId: " + extendedBolus.pumpId); - return false; - } - getDaoExtendedBolus().createOrUpdate(extendedBolus); - openHumansUploader.enqueueExtendedBolus(extendedBolus); - } - aapsLogger.debug(LTag.DATABASE, "EXTENDEDBOLUS: New record from: " + Source.getString(extendedBolus.source) + " " + extendedBolus.log()); - updateEarliestDataChange(extendedBolus.date); - scheduleExtendedBolusChange(); - return true; - } - if (extendedBolus.source == Source.NIGHTSCOUT) { - old = getDaoExtendedBolus().queryForId(extendedBolus.date); - if (old != null) { - if (!old.isEqual(extendedBolus)) { - long oldDate = old.date; - getDaoExtendedBolus().delete(old); // need to delete/create because date may change too - old.copyFrom(extendedBolus); - getDaoExtendedBolus().create(old); - aapsLogger.debug(LTag.DATABASE, "EXTENDEDBOLUS: Updating record by date from: " + Source.getString(extendedBolus.source) + " " + old.log()); - openHumansUploader.enqueueExtendedBolus(old); - updateEarliestDataChange(oldDate); - updateEarliestDataChange(old.date); - scheduleExtendedBolusChange(); - return true; - } - return false; - } - // find by NS _id - if (extendedBolus._id != null) { - QueryBuilder queryBuilder = getDaoExtendedBolus().queryBuilder(); - Where where = queryBuilder.where(); - where.eq("_id", extendedBolus._id); - PreparedQuery preparedQuery = queryBuilder.prepare(); - List trList = getDaoExtendedBolus().query(preparedQuery); - if (trList.size() > 0) { - old = trList.get(0); - if (!old.isEqual(extendedBolus)) { - long oldDate = old.date; - getDaoExtendedBolus().delete(old); // need to delete/create because date may change too - old.copyFrom(extendedBolus); - getDaoExtendedBolus().create(old); - aapsLogger.debug(LTag.DATABASE, "EXTENDEDBOLUS: Updating record by _id from: " + Source.getString(extendedBolus.source) + " " + old.log()); - openHumansUploader.enqueueExtendedBolus(old); - updateEarliestDataChange(oldDate); - updateEarliestDataChange(old.date); - scheduleExtendedBolusChange(); - return true; - } - } - } - getDaoExtendedBolus().create(extendedBolus); - aapsLogger.debug(LTag.DATABASE, "EXTENDEDBOLUS: New record from: " + Source.getString(extendedBolus.source) + " " + extendedBolus.log()); - openHumansUploader.enqueueExtendedBolus(extendedBolus); - updateEarliestDataChange(extendedBolus.date); - scheduleExtendedBolusChange(); - return true; - } - if (extendedBolus.source == Source.USER) { - getDaoExtendedBolus().create(extendedBolus); - aapsLogger.debug(LTag.DATABASE, "EXTENDEDBOLUS: New record from: " + Source.getString(extendedBolus.source) + " " + extendedBolus.log()); - openHumansUploader.enqueueExtendedBolus(extendedBolus); - updateEarliestDataChange(extendedBolus.date); - scheduleExtendedBolusChange(); - return true; - } - } catch (SQLException e) { - aapsLogger.error("Unhandled exception", e); - } - return false; - } - - public List getAllExtendedBoluses() { - try { - return getDaoExtendedBolus().queryForAll(); - } catch (SQLException e) { - aapsLogger.error("Unhandled exception", e); - } - return Collections.emptyList(); - } - public ExtendedBolus getExtendedBolusByPumpId(long pumpId) { try { return getDaoExtendedBolus().queryBuilder() @@ -907,69 +639,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { } catch (SQLException e) { aapsLogger.error("Unhandled exception", e); } - scheduleExtendedBolusChange(); - } - - public List getExtendedBolusDataFromTime(long mills, boolean ascending) { - try { - List extendedBoluses; - QueryBuilder queryBuilder = getDaoExtendedBolus().queryBuilder(); - queryBuilder.orderBy("date", ascending); - Where where = queryBuilder.where(); - where.ge("date", mills); - PreparedQuery preparedQuery = queryBuilder.prepare(); - extendedBoluses = getDaoExtendedBolus().query(preparedQuery); - return extendedBoluses; - } catch (SQLException e) { - aapsLogger.error("Unhandled exception", e); - } - return new ArrayList(); - } - - public List getExtendedBolusDataFromTime(long from, long to, boolean ascending) { - try { - List extendedBoluses; - QueryBuilder queryBuilder = getDaoExtendedBolus().queryBuilder(); - queryBuilder.orderBy("date", ascending); - Where where = queryBuilder.where(); - where.between("date", from, to); - PreparedQuery preparedQuery = queryBuilder.prepare(); - extendedBoluses = getDaoExtendedBolus().query(preparedQuery); - return extendedBoluses; - } catch (SQLException e) { - aapsLogger.error("Unhandled exception", e); - } - return new ArrayList(); - } - - public void deleteExtendedBolusById(String _id) { - ExtendedBolus stored = findExtendedBolusById(_id); - if (stored != null) { - aapsLogger.debug(LTag.DATABASE, "EXTENDEDBOLUS: Removing ExtendedBolus record from database: " + stored.toString()); - delete(stored); - updateEarliestDataChange(stored.date); - scheduleExtendedBolusChange(); - } - } - - public ExtendedBolus findExtendedBolusById(String _id) { - try { - QueryBuilder queryBuilder = null; - queryBuilder = getDaoExtendedBolus().queryBuilder(); - Where where = queryBuilder.where(); - where.eq("_id", _id); - PreparedQuery preparedQuery = queryBuilder.prepare(); - List list = getDaoExtendedBolus().query(preparedQuery); - - if (list.size() == 1) { - return list.get(0); - } else { - return null; - } - } catch (SQLException e) { - aapsLogger.error("Unhandled exception", e); - } - return null; +// scheduleExtendedBolusChange(); } /* @@ -989,33 +659,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { } */ - public void createExtendedBolusFromJsonIfNotExists(JSONObject json) { - ExtendedBolus extendedBolus = ExtendedBolus.createFromJson(StaticInjector.Companion.getInstance(), json); - if (extendedBolus != null) - createOrUpdate(extendedBolus); - } - - private void scheduleExtendedBolusChange() { - class PostRunnable implements Runnable { - public void run() { - aapsLogger.debug(LTag.DATABASE, "Firing EventExtendedBolusChange"); - rxBus.send(new EventReloadTreatmentData(new EventExtendedBolusChange())); - if (earliestDataChange != null) - rxBus.send(new EventNewHistoryData(earliestDataChange)); - earliestDataChange = null; - scheduledExtendedBolusPost = null; - } - } - // prepare task for execution in 1 sec - // cancel waiting task to prevent sending multiple posts - if (scheduledExtendedBolusPost != null) - scheduledExtendedBolusPost.cancel(false); - Runnable task = new PostRunnable(); - final int sec = 1; - scheduledExtendedBolusPost = extendedBolusWorker.schedule(task, sec, TimeUnit.SECONDS); - - } - // ---------------- ProfileSwitch handling --------------- public List getProfileSwitchData(long from, boolean ascending) { diff --git a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelperProvider.java b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelperProvider.java index 3b3b275506..bdea090609 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelperProvider.java +++ b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelperProvider.java @@ -16,6 +16,7 @@ import javax.inject.Singleton; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.interfaces.DatabaseHelperInterface; +@Deprecated @Singleton public class DatabaseHelperProvider implements DatabaseHelperInterface { @@ -82,6 +83,7 @@ public class DatabaseHelperProvider implements DatabaseHelperInterface { return MainApp.Companion.getDbHelper().findTempBasalByPumpId(id); } + @Deprecated @NonNull @Override public List getTemporaryBasalsDataFromTime(long mills, boolean ascending) { return MainApp.Companion.getDbHelper().getTemporaryBasalsDataFromTime(mills, ascending); } @@ -134,42 +136,14 @@ public class DatabaseHelperProvider implements DatabaseHelperInterface { return MainApp.Companion.getDbHelper().getPumpStoppedEvent(pumpSerial, before); } - @Override public boolean createOrUpdate(@NonNull ExtendedBolus extendedBolus) { - return MainApp.Companion.getDbHelper().createOrUpdate(extendedBolus); - } - @Override public void createOrUpdate(@NonNull ProfileSwitch profileSwitch) { MainApp.Companion.getDbHelper().createOrUpdate(profileSwitch); } - @Override public void delete(@NonNull TemporaryBasal tempBasal) { - MainApp.Companion.getDbHelper().delete(tempBasal); - } - - @NonNull @Override public List getExtendedBolusDataFromTime(long mills, boolean ascending) { - return MainApp.Companion.getDbHelper().getExtendedBolusDataFromTime(mills, ascending); - } - - @Override public void deleteTempBasalById(@NonNull String _id) { - MainApp.Companion.getDbHelper().deleteTempBasalById(_id); - } - - @Override public void deleteExtendedBolusById(@NonNull String _id) { - MainApp.Companion.getDbHelper().deleteExtendedBolusById(_id); - } - @Override public void deleteProfileSwitchById(@NonNull String _id) { MainApp.Companion.getDbHelper().deleteProfileSwitchById(_id); } - @Override public void createTempBasalFromJsonIfNotExists(@NonNull JSONObject json) { - MainApp.Companion.getDbHelper().createTempBasalFromJsonIfNotExists(json); - } - - @Override public void createExtendedBolusFromJsonIfNotExists(@NonNull JSONObject json) { - MainApp.Companion.getDbHelper().createExtendedBolusFromJsonIfNotExists(json); - } - @Override public void createProfileSwitchFromJsonIfNotExists(@NonNull JSONObject trJson) { MainApp.Companion.getDbHelper().createProfileSwitchFromJsonIfNotExists(trJson); } @@ -194,10 +168,6 @@ public class DatabaseHelperProvider implements DatabaseHelperInterface { return MainApp.Companion.getDbHelper().getProfileSwitchEventsFromTime(mills, ascending); } - @NonNull @Override public List getAllExtendedBoluses() { - return MainApp.Companion.getDbHelper().getAllExtendedBoluses(); - } - @NonNull @Override public List getAllProfileSwitches() { return MainApp.Companion.getDbHelper().getAllProfileSwitches(); } @@ -206,10 +176,6 @@ public class DatabaseHelperProvider implements DatabaseHelperInterface { return MainApp.Companion.getDbHelper().getAllTDDs(); } - @NonNull @Override public List getAllTemporaryBasals() { - return MainApp.Companion.getDbHelper().getAllTemporaryBasals(); - } - @NonNull @Override public List getAllOHQueueItems(long maxEntries) { return MainApp.Companion.getDbHelper().getAllOHQueueItems(maxEntries); } diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/CarbsDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/CarbsDialog.kt index ded8ac184d..df674b44af 100644 --- a/app/src/main/java/info/nightscout/androidaps/dialogs/CarbsDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/dialogs/CarbsDialog.kt @@ -31,7 +31,7 @@ import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.queue.CommandQueue import info.nightscout.androidaps.utils.* import info.nightscout.androidaps.utils.alertDialogs.OKDialog -import info.nightscout.androidaps.utils.extensions.formatColor +import info.nightscout.androidaps.extensions.formatColor import info.nightscout.androidaps.utils.resources.ResourceHelper import io.reactivex.disposables.CompositeDisposable import io.reactivex.rxkotlin.plusAssign diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/CareDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/CareDialog.kt index d566359e36..4c88beacb4 100644 --- a/app/src/main/java/info/nightscout/androidaps/dialogs/CareDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/dialogs/CareDialog.kt @@ -28,7 +28,7 @@ import info.nightscout.androidaps.utils.HtmlHelper import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.Translator import info.nightscout.androidaps.utils.alertDialogs.OKDialog -import info.nightscout.androidaps.utils.extensions.fromConstant +import info.nightscout.androidaps.extensions.fromConstant import info.nightscout.androidaps.utils.resources.ResourceHelper import io.reactivex.disposables.CompositeDisposable import io.reactivex.rxkotlin.plusAssign diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/ExtendedBolusDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/ExtendedBolusDialog.kt index 4116091eed..8858fcb6ca 100644 --- a/app/src/main/java/info/nightscout/androidaps/dialogs/ExtendedBolusDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/dialogs/ExtendedBolusDialog.kt @@ -19,7 +19,7 @@ import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.utils.HtmlHelper import info.nightscout.androidaps.utils.SafeParse import info.nightscout.androidaps.utils.alertDialogs.OKDialog -import info.nightscout.androidaps.utils.extensions.formatColor +import info.nightscout.androidaps.extensions.formatColor import info.nightscout.androidaps.utils.resources.ResourceHelper import java.text.DecimalFormat import java.util.* diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/FillDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/FillDialog.kt index dc45e32bbb..b6a209ca6d 100644 --- a/app/src/main/java/info/nightscout/androidaps/dialogs/FillDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/dialogs/FillDialog.kt @@ -27,7 +27,7 @@ import info.nightscout.androidaps.utils.DecimalFormatter import info.nightscout.androidaps.utils.HtmlHelper import info.nightscout.androidaps.utils.SafeParse import info.nightscout.androidaps.utils.alertDialogs.OKDialog -import info.nightscout.androidaps.utils.extensions.formatColor +import info.nightscout.androidaps.extensions.formatColor import info.nightscout.androidaps.utils.resources.ResourceHelper import io.reactivex.disposables.CompositeDisposable import io.reactivex.rxkotlin.plusAssign diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/InsulinDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/InsulinDialog.kt index c117f39e4a..beb4c54a31 100644 --- a/app/src/main/java/info/nightscout/androidaps/dialogs/InsulinDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/dialogs/InsulinDialog.kt @@ -28,13 +28,12 @@ import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker -import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.utils.* import info.nightscout.androidaps.utils.alertDialogs.OKDialog -import info.nightscout.androidaps.utils.extensions.formatColor +import info.nightscout.androidaps.extensions.formatColor import info.nightscout.androidaps.utils.extensions.toSignedString -import info.nightscout.androidaps.utils.extensions.toVisibility +import info.nightscout.androidaps.extensions.toVisibility import info.nightscout.androidaps.utils.resources.ResourceHelper import io.reactivex.disposables.CompositeDisposable import io.reactivex.rxkotlin.plusAssign @@ -57,7 +56,6 @@ class InsulinDialog : DialogFragmentWithDate() { @Inject lateinit var repository: AppRepository @Inject lateinit var config: Config @Inject lateinit var uel: UserEntryLogger - @Inject lateinit var nsUpload: NSUpload companion object { diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/LoopDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/LoopDialog.kt index 9b10142c8c..2820175a72 100644 --- a/app/src/main/java/info/nightscout/androidaps/dialogs/LoopDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/dialogs/LoopDialog.kt @@ -27,7 +27,7 @@ import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.ToastUtils import info.nightscout.androidaps.utils.alertDialogs.OKDialog -import info.nightscout.androidaps.utils.extensions.toVisibility +import info.nightscout.androidaps.extensions.toVisibility import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.sharedPreferences.SP import javax.inject.Inject diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/TempBasalDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/TempBasalDialog.kt index 287a0067b2..410833e519 100644 --- a/app/src/main/java/info/nightscout/androidaps/dialogs/TempBasalDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/dialogs/TempBasalDialog.kt @@ -17,7 +17,7 @@ import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.utils.HtmlHelper import info.nightscout.androidaps.utils.SafeParse import info.nightscout.androidaps.utils.alertDialogs.OKDialog -import info.nightscout.androidaps.utils.extensions.formatColor +import info.nightscout.androidaps.extensions.formatColor import info.nightscout.androidaps.utils.resources.ResourceHelper import java.text.DecimalFormat import java.util.* diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/TreatmentDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/TreatmentDialog.kt index 184bd9e4b7..1f0675bbb6 100644 --- a/app/src/main/java/info/nightscout/androidaps/dialogs/TreatmentDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/dialogs/TreatmentDialog.kt @@ -23,14 +23,13 @@ import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker -import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.utils.DecimalFormatter import info.nightscout.androidaps.utils.HtmlHelper import info.nightscout.androidaps.utils.SafeParse import info.nightscout.androidaps.utils.ToastUtils import info.nightscout.androidaps.utils.alertDialogs.OKDialog -import info.nightscout.androidaps.utils.extensions.formatColor +import info.nightscout.androidaps.extensions.formatColor import info.nightscout.androidaps.utils.resources.ResourceHelper import io.reactivex.disposables.CompositeDisposable import io.reactivex.rxkotlin.plusAssign @@ -48,7 +47,6 @@ class TreatmentDialog : DialogFragmentWithDate() { @Inject lateinit var ctx: Context @Inject lateinit var config: Config @Inject lateinit var uel: UserEntryLogger - @Inject lateinit var nsUpload: NSUpload @Inject lateinit var repository: AppRepository private val disposable = CompositeDisposable() diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/WizardDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/WizardDialog.kt index 0d69487179..39dc0165d9 100644 --- a/app/src/main/java/info/nightscout/androidaps/dialogs/WizardDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/dialogs/WizardDialog.kt @@ -27,7 +27,6 @@ import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.interfaces.IobCobCalculator import info.nightscout.androidaps.interfaces.ProfileFunction -import info.nightscout.androidaps.interfaces.TreatmentsInterface import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.bus.RxBusWrapper @@ -37,8 +36,8 @@ import info.nightscout.androidaps.utils.DecimalFormatter import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.SafeParse import info.nightscout.androidaps.utils.ToastUtils -import info.nightscout.androidaps.utils.extensions.toVisibility -import info.nightscout.androidaps.utils.extensions.valueToUnits +import info.nightscout.androidaps.extensions.toVisibility +import info.nightscout.androidaps.extensions.valueToUnits import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.sharedPreferences.SP @@ -64,7 +63,6 @@ class WizardDialog : DaggerDialogFragment() { @Inject lateinit var activePlugin: ActivePluginProvider @Inject lateinit var iobCobCalculator: IobCobCalculator @Inject lateinit var repository: AppRepository - @Inject lateinit var treatmentsPlugin: TreatmentsInterface @Inject lateinit var dateUtil: DateUtil private var wizard: BolusWizard? = null @@ -274,7 +272,7 @@ class WizardDialog : DaggerDialogFragment() { // IOB calculation val bolusIob = iobCobCalculator.calculateIobFromBolus().round() - val basalIob = treatmentsPlugin.lastCalculationTempBasals.round() + val basalIob = iobCobCalculator.calculateIobFromTempBasalsIncludingConvertedExtended().round() binding.bolusiobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, -bolusIob.iob) binding.basaliobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, -basalIob.basaliob) diff --git a/app/src/main/java/info/nightscout/androidaps/historyBrowser/HistoryBrowseActivity.kt b/app/src/main/java/info/nightscout/androidaps/historyBrowser/HistoryBrowseActivity.kt index 8ee346247e..97b157f416 100644 --- a/app/src/main/java/info/nightscout/androidaps/historyBrowser/HistoryBrowseActivity.kt +++ b/app/src/main/java/info/nightscout/androidaps/historyBrowser/HistoryBrowseActivity.kt @@ -31,7 +31,7 @@ import info.nightscout.androidaps.utils.DefaultValueHelper import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.buildHelper.BuildHelper -import info.nightscout.androidaps.utils.extensions.toVisibility +import info.nightscout.androidaps.extensions.toVisibility import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.sharedPreferences.SP import io.reactivex.disposables.CompositeDisposable diff --git a/app/src/main/java/info/nightscout/androidaps/historyBrowser/IobCobCalculatorPluginHistory.kt b/app/src/main/java/info/nightscout/androidaps/historyBrowser/IobCobCalculatorPluginHistory.kt index 8dc1ebfb32..65df3b28e8 100644 --- a/app/src/main/java/info/nightscout/androidaps/historyBrowser/IobCobCalculatorPluginHistory.kt +++ b/app/src/main/java/info/nightscout/androidaps/historyBrowser/IobCobCalculatorPluginHistory.kt @@ -28,7 +28,6 @@ class IobCobCalculatorPluginHistory @Inject constructor( resourceHelper: ResourceHelper, profileFunction: ProfileFunction, activePlugin: ActivePluginProvider, - treatmentsPluginHistory: TreatmentsPluginHistory, sensitivityOref1Plugin: SensitivityOref1Plugin, sensitivityAAPSPlugin: SensitivityAAPSPlugin, sensitivityWeightedAveragePlugin: SensitivityWeightedAveragePlugin, @@ -36,7 +35,7 @@ class IobCobCalculatorPluginHistory @Inject constructor( dateUtil: DateUtil, repository: AppRepository ) : IobCobCalculatorPlugin(injector, aapsLogger, aapsSchedulers, rxBus, sp, resourceHelper, profileFunction, - activePlugin, treatmentsPluginHistory, sensitivityOref1Plugin, sensitivityAAPSPlugin, sensitivityWeightedAveragePlugin, fabricPrivacy, dateUtil, repository) { + activePlugin, sensitivityOref1Plugin, sensitivityAAPSPlugin, sensitivityWeightedAveragePlugin, fabricPrivacy, dateUtil, repository) { override fun onStart() { // do not attach to rxbus } diff --git a/app/src/main/java/info/nightscout/androidaps/historyBrowser/TreatmentsPluginHistory.kt b/app/src/main/java/info/nightscout/androidaps/historyBrowser/TreatmentsPluginHistory.kt index 4b003538b3..1fb1652bfb 100644 --- a/app/src/main/java/info/nightscout/androidaps/historyBrowser/TreatmentsPluginHistory.kt +++ b/app/src/main/java/info/nightscout/androidaps/historyBrowser/TreatmentsPluginHistory.kt @@ -6,7 +6,6 @@ import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.DatabaseHelperInterface import info.nightscout.androidaps.interfaces.ProfileFunction -import info.nightscout.androidaps.interfaces.UploadQueueInterface import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.general.nsclient.NSUpload @@ -34,10 +33,9 @@ class TreatmentsPluginHistory @Inject constructor( nsUpload: NSUpload, fabricPrivacy: FabricPrivacy, dateUtil: DateUtil, - uploadQueue: UploadQueueInterface, databaseHelper: DatabaseHelperInterface, repository: AppRepository -) : TreatmentsPlugin(injector, aapsLogger, rxBus, aapsSchedulers, resourceHelper, context, sp, profileFunction, activePlugin, nsUpload, fabricPrivacy, dateUtil, uploadQueue, databaseHelper, repository) { +) : TreatmentsPlugin(injector, aapsLogger, rxBus, aapsSchedulers, resourceHelper, context, sp, profileFunction, activePlugin, nsUpload, fabricPrivacy, dateUtil, databaseHelper, repository) { init { onStart() diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.kt index 4b983f3771..9ae1108de3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.kt @@ -38,9 +38,7 @@ import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotifi import info.nightscout.androidaps.plugins.general.overview.notifications.Notification import info.nightscout.androidaps.plugins.general.wear.events.EventWearConfirmAction import info.nightscout.androidaps.plugins.general.wear.events.EventWearInitiateAction -import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin -import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.queue.commands.Command import info.nightscout.androidaps.receivers.ReceiverStatusStore @@ -48,7 +46,10 @@ import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.HardLimits import info.nightscout.androidaps.utils.T -import info.nightscout.androidaps.utils.extensions.buildDeviceStatus +import info.nightscout.androidaps.extensions.buildDeviceStatus +import info.nightscout.androidaps.extensions.convertedToAbsolute +import info.nightscout.androidaps.extensions.convertedToPercent +import info.nightscout.androidaps.extensions.plannedRemainingMinutes import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.sharedPreferences.SP @@ -72,9 +73,8 @@ open class LoopPlugin @Inject constructor( private val context: Context, private val commandQueue: CommandQueueProvider, private val activePlugin: ActivePluginProvider, - private val treatmentsPlugin: TreatmentsPlugin, private val virtualPumpPlugin: VirtualPumpPlugin, - private val iobCobCalculatorPlugin: IobCobCalculatorPlugin, + private val iobCobCalculator: IobCobCalculator, private val receiverStatusStore: ReceiverStatusStore, private val fabricPrivacy: FabricPrivacy, private val dateUtil: DateUtil, @@ -119,7 +119,7 @@ open class LoopPlugin @Inject constructor( .subscribe({ event: EventAutosensCalculationFinished -> // Autosens calculation not triggered by a new BG if (event.cause !is EventNewBG) return@subscribe - val glucoseValue = iobCobCalculatorPlugin.actualBg() ?: return@subscribe + val glucoseValue = iobCobCalculator.actualBg() ?: return@subscribe // BG outdated // already looped with that value if (glucoseValue.timestamp <= lastBgTriggeredRun) return@subscribe @@ -316,7 +316,7 @@ open class LoopPlugin @Inject constructor( lastRun.lastTBRRequest = 0 lastRun.lastSMBEnact = 0 lastRun.lastSMBRequest = 0 - buildDeviceStatus(dateUtil, this, iobCobCalculatorPlugin, profileFunction, + buildDeviceStatus(dateUtil, this, iobCobCalculator, profileFunction, activePlugin.activePump, receiverStatusStore, runningConfiguration, BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION)?.also { repository.insert(it) @@ -504,7 +504,7 @@ open class LoopPlugin @Inject constructor( lastRun.lastTBRRequest = lastRun.lastAPSRun lastRun.lastTBREnact = DateUtil.now() lastRun.lastOpenModeAccept = DateUtil.now() - buildDeviceStatus(dateUtil, this@LoopPlugin, iobCobCalculatorPlugin, profileFunction, + buildDeviceStatus(dateUtil, this@LoopPlugin, iobCobCalculator, profileFunction, activePlugin.activePump, receiverStatusStore, runningConfiguration, BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION)?.also { repository.insert(it) @@ -541,7 +541,7 @@ open class LoopPlugin @Inject constructor( } aapsLogger.debug(LTag.APS, "applyAPSRequest: $request") val now = System.currentTimeMillis() - val activeTemp = treatmentsPlugin.getTempBasalFromHistory(now) + val activeTemp = iobCobCalculator.getTempBasalIncludingConvertedExtended(now) if (request.usePercent && allowPercentage()) { if (request.percent == 100 && request.duration == 0) { if (activeTemp != null) { @@ -552,7 +552,7 @@ open class LoopPlugin @Inject constructor( callback?.result(PumpEnactResult(injector).percent(request.percent).duration(0) .enacted(false).success(true).comment(R.string.basal_set_correctly))?.run() } - } else if (activeTemp != null && activeTemp.plannedRemainingMinutes > 5 && request.duration - activeTemp.plannedRemainingMinutes < 30 && request.percent == activeTemp.percentRate) { + } else if (activeTemp != null && activeTemp.plannedRemainingMinutes > 5 && request.duration - activeTemp.plannedRemainingMinutes < 30 && request.percent == activeTemp.convertedToPercent(now, profile)) { aapsLogger.debug(LTag.APS, "applyAPSRequest: Temp basal set correctly") callback?.result(PumpEnactResult(injector).percent(request.percent) .enacted(false).success(true).duration(activeTemp.plannedRemainingMinutes) @@ -571,9 +571,9 @@ open class LoopPlugin @Inject constructor( callback?.result(PumpEnactResult(injector).absolute(request.rate).duration(0) .enacted(false).success(true).comment(R.string.basal_set_correctly))?.run() } - } else if (activeTemp != null && activeTemp.plannedRemainingMinutes > 5 && request.duration - activeTemp.plannedRemainingMinutes < 30 && abs(request.rate - activeTemp.tempBasalConvertedToAbsolute(now, profile)) < pump.pumpDescription.basalStep) { + } else if (activeTemp != null && activeTemp.plannedRemainingMinutes > 5 && request.duration - activeTemp.plannedRemainingMinutes < 30 && abs(request.rate - activeTemp.convertedToAbsolute(now, profile)) < pump.pumpDescription.basalStep) { aapsLogger.debug(LTag.APS, "applyAPSRequest: Temp basal set correctly") - callback?.result(PumpEnactResult(injector).absolute(activeTemp.tempBasalConvertedToAbsolute(now, profile)) + callback?.result(PumpEnactResult(injector).absolute(activeTemp.convertedToAbsolute(now, profile)) .enacted(false).success(true).duration(activeTemp.plannedRemainingMinutes) .comment(R.string.let_temp_basal_run))?.run() } else { @@ -643,7 +643,7 @@ open class LoopPlugin @Inject constructor( } }) } - if (pump.pumpDescription.isExtendedBolusCapable && treatmentsPlugin.isInHistoryExtendedBolusInProgress) { + if (pump.pumpDescription.isExtendedBolusCapable && iobCobCalculator.getExtendedBolus(dateUtil._now()) != null) { commandQueue.cancelExtended(object : Callback() { override fun run() { if (!result.success) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalAdapterAMAJS.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalAdapterAMAJS.kt index 1b186bd887..7ab62fe0e7 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalAdapterAMAJS.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalAdapterAMAJS.kt @@ -6,6 +6,7 @@ import info.nightscout.androidaps.R import info.nightscout.androidaps.data.IobTotal import info.nightscout.androidaps.data.MealData import info.nightscout.androidaps.data.Profile +import info.nightscout.androidaps.interfaces.IobCobCalculator import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag @@ -16,7 +17,9 @@ import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.general.openhumans.OpenHumansUploader import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin -import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin +import info.nightscout.androidaps.extensions.convertedToAbsolute +import info.nightscout.androidaps.extensions.getPassedDurationToTimeInMinutes +import info.nightscout.androidaps.extensions.plannedRemainingMinutes import info.nightscout.androidaps.utils.sharedPreferences.SP import org.json.JSONArray import org.json.JSONException @@ -37,7 +40,7 @@ class DetermineBasalAdapterAMAJS internal constructor(scriptReader: ScriptReader @Inject lateinit var constraintChecker: ConstraintChecker @Inject lateinit var sp: SP @Inject lateinit var profileFunction: ProfileFunction - @Inject lateinit var treatmentsPlugin: TreatmentsPlugin + @Inject lateinit var iobCobCalculator: IobCobCalculator @Inject lateinit var openHumansUploader: OpenHumansUploader private val mScriptReader: ScriptReader @@ -183,17 +186,14 @@ class DetermineBasalAdapterAMAJS internal constructor(scriptReader: ScriptReader this.profile.put("out_units", "mmol/L") } val now = System.currentTimeMillis() - val tb = treatmentsPlugin.getTempBasalFromHistory(now) + val tb = iobCobCalculator.getTempBasalIncludingConvertedExtended(now) currentTemp = JSONObject() currentTemp.put("temp", "absolute") currentTemp.put("duration", tb?.plannedRemainingMinutes ?: 0) - currentTemp.put("rate", tb?.tempBasalConvertedToAbsolute(now, profile) ?: 0.0) - + currentTemp.put("rate", tb?.convertedToAbsolute(now, profile) ?: 0.0) // as we have non default temps longer than 30 minutes - val tempBasal = treatmentsPlugin.getTempBasalFromHistory(System.currentTimeMillis()) - if (tempBasal != null) { - currentTemp.put("minutesrunning", tempBasal.realDuration) - } + if (tb != null) currentTemp.put("minutesrunning", tb.getPassedDurationToTimeInMinutes(now)) + iobData = IobCobCalculatorPlugin.convertToJSONArray(iobArray) this.glucoseStatus = JSONObject() this.glucoseStatus.put("glucose", glucoseStatus.glucose) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAPlugin.kt index e0e3ed1f71..9a4385ee1b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAPlugin.kt @@ -21,7 +21,7 @@ import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.HardLimits import info.nightscout.androidaps.utils.Profiler import info.nightscout.androidaps.utils.Round -import info.nightscout.androidaps.utils.extensions.target +import info.nightscout.androidaps.extensions.target import info.nightscout.androidaps.utils.resources.ResourceHelper import org.json.JSONException import javax.inject.Inject @@ -37,7 +37,6 @@ open class OpenAPSAMAPlugin @Inject constructor( private val profileFunction: ProfileFunction, private val context: Context, private val activePlugin: ActivePluginProvider, - private val treatmentsPlugin: TreatmentsInterface, private val iobCobCalculator: IobCobCalculator, private val hardLimits: HardLimits, private val profiler: Profiler, @@ -161,7 +160,7 @@ open class OpenAPSAMAPlugin @Inject constructor( lastAPSResult = null lastAPSRun = 0 } else { - if (determineBasalResultAMA.rate == 0.0 && determineBasalResultAMA.duration == 0 && !treatmentsPlugin.isTempBasalInProgress) determineBasalResultAMA.tempBasalRequested = false + if (determineBasalResultAMA.rate == 0.0 && determineBasalResultAMA.duration == 0 && iobCobCalculator.getTempBasalIncludingConvertedExtended(dateUtil._now()) == null) determineBasalResultAMA.tempBasalRequested = false determineBasalResultAMA.iob = iobArray[0] val now = System.currentTimeMillis() determineBasalResultAMA.json?.put("timestamp", DateUtil.toISOString(now)) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.kt index efc47a50cb..fbaddd7770 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.kt @@ -7,6 +7,7 @@ import info.nightscout.androidaps.data.IobTotal import info.nightscout.androidaps.data.MealData import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.interfaces.ActivePluginProvider +import info.nightscout.androidaps.interfaces.IobCobCalculator import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag @@ -16,8 +17,10 @@ import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.general.openhumans.OpenHumansUploader import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin -import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.utils.SafeParse +import info.nightscout.androidaps.extensions.convertedToAbsolute +import info.nightscout.androidaps.extensions.getPassedDurationToTimeInMinutes +import info.nightscout.androidaps.extensions.plannedRemainingMinutes import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.sharedPreferences.SP import org.json.JSONArray @@ -37,7 +40,7 @@ class DetermineBasalAdapterSMBJS internal constructor(private val scriptReader: @Inject lateinit var sp: SP @Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var profileFunction: ProfileFunction - @Inject lateinit var treatmentsPlugin: TreatmentsPlugin + @Inject lateinit var iobCobCalculator: IobCobCalculator @Inject lateinit var activePluginProvider: ActivePluginProvider @Inject lateinit var openHumansUploader: OpenHumansUploader @@ -227,16 +230,13 @@ class DetermineBasalAdapterSMBJS internal constructor(private val scriptReader: this.profile.put("out_units", "mmol/L") } val now = System.currentTimeMillis() - val tb = treatmentsPlugin.getTempBasalFromHistory(now) + val tb = iobCobCalculator.getTempBasalIncludingConvertedExtended(now) currentTemp.put("temp", "absolute") currentTemp.put("duration", tb?.plannedRemainingMinutes ?: 0) - currentTemp.put("rate", tb?.tempBasalConvertedToAbsolute(now, profile) ?: 0.0) - + currentTemp.put("rate", tb?.convertedToAbsolute(now, profile) ?: 0.0) // as we have non default temps longer than 30 mintues - val tempBasal = treatmentsPlugin.getTempBasalFromHistory(System.currentTimeMillis()) - if (tempBasal != null) { - currentTemp.put("minutesrunning", tempBasal.realDuration) - } + if (tb != null) currentTemp.put("minutesrunning", tb.getPassedDurationToTimeInMinutes(now)) + iobData = IobCobCalculatorPlugin.convertToJSONArray(iobArray) mGlucoseStatus.put("glucose", glucoseStatus.glucose) mGlucoseStatus.put("noise", glucoseStatus.noise) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.kt index fe8314dcb5..15da422113 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.kt @@ -22,7 +22,7 @@ import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.HardLimits import info.nightscout.androidaps.utils.Profiler import info.nightscout.androidaps.utils.Round -import info.nightscout.androidaps.utils.extensions.target +import info.nightscout.androidaps.extensions.target import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.sharedPreferences.SP import javax.inject.Inject @@ -38,7 +38,6 @@ open class OpenAPSSMBPlugin @Inject constructor( private val profileFunction: ProfileFunction, private val context: Context, private val activePlugin: ActivePluginProvider, - private val treatmentsPlugin: TreatmentsInterface, private val iobCobCalculator: IobCobCalculator, private val hardLimits: HardLimits, private val profiler: Profiler, @@ -188,7 +187,7 @@ open class OpenAPSSMBPlugin @Inject constructor( } else { // TODO still needed with oref1? // Fix bug determine basal - if (determineBasalResultSMB.rate == 0.0 && determineBasalResultSMB.duration == 0 && !treatmentsPlugin.isTempBasalInProgress) determineBasalResultSMB.tempBasalRequested = false + if (determineBasalResultSMB.rate == 0.0 && determineBasalResultSMB.duration == 0 && iobCobCalculator.getTempBasalIncludingConvertedExtended(dateUtil._now()) == null) determineBasalResultSMB.tempBasalRequested = false determineBasalResultSMB.iob = iobArray[0] determineBasalResultSMB.json?.put("timestamp", DateUtil.toISOString(now)) determineBasalResultSMB.inputConstraints = inputConstraints diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ConfigBuilderFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ConfigBuilderFragment.kt index 8a19808833..207384ac30 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ConfigBuilderFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ConfigBuilderFragment.kt @@ -19,7 +19,7 @@ import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.configBuilder.events.EventConfigBuilderUpdateGui import info.nightscout.androidaps.utils.FabricPrivacy import io.reactivex.rxkotlin.plusAssign -import info.nightscout.androidaps.utils.extensions.toVisibility +import info.nightscout.androidaps.extensions.toVisibility import info.nightscout.androidaps.utils.protection.ProtectionCheck import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPlugin.kt index c5d778eb4b..dbd3cc8ea6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPlugin.kt @@ -13,6 +13,7 @@ import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification import info.nightscout.androidaps.plugins.general.overview.notifications.Notification import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin +import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DecimalFormatter import info.nightscout.androidaps.utils.HardLimits import info.nightscout.androidaps.utils.Round @@ -37,8 +38,9 @@ class SafetyPlugin @Inject constructor( private val activePlugin: ActivePluginProvider, private val hardLimits: HardLimits, private val buildHelper: BuildHelper, - private val treatmentsPlugin: TreatmentsInterface, - private val config: Config + private val iobCobCalculator: IobCobCalculator, + private val config: Config, + private val dateUtil: DateUtil ) : PluginBase(PluginDescription() .mainType(PluginType.CONSTRAINTS) .neverVisible(true) @@ -68,7 +70,7 @@ class SafetyPlugin @Inject constructor( value[aapsLogger, false, resourceHelper.gs(R.string.closed_loop_disabled_on_dev_branch)] = this } val pump = activePlugin.activePump - if (!pump.isFakingTempsByExtendedBoluses && treatmentsPlugin.isInHistoryExtendedBolusInProgress) { + if (!pump.isFakingTempsByExtendedBoluses && iobCobCalculator.getExtendedBolus(dateUtil._now()) != null) { value[aapsLogger, false, resourceHelper.gs(R.string.closed_loop_disabled_with_eb)] = this } return value diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.kt index 6f735ba04b..24d19e3bae 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.kt @@ -16,12 +16,15 @@ import info.nightscout.androidaps.Constants import info.nightscout.androidaps.R import info.nightscout.androidaps.activities.ErrorHelperActivity import info.nightscout.androidaps.activities.TDDStatsActivity +import info.nightscout.androidaps.database.AppRepository +import info.nightscout.androidaps.database.ValueWrapper import info.nightscout.androidaps.database.entities.UserEntry.* import info.nightscout.androidaps.dialogs.* import info.nightscout.androidaps.events.* import info.nightscout.androidaps.historyBrowser.HistoryBrowseActivity import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.CommandQueueProvider +import info.nightscout.androidaps.interfaces.IobCobCalculator import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.UserEntryLogger @@ -31,10 +34,13 @@ import info.nightscout.androidaps.plugins.general.overview.StatusLightHandler import info.nightscout.androidaps.plugins.pump.omnipod.eros.OmnipodErosPumpPlugin import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.skins.SkinProvider +import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.buildHelper.BuildHelper -import info.nightscout.androidaps.utils.extensions.toVisibility +import info.nightscout.androidaps.extensions.toStringMedium +import info.nightscout.androidaps.extensions.toStringShort +import info.nightscout.androidaps.extensions.toVisibility import info.nightscout.androidaps.utils.protection.ProtectionCheck import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers @@ -52,18 +58,21 @@ class ActionsFragment : DaggerFragment() { @Inject lateinit var aapsSchedulers: AapsSchedulers @Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var sp: SP + @Inject lateinit var dateUtil: DateUtil @Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var ctx: Context @Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var statusLightHandler: StatusLightHandler @Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var activePlugin: ActivePluginProvider + @Inject lateinit var iobCobCalculator: IobCobCalculator @Inject lateinit var commandQueue: CommandQueueProvider @Inject lateinit var buildHelper: BuildHelper @Inject lateinit var protectionCheck: ProtectionCheck @Inject lateinit var skinProvider: SkinProvider @Inject lateinit var config: Config @Inject lateinit var uel: UserEntryLogger + @Inject lateinit var repository: AppRepository private var disposable: CompositeDisposable = CompositeDisposable() @@ -154,7 +163,7 @@ class ActionsFragment : DaggerFragment() { } } extendedBolusCancel?.setOnClickListener { - if (activePlugin.activeTreatments.isInHistoryExtendedBolusInProgress) { + if (iobCobCalculator.getExtendedBolus(dateUtil._now()) != null) { uel.log(Action.CANCEL_EXTENDED_BOLUS) commandQueue.cancelExtended(object : Callback() { override fun run() { @@ -169,7 +178,7 @@ class ActionsFragment : DaggerFragment() { TempBasalDialog().show(childFragmentManager, "Actions") } cancelTempBasal?.setOnClickListener { - if (activePlugin.activeTreatments.isTempBasalInProgress) { + if (iobCobCalculator.getTempBasalIncludingConvertedExtended(dateUtil._now()) != null) { uel.log(Action.CANCEL_TEMP_BASAL) commandQueue.cancelTempBasal(true, object : Callback() { override fun run() { @@ -264,12 +273,12 @@ class ActionsFragment : DaggerFragment() { extendedBolus?.visibility = View.GONE extendedBolusCancel?.visibility = View.GONE } else { - val activeExtendedBolus = activePlugin.activeTreatments.getExtendedBolusFromHistory(System.currentTimeMillis()) - if (activeExtendedBolus != null) { + val activeExtendedBolus = repository.getExtendedBolusActiveAt(dateUtil._now()).blockingGet() + if (activeExtendedBolus is ValueWrapper.Existing) { extendedBolus?.visibility = View.GONE extendedBolusCancel?.visibility = View.VISIBLE @Suppress("SetTextI18n") - extendedBolusCancel?.text = resourceHelper.gs(R.string.cancel) + " " + activeExtendedBolus.toStringMedium() + extendedBolusCancel?.text = resourceHelper.gs(R.string.cancel) + " " + activeExtendedBolus.value.toStringMedium(dateUtil) } else { extendedBolus?.visibility = View.VISIBLE extendedBolusCancel?.visibility = View.GONE @@ -280,7 +289,7 @@ class ActionsFragment : DaggerFragment() { setTempBasal?.visibility = View.GONE cancelTempBasal?.visibility = View.GONE } else { - val activeTemp = activePlugin.activeTreatments.getTempBasalFromHistory(System.currentTimeMillis()) + val activeTemp = iobCobCalculator.getTempBasalIncludingConvertedExtended(System.currentTimeMillis()) if (activeTemp != null) { setTempBasal?.visibility = View.GONE cancelTempBasal?.visibility = View.VISIBLE diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/dataBroadcaster/DataBroadcastPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/dataBroadcaster/DataBroadcastPlugin.kt index 8df0e83091..40665a164f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/dataBroadcaster/DataBroadcastPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/dataBroadcaster/DataBroadcastPlugin.kt @@ -7,7 +7,6 @@ import android.os.Bundle import dagger.android.HasAndroidInjector import info.nightscout.androidaps.Config import info.nightscout.androidaps.R -import info.nightscout.androidaps.data.IobTotal import info.nightscout.androidaps.events.* import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.logging.AAPSLogger @@ -20,8 +19,11 @@ import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewB import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider import info.nightscout.androidaps.receivers.ReceiverStatusStore import info.nightscout.androidaps.services.Intents +import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DefaultValueHelper import info.nightscout.androidaps.utils.FabricPrivacy +import info.nightscout.androidaps.extensions.durationInMinutes +import info.nightscout.androidaps.extensions.toStringFull import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers import io.reactivex.disposables.CompositeDisposable @@ -35,6 +37,7 @@ class DataBroadcastPlugin @Inject constructor( resourceHelper: ResourceHelper, private val aapsSchedulers: AapsSchedulers, private val context: Context, + private val dateUtil: DateUtil, private val fabricPrivacy: FabricPrivacy, private val rxBus: RxBusWrapper, private val iobCobCalculator: IobCobCalculator, @@ -131,8 +134,8 @@ class DataBroadcastPlugin @Inject constructor( private fun iobCob(bundle: Bundle) { profileFunction.getProfile() ?: return - val bolusIob: IobTotal = iobCobCalculator.calculateIobFromBolus().round() - val basalIob: IobTotal = activePlugin.activeTreatments.lastCalculationTempBasals.round() + val bolusIob = iobCobCalculator.calculateIobFromBolus().round() + val basalIob = iobCobCalculator.calculateIobFromTempBasalsIncludingConvertedExtended().round() bundle.putDouble("bolusIob", bolusIob.iob) bundle.putDouble("basalIob", basalIob.basaliob) bundle.putDouble("iob", bolusIob.iob + basalIob.basaliob) // total IOB @@ -174,12 +177,12 @@ class DataBroadcastPlugin @Inject constructor( bundle.putLong("basalTimeStamp", now) bundle.putDouble("baseBasal", profile.basal) bundle.putString("profile", profileFunction.getProfileName()) - activePlugin.activeTreatments.getTempBasalFromHistory(now)?.let { - bundle.putLong("tempBasalStart", it.date) - bundle.putInt("tempBasalDurationInMinutes", it.durationInMinutes) - if (it.isAbsolute) bundle.putDouble("tempBasalAbsolute", it.absoluteRate) // U/h for absolute TBR - else bundle.putInt("tempBasalPercent", it.percentRate) // % for percent type TBR - bundle.putString("tempBasalString", it.toStringFull()) // user friendly string + iobCobCalculator.getTempBasalIncludingConvertedExtended(now)?.let { + bundle.putLong("tempBasalStart", it.timestamp) + bundle.putLong("tempBasalDurationInMinutes", it.durationInMinutes) + if (it.isAbsolute) bundle.putDouble("tempBasalAbsolute", it.rate) // U/h for absolute TBR + else bundle.putInt("tempBasalPercent", it.rate.toInt()) // % for percent type TBR + bundle.putString("tempBasalString", it.toStringFull(profile, dateUtil)) // user friendly string } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/food/FoodFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/food/FoodFragment.kt index a8d4be0620..0e4ab8a198 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/food/FoodFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/food/FoodFragment.kt @@ -28,7 +28,7 @@ import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.alertDialogs.OKDialog -import info.nightscout.androidaps.utils.extensions.toVisibility +import info.nightscout.androidaps.extensions.toVisibility import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers import io.reactivex.Completable diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/food/FoodPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/food/FoodPlugin.kt index 34bc3a244c..bc095b1d8f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/food/FoodPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/food/FoodPlugin.kt @@ -16,7 +16,7 @@ import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.receivers.DataWorker import info.nightscout.androidaps.utils.JsonHelper -import info.nightscout.androidaps.utils.extensions.foodFromJson +import info.nightscout.androidaps.extensions.foodFromJson import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.sharedPreferences.SP import org.json.JSONObject 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 7d8c8d3dd2..345ac3f382 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 @@ -9,7 +9,7 @@ import info.nightscout.androidaps.interfaces.DataSyncSelector import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag -import info.nightscout.androidaps.utils.extensions.toJson +import info.nightscout.androidaps.extensions.toJson import info.nightscout.androidaps.utils.sharedPreferences.SP import javax.inject.Inject @@ -30,6 +30,8 @@ class DataSyncSelectorImplementation @Inject constructor( sp.remove(R.string.key_ns_carbs_last_synced_id) sp.remove(R.string.key_ns_bolus_calculator_result_last_synced_id) sp.remove(R.string.key_ns_device_status_last_synced_id) + sp.remove(R.string.key_ns_temporary_basal_last_synced_id) + sp.remove(R.string.key_ns_extended_bolus_last_synced_id) } override fun confirmLastBolusIdIfGreater(lastSynced: Long) { @@ -326,4 +328,81 @@ class DataSyncSelectorImplementation @Inject constructor( return false } + override fun confirmLastTemporaryBasalIdIfGreater(lastSynced: Long) { + if (lastSynced > sp.getLong(R.string.key_ns_temporary_basal_last_synced_id, 0)) { + aapsLogger.debug(LTag.NSCLIENT, "Setting TemporaryBasal data sync from $lastSynced") + sp.putLong(R.string.key_ns_temporary_basal_last_synced_id, lastSynced) + } + } + + // Prepared for v3 (returns all modified after) + override fun changedTemporaryBasals(): List { + val startId = sp.getLong(R.string.key_ns_temporary_basal_last_synced_id, 0) + return appRepository.getModifiedTemporaryBasalDataFromId(startId).blockingGet().also { + aapsLogger.debug(LTag.NSCLIENT, "Loading TemporaryBasal data for sync from $startId. Records ${it.size}") + } + } + + override fun processChangedTemporaryBasalsCompat(): Boolean { + val startId = sp.getLong(R.string.key_ns_temporary_basal_last_synced_id, 0) + appRepository.getNextSyncElementTemporaryBasal(startId).blockingGet()?.let { tb -> + aapsLogger.info(LTag.DATABASE, "Loading TemporaryBasal data Start: $startId ID: ${tb.first.id} HistoryID: ${tb.second} ") + profileFunction.getProfile(tb.first.timestamp)?.let { profile -> + when { + // removed and not uploaded yet = ignore + !tb.first.isValid && tb.first.interfaceIDs.nightscoutId == null -> Any() + // removed and already uploaded = send for removal + !tb.first.isValid && tb.first.interfaceIDs.nightscoutId != null -> + nsClientPlugin.nsClientService?.dbRemove("treatments", tb.first.interfaceIDs.nightscoutId, DataSyncSelector.PairTemporaryBasal(tb.first, tb.second)) + // existing without nsId = create new + tb.first.isValid && tb.first.interfaceIDs.nightscoutId == null -> + nsClientPlugin.nsClientService?.dbAdd("treatments", tb.first.toJson(profile), DataSyncSelector.PairTemporaryBasal(tb.first, tb.second)) + // existing with nsId = update + tb.first.isValid && tb.first.interfaceIDs.nightscoutId != null -> + nsClientPlugin.nsClientService?.dbUpdate("treatments", tb.first.interfaceIDs.nightscoutId, tb.first.toJson(profile), DataSyncSelector.PairTemporaryBasal(tb.first, tb.second)) + } + return true + } + } + return false + } + + override fun confirmLastExtendedBolusIdIfGreater(lastSynced: Long) { + if (lastSynced > sp.getLong(R.string.key_ns_extended_bolus_last_synced_id, 0)) { + aapsLogger.debug(LTag.NSCLIENT, "Setting ExtendedBolus data sync from $lastSynced") + sp.putLong(R.string.key_ns_extended_bolus_last_synced_id, lastSynced) + } + } + + // Prepared for v3 (returns all modified after) + override fun changedExtendedBoluses(): List { + val startId = sp.getLong(R.string.key_ns_extended_bolus_last_synced_id, 0) + return appRepository.getModifiedExtendedBolusDataFromId(startId).blockingGet().also { + aapsLogger.debug(LTag.NSCLIENT, "Loading ExtendedBolus data for sync from $startId. Records ${it.size}") + } + } + + override fun processChangedExtendedBolusesCompat(): Boolean { + val startId = sp.getLong(R.string.key_ns_extended_bolus_last_synced_id, 0) + appRepository.getNextSyncElementExtendedBolus(startId).blockingGet()?.let { eb -> + aapsLogger.info(LTag.DATABASE, "Loading ExtendedBolus data Start: $startId ID: ${eb.first.id} HistoryID: ${eb.second} ") + profileFunction.getProfile(eb.first.timestamp)?.let { profile -> + 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.PairExtendedBolus(eb.first, eb.second)) + // existing without nsId = create new + eb.first.isValid && eb.first.interfaceIDs.nightscoutId == null -> + nsClientPlugin.nsClientService?.dbAdd("treatments", eb.first.toJson(profile), DataSyncSelector.PairExtendedBolus(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(profile), DataSyncSelector.PairExtendedBolus(eb.first, eb.second)) + } + return true + } + } + return false + } } 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 ae90713332..17661e1992 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 @@ -1,7 +1,6 @@ package info.nightscout.androidaps.plugins.general.nsclient import android.content.Context -import androidx.work.Data import androidx.work.Worker import androidx.work.WorkerParameters import androidx.work.workDataOf @@ -11,10 +10,8 @@ import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.entities.TherapyEvent import info.nightscout.androidaps.database.entities.UserEntry import info.nightscout.androidaps.database.entities.UserEntry.ValueWithUnit -import info.nightscout.androidaps.database.transactions.SyncNsBolusTransaction -import info.nightscout.androidaps.database.transactions.SyncNsCarbsTransaction -import info.nightscout.androidaps.database.transactions.SyncNsTemporaryTargetTransaction -import info.nightscout.androidaps.database.transactions.SyncNsTherapyEventTransaction +import info.nightscout.androidaps.database.transactions.* +import info.nightscout.androidaps.extensions.* import info.nightscout.androidaps.interfaces.ConfigInterface import info.nightscout.androidaps.interfaces.DatabaseHelperInterface import info.nightscout.androidaps.logging.AAPSLogger @@ -28,10 +25,7 @@ import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.JsonHelper import info.nightscout.androidaps.utils.JsonHelper.safeGetLong import info.nightscout.androidaps.utils.buildHelper.BuildHelper -import info.nightscout.androidaps.utils.extensions.bolusFromJson -import info.nightscout.androidaps.utils.extensions.carbsFromJson -import info.nightscout.androidaps.utils.extensions.temporaryTargetFromJson -import info.nightscout.androidaps.utils.extensions.therapyEventFromJson +import info.nightscout.androidaps.utils.extensions.* import info.nightscout.androidaps.utils.sharedPreferences.SP import javax.inject.Inject @@ -92,12 +86,17 @@ class NSClientAddUpdateWorker( ValueWithUnit(it.timestamp, UserEntry.Units.Timestamp, true), ValueWithUnit(it.amount, UserEntry.Units.U) ) + aapsLogger.debug(LTag.DATABASE, "Inserted bolus $it") } result.invalidated.forEach { uel.log(UserEntry.Action.CAREPORTAL_DELETED_FROM_NS, ValueWithUnit(it.timestamp, UserEntry.Units.Timestamp, true), ValueWithUnit(it.amount, UserEntry.Units.U) ) + aapsLogger.debug(LTag.DATABASE, "Invalidated bolus $it") + } + result.updatedNsId.forEach { + aapsLogger.debug(LTag.DATABASE, "Updated bolus $it") } } } ?: aapsLogger.error("Error parsing bolus json $json") @@ -116,12 +115,17 @@ class NSClientAddUpdateWorker( ValueWithUnit(it.timestamp, UserEntry.Units.Timestamp, true), ValueWithUnit(it.amount, UserEntry.Units.G) ) + aapsLogger.debug(LTag.DATABASE, "Inserted carbs $it") } result.invalidated.forEach { uel.log(UserEntry.Action.CAREPORTAL_DELETED_FROM_NS, ValueWithUnit(it.timestamp, UserEntry.Units.Timestamp, true), ValueWithUnit(it.amount, UserEntry.Units.G) ) + aapsLogger.debug(LTag.DATABASE, "Invalidated carbs $it") + } + result.updatedNsId.forEach { + aapsLogger.debug(LTag.DATABASE, "Updated carbs $it") } } } ?: aapsLogger.error("Error parsing bolus json $json") @@ -144,6 +148,7 @@ class NSClientAddUpdateWorker( ValueWithUnit(it.highTarget, UserEntry.Units.Mg_Dl, it.lowTarget != it.highTarget), ValueWithUnit(it.duration.toInt() / 60000, UserEntry.Units.M, true) ) + aapsLogger.debug(LTag.DATABASE, "Inserted TemporaryTarget $it") } result.invalidated.forEach { uel.log(UserEntry.Action.TT_DELETED_FROM_NS, @@ -152,6 +157,7 @@ class NSClientAddUpdateWorker( ValueWithUnit(it.highTarget, UserEntry.Units.Mg_Dl, it.lowTarget != it.highTarget), ValueWithUnit(it.duration.toInt() / 60000, UserEntry.Units.M, true) ) + aapsLogger.debug(LTag.DATABASE, "Invalidated TemporaryTarget $it") } result.ended.forEach { uel.log(UserEntry.Action.TT_CANCELED_FROM_NS, @@ -160,6 +166,10 @@ class NSClientAddUpdateWorker( ValueWithUnit(it.highTarget, UserEntry.Units.Mg_Dl, it.lowTarget != it.highTarget), ValueWithUnit(it.duration.toInt() / 60000, UserEntry.Units.M, true) ) + aapsLogger.debug(LTag.DATABASE, "Updated TemporaryTarget $it") + } + result.updatedNsId.forEach { + aapsLogger.debug(LTag.DATABASE, "Updated TemporaryTarget $it") } } } ?: aapsLogger.error("Error parsing TT json $json") @@ -187,6 +197,7 @@ class NSClientAddUpdateWorker( ValueWithUnit(it.timestamp, UserEntry.Units.Timestamp, true), ValueWithUnit(it.type.text, UserEntry.Units.TherapyEvent) ) + aapsLogger.debug(LTag.DATABASE, "Inserted TherapyEvent $it") } result.invalidated.forEach { uel.log(UserEntry.Action.CAREPORTAL_DELETED_FROM_NS, @@ -194,13 +205,83 @@ class NSClientAddUpdateWorker( ValueWithUnit(it.timestamp, UserEntry.Units.Timestamp, true), ValueWithUnit(it.type.text, UserEntry.Units.TherapyEvent) ) + aapsLogger.debug(LTag.DATABASE, "Invalidated TherapyEvent $it") + } + result.updatedNsId.forEach { + aapsLogger.debug(LTag.DATABASE, "Updated TherapyEvent $it") } } } ?: aapsLogger.error("Error parsing TherapyEvent json $json") eventType == TherapyEvent.Type.TEMPORARY_BASAL.text -> - databaseHelper.createTempBasalFromJsonIfNotExists(json) + temporaryBasalFromJson(json)?.let { temporaryBasal -> + repository.runTransactionForResult(SyncNsTemporaryBasalTransaction(temporaryBasal)) + .doOnError { + aapsLogger.error(LTag.DATABASE, "Error while saving temporary basal", it) + ret = Result.failure(workDataOf("Error" to it)) + } + .blockingGet() + .also { result -> + result.inserted.forEach { + uel.log(UserEntry.Action.CAREPORTAL_FROM_NS, + ValueWithUnit(it.timestamp, UserEntry.Units.Timestamp, true), + ValueWithUnit(it.rate, UserEntry.Units.U_H) + ) + aapsLogger.debug(LTag.DATABASE, "Inserted TemporaryBasal $it") + } + result.invalidated.forEach { + uel.log(UserEntry.Action.CAREPORTAL_FROM_NS, + ValueWithUnit(it.timestamp, UserEntry.Units.Timestamp, true), + ValueWithUnit(it.rate, UserEntry.Units.U_H) + ) + aapsLogger.debug(LTag.DATABASE, "Invalidated TemporaryBasal $it") + } + result.ended.forEach { + uel.log(UserEntry.Action.CAREPORTAL_FROM_NS, + ValueWithUnit(it.timestamp, UserEntry.Units.Timestamp, true), + ValueWithUnit(it.rate, UserEntry.Units.U_H) + ) + aapsLogger.debug(LTag.DATABASE, "Updated TemporaryBasal $it") + } + result.updatedNsId.forEach { + aapsLogger.debug(LTag.DATABASE, "Updated TemporaryBasal $it") + } + } + } ?: aapsLogger.error("Error parsing TemporaryBasal json $json") eventType == TherapyEvent.Type.COMBO_BOLUS.text -> - databaseHelper.createExtendedBolusFromJsonIfNotExists(json) + extendedBolusFromJson(json)?.let { extendedBolus -> + repository.runTransactionForResult(SyncNsExtendedBolusTransaction(extendedBolus)) + .doOnError { + aapsLogger.error(LTag.DATABASE, "Error while saving extended bolus", it) + ret = Result.failure(workDataOf("Error" to it)) + } + .blockingGet() + .also { result -> + result.inserted.forEach { + uel.log(UserEntry.Action.CAREPORTAL_FROM_NS, + ValueWithUnit(it.timestamp, UserEntry.Units.Timestamp, true), + ValueWithUnit(it.rate, UserEntry.Units.U_H) + ) + aapsLogger.debug(LTag.DATABASE, "Inserted ExtendedBolus $it") + } + result.invalidated.forEach { + uel.log(UserEntry.Action.CAREPORTAL_FROM_NS, + ValueWithUnit(it.timestamp, UserEntry.Units.Timestamp, true), + ValueWithUnit(it.rate, UserEntry.Units.U_H) + ) + aapsLogger.debug(LTag.DATABASE, "Invalidated ExtendedBolus $it") + } + result.ended.forEach { + uel.log(UserEntry.Action.CAREPORTAL_FROM_NS, + ValueWithUnit(it.timestamp, UserEntry.Units.Timestamp, true), + ValueWithUnit(it.rate, UserEntry.Units.U_H) + ) + aapsLogger.debug(LTag.DATABASE, "Updated ExtendedBolus $it") + } + result.updatedNsId.forEach { + aapsLogger.debug(LTag.DATABASE, "Updated ExtendedBolus $it") + } + } + } ?: aapsLogger.error("Error parsing ExtendedBolus json $json") eventType == TherapyEvent.Type.PROFILE_SWITCH.text -> databaseHelper.createProfileSwitchFromJsonIfNotExists(json) } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientMbgWorker.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientMbgWorker.kt index 8ba3813be2..1050234465 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientMbgWorker.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientMbgWorker.kt @@ -14,7 +14,7 @@ import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.general.nsclient.data.NSMbg import info.nightscout.androidaps.receivers.DataWorker import info.nightscout.androidaps.utils.buildHelper.BuildHelper -import info.nightscout.androidaps.utils.extensions.therapyEventFromNsMbg +import info.nightscout.androidaps.extensions.therapyEventFromNsMbg import info.nightscout.androidaps.utils.sharedPreferences.SP import javax.inject.Inject 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 0687be4f52..346ac88f7a 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 @@ -9,10 +9,8 @@ import info.nightscout.androidaps.R import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.entities.UserEntry import info.nightscout.androidaps.database.entities.UserEntry.ValueWithUnit -import info.nightscout.androidaps.database.transactions.SyncNsBolusTransaction -import info.nightscout.androidaps.database.transactions.SyncNsCarbsTransaction -import info.nightscout.androidaps.database.transactions.SyncNsTemporaryTargetTransaction -import info.nightscout.androidaps.database.transactions.SyncNsTherapyEventTransaction +import info.nightscout.androidaps.database.transactions.* +import info.nightscout.androidaps.extensions.* import info.nightscout.androidaps.interfaces.ConfigInterface import info.nightscout.androidaps.interfaces.DatabaseHelperInterface import info.nightscout.androidaps.logging.AAPSLogger @@ -22,10 +20,7 @@ import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.receivers.DataWorker import info.nightscout.androidaps.utils.JsonHelper import info.nightscout.androidaps.utils.buildHelper.BuildHelper -import info.nightscout.androidaps.utils.extensions.bolusFromNsIdForInvalidating -import info.nightscout.androidaps.utils.extensions.carbsFromNsIdForInvalidating -import info.nightscout.androidaps.utils.extensions.temporaryTargetFromNsIdForInvalidating -import info.nightscout.androidaps.utils.extensions.therapyEventFromNsIdForInvalidating +import info.nightscout.androidaps.utils.extensions.* import info.nightscout.androidaps.utils.sharedPreferences.SP import javax.inject.Inject @@ -114,7 +109,7 @@ class NSClientRemoveWorker( } } - // room Bolus + // room Carbs val carbs = carbsFromNsIdForInvalidating(nsId) repository.runTransactionForResult(SyncNsCarbsTransaction(carbs)) .doOnError { @@ -131,9 +126,41 @@ class NSClientRemoveWorker( } } + // room TemporaryBasal + val temporaryBasal = temporaryBasalFromNsIdForInvalidating(nsId) + repository.runTransactionForResult(SyncNsTemporaryBasalTransaction(temporaryBasal)) + .doOnError { + aapsLogger.error(LTag.DATABASE, "Error while invalidating temporary basal", it) + ret = Result.failure(workDataOf("Error" to it)) + } + .blockingGet() + .also { result -> + result.invalidated.forEach { + uel.log( + UserEntry.Action.CAREPORTAL_DELETED_FROM_NS, + ValueWithUnit(it.timestamp, UserEntry.Units.Timestamp, true), + ValueWithUnit(it.rate, UserEntry.Units.U_H)) + } + } + // room ExtendedBolus + val extendedBolus = extendedBolusFromNsIdForInvalidating(nsId) + repository.runTransactionForResult(SyncNsExtendedBolusTransaction(extendedBolus)) + .doOnError { + aapsLogger.error(LTag.DATABASE, "Error while invalidating extended bolus", it) + ret = Result.failure(workDataOf("Error" to it)) + } + .blockingGet() + .also { result -> + result.invalidated.forEach { + uel.log( + UserEntry.Action.CAREPORTAL_DELETED_FROM_NS, + ValueWithUnit(it.timestamp, UserEntry.Units.Timestamp, true), + ValueWithUnit(it.amount, UserEntry.Units.U)) + } + } + + // old DB model - databaseHelper.deleteTempBasalById(nsId) - databaseHelper.deleteExtendedBolusById(nsId) databaseHelper.deleteProfileSwitchById(nsId) } 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 8f8d2bc0ea..bbc8258c8d 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 @@ -37,8 +37,10 @@ import info.nightscout.androidaps.database.transactions.UpdateNsIdBolusCalculato import info.nightscout.androidaps.database.transactions.UpdateNsIdBolusTransaction; import info.nightscout.androidaps.database.transactions.UpdateNsIdCarbsTransaction; import info.nightscout.androidaps.database.transactions.UpdateNsIdDeviceStatusTransaction; +import info.nightscout.androidaps.database.transactions.UpdateNsIdExtendedBolusTransaction; import info.nightscout.androidaps.database.transactions.UpdateNsIdFoodTransaction; import info.nightscout.androidaps.database.transactions.UpdateNsIdGlucoseValueTransaction; +import info.nightscout.androidaps.database.transactions.UpdateNsIdTemporaryBasalTransaction; import info.nightscout.androidaps.database.transactions.UpdateNsIdTemporaryTargetTransaction; import info.nightscout.androidaps.database.transactions.UpdateNsIdTherapyEventTransaction; import info.nightscout.androidaps.db.DbRequest; @@ -139,7 +141,7 @@ public class NSClientService extends DaggerService { private final ArrayList reconnections = new ArrayList<>(); private final int WATCHDOG_INTERVAL_MINUTES = 2; private final int WATCHDOG_RECONNECT_IN = 15; - private final int WATCHDOG_MAXCONNECTIONS = 5; + private final int WATCHDOG_MAX_CONNECTIONS = 5; public NSClientService() { super(); @@ -340,6 +342,38 @@ public class NSClientService extends DaggerService { dataSyncSelector.processChangedBolusCalculatorResultsCompat(); return; } + if (ack.getOriginalObject() instanceof DataSyncSelector.PairTemporaryBasal) { + DataSyncSelector.PairTemporaryBasal pair = (DataSyncSelector.PairTemporaryBasal) ack.getOriginalObject(); + pair.getValue().getInterfaceIDs().setNightscoutId(ack.getId()); + + disposable.add(repository.runTransactionForResult(new UpdateNsIdTemporaryBasalTransaction(pair.getValue())) + .observeOn(aapsSchedulers.getIo()) + .subscribe( + result -> aapsLogger.debug(LTag.DATABASE, "Updated ns id of TemporaryBasal " + pair.getValue()), + error -> aapsLogger.error(LTag.DATABASE, "Updated ns id of TemporaryBasal failed", error) + )); + dataSyncSelector.confirmLastTemporaryBasalIdIfGreater(pair.getUpdateRecordId()); + rxBus.send(new EventNSClientNewLog("DBADD", "Acked TemporaryBasal" + pair.getValue().getInterfaceIDs().getNightscoutId())); + // Send new if waiting + dataSyncSelector.processChangedTemporaryBasalsCompat(); + return; + } + if (ack.getOriginalObject() instanceof DataSyncSelector.PairExtendedBolus) { + DataSyncSelector.PairExtendedBolus pair = (DataSyncSelector.PairExtendedBolus) ack.getOriginalObject(); + pair.getValue().getInterfaceIDs().setNightscoutId(ack.getId()); + + disposable.add(repository.runTransactionForResult(new UpdateNsIdExtendedBolusTransaction(pair.getValue())) + .observeOn(aapsSchedulers.getIo()) + .subscribe( + result -> aapsLogger.debug(LTag.DATABASE, "Updated ns id of ExtendedBolus " + pair.getValue()), + error -> aapsLogger.error(LTag.DATABASE, "Updated ns id of ExtendedBolus failed", error) + )); + dataSyncSelector.confirmLastExtendedBolusIdIfGreater(pair.getUpdateRecordId()); + rxBus.send(new EventNSClientNewLog("DBADD", "Acked ExtendedBolus" + pair.getValue().getInterfaceIDs().getNightscoutId())); + // Send new if waiting + dataSyncSelector.processChangedTemporaryBasalsCompat(); + return; + } if (ack.getOriginalObject() instanceof DeviceStatus) { DeviceStatus deviceStatus = (DeviceStatus) ack.getOriginalObject(); deviceStatus.getInterfaceIDs().setNightscoutId(ack.getId()); @@ -424,6 +458,22 @@ public class NSClientService extends DaggerService { dataSyncSelector.processChangedBolusCalculatorResultsCompat(); return; } + if (ack.getOriginalObject() instanceof DataSyncSelector.PairTemporaryBasal) { + DataSyncSelector.PairTemporaryBasal pair = (DataSyncSelector.PairTemporaryBasal) ack.getOriginalObject(); + dataSyncSelector.confirmLastTemporaryBasalIdIfGreater(pair.getUpdateRecordId()); + rxBus.send(new EventNSClientNewLog("DBUPDATE/DBREMOVE", "Acked TemporaryBasal " + ack.get_id())); + // Send new if waiting + dataSyncSelector.processChangedTemporaryBasalsCompat(); + return; + } + if (ack.getOriginalObject() instanceof DataSyncSelector.PairExtendedBolus) { + DataSyncSelector.PairExtendedBolus pair = (DataSyncSelector.PairExtendedBolus) ack.getOriginalObject(); + dataSyncSelector.confirmLastExtendedBolusIdIfGreater(pair.getUpdateRecordId()); + rxBus.send(new EventNSClientNewLog("DBUPDATE/DBREMOVE", "Acked ExtendedBolus " + ack.get_id())); + // Send new if waiting + dataSyncSelector.processChangedExtendedBolusesCompat(); + return; + } // old way if (ack.getResult()) { uploadQueue.removeByMongoId(ack.getAction(), ack.get_id()); @@ -549,8 +599,8 @@ public class NSClientService extends DaggerService { reconnections.remove(r); } } - rxBus.send(new EventNSClientNewLog("WATCHDOG", "connections in last " + WATCHDOG_INTERVAL_MINUTES + " mins: " + reconnections.size() + "/" + WATCHDOG_MAXCONNECTIONS)); - if (reconnections.size() >= WATCHDOG_MAXCONNECTIONS) { + rxBus.send(new EventNSClientNewLog("WATCHDOG", "connections in last " + WATCHDOG_INTERVAL_MINUTES + " mins: " + reconnections.size() + "/" + WATCHDOG_MAX_CONNECTIONS)); + if (reconnections.size() >= WATCHDOG_MAX_CONNECTIONS) { Notification n = new Notification(Notification.NS_MALFUNCTION, resourceHelper.gs(R.string.nsmalfunction), Notification.URGENT); rxBus.send(new EventNewNotification(n)); rxBus.send(new EventNSClientNewLog("WATCHDOG", "pausing for " + WATCHDOG_RECONNECT_IN + " mins")); @@ -990,6 +1040,8 @@ public class NSClientService extends DaggerService { dataSyncSelector.processChangedBolusesCompat(); dataSyncSelector.processChangedCarbsCompat(); dataSyncSelector.processChangedBolusCalculatorResultsCompat(); + dataSyncSelector.processChangedTemporaryBasalsCompat(); + dataSyncSelector.processChangedExtendedBolusesCompat(); dataSyncSelector.processChangedGlucoseValuesCompat(); dataSyncSelector.processChangedTempTargetsCompat(); dataSyncSelector.processChangedFoodsCompat(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/openhumans/OpenHumansUploader.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/openhumans/OpenHumansUploader.kt index 2d621b1cc5..92e008ca91 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/openhumans/OpenHumansUploader.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/openhumans/OpenHumansUploader.kt @@ -28,7 +28,7 @@ import info.nightscout.androidaps.interfaces.PluginType import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.bus.RxBusWrapper -import info.nightscout.androidaps.utils.extensions.toConstant +import info.nightscout.androidaps.extensions.toConstant import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.sharedPreferences.SP @@ -365,18 +365,18 @@ class OpenHumansUploader @Inject constructor( .andThen(Observable.defer { Observable.fromIterable(repository.compatGetTherapyEventDataFromTime(0, true).blockingGet()) }) .map { enqueueTherapyEvent(it); increaseCounter() } .ignoreElements() - .andThen(Observable.defer { Observable.fromIterable(databaseHelper.getAllExtendedBoluses()) }) - .map { enqueueExtendedBolus(it); increaseCounter() } - .ignoreElements() +// .andThen(Observable.defer { Observable.fromIterable(databaseHelper.getAllExtendedBoluses()) }) +// .map { enqueueExtendedBolus(it); increaseCounter() } +// .ignoreElements() .andThen(Observable.defer { Observable.fromIterable(databaseHelper.getAllProfileSwitches()) }) .map { enqueueProfileSwitch(it); increaseCounter() } .ignoreElements() .andThen(Observable.defer { Observable.fromIterable(databaseHelper.getAllTDDs()) }) .map { enqueueTotalDailyDose(it); increaseCounter() } .ignoreElements() - .andThen(Observable.defer { Observable.fromIterable(databaseHelper.getAllTemporaryBasals()) }) - .map { enqueueTemporaryBasal(it); increaseCounter() } - .ignoreElements() + // .andThen(Observable.defer { Observable.fromIterable(databaseHelper.getAllTemporaryBasals()) }) + // .map { enqueueTemporaryBasal(it); increaseCounter() } + // .ignoreElements() .andThen(Observable.defer { Observable.fromIterable(repository.compatGetTemporaryTargetData().blockingGet()) }) .map { enqueueTempTarget(it); increaseCounter() } .ignoreElements() diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.kt index df4d0c0d3d..27ac836fef 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.kt @@ -36,6 +36,7 @@ import info.nightscout.androidaps.database.interfaces.end import info.nightscout.androidaps.databinding.OverviewFragmentBinding import info.nightscout.androidaps.dialogs.* import info.nightscout.androidaps.events.* +import info.nightscout.androidaps.extensions.* import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.UserEntryLogger @@ -61,10 +62,7 @@ import info.nightscout.androidaps.skins.SkinProvider import info.nightscout.androidaps.utils.* import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.buildHelper.BuildHelper -import info.nightscout.androidaps.utils.extensions.directionToIcon -import info.nightscout.androidaps.utils.extensions.toVisibility -import info.nightscout.androidaps.utils.extensions.valueToUnits -import info.nightscout.androidaps.utils.extensions.valueToUnitsString +import info.nightscout.androidaps.utils.extensions.* import info.nightscout.androidaps.utils.protection.ProtectionCheck import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers @@ -100,7 +98,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList @Inject lateinit var configBuilderPlugin: ConfigBuilderPlugin @Inject lateinit var activePlugin: ActivePluginProvider @Inject lateinit var treatmentsPlugin: TreatmentsPlugin - @Inject lateinit var iobCobCalculatorPlugin: IobCobCalculator + @Inject lateinit var iobCobCalculator: IobCobCalculator @Inject lateinit var dexcomPlugin: DexcomPlugin @Inject lateinit var dexcomMediator: DexcomPlugin.DexcomMediator @Inject lateinit var xdripPlugin: XdripPlugin @@ -412,7 +410,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList } private fun onClickQuickWizard() { - val actualBg = iobCobCalculatorPlugin.actualBg() + val actualBg = iobCobCalculator.actualBg() val profile = profileFunction.getProfile() val profileName = profileFunction.getProfileName() val pump = activePlugin.activePump @@ -447,11 +445,11 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList @SuppressLint("SetTextI18n") private fun processButtonsVisibility() { - val lastBG = iobCobCalculatorPlugin.lastBg() + val lastBG = iobCobCalculator.lastBg() val pump = activePlugin.activePump val profile = profileFunction.getProfile() val profileName = profileFunction.getProfileName() - val actualBG = iobCobCalculatorPlugin.actualBg() + val actualBG = iobCobCalculator.actualBg() // QuickWizard button val quickWizardEntry = quickWizard.getActive() @@ -563,8 +561,8 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList binding.loopPumpStatusLayout.loopLayout.visibility = View.VISIBLE val profile = profileFunction.getProfile() ?: return - val actualBG = iobCobCalculatorPlugin.actualBg() - val lastBG = iobCobCalculatorPlugin.lastBg() + val actualBG = iobCobCalculator.actualBg() + val lastBG = iobCobCalculator.lastBg() val pump = activePlugin.activePump val units = profileFunction.getUnits() val lowLine = defaultValueHelper.determineLowLine() @@ -703,13 +701,13 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList } // Basal, TBR - val activeTemp = treatmentsPlugin.getTempBasalFromHistory(System.currentTimeMillis()) - binding.infoLayout.baseBasal.text = activeTemp?.let { "T:" + activeTemp.toStringVeryShort() } + val activeTemp = iobCobCalculator.getTempBasalIncludingConvertedExtended(System.currentTimeMillis()) + binding.infoLayout.baseBasal.text = activeTemp?.let { "T:" + activeTemp.toStringShort() } ?: resourceHelper.gs(R.string.pump_basebasalrate, profile.basal) binding.infoLayout.basalLayout.setOnClickListener { var fullText = "${resourceHelper.gs(R.string.basebasalrate_label)}: ${resourceHelper.gs(R.string.pump_basebasalrate, profile.basal)}" if (activeTemp != null) - fullText += "\n" + resourceHelper.gs(R.string.tempbasal_label) + ": " + activeTemp.toStringFull() + fullText += "\n" + resourceHelper.gs(R.string.tempbasal_label) + ": " + activeTemp.toStringFull(profile, dateUtil) activity?.let { OKDialog.show(it, resourceHelper.gs(R.string.basal), fullText) } @@ -718,23 +716,23 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList ?: resourceHelper.gc(R.color.defaulttextcolor)) binding.infoLayout.baseBasalIcon.setImageResource(R.drawable.ic_cp_basal_no_tbr) - val percentRate = activeTemp?.tempBasalConvertedToPercent(System.currentTimeMillis(), profile) + val percentRate = activeTemp?.convertedToPercent(System.currentTimeMillis(), profile) ?: 100 if (percentRate > 100) binding.infoLayout.baseBasalIcon.setImageResource(R.drawable.ic_cp_basal_tbr_high) if (percentRate < 100) binding.infoLayout.baseBasalIcon.setImageResource(R.drawable.ic_cp_basal_tbr_low) // Extended bolus - val extendedBolus = treatmentsPlugin.getExtendedBolusFromHistory(System.currentTimeMillis()) + val extendedBolus = repository.getExtendedBolusActiveAt(dateUtil._now()).blockingGet() binding.infoLayout.extendedBolus.text = - if (extendedBolus != null && !pump.isFakingTempsByExtendedBoluses) - resourceHelper.gs(R.string.pump_basebasalrate, extendedBolus.absoluteRate()) + if (extendedBolus is ValueWrapper.Existing && !pump.isFakingTempsByExtendedBoluses) + resourceHelper.gs(R.string.pump_basebasalrate, extendedBolus.value.rate) else "" binding.infoLayout.extendedBolus.setOnClickListener { - if (extendedBolus != null) activity?.let { - OKDialog.show(it, resourceHelper.gs(R.string.extended_bolus), extendedBolus.toString()) + if (extendedBolus is ValueWrapper.Existing) activity?.let { + OKDialog.show(it, resourceHelper.gs(R.string.extended_bolus), extendedBolus.value.toStringFull(dateUtil)) } } - binding.infoLayout.extendedLayout.visibility = (extendedBolus != null && !pump.isFakingTempsByExtendedBoluses).toVisibility() + binding.infoLayout.extendedLayout.visibility = (extendedBolus is ValueWrapper.Existing && !pump.isFakingTempsByExtendedBoluses).toVisibility() // Active profile binding.loopPumpStatusLayout.activeProfile.text = profileFunction.getProfileNameWithDuration() @@ -749,8 +747,8 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList processButtonsVisibility() // iob - val bolusIob = iobCobCalculatorPlugin.calculateIobFromBolus().round() - val basalIob = treatmentsPlugin.lastCalculationTempBasals.round() + val bolusIob = iobCobCalculator.calculateIobFromBolus().round() + val basalIob = iobCobCalculator.calculateIobFromTempBasalsIncludingConvertedExtended().round() binding.infoLayout.iob.text = resourceHelper.gs(R.string.formatinsulinunits, bolusIob.iob + basalIob.basaliob) binding.infoLayout.iobLayout.setOnClickListener { @@ -769,7 +767,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList // cob var cobText: String = resourceHelper.gs(R.string.value_unavailable_short) - val cobInfo = iobCobCalculatorPlugin.getCobInfo(false, "Overview COB") + val cobInfo = iobCobCalculator.getCobInfo(false, "Overview COB") if (cobInfo.displayCob != null) { cobText = resourceHelper.gs(R.string.format_carbs, cobInfo.displayCob!!.toInt()) if (cobInfo.futureCarbs > 0) cobText += "(" + DecimalFormatter.to0Decimal(cobInfo.futureCarbs) + ")" @@ -813,7 +811,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList } binding.infoLayout.sensitivity.text = - iobCobCalculatorPlugin.getLastAutosensData("Overview")?.let { autosensData -> + iobCobCalculator.getLastAutosensData("Overview")?.let { autosensData -> String.format(Locale.ENGLISH, "%.0f%%", autosensData.autosensResult.ratio * 100) } ?: "" } @@ -823,7 +821,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList if (_binding == null) return@launch val menuChartSettings = overviewMenus.setting prepareGraphsIfNeeded(menuChartSettings.size) - val graphData = GraphData(injector, binding.graphsLayout.bgGraph, iobCobCalculatorPlugin, treatmentsPlugin) + val graphData = GraphData(injector, binding.graphsLayout.bgGraph, iobCobCalculator, treatmentsPlugin) val secondaryGraphsData: ArrayList = ArrayList() // do preparation in different thread @@ -890,7 +888,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList // ------------------ 2nd graph synchronized(graphLock) { for (g in 0 until min(secondaryGraphs.size, menuChartSettings.size + 1)) { - val secondGraphData = GraphData(injector, secondaryGraphs[g], iobCobCalculatorPlugin, treatmentsPlugin) + val secondGraphData = GraphData(injector, secondaryGraphs[g], iobCobCalculator, treatmentsPlugin) var useABSForScale = false var useIobForScale = false var useCobForScale = false diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewPlugin.kt index d8308f346e..d313ea81cf 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewPlugin.kt @@ -6,6 +6,7 @@ import dagger.android.HasAndroidInjector import info.nightscout.androidaps.Config import info.nightscout.androidaps.R import info.nightscout.androidaps.events.EventRefreshOverview +import info.nightscout.androidaps.extensions.* import info.nightscout.androidaps.interfaces.OverviewInterface import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.interfaces.PluginDescription diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/StatusLightHandler.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/StatusLightHandler.kt index ad6ce90b1e..b804a84d60 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/StatusLightHandler.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/StatusLightHandler.kt @@ -14,7 +14,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.eros.OmnipodErosPumpPlugi import info.nightscout.androidaps.plugins.pump.omnipod.eros.driver.definition.OmnipodConstants import info.nightscout.androidaps.utils.DecimalFormatter import info.nightscout.androidaps.utils.WarnColors -import info.nightscout.androidaps.utils.extensions.age +import info.nightscout.androidaps.extensions.age import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.sharedPreferences.SP import javax.inject.Inject diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphData/GraphData.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphData/GraphData.kt index 89cb764fd5..02023a8894 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphData/GraphData.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphData/GraphData.kt @@ -24,7 +24,7 @@ import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults import info.nightscout.androidaps.plugins.general.overview.graphExtensions.* import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult import info.nightscout.androidaps.utils.* -import info.nightscout.androidaps.utils.extensions.target +import info.nightscout.androidaps.extensions.target import info.nightscout.androidaps.utils.resources.ResourceHelper import java.util.* import javax.inject.Inject @@ -259,8 +259,8 @@ class GraphData( // Extended bolus if (!activePlugin.activePump.isFakingTempsByExtendedBoluses) { - treatmentsPlugin.extendedBolusesFromHistory.list - .filterTimeframe(fromTime, endTime) + repository.getExtendedBolusDataFromTimeToTime(fromTime, endTime, true).blockingGet() + .map { ExtendedBolusDataPoint(it) } .filter { it.duration != 0L } .forEach { it.y = getNearestBg(it.x.toLong()) @@ -529,9 +529,9 @@ class GraphData( while (time <= toTime) { // if align Dev Scale with BGI scale, then calculate BGI value, else bgi = 0.0 val bgi: Double = if (devBgiScale) { - val profile = profileFunction.getProfile(time) + val profile = profileFunction.getProfile(time) ?: continue total = iobCobCalculator.calculateFromTreatmentsAndTempsSynchronized(time, profile) - total.activity * (profile?.getIsfMgdl(time) ?: 0.0) * 5.0 + total.activity * profile.getIsfMgdl(time) * 5.0 } else 0.0 iobCobCalculator.getAutosensData(time)?.let { autosensData -> diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphExtensions/ExtendedBolusDataPoint.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphExtensions/ExtendedBolusDataPoint.kt new file mode 100644 index 0000000000..d286f83a45 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphExtensions/ExtendedBolusDataPoint.kt @@ -0,0 +1,25 @@ +package info.nightscout.androidaps.plugins.general.overview.graphExtensions + +import android.graphics.Color +import info.nightscout.androidaps.database.entities.ExtendedBolus +import info.nightscout.androidaps.extensions.toStringTotal +import javax.inject.Inject + +class ExtendedBolusDataPoint @Inject constructor( + val data: ExtendedBolus +) : DataPointWithLabelInterface { + + private var yValue = 0.0 + + override fun getX(): Double = data.timestamp.toDouble() + override fun getY(): Double = yValue + override fun getLabel(): String = data.toStringTotal() + override fun getDuration(): Long = data.duration + override fun getSize(): Float = 10f + override fun getShape(): PointsWithLabelGraphSeries.Shape = PointsWithLabelGraphSeries.Shape.EXTENDEDBOLUS + override fun getColor(): Int = Color.CYAN + + override fun setY(y: Double) { + yValue = y + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/PersistentNotificationPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/PersistentNotificationPlugin.kt index 781c1b82c7..b4f7522966 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/PersistentNotificationPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/PersistentNotificationPlugin.kt @@ -15,15 +15,14 @@ import info.nightscout.androidaps.events.* import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.plugins.bus.RxBusWrapper -import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider -import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin import info.nightscout.androidaps.utils.DecimalFormatter import info.nightscout.androidaps.utils.FabricPrivacy +import info.nightscout.androidaps.extensions.toStringShort import info.nightscout.androidaps.utils.resources.IconsProvider import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers -import info.nightscout.androidaps.utils.extensions.valueToUnitsString +import info.nightscout.androidaps.extensions.valueToUnitsString import io.reactivex.disposables.CompositeDisposable import javax.inject.Inject import javax.inject.Singleton @@ -150,14 +149,14 @@ class PersistentNotificationPlugin @Inject constructor( line1aa = resourceHelper.gs(R.string.missed_bg_readings) line1 = line1aa } - val activeTemp = activePlugins.activeTreatments.getTempBasalFromHistory(System.currentTimeMillis()) + val activeTemp = iobCobCalculator.getTempBasalIncludingConvertedExtended(System.currentTimeMillis()) if (activeTemp != null) { line1 += " " + activeTemp.toStringShort() line1aa += " " + activeTemp.toStringShort() + "." } //IOB val bolusIob = iobCobCalculator.calculateIobFromBolus().round() - val basalIob = activePlugins.activeTreatments.lastCalculationTempBasals.round() + val basalIob = iobCobCalculator.calculateIobFromTempBasalsIncludingConvertedExtended().round() line2 = resourceHelper.gs(R.string.treatments_iob_label_string) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U " + resourceHelper.gs(R.string.cob) + ": " + iobCobCalculator.getCobInfo(false, "PersistentNotificationPlugin").generateCOBString() val line2aa = resourceHelper.gs(R.string.treatments_iob_label_string) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U. " + resourceHelper.gs(R.string.cob) + ": " + iobCobCalculator.getCobInfo(false, "PersistentNotificationPlugin").generateCOBString() + "." line3 = DecimalFormatter.to2Decimal(pump.baseBasalRate) + " U/h" diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.kt index 66acbe94d8..4d18ce9559 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.kt @@ -41,7 +41,7 @@ import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProv import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.receivers.DataWorker import info.nightscout.androidaps.utils.* -import info.nightscout.androidaps.utils.extensions.valueToUnitsString +import info.nightscout.androidaps.extensions.valueToUnitsString import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.sharedPreferences.SP @@ -322,7 +322,7 @@ class SmsCommunicatorPlugin @Inject constructor( val glucoseStatus = glucoseStatusProvider.glucoseStatusData if (glucoseStatus != null) reply += resourceHelper.gs(R.string.sms_delta) + " " + Profile.toUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units) + " " + units + ", " val bolusIob = iobCobCalculator.calculateIobFromBolus().round() - val basalIob = activePlugin.activeTreatments.lastCalculationTempBasals.round() + val basalIob = iobCobCalculator.calculateIobFromTempBasalsIncludingConvertedExtended().round() val cobInfo = iobCobCalculator.getCobInfo(false, "SMS COB") reply += (resourceHelper.gs(R.string.sms_iob) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U (" + resourceHelper.gs(R.string.sms_bolus) + " " + DecimalFormatter.to2Decimal(bolusIob.iob) + "U " diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/UploadChunk.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/UploadChunk.kt index e8dcd49852..7fcf269e98 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/UploadChunk.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/UploadChunk.kt @@ -1,10 +1,9 @@ package info.nightscout.androidaps.plugins.general.tidepool.comm import info.nightscout.androidaps.R -import info.nightscout.androidaps.data.Intervals import info.nightscout.androidaps.database.AppRepository +import info.nightscout.androidaps.database.entities.TemporaryBasal import info.nightscout.androidaps.db.ProfileSwitch -import info.nightscout.androidaps.db.TemporaryBasal import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.DatabaseHelperInterface import info.nightscout.androidaps.interfaces.ProfileFunction @@ -146,18 +145,19 @@ class UploadChunk @Inject constructor( return selection } - private fun fromTemporaryBasals(tbrList: Intervals, start: Long, end: Long): List { + private fun fromTemporaryBasals(tbrList: List, start: Long, end: Long): List { val results = LinkedList() - for (tbr in tbrList.list) { - if (tbr.date in start..end && tbr.durationInMinutes != 0) - results.add(BasalElement(tbr, profileFunction)) + for (tbr in tbrList) { + if (tbr.timestamp in start..end) + profileFunction.getProfile(tbr.timestamp)?.let { + results.add(BasalElement(tbr, it)) + } } return results } private fun getBasals(start: Long, end: Long): List { - val temporaryBasals = treatmentsPlugin.temporaryBasalsFromHistory - temporaryBasals.merge() + val temporaryBasals = repository.getTemporaryBasalsDataFromTimeToTime(start, end, true).blockingGet() val selection = fromTemporaryBasals(temporaryBasals, start, end) // TODO do not upload running TBR if (selection.isNotEmpty()) rxBus.send(EventTidepoolStatus("${selection.size} TBRs selected for upload")) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/BasalElement.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/BasalElement.kt index 50e07a4096..a72e4c15cf 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/BasalElement.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/BasalElement.kt @@ -1,32 +1,38 @@ package info.nightscout.androidaps.plugins.general.tidepool.elements import com.google.gson.annotations.Expose -import info.nightscout.androidaps.db.TemporaryBasal -import info.nightscout.androidaps.interfaces.ProfileFunction +import info.nightscout.androidaps.data.Profile +import info.nightscout.androidaps.database.entities.TemporaryBasal +import info.nightscout.androidaps.extensions.convertedToAbsolute import java.util.* -class BasalElement(tbr: TemporaryBasal, private val profileFunction: ProfileFunction) - : BaseElement(tbr.date, UUID.nameUUIDFromBytes(("AAPS-basal" + tbr.date).toByteArray()).toString()) { +class BasalElement(tbr: TemporaryBasal, private val profile: Profile) + : BaseElement(tbr.timestamp, UUID.nameUUIDFromBytes(("AAPS-basal" + tbr.timestamp).toByteArray()).toString()) { internal var timestamp: Long = 0 // not exposed @Expose internal var deliveryType = "automated" + @Expose internal var duration: Long = 0 + @Expose internal var rate = -1.0 + @Expose internal var scheduleName = "AAPS" + @Expose internal var clockDriftOffset: Long = 0 + @Expose internal var conversionOffset: Long = 0 init { type = "basal" - timestamp = tbr.date - rate = tbr.tempBasalConvertedToAbsolute(tbr.date, profileFunction.getProfile(tbr.date)) - duration = tbr.end() - tbr.start() + timestamp = tbr.timestamp + rate = tbr.convertedToAbsolute(tbr.timestamp, profile) + duration = tbr.duration } } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/BloodGlucoseElement.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/BloodGlucoseElement.kt index a181a4a768..ffee11c3db 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/BloodGlucoseElement.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/BloodGlucoseElement.kt @@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.general.tidepool.elements import com.google.gson.annotations.Expose import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.database.entities.TherapyEvent -import info.nightscout.androidaps.utils.extensions.toConstant +import info.nightscout.androidaps.extensions.toConstant import java.util.* class BloodGlucoseElement(therapyEvent: TherapyEvent) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/ActionStringHandler.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/ActionStringHandler.kt index ae1db37455..8fcdf24920 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/ActionStringHandler.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/ActionStringHandler.kt @@ -33,7 +33,7 @@ import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorP import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.utils.* -import info.nightscout.androidaps.utils.extensions.valueToUnits +import info.nightscout.androidaps.extensions.valueToUnits import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.sharedPreferences.SP diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/wearintegration/WatchUpdaterService.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/wearintegration/WatchUpdaterService.java index d64cb9a38b..1955877cd6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/wearintegration/WatchUpdaterService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/wearintegration/WatchUpdaterService.java @@ -32,13 +32,14 @@ import dagger.android.AndroidInjection; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.general.overview.graphExtensions.GlucoseValueDataPoint; import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.database.AppRepository; import info.nightscout.androidaps.database.entities.Bolus; import info.nightscout.androidaps.database.entities.GlucoseValue; -import info.nightscout.androidaps.db.TemporaryBasal; +import info.nightscout.androidaps.database.entities.TemporaryBasal; +import info.nightscout.androidaps.extensions.GlucoseValueExtensionKt; +import info.nightscout.androidaps.extensions.TemporaryBasalExtensionKt; import info.nightscout.androidaps.interfaces.ActivePluginProvider; import info.nightscout.androidaps.interfaces.IobCobCalculator; import info.nightscout.androidaps.interfaces.PluginType; @@ -48,17 +49,16 @@ import info.nightscout.androidaps.logging.LTag; import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin; import info.nightscout.androidaps.plugins.bus.RxBusWrapper; import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus; +import info.nightscout.androidaps.plugins.general.overview.graphExtensions.GlucoseValueDataPoint; import info.nightscout.androidaps.plugins.general.wear.WearPlugin; import info.nightscout.androidaps.plugins.general.wear.events.EventWearConfirmAction; import info.nightscout.androidaps.plugins.general.wear.events.EventWearInitiateAction; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider; -import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; import info.nightscout.androidaps.receivers.ReceiverStatusStore; import info.nightscout.androidaps.utils.DecimalFormatter; import info.nightscout.androidaps.utils.DefaultValueHelper; import info.nightscout.androidaps.utils.ToastUtils; -import info.nightscout.androidaps.utils.extensions.GlucoseValueExtensionKt; import info.nightscout.androidaps.utils.resources.ResourceHelper; import info.nightscout.androidaps.utils.sharedPreferences.SP; @@ -75,7 +75,6 @@ public class WatchUpdaterService extends WearableListenerService implements Goog @Inject public ActivePluginProvider activePlugin; @Inject public LoopPlugin loopPlugin; @Inject public IobCobCalculator iobCobCalculator; - @Inject public TreatmentsPlugin treatmentsPlugin; @Inject public AppRepository repository; @Inject ReceiverStatusStore receiverStatusStore; @Inject Config config; @@ -437,8 +436,8 @@ public class WatchUpdaterService extends WearableListenerService implements Goog double beginBasalValue = profile.getBasal(beginBasalSegmentTime); double endBasalValue = beginBasalValue; - TemporaryBasal tb1 = treatmentsPlugin.getTempBasalFromHistory(runningTime); - TemporaryBasal tb2 = treatmentsPlugin.getTempBasalFromHistory(runningTime); //TODO for Adrian ... what's the meaning? + TemporaryBasal tb1 = iobCobCalculator.getTempBasalIncludingConvertedExtended(runningTime); + TemporaryBasal tb2 = iobCobCalculator.getTempBasalIncludingConvertedExtended(runningTime); //TODO for Adrian ... what's the meaning? double tb_before = beginBasalValue; double tb_amount = beginBasalValue; long tb_start = runningTime; @@ -447,7 +446,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog tb_before = beginBasalValue; Profile profileTB = profileFunction.getProfile(runningTime); if (profileTB != null) { - tb_amount = tb1.tempBasalConvertedToAbsolute(runningTime, profileTB); + tb_amount = TemporaryBasalExtensionKt.convertedToAbsolute(tb1, runningTime, profileTB); tb_start = runningTime; } } @@ -469,7 +468,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog } //temps - tb2 = treatmentsPlugin.getTempBasalFromHistory(runningTime); + tb2 = iobCobCalculator.getTempBasalIncludingConvertedExtended(runningTime); if (tb1 == null && tb2 == null) { //no temp stays no temp @@ -484,10 +483,10 @@ public class WatchUpdaterService extends WearableListenerService implements Goog tb1 = tb2; tb_start = runningTime; tb_before = endBasalValue; - tb_amount = tb1.tempBasalConvertedToAbsolute(runningTime, profileTB); + tb_amount = TemporaryBasalExtensionKt.convertedToAbsolute(tb1, runningTime, profileTB); } else if (tb1 != null && tb2 != null) { - double currentAmount = tb2.tempBasalConvertedToAbsolute(runningTime, profileTB); + double currentAmount = TemporaryBasalExtensionKt.convertedToAbsolute(tb2, runningTime, profileTB); if (currentAmount != tb_amount) { temps.add(tempDatamap(tb_start, tb_before, runningTime, currentAmount, tb_amount)); tb_start = runningTime; @@ -502,14 +501,14 @@ public class WatchUpdaterService extends WearableListenerService implements Goog basals.add(basalMap(beginBasalSegmentTime, runningTime, beginBasalValue)); } if (tb1 != null) { - tb2 = treatmentsPlugin.getTempBasalFromHistory(now); //use "now" to express current situation + tb2 = iobCobCalculator.getTempBasalIncludingConvertedExtended(now); //use "now" to express current situation if (tb2 == null) { //express the cancelled temp by painting it down one minute early temps.add(tempDatamap(tb_start, tb_before, now - 1 * 60 * 1000, endBasalValue, tb_amount)); } else { //express currently running temp by painting it a bit into the future Profile profileNow = profileFunction.getProfile(now); - double currentAmount = tb2.tempBasalConvertedToAbsolute(now, profileNow); + double currentAmount = TemporaryBasalExtensionKt.convertedToAbsolute(tb2, now, profileNow); if (currentAmount != tb_amount) { temps.add(tempDatamap(tb_start, tb_before, now, tb_amount, tb_amount)); temps.add(tempDatamap(now, tb_amount, runningTime + 5 * 60 * 1000, currentAmount, currentAmount)); @@ -518,11 +517,11 @@ public class WatchUpdaterService extends WearableListenerService implements Goog } } } else { - tb2 = treatmentsPlugin.getTempBasalFromHistory(now); //use "now" to express current situation + tb2 = iobCobCalculator.getTempBasalIncludingConvertedExtended(now); //use "now" to express current situation if (tb2 != null) { //onset at the end Profile profileTB = profileFunction.getProfile(runningTime); - double currentAmount = tb2.tempBasalConvertedToAbsolute(runningTime, profileTB); + double currentAmount = TemporaryBasalExtensionKt.convertedToAbsolute(tb2, runningTime, profileTB); temps.add(tempDatamap(now - 1 * 60 * 1000, endBasalValue, runningTime + 5 * 60 * 1000, currentAmount, currentAmount)); } } @@ -538,7 +537,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog if (sp.getBoolean("wear_predictions", true) && finalLastRun != null && finalLastRun.getRequest().getHasPredictions() && finalLastRun.getConstraintsProcessed() != null) { List predArray = finalLastRun.getConstraintsProcessed().getPredictions() - .stream().map( bg -> new GlucoseValueDataPoint(bg, defaultValueHelper, profileFunction, resourceHelper)) + .stream().map(bg -> new GlucoseValueDataPoint(bg, defaultValueHelper, profileFunction, resourceHelper)) .collect(Collectors.toList()); if (!predArray.isEmpty()) { @@ -688,7 +687,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog iobSum = iobDetail = cobString = currentBasal = bgiString = ""; if (profile != null) { IobTotal bolusIob = iobCobCalculator.calculateIobFromBolus().round(); - IobTotal basalIob = treatmentsPlugin.getLastCalculationTempBasals().round(); + IobTotal basalIob = iobCobCalculator.calculateIobFromTempBasalsIncludingConvertedExtended().round(); iobSum = DecimalFormatter.INSTANCE.to2Decimal(bolusIob.iob + basalIob.basaliob); iobDetail = "(" + DecimalFormatter.INSTANCE.to2Decimal(bolusIob.iob) + "|" + DecimalFormatter.INSTANCE.to2Decimal(basalIob.basaliob) + ")"; @@ -798,15 +797,11 @@ public class WatchUpdaterService extends WearableListenerService implements Goog if (profile == null) return ""; - TemporaryBasal activeTemp = treatmentsPlugin.getTempBasalFromHistory(System.currentTimeMillis()); + TemporaryBasal activeTemp = iobCobCalculator.getTempBasalIncludingConvertedExtended(System.currentTimeMillis()); if (activeTemp != null) { - basalStringResult = activeTemp.toStringShort(); + basalStringResult = TemporaryBasalExtensionKt.toStringShort(activeTemp); } else { - if (sp.getBoolean(R.string.key_danar_visualizeextendedaspercentage, false)) { - basalStringResult = "100%"; - } else { - basalStringResult = DecimalFormatter.INSTANCE.to2Decimal(profile.getBasal()) + "U/h"; - } + basalStringResult = DecimalFormatter.INSTANCE.to2Decimal(profile.getBasal()) + "U/h"; } return basalStringResult; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/xdripStatusline/StatusLinePlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/xdripStatusline/StatusLinePlugin.kt index 4dfc578292..81722b70c3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/xdripStatusline/StatusLinePlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/xdripStatusline/StatusLinePlugin.kt @@ -13,6 +13,7 @@ import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.utils.DecimalFormatter import info.nightscout.androidaps.utils.FabricPrivacy +import info.nightscout.androidaps.extensions.toStringShort import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.sharedPreferences.SP @@ -121,13 +122,13 @@ class StatusLinePlugin @Inject constructor( lastLoopStatus = true } //Temp basal - val activeTemp = activePlugin.activeTreatments.getTempBasalFromHistory(System.currentTimeMillis()) + val activeTemp = iobCobCalculator.getTempBasalIncludingConvertedExtended(System.currentTimeMillis()) if (activeTemp != null) { status += activeTemp.toStringShort() + " " } //IOB val bolusIob = iobCobCalculator.calculateIobFromBolus().round() - val basalIob = activePlugin.activeTreatments.lastCalculationTempBasals.round() + val basalIob = iobCobCalculator.calculateIobFromTempBasalsIncludingConvertedExtended().round() status += DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U" if (sp.getBoolean(R.string.key_xdripstatus_detailediob, true)) { status += ("(" diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/insulin/InsulinOrefFreePeakPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/insulin/InsulinOrefFreePeakPlugin.kt index 7200032b3c..1c27f8246c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/insulin/InsulinOrefFreePeakPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/insulin/InsulinOrefFreePeakPlugin.kt @@ -6,8 +6,8 @@ import info.nightscout.androidaps.interfaces.InsulinInterface import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.plugins.bus.RxBusWrapper -import info.nightscout.androidaps.utils.extensions.storeInt -import info.nightscout.androidaps.utils.extensions.putInt +import info.nightscout.androidaps.extensions.storeInt +import info.nightscout.androidaps.extensions.putInt import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.sharedPreferences.SP import org.json.JSONObject diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobCalculatorPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobCalculatorPlugin.kt index 54ff12c372..8619bd1296 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobCalculatorPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobCalculatorPlugin.kt @@ -9,9 +9,12 @@ import info.nightscout.androidaps.data.IobTotal import info.nightscout.androidaps.data.MealData import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.database.AppRepository +import info.nightscout.androidaps.database.ValueWrapper import info.nightscout.androidaps.database.entities.Bolus +import info.nightscout.androidaps.database.entities.ExtendedBolus import info.nightscout.androidaps.database.entities.GlucoseValue -import info.nightscout.androidaps.db.TemporaryBasal +import info.nightscout.androidaps.database.entities.TemporaryBasal +import info.nightscout.androidaps.database.interfaces.end import info.nightscout.androidaps.events.* import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.logging.AAPSLogger @@ -23,12 +26,13 @@ import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventNewHi import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin -import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DecimalFormatter import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.T -import info.nightscout.androidaps.utils.extensions.iobCalc +import info.nightscout.androidaps.extensions.convertedToAbsolute +import info.nightscout.androidaps.extensions.iobCalc +import info.nightscout.androidaps.extensions.toTemporaryBasal import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.sharedPreferences.SP @@ -52,7 +56,6 @@ open class IobCobCalculatorPlugin @Inject constructor( resourceHelper: ResourceHelper, private val profileFunction: ProfileFunction, private val activePlugin: ActivePluginProvider, - private val treatmentsPlugin: TreatmentsPlugin, private val sensitivityOref1Plugin: SensitivityOref1Plugin, private val sensitivityAAPSPlugin: SensitivityAAPSPlugin, private val sensitivityWeightedAveragePlugin: SensitivityWeightedAveragePlugin, @@ -173,7 +176,7 @@ open class IobCobCalculatorPlugin @Inject constructor( return autosensDataTable } - fun adjustToReferenceTime(someTime: Long): Long { + private fun adjustToReferenceTime(someTime: Long): Long { if (referenceTime == -1L) { referenceTime = someTime return someTime @@ -377,11 +380,25 @@ open class IobCobCalculatorPlugin @Inject constructor( bucketedData = bData } + fun oldestDataAvailable(): Long { + var oldestTime = System.currentTimeMillis() + val oldestTempBasal = repository.getOldestTemporaryBasalRecord() + if (oldestTempBasal != null) oldestTime = Math.min(oldestTime, oldestTempBasal.timestamp) + val oldestExtendedBolus = repository.getOldestExtendedBolusRecord() + if (oldestExtendedBolus != null) oldestTime = Math.min(oldestTime, oldestExtendedBolus.timestamp) + val oldestBolus = repository.getOldestBolusRecord() + if (oldestBolus != null) oldestTime = Math.min(oldestTime, oldestBolus.timestamp) + val oldestCarbs = repository.getOldestCarbsRecord() + if (oldestCarbs != null) oldestTime = Math.min(oldestTime, oldestCarbs.timestamp) + oldestTime -= 15 * 60 * 1000L // allow 15 min before + return oldestTime + } + fun calculateDetectionStart(from: Long, limitDataToOldestAvailable: Boolean): Long { val profile = profileFunction.getProfile(from) var dia = Constants.defaultDIA if (profile != null) dia = profile.dia - val oldestDataAvailable = treatmentsPlugin.oldestDataAvailable() + val oldestDataAvailable = oldestDataAvailable() val getBGDataFrom: Long if (limitDataToOldestAvailable) { getBGDataFrom = max(oldestDataAvailable, (from - T.hours(1).msecs() * (24 + dia)).toLong()) @@ -390,7 +407,7 @@ open class IobCobCalculatorPlugin @Inject constructor( return getBGDataFrom } - override fun calculateFromTreatmentsAndTempsSynchronized(time: Long, profile: Profile?): IobTotal { + override fun calculateFromTreatmentsAndTempsSynchronized(time: Long, profile: Profile): IobTotal { synchronized(dataLock) { return calculateFromTreatmentsAndTemps(time, profile) } } @@ -398,7 +415,7 @@ open class IobCobCalculatorPlugin @Inject constructor( synchronized(dataLock) { return calculateFromTreatmentsAndTemps(time, lastAutosensResult, exercise_mode, half_basal_exercise_target, isTempTarget) } } - fun calculateFromTreatmentsAndTemps(fromTime: Long, profile: Profile?): IobTotal { + fun calculateFromTreatmentsAndTemps(fromTime: Long, profile: Profile): IobTotal { val now = System.currentTimeMillis() val time = roundUpTime(fromTime) val cacheHit = iobTable[time] @@ -407,16 +424,18 @@ open class IobCobCalculatorPlugin @Inject constructor( return cacheHit } // else log.debug(">>> calculateFromTreatmentsAndTemps Cache miss " + new Date(time).toLocaleString()); val bolusIob = calculateIobFromBolusToTime(time).round() - val basalIob = treatmentsPlugin.getCalculationToTimeTempBasals(time, true, now).round() + val basalIob = calculateIobToTimeFromTempBasalsIncludingConvertedExtended(time).round() // OpenAPSSMB only // Add expected zero temp basal for next 240 minutes val basalIobWithZeroTemp = basalIob.copy() - val t = TemporaryBasal(injector) - .date(now + 60 * 1000L) - .duration(240) - .absolute(0.0) - if (t.date < time) { - val calc = t.iobCalc(time, profile) + val t = TemporaryBasal( + timestamp = now + 60 * 1000L, + duration = 240, + rate = 0.0, + isAbsolute = true, + type = TemporaryBasal.Type.NORMAL) + if (t.timestamp < time) { + val calc = t.iobCalc(time, profile, activePlugin.activeInsulin) basalIobWithZeroTemp.plus(calc) } basalIob.iobWithZeroTemp = IobTotal.combine(bolusIob, basalIobWithZeroTemp).round() @@ -437,7 +456,7 @@ open class IobCobCalculatorPlugin @Inject constructor( return cacheHit } // else log.debug(">>> calculateFromTreatmentsAndTemps Cache miss " + new Date(time).toLocaleString()); val bolusIob = calculateIobFromBolusToTime(time).round() - val basalIob = treatmentsPlugin.getAbsoluteIOBTempBasals(time).round() + val basalIob = calculateAbsoluteIobTempBasals(time).round() val iobTotal = IobTotal.combine(bolusIob, basalIob).round() if (time < System.currentTimeMillis()) { absIobTable.put(time, iobTotal) @@ -449,18 +468,20 @@ open class IobCobCalculatorPlugin @Inject constructor( private fun calculateFromTreatmentsAndTemps(time: Long, lastAutosensResult: AutosensResult, exercise_mode: Boolean, half_basal_exercise_target: Int, isTempTarget: Boolean): IobTotal { val now = DateUtil.now() val bolusIob = calculateIobFromBolusToTime(time).round() - val basalIob = treatmentsPlugin.getCalculationToTimeTempBasals(time, now, lastAutosensResult, exercise_mode, half_basal_exercise_target, isTempTarget).round() + val basalIob = getCalculationToTimeTempBasals(time, lastAutosensResult, exercise_mode, half_basal_exercise_target, isTempTarget).round() // OpenAPSSMB only // Add expected zero temp basal for next 240 minutes val basalIobWithZeroTemp = basalIob.copy() - val t = TemporaryBasal(injector) - .date(now + 60 * 1000L) - .duration(240) - .absolute(0.0) - if (t.date < time) { - val profile = profileFunction.getProfile(t.date) + val t = TemporaryBasal( + timestamp = now + 60 * 1000L, + duration = 240, + rate = 0.0, + isAbsolute = true, + type = TemporaryBasal.Type.NORMAL) + if (t.timestamp < time) { + val profile = profileFunction.getProfile(t.timestamp) if (profile != null) { - val calc = t.iobCalc(time, profile, lastAutosensResult, exercise_mode, half_basal_exercise_target, isTempTarget) + val calc = t.iobCalc(time, profile, lastAutosensResult, exercise_mode, half_basal_exercise_target, isTempTarget, activePlugin.activeInsulin) basalIobWithZeroTemp.plus(calc) } } @@ -484,11 +505,11 @@ open class IobCobCalculatorPlugin @Inject constructor( if (retVal == null) { //log.debug(">>> getBasalData Cache miss " + new Date(time).toLocaleString()); retVal = BasalData() - val tb = treatmentsPlugin.getTempBasalFromHistory(time) + val tb = getTempBasalIncludingConvertedExtended(time) retVal.basal = profile.getBasal(time) if (tb != null) { retVal.isTempBasalRunning = true - retVal.tempBasalAbsolute = tb.tempBasalConvertedToAbsolute(time, profile) + retVal.tempBasalAbsolute = tb.convertedToAbsolute(time, profile) } else { retVal.isTempBasalRunning = false retVal.tempBasalAbsolute = retVal.basal @@ -784,31 +805,29 @@ open class IobCobCalculatorPlugin @Inject constructor( * Time range to the past for IOB calculation * @return milliseconds */ - fun range(): Long { - val dia = profileFunction.getProfile()?.dia ?: Constants.defaultDIA - return (60 * 60 * 1000L * (24 + dia)).toLong() - } + fun range(): Long = ((profileFunction.getProfile()?.dia + ?: Constants.defaultDIA) * 60 * 60 * 1000).toLong() override fun calculateIobFromBolus(): IobTotal = calculateIobFromBolusToTime(dateUtil._now()) - override fun calculateIobFromBolusToTime(timestamp: Long): IobTotal { - val total = IobTotal(timestamp) + override fun calculateIobFromBolusToTime(toTime: Long): IobTotal { + val total = IobTotal(toTime) val profile = profileFunction.getProfile() ?: return total val dia = profile.dia val divisor = sp.getDouble(R.string.key_openapsama_bolussnooze_dia_divisor, 2.0) - val boluses = repository.getBolusesDataFromTime(timestamp - range(), true).blockingGet() + val boluses = repository.getBolusesDataFromTime(toTime - range(), true).blockingGet() boluses.forEach { t -> - if (t.isValid && t.timestamp < timestamp) { - val tIOB = t.iobCalc(activePlugin, timestamp, dia) + if (t.isValid && t.timestamp < toTime) { + val tIOB = t.iobCalc(activePlugin, toTime, dia) total.iob += tIOB.iobContrib total.activity += tIOB.activityContrib if (t.amount > 0 && t.timestamp > total.lastBolusTime) total.lastBolusTime = t.timestamp if (t.type != Bolus.Type.SMB) { // instead of dividing the DIA that only worked on the bilinear curves, // multiply the time the treatment is seen active. - val timeSinceTreatment = timestamp - t.timestamp + val timeSinceTreatment = toTime - t.timestamp val snoozeTime = t.timestamp + (timeSinceTreatment * divisor).toLong() val bIOB = t.iobCalc(activePlugin, snoozeTime, dia) total.bolussnooze += bIOB.iobContrib @@ -816,8 +835,146 @@ open class IobCobCalculatorPlugin @Inject constructor( } } - total.plus(treatmentsPlugin.getCalculationToTimeExtendedBoluses(timestamp)) + total.plus(calculateIobToTimeFromExtendedBoluses(toTime)) return total } + private fun calculateIobToTimeFromExtendedBoluses(toTime: Long): IobTotal { + val total = IobTotal(toTime) + val now = dateUtil._now() + val pumpInterface = activePlugin.activePump + if (!pumpInterface.isFakingTempsByExtendedBoluses) { + val extendedBoluses = repository.getExtendedBolusDataFromTimeToTime(toTime - range(), toTime, true).blockingGet() + for (pos in extendedBoluses.indices) { + val e = extendedBoluses[pos] + if (e.timestamp > toTime) continue + if (e.end > now) e.end = now + val profile = profileFunction.getProfile(e.timestamp) ?: return total + val calc = e.iobCalc(toTime, profile, activePlugin.activeInsulin) + total.plus(calc) + } + } + return total + } + + override fun getTempBasal(timestamp: Long): TemporaryBasal? { + val tb = repository.getTemporaryBasalActiveAt(timestamp).blockingGet() + if (tb is ValueWrapper.Existing) return tb.value + return null + } + + override fun getExtendedBolus(timestamp: Long): ExtendedBolus? { + val tb = repository.getExtendedBolusActiveAt(timestamp).blockingGet() + if (tb is ValueWrapper.Existing) return tb.value + return null + } + + override fun getTempBasalIncludingConvertedExtended(timestamp: Long): TemporaryBasal? { + val tb = repository.getTemporaryBasalActiveAt(timestamp).blockingGet() + if (tb is ValueWrapper.Existing) return tb.value + val eb = repository.getExtendedBolusActiveAt(timestamp).blockingGet() + val profile = profileFunction.getProfile(timestamp) ?: return null + if (eb is ValueWrapper.Existing && activePlugin.activePump.isFakingTempsByExtendedBoluses) + return eb.value.toTemporaryBasal(profile) + return null + } + + override fun calculateAbsoluteIobTempBasals(toTime: Long): IobTotal { + val total = IobTotal(toTime) + var i = toTime - range() + while (i < toTime) { + val profile = profileFunction.getProfile(i) + if (profile == null) { + i += T.mins(5).msecs() + continue + } + val runningTBR = getTempBasalIncludingConvertedExtended(i) + val running = runningTBR?.convertedToAbsolute(i, profile) ?: profile.getBasal(i) + val bolus = Bolus( + timestamp = i, + amount = running * 5.0 / 60.0, + type = Bolus.Type.NORMAL, + isBasalInsulin = true + ) + val iob = bolus.iobCalc(activePlugin, toTime, profile.dia) + total.basaliob += iob.iobContrib + total.activity += iob.activityContrib + i += T.mins(5).msecs() + } + return total + } + + override fun calculateIobFromTempBasalsIncludingConvertedExtended(): IobTotal = + calculateIobToTimeFromTempBasalsIncludingConvertedExtended(dateUtil._now()) + + override fun calculateIobToTimeFromTempBasalsIncludingConvertedExtended(toTime: Long): IobTotal { + val total = IobTotal(toTime) + val now = dateUtil._now() + val pumpInterface = activePlugin.activePump + + val temporaryBasals = repository.getTemporaryBasalsDataFromTimeToTime(toTime - range(), toTime, true).blockingGet() + for (pos in temporaryBasals.indices) { + val t = temporaryBasals[pos] + if (t.timestamp > toTime) continue + val profile = profileFunction.getProfile(t.timestamp) ?: continue + if (t.end > now) t.end = now + val calc = t.iobCalc(toTime, profile, activePlugin.activeInsulin) + //log.debug("BasalIOB " + new Date(time) + " >>> " + calc.basaliob); + total.plus(calc) + } + if (pumpInterface.isFakingTempsByExtendedBoluses) { + val totalExt = IobTotal(toTime) + val extendedBoluses = repository.getExtendedBolusDataFromTimeToTime(toTime - range(), toTime, true).blockingGet() + for (pos in extendedBoluses.indices) { + val e = extendedBoluses[pos] + if (e.timestamp > toTime) continue + val profile = profileFunction.getProfile(e.timestamp) ?: continue + if (e.end > now) e.end = now + val calc = e.iobCalc(toTime, profile, activePlugin.activeInsulin) + totalExt.plus(calc) + } + // Convert to basal iob + totalExt.basaliob = totalExt.iob + totalExt.iob = 0.0 + totalExt.netbasalinsulin = totalExt.extendedBolusInsulin + totalExt.hightempinsulin = totalExt.extendedBolusInsulin + total.plus(totalExt) + } + return total + } + + open fun getCalculationToTimeTempBasals(toTime: Long, lastAutosensResult: AutosensResult, exercise_mode: Boolean, half_basal_exercise_target: Int, isTempTarget: Boolean): IobTotal { + val total = IobTotal(toTime) + val pumpInterface = activePlugin.activePump + val now = dateUtil._now() + val temporaryBasals = repository.getTemporaryBasalsDataFromTimeToTime(toTime - range(), toTime, true).blockingGet() + for (pos in temporaryBasals.indices) { + val t = temporaryBasals[pos] + if (t.timestamp > toTime) continue + val profile = profileFunction.getProfile(t.timestamp) ?: continue + if (t.end > now) t.end = now + val calc = t.iobCalc(toTime, profile, lastAutosensResult, exercise_mode, half_basal_exercise_target, isTempTarget, activePlugin.activeInsulin) + //log.debug("BasalIOB " + new Date(time) + " >>> " + calc.basaliob); + total.plus(calc) + } + if (pumpInterface.isFakingTempsByExtendedBoluses) { + val totalExt = IobTotal(toTime) + val extendedBoluses = repository.getExtendedBolusDataFromTimeToTime(toTime - range(), toTime, true).blockingGet() + for (pos in extendedBoluses.indices) { + val e = extendedBoluses[pos] + if (e.timestamp > toTime) continue + val profile = profileFunction.getProfile(e.timestamp) ?: continue + if (e.end > now) e.end = now + val calc = e.iobCalc(toTime, profile, lastAutosensResult, exercise_mode, half_basal_exercise_target, isTempTarget, activePlugin.activeInsulin) + totalExt.plus(calc) + } + // Convert to basal iob + totalExt.basaliob = totalExt.iob + totalExt.iob = 0.0 + totalExt.netbasalinsulin = totalExt.extendedBolusInsulin + totalExt.hightempinsulin = totalExt.extendedBolusInsulin + total.plus(totalExt) + } + return total + } } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobOref1Thread.kt b/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobOref1Thread.kt index d1d155cbd9..ab3fe43111 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobOref1Thread.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobOref1Thread.kt @@ -25,7 +25,7 @@ import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin import info.nightscout.androidaps.utils.* import info.nightscout.androidaps.utils.buildHelper.BuildHelper -import info.nightscout.androidaps.utils.extensions.target +import info.nightscout.androidaps.extensions.target import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.sharedPreferences.SP import java.util.* diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/virtual/VirtualPumpFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/pump/virtual/VirtualPumpFragment.kt index bdbc298ff5..527e66eb3d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/virtual/VirtualPumpFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/virtual/VirtualPumpFragment.kt @@ -10,24 +10,29 @@ import info.nightscout.androidaps.R import info.nightscout.androidaps.databinding.VirtualpumpFragmentBinding import info.nightscout.androidaps.events.EventExtendedBolusChange import info.nightscout.androidaps.events.EventTempBasalChange +import info.nightscout.androidaps.interfaces.IobCobCalculator +import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.pump.virtual.events.EventVirtualPumpUpdateGui -import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin +import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.T -import io.reactivex.rxkotlin.plusAssign +import info.nightscout.androidaps.extensions.toStringFull import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers import io.reactivex.disposables.CompositeDisposable +import io.reactivex.rxkotlin.plusAssign import javax.inject.Inject class VirtualPumpFragment : DaggerFragment() { @Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var resourceHelper: ResourceHelper + @Inject lateinit var dateUtil: DateUtil @Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var virtualPumpPlugin: VirtualPumpPlugin - @Inject lateinit var treatmentsPlugin: TreatmentsPlugin + @Inject lateinit var profileFunction: ProfileFunction + @Inject lateinit var iobCobCalculator: IobCobCalculator @Inject lateinit var aapsSchedulers: AapsSchedulers private val disposable = CompositeDisposable() @@ -88,10 +93,11 @@ class VirtualPumpFragment : DaggerFragment() { @Synchronized private fun updateGui() { if (_binding == null) return + val profile = profileFunction.getProfile() ?: return binding.basabasalrate.text = resourceHelper.gs(R.string.pump_basebasalrate, virtualPumpPlugin.baseBasalRate) - binding.tempbasal.text = treatmentsPlugin.getTempBasalFromHistory(System.currentTimeMillis())?.toStringFull() + binding.tempbasal.text = iobCobCalculator.getTempBasal(dateUtil._now())?.toStringFull(profile, dateUtil) ?: "" - binding.extendedbolus.text = treatmentsPlugin.getExtendedBolusFromHistory(System.currentTimeMillis())?.toString() + binding.extendedbolus.text = iobCobCalculator.getExtendedBolus(dateUtil._now())?.toStringFull(dateUtil) ?: "" binding.battery.text = resourceHelper.gs(R.string.format_percent, virtualPumpPlugin.batteryPercent) binding.reservoir.text = resourceHelper.gs(R.string.formatinsulinunits, virtualPumpPlugin.reservoirInUnits.toDouble()) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/virtual/VirtualPumpPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/pump/virtual/VirtualPumpPlugin.kt index d2e761f3b3..bfa0c7a44f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/virtual/VirtualPumpPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/virtual/VirtualPumpPlugin.kt @@ -9,9 +9,6 @@ import info.nightscout.androidaps.R import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.PumpEnactResult -import info.nightscout.androidaps.db.ExtendedBolus -import info.nightscout.androidaps.db.Source -import info.nightscout.androidaps.db.TemporaryBasal import info.nightscout.androidaps.events.EventPreferenceChange import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.logging.AAPSLogger @@ -23,12 +20,13 @@ import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewB import info.nightscout.androidaps.plugins.general.overview.notifications.Notification import info.nightscout.androidaps.plugins.pump.common.defs.PumpType import info.nightscout.androidaps.plugins.pump.virtual.events.EventVirtualPumpUpdateGui -import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.InstanceId.instanceId import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.TimeChangeType +import info.nightscout.androidaps.extensions.convertedToAbsolute +import info.nightscout.androidaps.extensions.plannedRemainingMinutes import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.sharedPreferences.SP @@ -50,7 +48,7 @@ open class VirtualPumpPlugin @Inject constructor( private val aapsSchedulers: AapsSchedulers, private val sp: SP, private val profileFunction: ProfileFunction, - private val treatmentsPlugin: TreatmentsPlugin, + private val iobCobCalculator: IobCobCalculator, commandQueue: CommandQueueProvider, private val pumpSync: PumpSync, private val config: Config, @@ -223,11 +221,6 @@ open class VirtualPumpPlugin @Inject constructor( override fun stopBolusDelivering() {} override fun setTempBasalAbsolute(absoluteRate: Double, durationInMinutes: Int, profile: Profile, enforceNew: Boolean, tbrType: PumpSync.TemporaryBasalType): PumpEnactResult { - val tempBasal = TemporaryBasal(injector) - .date(System.currentTimeMillis()) - .absolute(absoluteRate) - .duration(durationInMinutes) - .source(Source.USER) val result = PumpEnactResult(injector) result.success = true result.enacted = true @@ -235,7 +228,16 @@ open class VirtualPumpPlugin @Inject constructor( result.absolute = absoluteRate result.duration = durationInMinutes result.comment = resourceHelper.gs(R.string.virtualpump_resultok) - treatmentsPlugin.addToHistoryTempBasal(tempBasal) + pumpSync.syncTemporaryBasalWithPumpId( + timestamp = dateUtil._now(), + rate = absoluteRate, + duration = T.mins(durationInMinutes.toLong()).msecs(), + isAbsolute = true, + type = tbrType, + pumpId = dateUtil._now(), + pumpType = pumpType ?: PumpType.GENERIC_AAPS, + pumpSerial = serialNumber() + ) aapsLogger.debug(LTag.PUMP, "Setting temp basal absolute: $result") rxBus.send(EventVirtualPumpUpdateGui()) lastDataTime = System.currentTimeMillis() @@ -243,11 +245,6 @@ open class VirtualPumpPlugin @Inject constructor( } override fun setTempBasalPercent(percent: Int, durationInMinutes: Int, profile: Profile, enforceNew: Boolean, tbrType: PumpSync.TemporaryBasalType): PumpEnactResult { - val tempBasal = TemporaryBasal(injector) - .date(System.currentTimeMillis()) - .percent(percent) - .duration(durationInMinutes) - .source(Source.USER) val result = PumpEnactResult(injector) result.success = true result.enacted = true @@ -256,7 +253,16 @@ open class VirtualPumpPlugin @Inject constructor( result.isTempCancel = false result.duration = durationInMinutes result.comment = resourceHelper.gs(R.string.virtualpump_resultok) - treatmentsPlugin.addToHistoryTempBasal(tempBasal) + pumpSync.syncTemporaryBasalWithPumpId( + timestamp = dateUtil._now(), + rate = percent.toDouble(), + duration = T.mins(durationInMinutes.toLong()).msecs(), + isAbsolute = false, + type = tbrType, + pumpId = dateUtil._now(), + pumpType = pumpType ?: PumpType.GENERIC_AAPS, + pumpSerial = serialNumber() + ) aapsLogger.debug(LTag.PUMP, "Settings temp basal percent: $result") rxBus.send(EventVirtualPumpUpdateGui()) lastDataTime = System.currentTimeMillis() @@ -266,18 +272,21 @@ open class VirtualPumpPlugin @Inject constructor( override fun setExtendedBolus(insulin: Double, durationInMinutes: Int): PumpEnactResult { val result = cancelExtendedBolus() if (!result.success) return result - val extendedBolus = ExtendedBolus(injector) - .date(System.currentTimeMillis()) - .insulin(insulin) - .durationInMinutes(durationInMinutes) - .source(Source.USER) result.success = true result.enacted = true result.bolusDelivered = insulin result.isTempCancel = false result.duration = durationInMinutes result.comment = resourceHelper.gs(R.string.virtualpump_resultok) - treatmentsPlugin.addToHistoryExtendedBolus(extendedBolus) + pumpSync.syncExtendedBolusWithPumpId( + timestamp = dateUtil._now(), + amount = insulin, + duration = T.mins(durationInMinutes.toLong()).msecs(), + isEmulatingTB = false, + pumpId = dateUtil._now(), + pumpType = pumpType ?: PumpType.GENERIC_AAPS, + pumpSerial = serialNumber() + ) aapsLogger.debug(LTag.PUMP, "Setting extended bolus: $result") rxBus.send(EventVirtualPumpUpdateGui()) lastDataTime = System.currentTimeMillis() @@ -289,11 +298,14 @@ open class VirtualPumpPlugin @Inject constructor( result.success = true result.isTempCancel = true result.comment = resourceHelper.gs(R.string.virtualpump_resultok) - if (treatmentsPlugin.isTempBasalInProgress) { + if (pumpSync.expectedPumpState().temporaryBasal != null) { result.enacted = true - val tempStop = TemporaryBasal(injector).date(System.currentTimeMillis()).source(Source.USER) - treatmentsPlugin.addToHistoryTempBasal(tempStop) - //tempBasal = null; + pumpSync.syncStopTemporaryBasalWithPumpId( + timestamp = dateUtil._now(), + endPumpId = dateUtil._now(), + pumpType = pumpType ?: PumpType.GENERIC_AAPS, + pumpSerial = serialNumber() + ) aapsLogger.debug(LTag.PUMP, "Canceling temp basal: $result") rxBus.send(EventVirtualPumpUpdateGui()) } @@ -303,10 +315,13 @@ open class VirtualPumpPlugin @Inject constructor( override fun cancelExtendedBolus(): PumpEnactResult { val result = PumpEnactResult(injector) - if (treatmentsPlugin.isInHistoryExtendedBolusInProgress) { - val exStop = ExtendedBolus(injector, System.currentTimeMillis()) - exStop.source = Source.USER - treatmentsPlugin.addToHistoryExtendedBolus(exStop) + if (pumpSync.expectedPumpState().extendedBolus != null) { + pumpSync.syncStopExtendedBolusWithPumpId( + timestamp = dateUtil._now(), + endPumpId = dateUtil._now(), + pumpType = pumpType ?: PumpType.GENERIC_AAPS, + pumpSerial = serialNumber() + ) } result.success = true result.enacted = true @@ -335,16 +350,16 @@ open class VirtualPumpPlugin @Inject constructor( extended.put("ActiveProfile", profileName) } catch (ignored: Exception) { } - val tb = treatmentsPlugin.getTempBasalFromHistory(now) + val tb = iobCobCalculator.getTempBasal(now) if (tb != null) { - extended.put("TempBasalAbsoluteRate", tb.tempBasalConvertedToAbsolute(now, profile)) - extended.put("TempBasalStart", dateUtil.dateAndTimeString(tb.date)) + extended.put("TempBasalAbsoluteRate", tb.convertedToAbsolute(now, profile)) + extended.put("TempBasalStart", dateUtil.dateAndTimeString(tb.timestamp)) extended.put("TempBasalRemaining", tb.plannedRemainingMinutes) } - val eb = treatmentsPlugin.getExtendedBolusFromHistory(now) + val eb = iobCobCalculator.getExtendedBolus(now) if (eb != null) { - extended.put("ExtendedBolusAbsoluteRate", eb.absoluteRate()) - extended.put("ExtendedBolusStart", dateUtil.dateAndTimeString(eb.date)) + extended.put("ExtendedBolusAbsoluteRate", eb.rate) + extended.put("ExtendedBolusStart", dateUtil.dateAndTimeString(eb.timestamp)) extended.put("ExtendedBolusRemaining", eb.plannedRemainingMinutes) } status.put("timestamp", DateUtil.toISOString(now)) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/sensitivity/SensitivityAAPSPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/sensitivity/SensitivityAAPSPlugin.kt index 48315d3fed..b232b03db3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/sensitivity/SensitivityAAPSPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/sensitivity/SensitivityAAPSPlugin.kt @@ -18,7 +18,7 @@ import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin.Companion.percentile import info.nightscout.androidaps.utils.DateUtil -import info.nightscout.androidaps.utils.extensions.isEvent5minBack +import info.nightscout.androidaps.extensions.isEvent5minBack import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.sharedPreferences.SP import org.json.JSONException diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/sensitivity/SensitivityOref1Plugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/sensitivity/SensitivityOref1Plugin.kt index e0d6af60c1..6627a37efe 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/sensitivity/SensitivityOref1Plugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/sensitivity/SensitivityOref1Plugin.kt @@ -19,7 +19,7 @@ import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin.Companion.percentile import info.nightscout.androidaps.utils.DateUtil -import info.nightscout.androidaps.utils.extensions.isEvent5minBack +import info.nightscout.androidaps.extensions.isEvent5minBack import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.sharedPreferences.SP import org.json.JSONException diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/sensitivity/SensitivityWeightedAveragePlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/sensitivity/SensitivityWeightedAveragePlugin.kt index b751a70389..9ea309e43d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/sensitivity/SensitivityWeightedAveragePlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/sensitivity/SensitivityWeightedAveragePlugin.kt @@ -18,7 +18,7 @@ import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult import info.nightscout.androidaps.utils.DateUtil -import info.nightscout.androidaps.utils.extensions.isEvent5minBack +import info.nightscout.androidaps.extensions.isEvent5minBack import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.sharedPreferences.SP import org.json.JSONException diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/BGSourceFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/BGSourceFragment.kt index a889ea38ba..07d9892305 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/BGSourceFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/BGSourceFragment.kt @@ -24,9 +24,9 @@ import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.alertDialogs.OKDialog -import info.nightscout.androidaps.utils.extensions.directionToIcon -import info.nightscout.androidaps.utils.extensions.toVisibility -import info.nightscout.androidaps.utils.extensions.valueToUnitsString +import info.nightscout.androidaps.extensions.directionToIcon +import info.nightscout.androidaps.extensions.toVisibility +import info.nightscout.androidaps.extensions.valueToUnitsString import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers import io.reactivex.disposables.CompositeDisposable diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/DexcomPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/DexcomPlugin.kt index 1614a1aa61..75dde2a6d4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/DexcomPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/DexcomPlugin.kt @@ -21,15 +21,12 @@ import info.nightscout.androidaps.interfaces.PluginDescription import info.nightscout.androidaps.interfaces.PluginType import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag -import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.receivers.DataWorker import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.XDripBroadcast import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.sharedPreferences.SP -import io.reactivex.disposables.CompositeDisposable -import io.reactivex.rxkotlin.plusAssign import javax.inject.Inject import javax.inject.Singleton @@ -73,10 +70,6 @@ class DexcomPlugin @Inject constructor( dexcomMediator.requestPermissionIfNeeded() } - override fun onStop() { - super.onStop() - } - // cannot be inner class because of needed injection class DexcomWorker( context: Context, diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/RandomBgPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/RandomBgPlugin.kt index 89f8dc7f6d..30a814e5e1 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/RandomBgPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/RandomBgPlugin.kt @@ -57,6 +57,9 @@ class RandomBgPlugin @Inject constructor( companion object { const val interval = 5L // minutes + const val min = 70 // mgdl + const val max = 190 // mgdl + const val period = 30.0 // minutes } init { @@ -93,12 +96,10 @@ class RandomBgPlugin @Inject constructor( private fun handleNewData() { if (!isEnabled(PluginType.BGSOURCE)) return - val min = 70 - val max = 190 val cal = GregorianCalendar() val currentMinute = cal.get(Calendar.MINUTE) + (cal.get(Calendar.HOUR_OF_DAY) % 2) * 60 - val bgMgdl = min + ((max - min) + (max - min) * sin(currentMinute / 120.0 * 2 * PI)) / 2 + val bgMgdl = min + ((max - min) + (max - min) * sin(currentMinute / period * 2 * PI)) / 2 val glucoseValues = mutableListOf() glucoseValues += CgmSourceTransaction.TransactionGlucoseValue( diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/TomatoPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/TomatoPlugin.kt index 92a92e7ef2..831770f3d5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/TomatoPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/TomatoPlugin.kt @@ -15,7 +15,6 @@ import info.nightscout.androidaps.interfaces.PluginDescription import info.nightscout.androidaps.interfaces.PluginType import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag -import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.utils.XDripBroadcast import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.sharedPreferences.SP @@ -49,7 +48,6 @@ class TomatoPlugin @Inject constructor( @Inject lateinit var tomatoPlugin: TomatoPlugin @Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var sp: SP - @Inject lateinit var nsUpload: NSUpload @Inject lateinit var repository: AppRepository @Inject lateinit var broadcastToXDrip: XDripBroadcast diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsFragment.kt index bb9b84edd0..ff941b4af9 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsFragment.kt @@ -11,11 +11,13 @@ import info.nightscout.androidaps.R import info.nightscout.androidaps.databinding.TreatmentsFragmentBinding import info.nightscout.androidaps.events.EventExtendedBolusChange import info.nightscout.androidaps.interfaces.ActivePluginProvider +import info.nightscout.androidaps.interfaces.IobCobCalculator import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.treatments.fragments.* +import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.buildHelper.BuildHelper -import info.nightscout.androidaps.utils.extensions.toVisibility +import info.nightscout.androidaps.extensions.toVisibility import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers import io.reactivex.disposables.CompositeDisposable @@ -28,9 +30,10 @@ class TreatmentsFragment : DaggerFragment() { @Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var activePlugin: ActivePluginProvider - @Inject lateinit var treatmentsPlugin: TreatmentsPlugin + @Inject lateinit var iobCobCalculator: IobCobCalculator @Inject lateinit var aapsSchedulers: AapsSchedulers @Inject lateinit var buildHelper: BuildHelper + @Inject lateinit var dateUtil: DateUtil private val disposable = CompositeDisposable() @@ -124,6 +127,6 @@ class TreatmentsFragment : DaggerFragment() { private fun updateGui() { if (_binding == null) return - binding.extendedBoluses.visibility = (activePlugin.activePump.pumpDescription.isExtendedBolusCapable || treatmentsPlugin.extendedBolusesFromHistory.size() > 0).toVisibility() + binding.extendedBoluses.visibility = (activePlugin.activePump.pumpDescription.isExtendedBolusCapable || iobCobCalculator.getExtendedBolus(dateUtil._now()) != null).toVisibility() } } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPlugin.java index 402017e384..ce54206dbe 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPlugin.java @@ -1,13 +1,10 @@ package info.nightscout.androidaps.plugins.treatments; import android.content.Context; -import android.os.Bundle; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import com.google.firebase.analytics.FirebaseAnalytics; - import java.util.List; import java.util.stream.Collectors; @@ -17,25 +14,15 @@ import javax.inject.Singleton; import dagger.android.HasAndroidInjector; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.activities.ErrorHelperActivity; import info.nightscout.androidaps.data.DetailedBolusInfo; -import info.nightscout.androidaps.data.Intervals; -import info.nightscout.androidaps.data.Iob; -import info.nightscout.androidaps.data.IobTotal; -import info.nightscout.androidaps.data.NonOverlappingIntervals; -import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.ProfileIntervals; import info.nightscout.androidaps.database.AppRepository; -import info.nightscout.androidaps.database.entities.Bolus; -import info.nightscout.androidaps.database.entities.Carbs; import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.ProfileSwitch; import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.events.EventReloadProfileSwitchData; -import info.nightscout.androidaps.events.EventReloadTempBasalData; -import info.nightscout.androidaps.events.EventReloadTreatmentData; import info.nightscout.androidaps.interfaces.ActivePluginProvider; import info.nightscout.androidaps.interfaces.DatabaseHelperInterface; import info.nightscout.androidaps.interfaces.PluginBase; @@ -43,25 +30,16 @@ import info.nightscout.androidaps.interfaces.PluginDescription; import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.interfaces.ProfileFunction; import info.nightscout.androidaps.interfaces.ProfileStore; -import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.TreatmentServiceInterface; import info.nightscout.androidaps.interfaces.TreatmentsInterface; -import info.nightscout.androidaps.interfaces.UpdateReturn; -import info.nightscout.androidaps.interfaces.UploadQueueInterface; import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.logging.LTag; import info.nightscout.androidaps.plugins.bus.RxBusWrapper; import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; -import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult; -import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; -import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin; -import info.nightscout.androidaps.plugins.pump.medtronic.data.MedtronicHistoryData; import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.FabricPrivacy; -import info.nightscout.androidaps.utils.T; -import info.nightscout.androidaps.utils.extensions.BolusExtensionKt; import info.nightscout.androidaps.utils.resources.ResourceHelper; import info.nightscout.androidaps.utils.rx.AapsSchedulers; import info.nightscout.androidaps.utils.sharedPreferences.SP; @@ -78,7 +56,6 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface private final ProfileFunction profileFunction; private final ActivePluginProvider activePlugin; private final NSUpload nsUpload; - private final UploadQueueInterface uploadQueue; private final FabricPrivacy fabricPrivacy; private final DateUtil dateUtil; private final DatabaseHelperInterface databaseHelper; @@ -88,8 +65,6 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface protected TreatmentServiceInterface service; - private final Intervals tempBasals = new NonOverlappingIntervals<>(); - private final Intervals extendedBoluses = new NonOverlappingIntervals<>(); private final ProfileIntervals profiles = new ProfileIntervals<>(); @Inject @@ -106,7 +81,6 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface NSUpload nsUpload, FabricPrivacy fabricPrivacy, DateUtil dateUtil, - UploadQueueInterface uploadQueue, DatabaseHelperInterface databaseHelper, AppRepository repository ) { @@ -131,7 +105,6 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface this.fabricPrivacy = fabricPrivacy; this.dateUtil = dateUtil; this.nsUpload = nsUpload; - this.uploadQueue = uploadQueue; this.databaseHelper = databaseHelper; this.repository = repository; } @@ -141,32 +114,12 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface this.service = new TreatmentService(getInjector()); initializeData(range()); super.onStart(); - disposable.add(rxBus - .toObservable(EventReloadTreatmentData.class) - .observeOn(aapsSchedulers.getIo()) - .subscribe(event -> { - getAapsLogger().debug(LTag.DATATREATMENTS, "EventReloadTreatmentData"); - //initializeTreatmentData(range()); - initializeExtendedBolusData(range()); - rxBus.send(event.getNext()); - }, - fabricPrivacy::logException - )); disposable.add(rxBus .toObservable(EventReloadProfileSwitchData.class) .observeOn(aapsSchedulers.getIo()) .subscribe(event -> initializeProfileSwitchData(range()), fabricPrivacy::logException )); - disposable.add(rxBus - .toObservable(EventReloadTempBasalData.class) - .observeOn(aapsSchedulers.getIo()) - .subscribe(event -> { - getAapsLogger().debug(LTag.DATATREATMENTS, "EventReloadTempBasalData"); - initializeTempBasalData(range()); - }, - fabricPrivacy::logException - )); } @Override @@ -188,27 +141,9 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface } public void initializeData(long range) { - initializeTempBasalData(range); - initializeExtendedBolusData(range); initializeProfileSwitchData(range); } - private void initializeTempBasalData(long range) { - getAapsLogger().debug(LTag.DATATREATMENTS, "initializeTempBasalData"); - synchronized (tempBasals) { - tempBasals.reset().add(databaseHelper.getTemporaryBasalsDataFromTime(DateUtil.now() - range, false)); - } - - } - - private void initializeExtendedBolusData(long range) { - getAapsLogger().debug(LTag.DATATREATMENTS, "initializeExtendedBolusData"); - synchronized (extendedBoluses) { - extendedBoluses.reset().add(databaseHelper.getExtendedBolusDataFromTime(DateUtil.now() - range, false)); - } - - } - private void initializeProfileSwitchData(long range) { getAapsLogger().debug(LTag.DATATREATMENTS, "initializeProfileSwitchData"); synchronized (profiles) { @@ -216,28 +151,6 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface } } - @Override - public IobTotal getCalculationToTimeExtendedBoluses(long time) { - IobTotal total = new IobTotal(time); - - Profile profile = profileFunction.getProfile(); - if (profile == null) - return total; - - PumpInterface pumpInterface = activePlugin.getActivePump(); - - if (!pumpInterface.isFakingTempsByExtendedBoluses()) - synchronized (extendedBoluses) { - for (int pos = 0; pos < extendedBoluses.size(); pos++) { - ExtendedBolus e = extendedBoluses.get(pos); - if (e.date > time) continue; - IobTotal calc = e.iobCalc(time, profile); - total.plus(calc); - } - } - return total; - } - /** * Returns all Treatments after specified timestamp. Also returns invalid entries (required to * map "Fill Cannula" entries to history (and not to add double bolus for it) @@ -307,211 +220,12 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface */ - @Override - public boolean isInHistoryRealTempBasalInProgress() { - return getRealTempBasalFromHistory(System.currentTimeMillis()) != null; - } - - @Override - public TemporaryBasal getRealTempBasalFromHistory(long time) { - synchronized (tempBasals) { - return tempBasals.getValueByInterval(time); - } - } - - @Override - public boolean isTempBasalInProgress() { - return getTempBasalFromHistory(System.currentTimeMillis()) != null; - } - - @Override public void removeTempBasal(TemporaryBasal tempBasal) { - String tempBasalId = tempBasal._id; - if (NSUpload.isIdValid(tempBasalId)) { - nsUpload.removeCareportalEntryFromNS(tempBasalId); - } else { - uploadQueue.removeByMongoId("dbAdd", tempBasalId); - } - databaseHelper.delete(tempBasal); - } - - @Override - public boolean isInHistoryExtendedBolusInProgress() { - return getExtendedBolusFromHistory(System.currentTimeMillis()) != null; //TODO: crosscheck here - } - - @Override - public IobTotal getLastCalculationTempBasals() { - return getCalculationToTimeTempBasals(DateUtil.now()); - } - - @Override - public IobTotal getCalculationToTimeTempBasals(long time) { - return getCalculationToTimeTempBasals(time, false, 0); - } - - public IobTotal getCalculationToTimeTempBasals(long time, boolean truncate, long truncateTime) { - IobTotal total = new IobTotal(time); - - PumpInterface pumpInterface = activePlugin.getActivePump(); - - synchronized (tempBasals) { - for (int pos = 0; pos < tempBasals.size(); pos++) { - TemporaryBasal t = tempBasals.get(pos); - if (t.date > time) continue; - IobTotal calc; - Profile profile = profileFunction.getProfile(t.date); - if (profile == null) continue; - if (truncate && t.end() > truncateTime) { - TemporaryBasal dummyTemp = new TemporaryBasal(getInjector()); - dummyTemp.copyFrom(t); - dummyTemp.cutEndTo(truncateTime); - calc = dummyTemp.iobCalc(time, profile); - } else { - calc = t.iobCalc(time, profile); - } - //log.debug("BasalIOB " + new Date(time) + " >>> " + calc.basaliob); - total.plus(calc); - } - } - if (pumpInterface.isFakingTempsByExtendedBoluses()) { - IobTotal totalExt = new IobTotal(time); - synchronized (extendedBoluses) { - for (int pos = 0; pos < extendedBoluses.size(); pos++) { - ExtendedBolus e = extendedBoluses.get(pos); - if (e.date > time) continue; - IobTotal calc; - Profile profile = profileFunction.getProfile(e.date); - if (profile == null) continue; - if (truncate && e.end() > truncateTime) { - ExtendedBolus dummyExt = new ExtendedBolus(getInjector()); - dummyExt.copyFrom(e); - dummyExt.cutEndTo(truncateTime); - calc = dummyExt.iobCalc(time, profile); - } else { - calc = e.iobCalc(time, profile); - } - totalExt.plus(calc); - } - } - // Convert to basal iob - totalExt.basaliob = totalExt.iob; - totalExt.iob = 0d; - totalExt.netbasalinsulin = totalExt.extendedBolusInsulin; - totalExt.hightempinsulin = totalExt.extendedBolusInsulin; - total.plus(totalExt); - } - return total; - } - - public IobTotal getAbsoluteIOBTempBasals(long time) { - IobTotal total = new IobTotal(time); - - for (long i = time - range(); i < time; i += T.mins(5).msecs()) { - Profile profile = profileFunction.getProfile(i); - if (profile == null) continue; - double basal = profile.getBasal(i); - TemporaryBasal runningTBR = getTempBasalFromHistory(i); - double running = basal; - if (runningTBR != null) { - running = runningTBR.tempBasalConvertedToAbsolute(i, profile); - } - Bolus bolus = new Bolus( - 0, // id - 0, // version - 0, //dateCreated - true, // isValid - null, - null, - i, - 0, - running * 5.0 / 60.0, - Bolus.Type.NORMAL, - true, - null - ); - Iob iob = BolusExtensionKt.iobCalc(bolus, activePlugin, time, profile.getDia()); - total.basaliob += iob.getIobContrib(); - total.activity += iob.getActivityContrib(); - } - return total; - } - - public IobTotal getCalculationToTimeTempBasals(long time, long truncateTime, AutosensResult lastAutosensResult, boolean exercise_mode, int half_basal_exercise_target, boolean isTempTarget) { - IobTotal total = new IobTotal(time); - - PumpInterface pumpInterface = activePlugin.getActivePump(); - - synchronized (tempBasals) { - for (int pos = 0; pos < tempBasals.size(); pos++) { - TemporaryBasal t = tempBasals.get(pos); - if (t.date > time) continue; - IobTotal calc; - Profile profile = profileFunction.getProfile(t.date); - if (profile == null) continue; - if (t.end() > truncateTime) { - TemporaryBasal dummyTemp = new TemporaryBasal(getInjector()); - dummyTemp.copyFrom(t); - dummyTemp.cutEndTo(truncateTime); - calc = dummyTemp.iobCalc(time, profile, lastAutosensResult, exercise_mode, half_basal_exercise_target, isTempTarget); - } else { - calc = t.iobCalc(time, profile, lastAutosensResult, exercise_mode, half_basal_exercise_target, isTempTarget); - } - //log.debug("BasalIOB " + new Date(time) + " >>> " + calc.basaliob); - total.plus(calc); - } - } - if (pumpInterface.isFakingTempsByExtendedBoluses()) { - IobTotal totalExt = new IobTotal(time); - synchronized (extendedBoluses) { - for (int pos = 0; pos < extendedBoluses.size(); pos++) { - ExtendedBolus e = extendedBoluses.get(pos); - if (e.date > time) continue; - IobTotal calc; - Profile profile = profileFunction.getProfile(e.date); - if (profile == null) continue; - if (e.end() > truncateTime) { - ExtendedBolus dummyExt = new ExtendedBolus(getInjector()); - dummyExt.copyFrom(e); - dummyExt.cutEndTo(truncateTime); - calc = dummyExt.iobCalc(time, profile, lastAutosensResult, exercise_mode, half_basal_exercise_target, isTempTarget); - } else { - calc = e.iobCalc(time, profile, lastAutosensResult, exercise_mode, half_basal_exercise_target, isTempTarget); - } - totalExt.plus(calc); - } - } - // Convert to basal iob - totalExt.basaliob = totalExt.iob; - totalExt.iob = 0d; - totalExt.netbasalinsulin = totalExt.extendedBolusInsulin; - totalExt.hightempinsulin = totalExt.extendedBolusInsulin; - total.plus(totalExt); - } - return total; - } - - @Nullable - @Override - public TemporaryBasal getTempBasalFromHistory(long time) { - TemporaryBasal tb = getRealTempBasalFromHistory(time); - if (tb != null) - return tb; - ExtendedBolus eb = getExtendedBolusFromHistory(time); - if (eb != null && activePlugin.getActivePump().isFakingTempsByExtendedBoluses()) - return new TemporaryBasal(eb); - return null; - } - - @Override - public ExtendedBolus getExtendedBolusFromHistory(long time) { - synchronized (extendedBoluses) { - return extendedBoluses.getValueByInterval(time); - } - } - + @Deprecated @Override public boolean addToHistoryExtendedBolus(ExtendedBolus extendedBolus) { + throw new IllegalStateException("Migrate to new DB"); //log.debug("Adding new ExtentedBolus record" + extendedBolus.log()); + /* boolean newRecordCreated = databaseHelper.createOrUpdate(extendedBolus); if (newRecordCreated) { if (extendedBolus.durationInMinutes == 0) { @@ -525,26 +239,14 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface nsUpload.uploadExtendedBolus(extendedBolus); } return newRecordCreated; + */ } - @Override - @NonNull - public Intervals getExtendedBolusesFromHistory() { - synchronized (extendedBoluses) { - return new NonOverlappingIntervals<>(extendedBoluses); - } - } - - @Override - @NonNull - public NonOverlappingIntervals getTemporaryBasalsFromHistory() { - synchronized (tempBasals) { - return new NonOverlappingIntervals<>(tempBasals); - } - } - + @Deprecated @Override public boolean addToHistoryTempBasal(TemporaryBasal tempBasal) { + throw new IllegalStateException("Migrate to new DB"); +/* //log.debug("Adding new TemporaryBasal record" + tempBasal.toString()); boolean newRecordCreated = databaseHelper.createOrUpdate(tempBasal); if (newRecordCreated) { @@ -556,17 +258,25 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface nsUpload.uploadTempBasalStartPercent(tempBasal, profileFunction.getProfile(tempBasal.date)); } return newRecordCreated; + */ } + @Deprecated public TreatmentUpdateReturn createOrUpdateMedtronic(Treatment treatment, boolean fromNightScout) { + throw new IllegalStateException("Migrate to new DB"); +/* UpdateReturn resultRecord = getService().createOrUpdateMedtronic(treatment, fromNightScout); return new TreatmentUpdateReturn(resultRecord.getSuccess(), resultRecord.getNewRecord()); + */ } // return true if new record is created + @Deprecated @Override public boolean addToHistoryTreatment(DetailedBolusInfo detailedBolusInfo, boolean allowUpdate) { + throw new IllegalStateException("Migrate to new DB"); +/* boolean medtronicPump = activePlugin.getActivePump() instanceof MedtronicPumpPlugin; getAapsLogger().debug(MedtronicHistoryData.doubleBolusDebug, LTag.DATATREATMENTS, "DoubleBolusDebug: addToHistoryTreatment::isMedtronicPump={} " + medtronicPump); @@ -627,27 +337,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface } return newRecordCreated; - } - - @Override - public long oldestDataAvailable() { - long oldestTime = System.currentTimeMillis(); - synchronized (tempBasals) { - if (tempBasals.size() > 0) - oldestTime = Math.min(oldestTime, tempBasals.get(0).date); - } - synchronized (extendedBoluses) { - if (extendedBoluses.size() > 0) - oldestTime = Math.min(oldestTime, extendedBoluses.get(0).date); - } - Bolus oldestBolus = repository.getOldestBolusRecord(); - if (oldestBolus != null) - oldestTime = Math.min(oldestTime, oldestBolus.getTimestamp()); - Carbs oldestCarbs = repository.getOldestCarbsRecord(); - if (oldestCarbs != null) - oldestTime = Math.min(oldestTime, oldestCarbs.getTimestamp()); - oldestTime -= 15 * 60 * 1000L; // allow 15 min before - return oldestTime; + */ } @Override diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsBolusCarbsFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsBolusCarbsFragment.kt index 19f553c1dc..ec859711bf 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsBolusCarbsFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsBolusCarbsFragment.kt @@ -28,7 +28,6 @@ import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.plugins.bus.RxBusWrapper -import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart import info.nightscout.androidaps.plugins.treatments.events.EventTreatmentUpdateGui import info.nightscout.androidaps.utils.DateUtil @@ -36,8 +35,8 @@ import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.buildHelper.BuildHelper -import info.nightscout.androidaps.utils.extensions.iobCalc -import info.nightscout.androidaps.utils.extensions.toVisibility +import info.nightscout.androidaps.extensions.iobCalc +import info.nightscout.androidaps.extensions.toVisibility import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.sharedPreferences.SP @@ -274,7 +273,7 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { ml.bolus?.let { bolus -> holder.binding.bolusDate.text = dateUtil.timeString(bolus.timestamp) holder.binding.insulin.text = resourceHelper.gs(R.string.formatinsulinunits, bolus.amount) - holder.binding.bolusNs.visibility = (NSUpload.isIdValid(bolus.interfaceIDs.nightscoutId)).toVisibility() + holder.binding.bolusNs.visibility = (bolus.interfaceIDs.nightscoutId != null).toVisibility() holder.binding.bolusPump.visibility = (bolus.interfaceIDs.pumpId != null).toVisibility() holder.binding.bolusInvalid.visibility = bolus.isValid.not().toVisibility() val iob = bolus.iobCalc(activePlugin, System.currentTimeMillis(), profile.dia) @@ -283,8 +282,8 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { if (bolus.timestamp > dateUtil._now()) holder.binding.date.setTextColor(resourceHelper.gc(R.color.colorScheduled)) else holder.binding.date.setTextColor(holder.binding.carbs.currentTextColor) holder.binding.mealOrCorrection.text = when (ml.bolus.type) { - Bolus.Type.SMB -> "SMB" - Bolus.Type.NORMAL -> resourceHelper.gs(R.string.mealbolus) + Bolus.Type.SMB -> "SMB" + Bolus.Type.NORMAL -> resourceHelper.gs(R.string.mealbolus) Bolus.Type.PRIMING -> resourceHelper.gs(R.string.prime) } } @@ -293,8 +292,8 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { ml.carbs?.let { carbs -> holder.binding.carbsDate.text = dateUtil.timeString(carbs.timestamp) holder.binding.carbs.text = resourceHelper.gs(R.string.format_carbs, carbs.amount.toInt()) - holder.binding.carbsDuration.text = if (carbs.duration> 0) resourceHelper.gs(R.string.format_mins, T.msecs(carbs.duration).mins().toInt()) else "" - holder.binding.carbsNs.visibility = (NSUpload.isIdValid(carbs.interfaceIDs.nightscoutId)).toVisibility() + holder.binding.carbsDuration.text = if (carbs.duration > 0) resourceHelper.gs(R.string.format_mins, T.msecs(carbs.duration).mins().toInt()) else "" + holder.binding.carbsNs.visibility = (carbs.interfaceIDs.nightscoutId != null).toVisibility() holder.binding.carbsPump.visibility = (carbs.interfaceIDs.pumpId != null).toVisibility() holder.binding.carbsInvalid.visibility = carbs.isValid.not().toVisibility() } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsCareportalFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsCareportalFragment.kt index 180bf12864..7d0e5d1807 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsCareportalFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsCareportalFragment.kt @@ -32,7 +32,7 @@ import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.Translator import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.buildHelper.BuildHelper -import info.nightscout.androidaps.utils.extensions.toVisibility +import info.nightscout.androidaps.extensions.toVisibility import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.sharedPreferences.SP diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsExtendedBolusesFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsExtendedBolusesFragment.kt index bbecd9b5bd..8b789b07e1 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsExtendedBolusesFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsExtendedBolusesFragment.kt @@ -11,45 +11,52 @@ import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import dagger.android.support.DaggerFragment import info.nightscout.androidaps.R -import info.nightscout.androidaps.data.Intervals -import info.nightscout.androidaps.database.entities.UserEntry.* +import info.nightscout.androidaps.database.AppRepository +import info.nightscout.androidaps.database.entities.ExtendedBolus +import info.nightscout.androidaps.database.entities.UserEntry.Action +import info.nightscout.androidaps.database.interfaces.end +import info.nightscout.androidaps.database.transactions.InvalidateExtendedBolusTransaction import info.nightscout.androidaps.databinding.TreatmentsExtendedbolusFragmentBinding import info.nightscout.androidaps.databinding.TreatmentsExtendedbolusItemBinding -import info.nightscout.androidaps.db.ExtendedBolus -import info.nightscout.androidaps.db.Source -import info.nightscout.androidaps.events.EventAutosensCalculationFinished import info.nightscout.androidaps.events.EventExtendedBolusChange import info.nightscout.androidaps.interfaces.ActivePluginProvider -import info.nightscout.androidaps.interfaces.DatabaseHelperInterface import info.nightscout.androidaps.interfaces.ProfileFunction -import info.nightscout.androidaps.interfaces.UploadQueueInterface +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.plugins.bus.RxBusWrapper -import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.plugins.treatments.fragments.TreatmentsExtendedBolusesFragment.RecyclerViewAdapter.ExtendedBolusesViewHolder import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.FabricPrivacy +import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.alertDialogs.OKDialog +import info.nightscout.androidaps.extensions.getPassedDurationToTimeInMinutes +import info.nightscout.androidaps.extensions.iobCalc +import info.nightscout.androidaps.extensions.isInProgress +import info.nightscout.androidaps.extensions.toVisibility import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers import io.reactivex.disposables.CompositeDisposable +import io.reactivex.rxkotlin.plusAssign +import java.util.concurrent.TimeUnit import javax.inject.Inject class TreatmentsExtendedBolusesFragment : DaggerFragment() { private val disposable = CompositeDisposable() + private val millsToThePast = T.days(30).msecs() + @Inject lateinit var activePlugin: ActivePluginProvider @Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var resourceHelper: ResourceHelper + @Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var fabricPrivacy: FabricPrivacy - @Inject lateinit var nsUpload: NSUpload - @Inject lateinit var uploadQueue: UploadQueueInterface @Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var dateUtil: DateUtil @Inject lateinit var aapsSchedulers: AapsSchedulers - @Inject lateinit var databaseHelper: DatabaseHelperInterface @Inject lateinit var uel: UserEntryLogger + @Inject lateinit var repository: AppRepository private var _binding: TreatmentsExtendedbolusFragmentBinding? = null @@ -58,18 +65,54 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() { private val binding get() = _binding!! override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle?): View { - _binding = TreatmentsExtendedbolusFragmentBinding.inflate(inflater, container, false) - return binding.root - } + savedInstanceState: Bundle?): View = + TreatmentsExtendedbolusFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root override fun onViewCreated(view: View, savedInstanceState: Bundle?) { binding.recyclerview.setHasFixedSize(true) binding.recyclerview.layoutManager = LinearLayoutManager(view.context) - binding.recyclerview.adapter = RecyclerViewAdapter(activePlugin.activeTreatments.extendedBolusesFromHistory) } - private inner class RecyclerViewAdapter(private var extendedBolusList: Intervals) : RecyclerView.Adapter() { + fun swapAdapter() { + val now = System.currentTimeMillis() + if (binding.showInvalidated.isChecked) + repository + .getExtendedBolusDataIncludingInvalidFromTime(now - millsToThePast, false) + .observeOn(aapsSchedulers.main) + .subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) } + else + repository + .getExtendedBolusDataFromTime(now - millsToThePast, false) + .observeOn(aapsSchedulers.main) + .subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) } + } + + @Synchronized + override fun onResume() { + super.onResume() + swapAdapter() + + disposable += rxBus + .toObservable(EventExtendedBolusChange::class.java) + .observeOn(aapsSchedulers.io) + .debounce(1L, TimeUnit.SECONDS) + .subscribe({ swapAdapter() }, fabricPrivacy::logException) + } + + @Synchronized + override fun onPause() { + super.onPause() + disposable.clear() + } + + @Synchronized + override fun onDestroyView() { + super.onDestroyView() + binding.recyclerview.adapter = null // avoid leaks + _binding = null + } + + private inner class RecyclerViewAdapter(private var extendedBolusList: List) : RecyclerView.Adapter() { override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ExtendedBolusesViewHolder { val v = LayoutInflater.from(viewGroup.context).inflate(R.layout.treatments_extendedbolus_item, viewGroup, false) @@ -77,38 +120,28 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() { } override fun onBindViewHolder(holder: ExtendedBolusesViewHolder, position: Int) { - val extendedBolus = extendedBolusList.getReversed(position) - holder.binding.ph.visibility = if (extendedBolus.source == Source.PUMP) View.VISIBLE else View.GONE - holder.binding.ns.visibility = if (NSUpload.isIdValid(extendedBolus._id)) View.VISIBLE else View.GONE - if (extendedBolus.isEndingEvent) { - holder.binding.date.text = dateUtil.dateAndTimeString(extendedBolus.date) - holder.binding.duration.text = resourceHelper.gs(R.string.cancel) - holder.binding.insulin.text = "" - holder.binding.realDuration.text = "" - holder.binding.iob.text = "" - holder.binding.insulinSoFar.text = "" - holder.binding.ratio.text = "" + val extendedBolus = extendedBolusList[position] + holder.binding.ph.visibility = (extendedBolus.interfaceIDs.nightscoutId != null).toVisibility() + holder.binding.invalid.visibility = extendedBolus.isValid.not().toVisibility() + @SuppressLint("SetTextI18n") + if (extendedBolus.isInProgress(dateUtil)) { + holder.binding.date.text = dateUtil.dateAndTimeString(extendedBolus.timestamp) + holder.binding.date.setTextColor(resourceHelper.gc(R.color.colorActive)) } else { - @SuppressLint("SetTextI18n") - if (extendedBolus.isInProgress) holder.binding.date.text = dateUtil.dateAndTimeString(extendedBolus.date) - else holder.binding.date.text = dateUtil.dateAndTimeString(extendedBolus.date) + " - " + dateUtil.timeString(extendedBolus.end()) - val profile = profileFunction.getProfile(extendedBolus.date) - holder.binding.duration.text = resourceHelper.gs(R.string.format_mins, extendedBolus.durationInMinutes) - holder.binding.insulin.text = resourceHelper.gs(R.string.formatinsulinunits, extendedBolus.insulin) - holder.binding.realDuration.text = resourceHelper.gs(R.string.format_mins, extendedBolus.realDuration) - val iob = extendedBolus.iobCalc(System.currentTimeMillis(), profile) - holder.binding.iob.text = resourceHelper.gs(R.string.formatinsulinunits, iob.iob) - holder.binding.insulinSoFar.text = resourceHelper.gs(R.string.formatinsulinunits, extendedBolus.insulinSoFar()) - holder.binding.ratio.text = resourceHelper.gs(R.string.pump_basebasalrate, extendedBolus.absoluteRate()) - if (extendedBolus.isInProgress) holder.binding.date.setTextColor(resourceHelper.gc(R.color.colorActive)) else holder.binding.date.setTextColor(holder.binding.insulin.currentTextColor) - if (iob.iob != 0.0) holder.binding.iob.setTextColor(resourceHelper.gc(R.color.colorActive)) else holder.binding.iob.setTextColor(holder.binding.insulin.currentTextColor) + holder.binding.date.text = dateUtil.dateAndTimeString(extendedBolus.timestamp) + " - " + dateUtil.timeString(extendedBolus.end) + holder.binding.date.setTextColor(holder.binding.insulin.currentTextColor) } + val profile = profileFunction.getProfile(extendedBolus.timestamp) ?: return + holder.binding.duration.text = resourceHelper.gs(R.string.format_mins, T.msecs(extendedBolus.duration).mins()) + holder.binding.insulin.text = resourceHelper.gs(R.string.formatinsulinunits, extendedBolus.amount) + val iob = extendedBolus.iobCalc(System.currentTimeMillis(), profile, activePlugin.activeInsulin) + holder.binding.iob.text = resourceHelper.gs(R.string.formatinsulinunits, iob.iob) + holder.binding.ratio.text = resourceHelper.gs(R.string.pump_basebasalrate, extendedBolus.rate) + if (iob.iob != 0.0) holder.binding.iob.setTextColor(resourceHelper.gc(R.color.colorActive)) else holder.binding.iob.setTextColor(holder.binding.insulin.currentTextColor) holder.binding.remove.tag = extendedBolus } - override fun getItemCount(): Int { - return extendedBolusList.size() - } + override fun getItemCount(): Int = extendedBolusList.size inner class ExtendedBolusesViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { @@ -117,17 +150,17 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() { init { binding.remove.setOnClickListener { v: View -> val extendedBolus = v.tag as ExtendedBolus - context?.let { - OKDialog.showConfirmation(it, resourceHelper.gs(R.string.removerecord), + context?.let { context -> + OKDialog.showConfirmation(context, resourceHelper.gs(R.string.removerecord), """ ${resourceHelper.gs(R.string.extended_bolus)} - ${resourceHelper.gs(R.string.date)}: ${dateUtil.dateAndTimeString(extendedBolus.date)} + ${resourceHelper.gs(R.string.date)}: ${dateUtil.dateAndTimeString(extendedBolus.timestamp)} """.trimIndent(), { _: DialogInterface, _: Int -> uel.log(Action.EXTENDED_BOLUS_REMOVED) - val id = extendedBolus._id - if (NSUpload.isIdValid(id)) nsUpload.removeCareportalEntryFromNS(id) - else uploadQueue.removeByMongoId("dbAdd", id) - databaseHelper.delete(extendedBolus) + disposable += repository.runTransactionForResult(InvalidateExtendedBolusTransaction(extendedBolus.id)) + .subscribe( + { aapsLogger.debug(LTag.DATABASE, "Removed extended bolus $extendedBolus") }, + { aapsLogger.error(LTag.DATABASE, "Error while invalidating extended bolus", it) }) }, null) } } @@ -136,35 +169,4 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() { } } - - @Synchronized override fun onResume() { - super.onResume() - disposable.add(rxBus - .toObservable(EventExtendedBolusChange::class.java) - .observeOn(aapsSchedulers.main) - .subscribe({ updateGui() }, fabricPrivacy::logException) - ) - disposable.add(rxBus - .toObservable(EventAutosensCalculationFinished::class.java) - .observeOn(aapsSchedulers.main) - .subscribe({ updateGui() }, fabricPrivacy::logException) - ) - updateGui() - } - - @Synchronized override fun onPause() { - super.onPause() - disposable.clear() - } - - @Synchronized - override fun onDestroyView() { - super.onDestroyView() - _binding = null - } - - private fun updateGui() { - if (_binding == null) return - binding.recyclerview.swapAdapter(RecyclerViewAdapter(activePlugin.activeTreatments.extendedBolusesFromHistory), false) - } } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsProfileSwitchFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsProfileSwitchFragment.kt index c7b667b2fd..f39b5bd524 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsProfileSwitchFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsProfileSwitchFragment.kt @@ -30,7 +30,7 @@ import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.buildHelper.BuildHelper -import info.nightscout.androidaps.utils.extensions.toVisibility +import info.nightscout.androidaps.extensions.toVisibility import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.sharedPreferences.SP diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsTempTargetFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsTempTargetFragment.kt index 276043e30f..b2e7d100fb 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsTempTargetFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsTempTargetFragment.kt @@ -37,10 +37,10 @@ import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.Translator import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.buildHelper.BuildHelper -import info.nightscout.androidaps.utils.extensions.friendlyDescription -import info.nightscout.androidaps.utils.extensions.highValueToUnitsToString -import info.nightscout.androidaps.utils.extensions.lowValueToUnitsToString -import info.nightscout.androidaps.utils.extensions.toVisibility +import info.nightscout.androidaps.extensions.friendlyDescription +import info.nightscout.androidaps.extensions.highValueToUnitsToString +import info.nightscout.androidaps.extensions.lowValueToUnitsToString +import info.nightscout.androidaps.extensions.toVisibility import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.sharedPreferences.SP @@ -151,7 +151,7 @@ class TreatmentsTempTargetFragment : DaggerFragment() { _binding = null } - inner class RecyclerViewAdapter internal constructor(private var tempTargetList: List) : RecyclerView.Adapter() { + private inner class RecyclerViewAdapter internal constructor(private var tempTargetList: List) : RecyclerView.Adapter() { private val dbRecord = repository.getTemporaryTargetActiveAt(dateUtil._now()).blockingGet() private val currentlyActiveTarget = if (dbRecord is ValueWrapper.Existing) dbRecord.value else null diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsTemporaryBasalsFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsTemporaryBasalsFragment.kt index 365c5ae4c2..ec6113266c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsTemporaryBasalsFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsTemporaryBasalsFragment.kt @@ -10,33 +10,43 @@ import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import dagger.android.support.DaggerFragment import info.nightscout.androidaps.R -import info.nightscout.androidaps.data.Intervals import info.nightscout.androidaps.data.IobTotal +import info.nightscout.androidaps.database.AppRepository +import info.nightscout.androidaps.database.entities.TemporaryBasal import info.nightscout.androidaps.database.entities.UserEntry.* +import info.nightscout.androidaps.database.interfaces.end +import info.nightscout.androidaps.database.transactions.InvalidateTemporaryBasalTransaction import info.nightscout.androidaps.databinding.TreatmentsTempbasalsFragmentBinding import info.nightscout.androidaps.databinding.TreatmentsTempbasalsItemBinding -import info.nightscout.androidaps.db.Source -import info.nightscout.androidaps.db.TemporaryBasal +import info.nightscout.androidaps.events.EventAutosensCalculationFinished import info.nightscout.androidaps.events.EventTempBasalChange import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.ProfileFunction +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.plugins.bus.RxBusWrapper -import info.nightscout.androidaps.plugins.general.nsclient.NSUpload -import info.nightscout.androidaps.events.EventAutosensCalculationFinished import info.nightscout.androidaps.plugins.treatments.fragments.TreatmentsTemporaryBasalsFragment.RecyclerViewAdapter.TempBasalsViewHolder import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.FabricPrivacy +import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.alertDialogs.OKDialog +import info.nightscout.androidaps.extensions.getPassedDurationToTimeInMinutes +import info.nightscout.androidaps.extensions.iobCalc +import info.nightscout.androidaps.extensions.toStringFull +import info.nightscout.androidaps.extensions.toVisibility import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers import io.reactivex.disposables.CompositeDisposable +import io.reactivex.rxkotlin.plusAssign import javax.inject.Inject +import kotlin.math.abs class TreatmentsTemporaryBasalsFragment : DaggerFragment() { private val disposable = CompositeDisposable() + @Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var fabricPrivacy: FabricPrivacy @@ -45,9 +55,12 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() { @Inject lateinit var dateUtil: DateUtil @Inject lateinit var aapsSchedulers: AapsSchedulers @Inject lateinit var uel: UserEntryLogger + @Inject lateinit var repository: AppRepository private var _binding: TreatmentsTempbasalsFragmentBinding? = null + private val millsToThePast = T.days(30).msecs() + // This property is only valid between onCreateView and // onDestroyView. private val binding get() = _binding!! @@ -59,23 +72,37 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() { super.onViewCreated(view, savedInstanceState) binding.recyclerview.setHasFixedSize(true) binding.recyclerview.layoutManager = LinearLayoutManager(view.context) - binding.recyclerview.adapter = RecyclerViewAdapter(activePlugin.activeTreatments.temporaryBasalsFromHistory) + } + + fun swapAdapter() { + val now = System.currentTimeMillis() + if (binding.showInvalidated.isChecked) + repository + .getTemporaryBasalsDataIncludingInvalidFromTime(now - millsToThePast, false) + .observeOn(aapsSchedulers.main) + .subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) } + else + repository + .getTemporaryBasalsDataFromTime(now - millsToThePast, false) + .observeOn(aapsSchedulers.main) + .subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) } } @Synchronized override fun onResume() { super.onResume() + swapAdapter() + disposable.add(rxBus .toObservable(EventTempBasalChange::class.java) .observeOn(aapsSchedulers.main) - .subscribe({ updateGui() }, fabricPrivacy::logException) + .subscribe({ swapAdapter() }, fabricPrivacy::logException) ) disposable.add(rxBus .toObservable(EventAutosensCalculationFinished::class.java) .observeOn(aapsSchedulers.main) - .subscribe({ updateGui() }, fabricPrivacy::logException) + .subscribe({ swapAdapter() }, fabricPrivacy::logException) ) - updateGui() } @Synchronized @@ -87,69 +114,44 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() { @Synchronized override fun onDestroyView() { super.onDestroyView() + binding.recyclerview.adapter = null // avoid leaks _binding = null } - inner class RecyclerViewAdapter internal constructor(private var tempBasalList: Intervals) : RecyclerView.Adapter() { + inner class RecyclerViewAdapter internal constructor(private var tempBasalList: List) : RecyclerView.Adapter() { override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): TempBasalsViewHolder = TempBasalsViewHolder(LayoutInflater.from(viewGroup.context).inflate(R.layout.treatments_tempbasals_item, viewGroup, false)) override fun onBindViewHolder(holder: TempBasalsViewHolder, position: Int) { - val tempBasal = tempBasalList.getReversed(position) - holder.binding.ph.visibility = if (tempBasal.source == Source.PUMP) View.VISIBLE else View.GONE - holder.binding.ns.visibility = if (NSUpload.isIdValid(tempBasal._id)) View.VISIBLE else View.GONE - if (tempBasal.isEndingEvent) { - holder.binding.date.text = dateUtil.dateAndTimeString(tempBasal.date) - holder.binding.duration.text = resourceHelper.gs(R.string.cancel) - holder.binding.absolute.text = "" - holder.binding.percent.text = "" - holder.binding.realDuration.text = "" - holder.binding.iob.text = "" - holder.binding.netInsulin.text = "" - holder.binding.netRatio.text = "" - holder.binding.extendedFlag.visibility = View.GONE - holder.binding.iob.setTextColor(holder.binding.netRatio.currentTextColor) + val tempBasal = tempBasalList[position] + holder.binding.ns.visibility = (tempBasal.interfaceIDs.nightscoutId != null).toVisibility() + holder.binding.invalid.visibility = tempBasal.isValid.not().toVisibility() + holder.binding.ph.visibility = (tempBasal.interfaceIDs.pumpId != null).toVisibility() + if (tempBasal.isInProgress) { + holder.binding.date.text = dateUtil.dateAndTimeString(tempBasal.timestamp) + holder.binding.date.setTextColor(resourceHelper.gc(R.color.colorActive)) } else { - if (tempBasal.isInProgress) { - holder.binding.date.text = dateUtil.dateAndTimeString(tempBasal.date) - holder.binding.date.setTextColor(resourceHelper.gc(R.color.colorActive)) - } else { - holder.binding.date.text = dateUtil.dateAndTimeRangeString(tempBasal.date, tempBasal.end()) - holder.binding.date.setTextColor(holder.binding.netRatio.currentTextColor) - } - holder.binding.duration.text = resourceHelper.gs(R.string.format_mins, tempBasal.durationInMinutes) - if (tempBasal.isAbsolute) { - val profile = profileFunction.getProfile(tempBasal.date) - if (profile != null) { - holder.binding.absolute.text = resourceHelper.gs(R.string.pump_basebasalrate, tempBasal.tempBasalConvertedToAbsolute(tempBasal.date, profile)) - holder.binding.percent.text = "" - } else { - holder.binding.absolute.text = resourceHelper.gs(R.string.noprofile) - holder.binding.percent.text = "" - } - } else { - holder.binding.absolute.text = "" - holder.binding.percent.text = resourceHelper.gs(R.string.format_percent, tempBasal.percentRate) - } - holder.binding.realDuration.text = resourceHelper.gs(R.string.format_mins, tempBasal.realDuration) - val now = DateUtil.now() - var iob = IobTotal(now) - val profile = profileFunction.getProfile(now) - if (profile != null) iob = tempBasal.iobCalc(now, profile) - holder.binding.iob.text = resourceHelper.gs(R.string.formatinsulinunits, iob.basaliob) - holder.binding.netInsulin.text = resourceHelper.gs(R.string.formatinsulinunits, iob.netInsulin) - holder.binding.netRatio.text = resourceHelper.gs(R.string.pump_basebasalrate, iob.netRatio) - holder.binding.extendedFlag.visibility = View.GONE - if (iob.basaliob != 0.0) holder.binding.iob.setTextColor(resourceHelper.gc(R.color.colorActive)) else holder.binding.iob.setTextColor(holder.binding.netRatio.currentTextColor) + holder.binding.date.text = dateUtil.dateAndTimeRangeString(tempBasal.timestamp, tempBasal.end) + holder.binding.date.setTextColor(holder.binding.duration.currentTextColor) } + holder.binding.duration.text = resourceHelper.gs(R.string.format_mins, T.msecs(tempBasal.duration).mins()) + if (tempBasal.isAbsolute) holder.binding.rate.text = resourceHelper.gs(R.string.pump_basebasalrate, tempBasal.rate) + else holder.binding.rate.text = resourceHelper.gs(R.string.format_percent, tempBasal.rate.toInt()) + val now = DateUtil.now() + var iob = IobTotal(now) + val profile = profileFunction.getProfile(now) + if (profile != null) iob = tempBasal.iobCalc(now, profile, activePlugin.activeInsulin) + holder.binding.iob.text = resourceHelper.gs(R.string.formatinsulinunits, iob.basaliob) + holder.binding.extendedFlag.visibility = (tempBasal.type == TemporaryBasal.Type.FAKE_EXTENDED).toVisibility() + if (abs(iob.basaliob) > 0.01) holder.binding.iob.setTextColor(resourceHelper.gc(R.color.colorActive)) else holder.binding.iob.setTextColor(holder.binding.duration.currentTextColor) + holder.binding.type.text = tempBasal.type.toString() holder.binding.remove.tag = tempBasal } - override fun getItemCount(): Int { - return tempBasalList.size() - } + override fun getItemCount(): Int = tempBasalList.size + @Deprecated("remove remove functionality after finish") inner class TempBasalsViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val binding = TreatmentsTempbasalsItemBinding.bind(itemView) @@ -157,15 +159,20 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() { init { binding.remove.setOnClickListener { v: View -> val tempBasal = v.tag as TemporaryBasal + val profile = profileFunction.getProfile(dateUtil._now()) + ?: return@setOnClickListener context?.let { OKDialog.showConfirmation(it, resourceHelper.gs(R.string.removerecord), """ - ${resourceHelper.gs(R.string.tempbasal_label)}: ${tempBasal.toStringFull()} - ${resourceHelper.gs(R.string.date)}: ${dateUtil.dateAndTimeString(tempBasal.date)} + ${resourceHelper.gs(R.string.tempbasal_label)}: ${tempBasal.toStringFull(profile, dateUtil)} + ${resourceHelper.gs(R.string.date)}: ${dateUtil.dateAndTimeString(tempBasal.timestamp)} """.trimIndent(), { _: DialogInterface?, _: Int -> - uel.log(Action.TT_REMOVED, ValueWithUnit(tempBasal.date, Units.Timestamp)) - activePlugin.activeTreatments.removeTempBasal(tempBasal) + uel.log(Action.TB_REMOVED, ValueWithUnit(tempBasal.timestamp, Units.Timestamp)) + disposable += repository.runTransactionForResult(InvalidateTemporaryBasalTransaction(tempBasal.id)) + .subscribe( + { aapsLogger.debug(LTag.DATABASE, "Removed temporary basal $tempBasal") }, + { aapsLogger.error(LTag.DATABASE, "Error while invalidating temporary basal", it) }) }, null) } } @@ -174,11 +181,4 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() { } } - - private fun updateGui() { - if (_binding == null) return - binding.recyclerview.swapAdapter(RecyclerViewAdapter(activePlugin.activeTreatments.temporaryBasalsFromHistory), false) - val tempBasalsCalculation = activePlugin.activeTreatments.lastCalculationTempBasals - if (tempBasalsCalculation != null) binding.totalTempIob.text = resourceHelper.gs(R.string.formatinsulinunits, tempBasalsCalculation.basaliob) - } } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsUserEntryFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsUserEntryFragment.kt index 5a7c6432f1..903f1e96eb 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsUserEntryFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsUserEntryFragment.kt @@ -15,6 +15,7 @@ import info.nightscout.androidaps.database.entities.UserEntry.* import info.nightscout.androidaps.databinding.TreatmentsUserEntryFragmentBinding import info.nightscout.androidaps.databinding.TreatmentsUserEntryItemBinding import info.nightscout.androidaps.events.EventPreferenceChange +import info.nightscout.androidaps.extensions.colorId import info.nightscout.androidaps.interfaces.ImportExportPrefsInterface import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.logging.UserEntryLogger diff --git a/app/src/main/java/info/nightscout/androidaps/receivers/KeepAliveReceiver.kt b/app/src/main/java/info/nightscout/androidaps/receivers/KeepAliveReceiver.kt index 05f6603305..4b0bd1f534 100644 --- a/app/src/main/java/info/nightscout/androidaps/receivers/KeepAliveReceiver.kt +++ b/app/src/main/java/info/nightscout/androidaps/receivers/KeepAliveReceiver.kt @@ -31,7 +31,7 @@ import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.LocalAlertUtils import info.nightscout.androidaps.utils.T -import info.nightscout.androidaps.utils.extensions.buildDeviceStatus +import info.nightscout.androidaps.extensions.buildDeviceStatus import javax.inject.Inject import kotlin.math.abs diff --git a/app/src/main/java/info/nightscout/androidaps/utils/alertDialogs/PrefImportSummaryDialog.kt b/app/src/main/java/info/nightscout/androidaps/utils/alertDialogs/PrefImportSummaryDialog.kt index 976feb9ed1..7a2aa6f513 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/alertDialogs/PrefImportSummaryDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/utils/alertDialogs/PrefImportSummaryDialog.kt @@ -20,7 +20,7 @@ import info.nightscout.androidaps.R import info.nightscout.androidaps.plugins.general.maintenance.formats.Prefs import info.nightscout.androidaps.plugins.general.maintenance.formats.PrefsStatus import info.nightscout.androidaps.utils.ToastUtils -import info.nightscout.androidaps.utils.extensions.runOnUiThread +import info.nightscout.androidaps.extensions.runOnUiThread import java.util.* object PrefImportSummaryDialog { diff --git a/app/src/main/java/info/nightscout/androidaps/utils/alertDialogs/TwoMessagesAlertDialog.kt b/app/src/main/java/info/nightscout/androidaps/utils/alertDialogs/TwoMessagesAlertDialog.kt index c3049a3597..b8bc6466a2 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/alertDialogs/TwoMessagesAlertDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/utils/alertDialogs/TwoMessagesAlertDialog.kt @@ -9,7 +9,7 @@ import android.view.View import android.widget.TextView import androidx.annotation.DrawableRes import info.nightscout.androidaps.R -import info.nightscout.androidaps.utils.extensions.runOnUiThread +import info.nightscout.androidaps.extensions.runOnUiThread object TwoMessagesAlertDialog { diff --git a/app/src/main/java/info/nightscout/androidaps/utils/stats/TddCalculator.kt b/app/src/main/java/info/nightscout/androidaps/utils/stats/TddCalculator.kt index 366147a92a..5ea46d24fd 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/stats/TddCalculator.kt +++ b/app/src/main/java/info/nightscout/androidaps/utils/stats/TddCalculator.kt @@ -1,71 +1,48 @@ package info.nightscout.androidaps.utils.stats -import android.content.Context import android.text.Spanned import android.util.LongSparseArray -import dagger.android.HasAndroidInjector import info.nightscout.androidaps.R import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.entities.Bolus import info.nightscout.androidaps.db.TDD import info.nightscout.androidaps.interfaces.ActivePluginProvider -import info.nightscout.androidaps.interfaces.DatabaseHelperInterface +import info.nightscout.androidaps.interfaces.IobCobCalculator import info.nightscout.androidaps.interfaces.ProfileFunction -import info.nightscout.androidaps.interfaces.UploadQueueInterface import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag -import info.nightscout.androidaps.plugins.bus.RxBusWrapper -import info.nightscout.androidaps.plugins.general.nsclient.NSUpload -import info.nightscout.androidaps.plugins.treatments.TreatmentService -import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.utils.DateUtil -import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.HtmlHelper import info.nightscout.androidaps.utils.MidnightTime import info.nightscout.androidaps.utils.T +import info.nightscout.androidaps.extensions.convertedToAbsolute import info.nightscout.androidaps.utils.resources.ResourceHelper -import info.nightscout.androidaps.utils.rx.AapsSchedulers -import info.nightscout.androidaps.utils.sharedPreferences.SP import javax.inject.Inject class TddCalculator @Inject constructor( - injector: HasAndroidInjector, - aapsLogger: AAPSLogger, - rxBus: RxBusWrapper, - resourceHelper: ResourceHelper, - context: Context, - aapsSchedulers: AapsSchedulers, - sp: SP, + private val aapsLogger: AAPSLogger, + private val resourceHelper: ResourceHelper, private val activePlugin: ActivePluginProvider, private val profileFunction: ProfileFunction, - fabricPrivacy: FabricPrivacy, - nsUpload: NSUpload, private val dateUtil: DateUtil, - uploadQueue: UploadQueueInterface, - databaseHelper: DatabaseHelperInterface, + private val iobCobCalculator: IobCobCalculator, private val repository: AppRepository -) : TreatmentsPlugin(injector, aapsLogger, rxBus, aapsSchedulers, resourceHelper, context, sp, profileFunction, activePlugin, nsUpload, fabricPrivacy, dateUtil, uploadQueue, databaseHelper, repository) { - - init { - service = TreatmentService(injector) // plugin is not started - } +) { fun calculate(days: Long): LongSparseArray { - val range = T.days(days + 1).msecs() val startTime = MidnightTime.calc(DateUtil.now() - T.days(days).msecs()) val endTime = MidnightTime.calc(DateUtil.now()) - initializeData(range) val result = LongSparseArray() repository.getBolusesDataFromTimeToTime(startTime, endTime, true).blockingGet() .filter { it.type != Bolus.Type.PRIMING } - .forEach { t-> - val midnight = MidnightTime.calc(t.timestamp) - val tdd = result[midnight] ?: TDD(midnight, 0.0, 0.0, 0.0) - tdd.bolus += t.amount - result.put(midnight, tdd) - } - repository.getCarbsDataFromTimeToTimeExpanded(startTime, endTime, true).blockingGet().forEach { t-> + .forEach { t -> + val midnight = MidnightTime.calc(t.timestamp) + val tdd = result[midnight] ?: TDD(midnight, 0.0, 0.0, 0.0) + tdd.bolus += t.amount + result.put(midnight, tdd) + } + repository.getCarbsDataFromTimeToTimeExpanded(startTime, endTime, true).blockingGet().forEach { t -> val midnight = MidnightTime.calc(t.timestamp) val tdd = result[midnight] ?: TDD(midnight, 0.0, 0.0, 0.0) tdd.carbs += t.amount @@ -75,15 +52,15 @@ class TddCalculator @Inject constructor( for (t in startTime until endTime step T.mins(5).msecs()) { val midnight = MidnightTime.calc(t) val tdd = result[midnight] ?: TDD(midnight, 0.0, 0.0, 0.0) - val tbr = getTempBasalFromHistory(t) - val profile = profileFunction.getProfile(t, this) ?: continue - val absoluteRate = tbr?.tempBasalConvertedToAbsolute(t, profile) ?: profile.getBasal(t) + val tbr = iobCobCalculator.getTempBasalIncludingConvertedExtended(t) + val profile = profileFunction.getProfile(t) ?: continue + val absoluteRate = tbr?.convertedToAbsolute(t, profile) ?: profile.getBasal(t) tdd.basal += absoluteRate / 60.0 * 5.0 if (!activePlugin.activePump.isFakingTempsByExtendedBoluses) { // they are not included in TBRs - val eb = getExtendedBolusFromHistory(t) - val absoluteEbRate = eb?.absoluteRate() ?: 0.0 + val eb = iobCobCalculator.getExtendedBolus(t) + val absoluteEbRate = eb?.rate ?: 0.0 tdd.bolus += absoluteEbRate / 60.0 * 5.0 } result.put(midnight, tdd) diff --git a/app/src/main/java/info/nightscout/androidaps/utils/wizard/BolusWizard.kt b/app/src/main/java/info/nightscout/androidaps/utils/wizard/BolusWizard.kt index 1ba7557c92..7be6343e0d 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/wizard/BolusWizard.kt +++ b/app/src/main/java/info/nightscout/androidaps/utils/wizard/BolusWizard.kt @@ -23,7 +23,6 @@ import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker -import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider import info.nightscout.androidaps.queue.Callback @@ -33,7 +32,7 @@ import info.nightscout.androidaps.utils.HtmlHelper import info.nightscout.androidaps.utils.Round import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.alertDialogs.OKDialog -import info.nightscout.androidaps.utils.extensions.formatColor +import info.nightscout.androidaps.extensions.formatColor import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.sharedPreferences.SP import io.reactivex.disposables.CompositeDisposable @@ -62,7 +61,6 @@ class BolusWizard @Inject constructor( @Inject lateinit var carbTimer: CarbTimer @Inject lateinit var glucoseStatusProvider: GlucoseStatusProvider @Inject lateinit var repository: AppRepository - @Inject lateinit var nsUpload: NSUpload private val disposable = CompositeDisposable() @@ -205,7 +203,7 @@ class BolusWizard @Inject constructor( // Insulin from IOB // IOB calculation val bolusIob = iobCobCalculator.calculateIobFromBolus().round() - val basalIob = activePlugin.activeTreatments.lastCalculationTempBasals.round() + val basalIob = iobCobCalculator.calculateIobFromTempBasalsIncludingConvertedExtended().round() insulinFromBolusIOB = if (includeBolusIOB) -bolusIob.iob else 0.0 insulinFromBasalIOB = if (includeBasalIOB) -basalIob.basaliob else 0.0 diff --git a/app/src/main/java/info/nightscout/androidaps/utils/wizard/QuickWizardEntry.kt b/app/src/main/java/info/nightscout/androidaps/utils/wizard/QuickWizardEntry.kt index 2aff9f479f..a3f08d07a4 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/wizard/QuickWizardEntry.kt +++ b/app/src/main/java/info/nightscout/androidaps/utils/wizard/QuickWizardEntry.kt @@ -6,16 +6,15 @@ import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.ValueWrapper import info.nightscout.androidaps.database.entities.GlucoseValue +import info.nightscout.androidaps.interfaces.IobCobCalculator import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider -import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin -import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.JsonHelper.safeGetInt import info.nightscout.androidaps.utils.JsonHelper.safeGetString -import info.nightscout.androidaps.utils.extensions.valueToUnits +import info.nightscout.androidaps.extensions.valueToUnits import info.nightscout.androidaps.utils.sharedPreferences.SP import org.json.JSONException import org.json.JSONObject @@ -27,9 +26,8 @@ class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjec @Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var sp: SP @Inject lateinit var profileFunction: ProfileFunction - @Inject lateinit var treatmentsPlugin: TreatmentsPlugin @Inject lateinit var loopPlugin: LoopPlugin - @Inject lateinit var iobCobCalculatorPlugin: IobCobCalculatorPlugin + @Inject lateinit var iobCobCalculator: IobCobCalculator @Inject lateinit var repository: AppRepository @Inject lateinit var dateUtil: DateUtil @Inject lateinit var glucoseStatusProvider: GlucoseStatusProvider @@ -89,7 +87,7 @@ class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjec // COB var cob = 0.0 if (useCOB() == YES) { - val cobInfo = iobCobCalculatorPlugin.getCobInfo(_synchronized, "QuickWizard COB") + val cobInfo = iobCobCalculator.getCobInfo(_synchronized, "QuickWizard COB") if (cobInfo.displayCob != null) cob = cobInfo.displayCob!! } // Bolus IOB @@ -98,7 +96,7 @@ class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjec bolusIOB = true } // Basal IOB - val basalIob = treatmentsPlugin.lastCalculationTempBasals.round() + val basalIob = iobCobCalculator.calculateIobFromTempBasalsIncludingConvertedExtended().round() var basalIOB = false if (useBasalIOB() == YES) { basalIOB = true diff --git a/app/src/main/res/layout/dialog_temptarget.xml b/app/src/main/res/layout/dialog_temptarget.xml index 7a53ea8496..61f92c402f 100644 --- a/app/src/main/res/layout/dialog_temptarget.xml +++ b/app/src/main/res/layout/dialog_temptarget.xml @@ -141,8 +141,6 @@ - - + + + + + + + + - - - - - - - - - - - - - - - - @@ -156,6 +92,25 @@ android:layout_height="wrap_content" android:layout_gravity="top" android:paddingLeft="10dp" + android:paddingEnd="5dp" + android:text="@string/tempbasals_netratio_label_string" + android:textAppearance="?android:attr/textAppearanceSmall" + tools:ignore="RtlSymmetry" /> + + + + @@ -171,15 +126,35 @@ tools:ignore="HardcodedText" /> + + + + + + + android:orientation="horizontal"> - - + android:layout_gravity="center_vertical" + android:contentDescription="@string/show_removed" + app:srcCompat="@drawable/ic_visibility" /> + diff --git a/app/src/main/res/layout/treatments_tempbasals_item.xml b/app/src/main/res/layout/treatments_tempbasals_item.xml index 3816019fb9..801a308f72 100644 --- a/app/src/main/res/layout/treatments_tempbasals_item.xml +++ b/app/src/main/res/layout/treatments_tempbasals_item.xml @@ -38,16 +38,7 @@ tools:ignore="HardcodedText" /> - - + + - - - - - - - - - - - - - - - - - - - @@ -160,11 +82,17 @@ android:id="@+id/ns" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginEnd="10dp" + android:layout_marginStart="5dp" android:text="NS" android:textColor="@color/colorSetTempButton" tools:ignore="HardcodedText" /> + + + + + + + + + + diff --git a/app/src/main/res/layout/treatments_temptarget_fragment.xml b/app/src/main/res/layout/treatments_temptarget_fragment.xml index 1e68d571e9..b264f63d79 100644 --- a/app/src/main/res/layout/treatments_temptarget_fragment.xml +++ b/app/src/main/res/layout/treatments_temptarget_fragment.xml @@ -38,7 +38,6 @@ android:contentDescription="@string/show_removed" app:srcCompat="@drawable/ic_visibility" /> - ns_carbs_last_synced_id ns_bolus_last_synced_id ns_device_status_last_synced_id + ns_temporary_basal_last_synced_id + ns_extended_bolus_last_synced_id Treatments safety Max allowed bolus [U] diff --git a/app/src/test/java/info/nightscout/androidaps/TestBaseWithProfile.kt b/app/src/test/java/info/nightscout/androidaps/TestBaseWithProfile.kt index be4e29d439..bb20d622d0 100644 --- a/app/src/test/java/info/nightscout/androidaps/TestBaseWithProfile.kt +++ b/app/src/test/java/info/nightscout/androidaps/TestBaseWithProfile.kt @@ -4,11 +4,7 @@ import dagger.android.AndroidInjector import dagger.android.HasAndroidInjector import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.db.ProfileSwitch -import info.nightscout.androidaps.interfaces.ActivePluginProvider -import info.nightscout.androidaps.interfaces.ConfigInterface -import info.nightscout.androidaps.interfaces.ProfileFunction -import info.nightscout.androidaps.interfaces.ProfileStore -import info.nightscout.androidaps.interfaces.TreatmentsInterface +import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DefaultValueHelper @@ -26,6 +22,7 @@ open class TestBaseWithProfile : TestBase() { @Mock lateinit var activePluginProvider: ActivePluginProvider @Mock lateinit var resourceHelper: ResourceHelper @Mock lateinit var treatmentsInterface: TreatmentsInterface + @Mock lateinit var iobCobCalculator: IobCobCalculator @Mock lateinit var fabricPrivacy: FabricPrivacy @Mock lateinit var profileFunction: ProfileFunction @Mock lateinit var defaultValueHelper: DefaultValueHelper diff --git a/app/src/test/java/info/nightscout/androidaps/TestPumpPlugin.kt b/app/src/test/java/info/nightscout/androidaps/TestPumpPlugin.kt index d104302084..bfc9e86370 100644 --- a/app/src/test/java/info/nightscout/androidaps/TestPumpPlugin.kt +++ b/app/src/test/java/info/nightscout/androidaps/TestPumpPlugin.kt @@ -6,6 +6,7 @@ import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.interfaces.PumpDescription import info.nightscout.androidaps.interfaces.PumpInterface +import info.nightscout.androidaps.interfaces.PumpSync import info.nightscout.androidaps.plugins.common.ManufacturerType import info.nightscout.androidaps.plugins.pump.common.defs.PumpType import info.nightscout.androidaps.utils.TimeChangeType @@ -50,8 +51,8 @@ class TestPumpPlugin(val injector: HasAndroidInjector) : PumpInterface { override val batteryLevel: Int = 0 override fun deliverTreatment(detailedBolusInfo: DetailedBolusInfo): PumpEnactResult = PumpEnactResult(injector).success(true) override fun stopBolusDelivering() {} - override fun setTempBasalAbsolute(absoluteRate: Double, durationInMinutes: Int, profile: Profile, enforceNew: Boolean): PumpEnactResult = PumpEnactResult(injector).success(true) - override fun setTempBasalPercent(percent: Int, durationInMinutes: Int, profile: Profile, enforceNew: Boolean): PumpEnactResult = PumpEnactResult(injector).success(true) + override fun setTempBasalAbsolute(absoluteRate: Double, durationInMinutes: Int, profile: Profile, enforceNew: Boolean, tbrType: PumpSync.TemporaryBasalType): PumpEnactResult = PumpEnactResult(injector).success(true) + override fun setTempBasalPercent(percent: Int, durationInMinutes: Int, profile: Profile, enforceNew: Boolean, tbrType: PumpSync.TemporaryBasalType): PumpEnactResult = PumpEnactResult(injector).success(true) override fun setExtendedBolus(insulin: Double, durationInMinutes: Int): PumpEnactResult = PumpEnactResult(injector).success(true) override fun cancelTempBasal(enforceNew: Boolean): PumpEnactResult = PumpEnactResult(injector).success(true) override fun cancelExtendedBolus(): PumpEnactResult = PumpEnactResult(injector).success(true) diff --git a/app/src/test/java/info/nightscout/androidaps/data/QuickWizardTest.kt b/app/src/test/java/info/nightscout/androidaps/data/QuickWizardTest.kt index 6deef1f826..9cf9031a61 100644 --- a/app/src/test/java/info/nightscout/androidaps/data/QuickWizardTest.kt +++ b/app/src/test/java/info/nightscout/androidaps/data/QuickWizardTest.kt @@ -30,13 +30,12 @@ class QuickWizardTest : TestBase() { @Mock lateinit var profileFunction: ProfileFunction @Mock lateinit var treatmentsPlugin: TreatmentsPlugin @Mock lateinit var loopPlugin: LoopPlugin - @Mock lateinit var iobCobCalculatorPlugin: IobCobCalculatorPlugin private val data1 = "{\"buttonText\":\"Meal\",\"carbs\":36,\"validFrom\":0,\"validTo\":18000," + "\"useBG\":0,\"useCOB\":0,\"useBolusIOB\":0,\"useBasalIOB\":0,\"useTrend\":0,\"useSuperBolus\":0,\"useTemptarget\":0}" private val data2 = "{\"buttonText\":\"Lunch\",\"carbs\":18,\"validFrom\":36000,\"validTo\":39600," + "\"useBG\":0,\"useCOB\":0,\"useBolusIOB\":1,\"useBasalIOB\":2,\"useTrend\":0,\"useSuperBolus\":0,\"useTemptarget\":0}" - var array: JSONArray = JSONArray("[$data1,$data2]") + private var array: JSONArray = JSONArray("[$data1,$data2]") val injector = HasAndroidInjector { AndroidInjector { @@ -44,9 +43,7 @@ class QuickWizardTest : TestBase() { it.aapsLogger = aapsLogger it.sp = sp it.profileFunction = profileFunction - it.treatmentsPlugin = treatmentsPlugin it.loopPlugin = loopPlugin - it.iobCobCalculatorPlugin = iobCobCalculatorPlugin } } } diff --git a/app/src/test/java/info/nightscout/androidaps/interfaces/ConstraintsCheckerTest.kt b/app/src/test/java/info/nightscout/androidaps/interfaces/ConstraintsCheckerTest.kt index 79894eba45..c4286be513 100644 --- a/app/src/test/java/info/nightscout/androidaps/interfaces/ConstraintsCheckerTest.kt +++ b/app/src/test/java/info/nightscout/androidaps/interfaces/ConstraintsCheckerTest.kt @@ -25,6 +25,7 @@ import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProv import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin import info.nightscout.androidaps.plugins.pump.combo.ComboPlugin import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInfoStorage +import info.nightscout.androidaps.plugins.pump.common.bolusInfo.TemporaryBasalStorage import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin @@ -61,8 +62,8 @@ class ConstraintsCheckerTest : TestBaseWithProfile() { @Mock lateinit var sp: SP @Mock lateinit var commandQueue: CommandQueueProvider @Mock lateinit var detailedBolusInfoStorage: DetailedBolusInfoStorage + @Mock lateinit var temporaryBasalStorage: TemporaryBasalStorage @Mock lateinit var context: Context - @Mock lateinit var iobCobCalculator: IobCobCalculator @Mock lateinit var glimpPlugin: GlimpPlugin @Mock lateinit var sensitivityOref1Plugin: SensitivityOref1Plugin @Mock lateinit var profiler: Profiler @@ -139,16 +140,16 @@ class ConstraintsCheckerTest : TestBaseWithProfile() { val glucoseStatusProvider = GlucoseStatusProvider(aapsLogger = aapsLogger, iobCobCalculator = iobCobCalculator) - danaPump = DanaPump(aapsLogger, sp, injector) + danaPump = DanaPump(aapsLogger, sp, dateUtil, injector) hardLimits = HardLimits(aapsLogger, rxBus, sp, resourceHelper, context, repository) objectivesPlugin = ObjectivesPlugin(injector, aapsLogger, resourceHelper, activePlugin, sp, Config(), uel) - comboPlugin = ComboPlugin(injector, aapsLogger, rxBus, resourceHelper, profileFunction, treatmentsInterface, sp, commandQueue, context, databaseHelper) + comboPlugin = ComboPlugin(injector, aapsLogger, rxBus, resourceHelper, profileFunction, sp, commandQueue, context, databaseHelper, pumpSync) danaRPlugin = DanaRPlugin(injector, aapsLogger, aapsSchedulers, rxBus, context, resourceHelper, constraintChecker, activePlugin, sp, commandQueue, danaPump, dateUtil, fabricPrivacy, pumpSync) - danaRSPlugin = DanaRSPlugin(injector, aapsLogger, aapsSchedulers, rxBus, context, resourceHelper, constraintChecker, profileFunction, activePluginProvider, sp, commandQueue, danaPump, detailedBolusInfoStorage, fabricPrivacy, dateUtil) + danaRSPlugin = DanaRSPlugin(injector, aapsLogger, aapsSchedulers, rxBus, context, resourceHelper, constraintChecker, profileFunction, sp, commandQueue, danaPump, pumpSync, detailedBolusInfoStorage, temporaryBasalStorage, fabricPrivacy, dateUtil) insightPlugin = LocalInsightPlugin(injector, aapsLogger, rxBus, resourceHelper, treatmentsInterface, sp, commandQueue, profileFunction, nsUpload, context, uploadQueue, Config(), dateUtil, databaseHelper, pumpSync) - openAPSSMBPlugin = OpenAPSSMBPlugin(injector, aapsLogger, rxBus, constraintChecker, resourceHelper, profileFunction, context, activePlugin, treatmentsInterface, iobCobCalculator, hardLimits, profiler, sp, dateUtil, repository, glucoseStatusProvider) - openAPSAMAPlugin = OpenAPSAMAPlugin(injector, aapsLogger, rxBus, constraintChecker, resourceHelper, profileFunction, context, activePlugin, treatmentsInterface, iobCobCalculator, hardLimits, profiler, fabricPrivacy, dateUtil, repository, glucoseStatusProvider) - safetyPlugin = SafetyPlugin(injector, aapsLogger, resourceHelper, sp, rxBus, constraintChecker, openAPSAMAPlugin, openAPSSMBPlugin, sensitivityOref1Plugin, activePlugin, hardLimits, BuildHelper(Config(), loggerUtils), treatmentsInterface, Config()) + openAPSSMBPlugin = OpenAPSSMBPlugin(injector, aapsLogger, rxBus, constraintChecker, resourceHelper, profileFunction, context, activePlugin, iobCobCalculator, hardLimits, profiler, sp, dateUtil, repository, glucoseStatusProvider) + openAPSAMAPlugin = OpenAPSAMAPlugin(injector, aapsLogger, rxBus, constraintChecker, resourceHelper, profileFunction, context, activePlugin, iobCobCalculator, hardLimits, profiler, fabricPrivacy, dateUtil, repository, glucoseStatusProvider) + safetyPlugin = SafetyPlugin(injector, aapsLogger, resourceHelper, sp, rxBus, constraintChecker, openAPSAMAPlugin, openAPSSMBPlugin, sensitivityOref1Plugin, activePlugin, hardLimits, BuildHelper(Config(), loggerUtils), iobCobCalculator, Config(), dateUtil) val constraintsPluginsList = ArrayList() constraintsPluginsList.add(safetyPlugin) constraintsPluginsList.add(objectivesPlugin) diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/aps/loop/LoopPluginTest.kt b/app/src/test/java/info/nightscout/androidaps/plugins/aps/loop/LoopPluginTest.kt index 721d4402c8..ff7321cd4f 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/aps/loop/LoopPluginTest.kt +++ b/app/src/test/java/info/nightscout/androidaps/plugins/aps/loop/LoopPluginTest.kt @@ -13,7 +13,6 @@ import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.configBuilder.RunningConfiguration import info.nightscout.androidaps.plugins.general.nsclient.NSUpload -import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.receivers.ReceiverStatusStore @@ -44,10 +43,9 @@ class LoopPluginTest : TestBase() { @Mock lateinit var activePlugin: ActivePluginProvider @Mock lateinit var treatmentsPlugin: TreatmentsPlugin @Mock lateinit var virtualPumpPlugin: VirtualPumpPlugin - @Mock lateinit var iobCobCalculatorPlugin: IobCobCalculatorPlugin + @Mock lateinit var iobCobCalculator: IobCobCalculator @Mock lateinit var fabricPrivacy: FabricPrivacy @Mock lateinit var receiverStatusStore: ReceiverStatusStore - @Mock lateinit var nsUpload: NSUpload @Mock lateinit var notificationManager: NotificationManager @Mock lateinit var repository: AppRepository @Mock lateinit var dateUtil: DateUtil @@ -58,7 +56,7 @@ class LoopPluginTest : TestBase() { val injector = HasAndroidInjector { AndroidInjector { } } @Before fun prepareMock() { - loopPlugin = LoopPlugin(injector, aapsLogger, aapsSchedulers, rxBus, sp, Config(), constraintChecker, resourceHelper, profileFunction, context, commandQueue, activePlugin, treatmentsPlugin, virtualPumpPlugin, iobCobCalculatorPlugin, receiverStatusStore, fabricPrivacy, nsUpload, dateUtil, repository, runningConfiguration) + loopPlugin = LoopPlugin(injector, aapsLogger, aapsSchedulers, rxBus, sp, Config(), constraintChecker, resourceHelper, profileFunction, context, commandQueue, activePlugin, virtualPumpPlugin, iobCobCalculator, receiverStatusStore, fabricPrivacy, dateUtil, repository, runningConfiguration) `when`(activePlugin.activePump).thenReturn(virtualPumpPlugin) `when`(context.getSystemService(Context.NOTIFICATION_SERVICE)).thenReturn(notificationManager) } diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPluginTest.kt b/app/src/test/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPluginTest.kt index 1169498d11..6531cdea1f 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPluginTest.kt +++ b/app/src/test/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPluginTest.kt @@ -76,7 +76,7 @@ class SafetyPluginTest : TestBaseWithProfile() { `when`(activePlugin.activePump).thenReturn(virtualPumpPlugin) `when`(virtualPumpPlugin.pumpDescription).thenReturn(pumpDescription) hardLimits = HardLimits(aapsLogger, rxBus, sp, resourceHelper, context, repository) - safetyPlugin = SafetyPlugin(injector, aapsLogger, resourceHelper, sp, rxBus, constraintChecker, openAPSAMAPlugin, openAPSSMBPlugin, sensitivityOref1Plugin, activePlugin, hardLimits, buildHelper, treatmentsInterface, Config()) + safetyPlugin = SafetyPlugin(injector, aapsLogger, resourceHelper, sp, rxBus, constraintChecker, openAPSAMAPlugin, openAPSSMBPlugin, sensitivityOref1Plugin, activePlugin, hardLimits, buildHelper, iobCobCalculator, Config(), dateUtil) } @Test fun pumpDescriptionShouldLimitLoopInvocation() { diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPluginTest.kt b/app/src/test/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPluginTest.kt index 94e18a5b48..9e0b938e57 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPluginTest.kt +++ b/app/src/test/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPluginTest.kt @@ -19,7 +19,6 @@ import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker -import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.plugins.general.smsCommunicator.otp.OneTimePassword import info.nightscout.androidaps.plugins.general.smsCommunicator.otp.OneTimePasswordValidationResult import info.nightscout.androidaps.plugins.iob.iobCobCalculator.CobInfo @@ -66,14 +65,12 @@ class SmsCommunicatorPluginTest : TestBaseWithProfile() { @Mock lateinit var activePlugin: ActivePluginProvider @Mock lateinit var commandQueue: CommandQueueProvider @Mock lateinit var loopPlugin: LoopPlugin - @Mock lateinit var iobCobCalculator: IobCobCalculator @Mock lateinit var virtualPumpPlugin: VirtualPumpPlugin @Mock lateinit var localProfilePlugin: LocalProfilePlugin @Mock lateinit var treatmentService: TreatmentService @Mock lateinit var otp: OneTimePassword @Mock lateinit var xdripCalibrations: XdripCalibrations @Mock lateinit var uel: UserEntryLogger - @Mock lateinit var nsUpload: NSUpload @Mock lateinit var repository: AppRepository var injector: HasAndroidInjector = HasAndroidInjector { @@ -146,13 +143,13 @@ class SmsCommunicatorPluginTest : TestBaseWithProfile() { callback.result = PumpEnactResult(injector).success(true).isPercent(true).percent(invocation.getArgument(0)).duration(invocation.getArgument(1)) callback.run() null - }.`when`(commandQueue).tempBasalPercent(ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt(), ArgumentMatchers.anyBoolean(), anyObject(), ArgumentMatchers.any(Callback::class.java)) + }.`when`(commandQueue).tempBasalPercent(ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt(), ArgumentMatchers.anyBoolean(), anyObject(), ArgumentMatchers.any(PumpSync.TemporaryBasalType::class.java), ArgumentMatchers.any(Callback::class.java)) Mockito.doAnswer { invocation: InvocationOnMock -> val callback = invocation.getArgument(4) callback.result = PumpEnactResult(injector).success(true).isPercent(false).absolute(invocation.getArgument(0)).duration(invocation.getArgument(1)) callback.run() null - }.`when`(commandQueue).tempBasalAbsolute(ArgumentMatchers.anyDouble(), ArgumentMatchers.anyInt(), ArgumentMatchers.anyBoolean(), anyObject(), ArgumentMatchers.any(Callback::class.java)) + }.`when`(commandQueue).tempBasalAbsolute(ArgumentMatchers.anyDouble(), ArgumentMatchers.anyInt(), ArgumentMatchers.anyBoolean(), anyObject(), ArgumentMatchers.any(PumpSync.TemporaryBasalType::class.java), ArgumentMatchers.any(Callback::class.java)) Mockito.doAnswer { invocation: InvocationOnMock -> val callback = invocation.getArgument(2) callback.result = PumpEnactResult(injector).success(true).isPercent(false).absolute(invocation.getArgument(0)).duration(invocation.getArgument(1)) @@ -169,7 +166,7 @@ class SmsCommunicatorPluginTest : TestBaseWithProfile() { `when`(virtualPumpPlugin.model()).thenReturn(PumpType.GENERIC_AAPS) `when`(iobCobCalculator.calculateIobFromBolus()).thenReturn(IobTotal(0)) - `when`(treatmentsInterface.lastCalculationTempBasals).thenReturn(IobTotal(0)) + `when`(iobCobCalculator.calculateIobFromTempBasalsIncludingConvertedExtended()).thenReturn(IobTotal(0)) `when`(treatmentsInterface.service).thenReturn(treatmentService) `when`(activePlugin.activeProfileInterface).thenReturn(localProfilePlugin) diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobCalculatorPluginTest.kt b/app/src/test/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobCalculatorPluginTest.kt index 391e54f035..0bf79edf7a 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobCalculatorPluginTest.kt +++ b/app/src/test/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobCalculatorPluginTest.kt @@ -11,7 +11,6 @@ import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin -import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.T @@ -35,7 +34,6 @@ class IobCobCalculatorPluginTest : TestBase() { @Mock lateinit var resourceHelper: ResourceHelper @Mock lateinit var profileFunction: ProfileFunction @Mock lateinit var activePlugin: ActivePluginProvider - @Mock lateinit var treatmentsPlugin: TreatmentsPlugin @Mock lateinit var sensitivityOref1Plugin: SensitivityOref1Plugin @Mock lateinit var sensitivityAAPSPlugin: SensitivityAAPSPlugin @Mock lateinit var sensitivityWeightedAveragePlugin: SensitivityWeightedAveragePlugin @@ -52,7 +50,7 @@ class IobCobCalculatorPluginTest : TestBase() { @Before fun mock() { - iobCobCalculatorPlugin = IobCobCalculatorPlugin(injector, aapsLogger, aapsSchedulers, rxBus, sp, resourceHelper, profileFunction, activePlugin, treatmentsPlugin, sensitivityOref1Plugin, sensitivityAAPSPlugin, sensitivityWeightedAveragePlugin, fabricPrivacy, dateUtil, repository) + iobCobCalculatorPlugin = IobCobCalculatorPlugin(injector, aapsLogger, aapsSchedulers, rxBus, sp, resourceHelper, profileFunction, activePlugin, sensitivityOref1Plugin, sensitivityAAPSPlugin, sensitivityWeightedAveragePlugin, fabricPrivacy, dateUtil, repository) } @Test diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/pump/virtual/VirtualPumpPluginUTest.kt b/app/src/test/java/info/nightscout/androidaps/plugins/pump/virtual/VirtualPumpPluginUTest.kt index 2974a74044..fa3bf196fb 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/pump/virtual/VirtualPumpPluginUTest.kt +++ b/app/src/test/java/info/nightscout/androidaps/plugins/pump/virtual/VirtualPumpPluginUTest.kt @@ -5,11 +5,11 @@ import info.nightscout.androidaps.Config import info.nightscout.androidaps.R import info.nightscout.androidaps.TestBase import info.nightscout.androidaps.interfaces.CommandQueueProvider +import info.nightscout.androidaps.interfaces.IobCobCalculator import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.PumpSync import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.pump.common.defs.PumpType -import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.resources.ResourceHelper @@ -32,7 +32,7 @@ class VirtualPumpPluginUTest : TestBase() { @Mock lateinit var resourceHelper: ResourceHelper @Mock lateinit var sp: SP @Mock lateinit var profileFunction: ProfileFunction - @Mock lateinit var treatmentsPlugin: TreatmentsPlugin + @Mock lateinit var iobCobCalculator: IobCobCalculator @Mock lateinit var commandQueue: CommandQueueProvider @Mock lateinit var dateUtil: DateUtil @Mock lateinit var pumpSync: PumpSync @@ -41,7 +41,7 @@ class VirtualPumpPluginUTest : TestBase() { @Before fun prepareMocks() { - virtualPumpPlugin = VirtualPumpPlugin({ AndroidInjector { } }, aapsLogger, rxBus, fabricPrivacy, resourceHelper, aapsSchedulers, sp, profileFunction, treatmentsPlugin, commandQueue, pumpSync, Config(), dateUtil) + virtualPumpPlugin = VirtualPumpPlugin({ AndroidInjector { } }, aapsLogger, rxBus, fabricPrivacy, resourceHelper, aapsSchedulers, sp, profileFunction, iobCobCalculator, commandQueue, pumpSync, Config(), dateUtil) } @Test diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPluginTest.kt b/app/src/test/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPluginTest.kt index 4b0a188556..3e8b964004 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPluginTest.kt +++ b/app/src/test/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPluginTest.kt @@ -48,7 +48,7 @@ class TreatmentsPluginTest : TestBaseWithProfile() { } } } - +/* private lateinit var insulinOrefRapidActingPlugin: InsulinOrefRapidActingPlugin private lateinit var sot: TreatmentsPlugin @@ -59,7 +59,7 @@ class TreatmentsPluginTest : TestBaseWithProfile() { `when`(profileFunction.getProfile(ArgumentMatchers.anyLong())).thenReturn(validProfile) `when`(activePluginProvider.activeInsulin).thenReturn(insulinOrefRapidActingPlugin) - sot = TreatmentsPlugin(profileInjector, aapsLogger, rxBus, aapsSchedulers, resourceHelper, context, sp, profileFunction, activePluginProvider, nsUpload, fabricPrivacy, dateUtil, uploadQueue, databaseHelper, repository) + sot = TreatmentsPlugin(profileInjector, aapsLogger, rxBus, aapsSchedulers, resourceHelper, context, sp, profileFunction, activePluginProvider, nsUpload, fabricPrivacy, dateUtil, databaseHelper, repository) sot.service = treatmentService } @@ -102,4 +102,6 @@ class TreatmentsPluginTest : TestBaseWithProfile() { val iob110pct = sot.getAbsoluteIOBTempBasals(now) Assert.assertEquals(1.1, iob110pct.basaliob / iob100pct.basaliob, 0.0001) } + + */ } \ No newline at end of file diff --git a/app/src/test/java/info/nightscout/androidaps/queue/CommandQueueTest.kt b/app/src/test/java/info/nightscout/androidaps/queue/CommandQueueTest.kt index b07c724aab..be6c9b202b 100644 --- a/app/src/test/java/info/nightscout/androidaps/queue/CommandQueueTest.kt +++ b/app/src/test/java/info/nightscout/androidaps/queue/CommandQueueTest.kt @@ -15,6 +15,7 @@ import info.nightscout.androidaps.database.entities.Bolus import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.interfaces.ProfileFunction +import info.nightscout.androidaps.interfaces.PumpSync import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker @@ -175,11 +176,11 @@ class CommandQueueTest : TestBaseWithProfile() { Assert.assertEquals(0, commandQueue.size()) // add tempbasal - commandQueue.tempBasalAbsolute(0.0, 30, true, validProfile, null) + commandQueue.tempBasalAbsolute(0.0, 30, true, validProfile, PumpSync.TemporaryBasalType.NORMAL, null) Assert.assertEquals(1, commandQueue.size()) // add tempbasal percent. it should replace previous TEMPBASAL - commandQueue.tempBasalPercent(0, 30, true, validProfile, null) + commandQueue.tempBasalPercent(0, 30, true, validProfile, PumpSync.TemporaryBasalType.NORMAL, null) Assert.assertEquals(1, commandQueue.size()) // cancel tempbasal it should replace previous TEMPBASAL @@ -211,7 +212,7 @@ class CommandQueueTest : TestBaseWithProfile() { commandQueue.loadEvents(null) Assert.assertEquals(4, commandQueue.size()) commandQueue.clear() - commandQueue.tempBasalAbsolute(0.0, 30, true, validProfile, null) + commandQueue.tempBasalAbsolute(0.0, 30, true, validProfile, PumpSync.TemporaryBasalType.NORMAL, null) commandQueue.pickup() Assert.assertEquals(0, commandQueue.size()) Assert.assertNotNull(commandQueue.performing) diff --git a/app/src/test/java/info/nightscout/androidaps/queue/QueueThreadTest.kt b/app/src/test/java/info/nightscout/androidaps/queue/QueueThreadTest.kt index ef0c2cd756..58ebba63d7 100644 --- a/app/src/test/java/info/nightscout/androidaps/queue/QueueThreadTest.kt +++ b/app/src/test/java/info/nightscout/androidaps/queue/QueueThreadTest.kt @@ -12,6 +12,7 @@ import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.interfaces.PumpDescription +import info.nightscout.androidaps.interfaces.PumpSync import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.general.maintenance.LoggerUtils import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin @@ -30,7 +31,6 @@ import org.mockito.Mock import org.mockito.Mockito import org.powermock.core.classloader.annotations.PrepareForTest import org.powermock.modules.junit4.PowerMockRunner -import java.util.* @RunWith(PowerMockRunner::class) @PrepareForTest( @@ -93,7 +93,7 @@ class QueueThreadTest : TestBaseWithProfile() { @Test fun commandIsPickedUp() { - commandQueue.tempBasalAbsolute(2.0, 60, true, validProfile, null) + commandQueue.tempBasalAbsolute(2.0, 60, true, validProfile, PumpSync.TemporaryBasalType.NORMAL, null) sut.run() Assert.assertEquals(0, commandQueue.size()) } diff --git a/app/src/test/java/info/nightscout/androidaps/utils/wizard/BolusWizardTest.kt b/app/src/test/java/info/nightscout/androidaps/utils/wizard/BolusWizardTest.kt index 294f2c7999..c1c22dc89e 100644 --- a/app/src/test/java/info/nightscout/androidaps/utils/wizard/BolusWizardTest.kt +++ b/app/src/test/java/info/nightscout/androidaps/utils/wizard/BolusWizardTest.kt @@ -72,7 +72,7 @@ class BolusWizardTest : TestBase() { `when`(iobCobCalculator.dataLock).thenReturn(Any()) `when`(activePlugin.activeTreatments).thenReturn(treatmentsPlugin) `when`(iobCobCalculator.calculateIobFromBolus()).thenReturn(IobTotal(System.currentTimeMillis())) - `when`(treatmentsPlugin.lastCalculationTempBasals).thenReturn(IobTotal(System.currentTimeMillis())) + `when`(iobCobCalculator.calculateIobFromTempBasalsIncludingConvertedExtended()).thenReturn(IobTotal(System.currentTimeMillis())) `when`(activePlugin.activePump).thenReturn(virtualPumpPlugin) val pumpDescription = PumpDescription() pumpDescription.bolusStep = pumpBolusStep diff --git a/automation/src/main/java/info/nightscout/androidaps/plugins/general/automation/AutomationFragment.kt b/automation/src/main/java/info/nightscout/androidaps/plugins/general/automation/AutomationFragment.kt index b7ea2b3db0..8df0ebbc6d 100644 --- a/automation/src/main/java/info/nightscout/androidaps/plugins/general/automation/AutomationFragment.kt +++ b/automation/src/main/java/info/nightscout/androidaps/plugins/general/automation/AutomationFragment.kt @@ -35,7 +35,7 @@ import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.HtmlHelper import info.nightscout.androidaps.utils.alertDialogs.OKDialog import io.reactivex.rxkotlin.plusAssign -import info.nightscout.androidaps.utils.extensions.toVisibility +import info.nightscout.androidaps.extensions.toVisibility import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers import io.reactivex.disposables.CompositeDisposable diff --git a/automation/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionStartTempTarget.kt b/automation/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionStartTempTarget.kt index bb81292848..3efc6b697c 100644 --- a/automation/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionStartTempTarget.kt +++ b/automation/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionStartTempTarget.kt @@ -23,7 +23,7 @@ import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.JsonHelper import info.nightscout.androidaps.utils.JsonHelper.safeGetDouble -import info.nightscout.androidaps.utils.extensions.friendlyDescription +import info.nightscout.androidaps.extensions.friendlyDescription import info.nightscout.androidaps.utils.resources.ResourceHelper import io.reactivex.disposables.CompositeDisposable import io.reactivex.rxkotlin.plusAssign diff --git a/automation/src/main/java/info/nightscout/androidaps/plugins/general/automation/dialogs/EditEventDialog.kt b/automation/src/main/java/info/nightscout/androidaps/plugins/general/automation/dialogs/EditEventDialog.kt index b408ff76fa..9c2e327cbc 100644 --- a/automation/src/main/java/info/nightscout/androidaps/plugins/general/automation/dialogs/EditEventDialog.kt +++ b/automation/src/main/java/info/nightscout/androidaps/plugins/general/automation/dialogs/EditEventDialog.kt @@ -26,7 +26,7 @@ import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerCon import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.ToastUtils import io.reactivex.rxkotlin.plusAssign -import info.nightscout.androidaps.utils.extensions.toVisibility +import info.nightscout.androidaps.extensions.toVisibility import info.nightscout.androidaps.utils.rx.AapsSchedulers import io.reactivex.disposables.CompositeDisposable import javax.inject.Inject diff --git a/automation/src/test/java/info/nightscout/androidaps/plugins/general/automation/TestPumpPlugin.kt b/automation/src/test/java/info/nightscout/androidaps/plugins/general/automation/TestPumpPlugin.kt index b5c6682093..742d0a4ebf 100644 --- a/automation/src/test/java/info/nightscout/androidaps/plugins/general/automation/TestPumpPlugin.kt +++ b/automation/src/test/java/info/nightscout/androidaps/plugins/general/automation/TestPumpPlugin.kt @@ -8,6 +8,7 @@ import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.interfaces.PluginDescription import info.nightscout.androidaps.interfaces.PumpDescription import info.nightscout.androidaps.interfaces.PumpInterface +import info.nightscout.androidaps.interfaces.PumpSync import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.plugins.common.ManufacturerType import info.nightscout.androidaps.plugins.pump.common.defs.PumpType @@ -61,8 +62,8 @@ class TestPumpPlugin(pluginDescription: PluginDescription, override val batteryLevel: Int = 0 override fun deliverTreatment(detailedBolusInfo: DetailedBolusInfo): PumpEnactResult = PumpEnactResult(injector).success(true) override fun stopBolusDelivering() {} - override fun setTempBasalAbsolute(absoluteRate: Double, durationInMinutes: Int, profile: Profile, enforceNew: Boolean): PumpEnactResult = PumpEnactResult(injector).success(true) - override fun setTempBasalPercent(percent: Int, durationInMinutes: Int, profile: Profile, enforceNew: Boolean): PumpEnactResult = PumpEnactResult(injector).success(true) + override fun setTempBasalAbsolute(absoluteRate: Double, durationInMinutes: Int, profile: Profile, enforceNew: Boolean, tbrType: PumpSync.TemporaryBasalType): PumpEnactResult = PumpEnactResult(injector).success(true) + override fun setTempBasalPercent(percent: Int, durationInMinutes: Int, profile: Profile, enforceNew: Boolean, tbrType: PumpSync.TemporaryBasalType): PumpEnactResult = PumpEnactResult(injector).success(true) override fun setExtendedBolus(insulin: Double, durationInMinutes: Int): PumpEnactResult = PumpEnactResult(injector).success(true) override fun cancelTempBasal(enforceNew: Boolean): PumpEnactResult = PumpEnactResult(injector).success(true) override fun cancelExtendedBolus(): PumpEnactResult = PumpEnactResult(injector).success(true) diff --git a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ComboPlugin.java b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ComboPlugin.java index ae38482ddd..26c23e8e9d 100644 --- a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ComboPlugin.java +++ b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ComboPlugin.java @@ -66,6 +66,8 @@ import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.history.Tdd; import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.InstanceId; + +import info.nightscout.androidaps.utils.T; import info.nightscout.androidaps.utils.resources.ResourceHelper; import info.nightscout.androidaps.utils.sharedPreferences.SP; @@ -78,12 +80,12 @@ public class ComboPlugin extends PumpPluginBase implements PumpInterface, Constr static final String COMBO_BOLUSES_DELIVERED = "combo_boluses_delivered"; private final ProfileFunction profileFunction; - private final TreatmentsInterface treatmentsPlugin; - private final info.nightscout.androidaps.utils.sharedPreferences.SP sp; + private final SP sp; private RxBusWrapper rxBus; private final CommandQueueProvider commandQueue; private final Context context; private final DatabaseHelperInterface databaseHelper; + private final PumpSync pumpSync; private final static PumpDescription pumpDescription = new PumpDescription(); @@ -105,7 +107,7 @@ public class ComboPlugin extends PumpPluginBase implements PumpInterface, Constr /** * This is set (in {@link #checkHistory()} whenever a connection to the pump is made and * indicates if new history records on the pump have been found. This effectively blocks - * high temps ({@link #setTempBasalPercent(Integer, Integer)} and boluses + * high temps ({@link #setTempBasalPercent(Integer, Integer, PumpSync.TemporaryBasalType)} and boluses * ({@link #deliverBolus(DetailedBolusInfo)} till the queue is empty and the connection * is shut down. * {@link #initializePump()} resets this since on startup the history is allowed to have @@ -135,11 +137,11 @@ public class ComboPlugin extends PumpPluginBase implements PumpInterface, Constr RxBusWrapper rxBus, ResourceHelper resourceHelper, ProfileFunction profileFunction, - TreatmentsInterface treatmentsPlugin, SP sp, CommandQueueProvider commandQueue, Context context, - DatabaseHelperInterface databaseHelper + DatabaseHelperInterface databaseHelper, + PumpSync pumpSync ) { super(new PluginDescription() .mainType(PluginType.PUMP) @@ -152,11 +154,11 @@ public class ComboPlugin extends PumpPluginBase implements PumpInterface, Constr ); this.rxBus = rxBus; this.profileFunction = profileFunction; - this.treatmentsPlugin = treatmentsPlugin; this.sp = sp; this.commandQueue = commandQueue; this.context = context; this.databaseHelper = databaseHelper; + this.pumpSync = pumpSync; pumpDescription.setPumpDescription(PumpType.ACCU_CHEK_COMBO); } @@ -480,10 +482,13 @@ public class ComboPlugin extends PumpPluginBase implements PumpInterface, Constr return new PumpEnactResult(getInjector()).success(false).enacted(false) .bolusDelivered(0d).carbsDelivered(0d) .comment(R.string.invalidinput); - } else if (detailedBolusInfo.insulin > 0) { +// } else if (detailedBolusInfo.insulin > 0) { + } else { // bolus needed, ask pump to deliver it return deliverBolus(detailedBolusInfo); - } else { + } +/* This should not happen anymore + else { // no bolus required, carb only treatment treatmentsPlugin.addToHistoryTreatment(detailedBolusInfo, false); @@ -496,6 +501,8 @@ public class ComboPlugin extends PumpPluginBase implements PumpInterface, Constr .bolusDelivered(0d).carbsDelivered(detailedBolusInfo.carbs) .comment(R.string.virtualpump_resultok); } + + */ } finally { rxBus.send(new EventComboPumpUpdateGUI()); } @@ -669,6 +676,7 @@ public class ComboPlugin extends PumpPluginBase implements PumpInterface, Constr bolusInfo.setBolusPumpId(bolusInfo.timestamp); bolusInfo.insulin = lastPumpBolus.amount; try { +/* this should not happen if (bolusInfo.carbs > 0 && bolusInfo.carbTime != 0) { // split out a separate carbs record without a pumpId DetailedBolusInfo carbInfo = new DetailedBolusInfo(); @@ -682,7 +690,15 @@ public class ComboPlugin extends PumpPluginBase implements PumpInterface, Constr bolusInfo.carbTime = 0; bolusInfo.carbs = 0; } - treatmentsPlugin.addToHistoryTreatment(bolusInfo, true); + */ + pumpSync.syncBolusWithPumpId( + calculateFakeBolusDate(lastPumpBolus), + lastPumpBolus.amount, + detailedBolusInfo.getBolusType(), + bolusInfo.timestamp, + PumpType.ACCU_CHEK_COMBO, + serialNumber() + ); } catch (Exception e) { getAapsLogger().error("Adding treatment record failed", e); if (bolusInfo.getBolusType() == DetailedBolusInfo.BolusType.SMB) { @@ -712,7 +728,7 @@ public class ComboPlugin extends PumpPluginBase implements PumpInterface, Constr * the new value (and thus still has the old duration of e.g. 1 min) expires?) */ @NonNull @Override - public PumpEnactResult setTempBasalAbsolute(double absoluteRate, int durationInMinutes, @NonNull Profile profile, boolean force, PumpSync.TemporaryBasalType tbrType) { + public PumpEnactResult setTempBasalAbsolute(double absoluteRate, int durationInMinutes, @NonNull Profile profile, boolean force, @NonNull PumpSync.TemporaryBasalType tbrType) { getAapsLogger().debug(LTag.PUMP, "setTempBasalAbsolute called with a rate of " + absoluteRate + " for " + durationInMinutes + " min."); int unroundedPercentage = Double.valueOf(absoluteRate / getBaseBasalRate() * 100).intValue(); int roundedPercentage = (int) (Math.round(absoluteRate / getBaseBasalRate() * 10) * 10); @@ -720,7 +736,7 @@ public class ComboPlugin extends PumpPluginBase implements PumpInterface, Constr getAapsLogger().debug(LTag.PUMP, "Rounded requested rate " + unroundedPercentage + "% -> " + roundedPercentage + "%"); } - return setTempBasalPercent(roundedPercentage, durationInMinutes); + return setTempBasalPercent(roundedPercentage, durationInMinutes, tbrType); } /** @@ -730,11 +746,11 @@ public class ComboPlugin extends PumpPluginBase implements PumpInterface, Constr * is or isn't running at the moment */ @NonNull @Override - public PumpEnactResult setTempBasalPercent(int percent, int durationInMinutes, @NonNull Profile profile, boolean forceNew, PumpSync.TemporaryBasalType tbrType) { - return setTempBasalPercent(percent, durationInMinutes); + public PumpEnactResult setTempBasalPercent(int percent, int durationInMinutes, @NonNull Profile profile, boolean forceNew, @NonNull PumpSync.TemporaryBasalType tbrType) { + return setTempBasalPercent(percent, durationInMinutes, tbrType); } - private PumpEnactResult setTempBasalPercent(Integer percent, final Integer durationInMinutes) { + private PumpEnactResult setTempBasalPercent(Integer percent, final Integer durationInMinutes, @NonNull PumpSync.TemporaryBasalType tbrType) { getAapsLogger().debug(LTag.PUMP, "setTempBasalPercent called with " + percent + "% for " + durationInMinutes + "min"); if (pumpHistoryChanged && percent > 110) { @@ -770,12 +786,16 @@ public class ComboPlugin extends PumpPluginBase implements PumpInterface, Constr PumpState state = commandResult.state; if (state.tbrActive && state.tbrPercent == adjustedPercent && (state.tbrRemainingDuration == durationInMinutes || state.tbrRemainingDuration == durationInMinutes - 1)) { - TemporaryBasal tempStart = new TemporaryBasal(getInjector()) - .date(state.timestamp) - .duration(state.tbrRemainingDuration) - .percent(state.tbrPercent) - .source(Source.USER); - treatmentsPlugin.addToHistoryTempBasal(tempStart); + pumpSync.syncTemporaryBasalWithPumpId( + state.timestamp, + state.tbrPercent, + T.mins(state.tbrRemainingDuration).msecs(), + false, + tbrType, + state.timestamp, // no pumpId available ???? + PumpType.ACCU_CHEK_COMBO, + serialNumber() + ); rxBus.send(new EventComboPumpUpdateGUI()); } @@ -801,7 +821,9 @@ public class ComboPlugin extends PumpPluginBase implements PumpInterface, Constr @NonNull @Override public PumpEnactResult cancelTempBasal(boolean enforceNew) { getAapsLogger().debug(LTag.PUMP, "cancelTempBasal called"); - final TemporaryBasal activeTemp = treatmentsPlugin.getTempBasalFromHistory(System.currentTimeMillis()); + //final TemporaryBasal activeTemp = treatmentsPlugin.getTempBasalFromHistoryIncludingConvertedExtended(System.currentTimeMillis()); + PumpSync.PumpState pumpSate = pumpSync.expectedPumpState(); + final PumpSync.PumpState.TemporaryBasal activeTemp = pumpSate.getTemporaryBasal(); if (enforceNew) { CommandResult stateResult = runCommand(getResourceHelper().gs(R.string.combo_pump_action_refreshing), 2, ruffyScripter::readPumpState); if (!stateResult.success) { @@ -816,32 +838,33 @@ public class ComboPlugin extends PumpPluginBase implements PumpInterface, Constr return new PumpEnactResult(getInjector()).success(false).enacted(false); } if (!cancelResult.state.tbrActive) { - TemporaryBasal tempBasal = new TemporaryBasal(getInjector()) - .date(cancelResult.state.timestamp) - .duration(0) - .source(Source.USER); - treatmentsPlugin.addToHistoryTempBasal(tempBasal); + pumpSync.syncStopTemporaryBasalWithPumpId( + cancelResult.state.timestamp, + cancelResult.state.timestamp, + PumpType.ACCU_CHEK_COMBO, + serialNumber() + ); return new PumpEnactResult(getInjector()).isTempCancel(true).success(true).enacted(true); } else { return new PumpEnactResult(getInjector()).success(false).enacted(false); } } else if (activeTemp == null) { return new PumpEnactResult(getInjector()).success(true).enacted(false); - } else if ((activeTemp.percentRate >= 90 && activeTemp.percentRate <= 110) && activeTemp.getPlannedRemainingMinutes() <= 15) { + } else if ((activeTemp.getRate() >= 90 && activeTemp.getRate() <= 110) && info.nightscout.androidaps.extensions.PumpStateExtensionKt.getPlannedRemainingMinutes(activeTemp) <= 15) { // Let fake neutral temp keep run (see below) // Note that since this runs on the queue a connection is opened regardless, but this // case doesn't occur all that often, so it's not worth optimizing (1.3k SetTBR vs 4 cancelTBR). - getAapsLogger().debug(LTag.PUMP, "cancelTempBasal: skipping changing tbr since it already is at " + activeTemp.percentRate + "% and running for another " + activeTemp.getPlannedRemainingMinutes() + " mins."); + getAapsLogger().debug(LTag.PUMP, "cancelTempBasal: skipping changing tbr since it already is at " + activeTemp.getRate() + "% and running for another " + info.nightscout.androidaps.extensions.PumpStateExtensionKt.getPlannedRemainingMinutes(activeTemp) + " mins."); return new PumpEnactResult(getInjector()).success(true).enacted(true) .comment("cancelTempBasal skipping changing tbr since it already is at " - + activeTemp.percentRate + "% and running for another " - + activeTemp.getPlannedRemainingMinutes() + " mins."); + + activeTemp.getRate() + "% and running for another " + + info.nightscout.androidaps.extensions.PumpStateExtensionKt.getPlannedRemainingMinutes(activeTemp) + " mins."); } else { // Set a fake neutral temp to avoid TBR cancel alert. Decide 90% vs 110% based on // on whether the TBR we're cancelling is above or below 100%. - final int percentage = (activeTemp.percentRate > 100) ? 110 : 90; + final int percentage = (activeTemp.getRate() > 100) ? 110 : 90; getAapsLogger().debug(LTag.PUMP, "cancelTempBasal: changing TBR to " + percentage + "% for 15 mins."); - return setTempBasalPercent(percentage, 15); + return setTempBasalPercent(percentage, 15, PumpSync.TemporaryBasalType.NORMAL); } } @@ -961,15 +984,19 @@ public class ComboPlugin extends PumpPluginBase implements PumpInterface, Constr return checkHistory(); } else { long now = System.currentTimeMillis(); - TemporaryBasal aapsTbr = treatmentsPlugin.getTempBasalFromHistory(now); - if (aapsTbr == null || aapsTbr.percentRate != 0) { + PumpSync.PumpState.TemporaryBasal aapsTbr = pumpSync.expectedPumpState().getTemporaryBasal(); + if (aapsTbr == null || aapsTbr.getRate() != 0) { getAapsLogger().debug(LTag.PUMP, "Creating 15m zero temp since pump is suspended"); - TemporaryBasal newTempBasal = new TemporaryBasal(getInjector()) - .date(now) - .percent(0) - .duration(15) - .source(Source.USER); - treatmentsPlugin.addToHistoryTempBasal(newTempBasal); + pumpSync.syncTemporaryBasalWithPumpId( + now, + 0.0, + T.mins(15).msecs(), + false, + PumpSync.TemporaryBasalType.PUMP_SUSPEND, + now, // no pumpId available ???? + PumpType.ACCU_CHEK_COMBO, + serialNumber() + ); } } @@ -1087,38 +1114,49 @@ public class ComboPlugin extends PumpPluginBase implements PumpInterface, Constr private void checkAndResolveTbrMismatch(PumpState state) { // compare with: info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatusTempBasal.updateTempBasalInDB() long now = System.currentTimeMillis(); - TemporaryBasal aapsTbr = treatmentsPlugin.getTempBasalFromHistory(now); + //TemporaryBasal aapsTbr = treatmentsPlugin.getTempBasalFromHistoryIncludingConvertedExtended(now); + PumpSync.PumpState.TemporaryBasal aapsTbr = pumpSync.expectedPumpState().getTemporaryBasal(); if (aapsTbr == null && state.tbrActive && state.tbrRemainingDuration > 2) { getAapsLogger().debug(LTag.PUMP, "Creating temp basal from pump TBR"); - TemporaryBasal newTempBasal = new TemporaryBasal(getInjector()) - .date(now) - .percent(state.tbrPercent) - .duration(state.tbrRemainingDuration) - .source(Source.USER); - treatmentsPlugin.addToHistoryTempBasal(newTempBasal); - } else if (aapsTbr != null && aapsTbr.getPlannedRemainingMinutes() > 2 && !state.tbrActive) { + pumpSync.syncTemporaryBasalWithPumpId( + now, + state.tbrPercent, + T.mins(state.tbrRemainingDuration).msecs(), + false, + PumpSync.TemporaryBasalType.NORMAL, + now, // no pumpId available ???? + PumpType.ACCU_CHEK_COMBO, + serialNumber() + ); + } else if (aapsTbr != null && info.nightscout.androidaps.extensions.PumpStateExtensionKt.getPlannedRemainingMinutes(aapsTbr) > 2 && !state.tbrActive) { getAapsLogger().debug(LTag.PUMP, "Ending AAPS-TBR since pump has no TBR active"); - TemporaryBasal tempStop = new TemporaryBasal(getInjector()) - .date(now) - .duration(0) - .source(Source.USER); - treatmentsPlugin.addToHistoryTempBasal(tempStop); + pumpSync.syncStopTemporaryBasalWithPumpId( + now, + now, + PumpType.ACCU_CHEK_COMBO, + serialNumber() + ); } else if (aapsTbr != null && state.tbrActive - && (aapsTbr.percentRate != state.tbrPercent || - Math.abs(aapsTbr.getPlannedRemainingMinutes() - state.tbrRemainingDuration) > 2)) { + && (aapsTbr.getRate() != state.tbrPercent || + Math.abs(info.nightscout.androidaps.extensions.PumpStateExtensionKt.getPlannedRemainingMinutes(aapsTbr) - state.tbrRemainingDuration) > 2)) { getAapsLogger().debug(LTag.PUMP, "AAPSs and pump-TBR differ; ending AAPS-TBR and creating new TBR based on pump TBR"); - TemporaryBasal tempStop = new TemporaryBasal(getInjector()) - .date(now - 1000) - .duration(0) - .source(Source.USER); - treatmentsPlugin.addToHistoryTempBasal(tempStop); + pumpSync.syncStopTemporaryBasalWithPumpId( + now - 1000, + now - 1000, + PumpType.ACCU_CHEK_COMBO, + serialNumber() + ); - TemporaryBasal newTempBasal = new TemporaryBasal(getInjector()) - .date(now) - .percent(state.tbrPercent) - .duration(state.tbrRemainingDuration) - .source(Source.USER); - treatmentsPlugin.addToHistoryTempBasal(newTempBasal); + pumpSync.syncTemporaryBasalWithPumpId( + now, + state.tbrPercent, + T.mins(state.tbrRemainingDuration).msecs(), + false, + PumpSync.TemporaryBasalType.NORMAL, + now, // no pumpId available ???? + PumpType.ACCU_CHEK_COMBO, + serialNumber() + ); } } @@ -1151,14 +1189,14 @@ public class ComboPlugin extends PumpPluginBase implements PumpInterface, Constr private boolean updateDbFromPumpHistory(@NonNull PumpHistory history) { boolean updated = false; for (Bolus pumpBolus : history.bolusHistory) { - DetailedBolusInfo dbi = new DetailedBolusInfo(); - dbi.setBolusTimestamp(calculateFakeBolusDate(pumpBolus)); - dbi.setPumpType(PumpType.ACCU_CHEK_COMBO); - dbi.setPumpSerial(serialNumber()); - dbi.setBolusPumpId(dbi.timestamp); - dbi.insulin = pumpBolus.amount; - dbi.setEventType(DetailedBolusInfo.EventType.CORRECTION_BOLUS); - if (treatmentsPlugin.addToHistoryTreatment(dbi, true)) { + if (pumpSync.syncBolusWithPumpId( + calculateFakeBolusDate(pumpBolus), + pumpBolus.amount, + DetailedBolusInfo.BolusType.NORMAL, + System.currentTimeMillis(), + PumpType.ACCU_CHEK_COMBO, + serialNumber() + )) { updated = true; } } diff --git a/combo/src/test/java/info/nightscout/androidaps/plugins/pump/combo/ComboPluginTest.kt b/combo/src/test/java/info/nightscout/androidaps/plugins/pump/combo/ComboPluginTest.kt index 108973affd..7ff9cd82e1 100644 --- a/combo/src/test/java/info/nightscout/androidaps/plugins/pump/combo/ComboPluginTest.kt +++ b/combo/src/test/java/info/nightscout/androidaps/plugins/pump/combo/ComboPluginTest.kt @@ -28,7 +28,7 @@ class ComboPluginTest : TestBase() { @Mock lateinit var profileFunction: ProfileFunction @Mock lateinit var activePlugin: ActivePluginProvider @Mock lateinit var commandQueue: CommandQueueProvider - @Mock lateinit var treatmentsPlugin: TreatmentsInterface + @Mock lateinit var pumpSync: PumpSync @Mock lateinit var sp: SP @Mock lateinit var context: Context @Mock lateinit var databaseHelper: DatabaseHelperInterface @@ -47,7 +47,7 @@ class ComboPluginTest : TestBase() { fun prepareMocks() { `when`(resourceHelper.gs(R.string.novalidbasalrate)).thenReturn("No valid basal rate read from pump") `when`(resourceHelper.gs(R.string.combo_pump_unsupported_operation)).thenReturn("Requested operation not supported by pump") - comboPlugin = ComboPlugin(injector, aapsLogger, RxBusWrapper(aapsSchedulers), resourceHelper, profileFunction, treatmentsPlugin, sp, commandQueue, context, databaseHelper) + comboPlugin = ComboPlugin(injector, aapsLogger, RxBusWrapper(aapsSchedulers), resourceHelper, profileFunction, sp, commandQueue, context, databaseHelper, pumpSync) } @Test diff --git a/core/src/main/java/info/nightscout/androidaps/Constants.java b/core/src/main/java/info/nightscout/androidaps/Constants.java index 94f76cc2d7..401bd3bf22 100644 --- a/core/src/main/java/info/nightscout/androidaps/Constants.java +++ b/core/src/main/java/info/nightscout/androidaps/Constants.java @@ -72,7 +72,7 @@ public class Constants { public static final int MIN_WATCHDOG_INTERVAL_IN_SECONDS = 12 * 60; //SMS Communicator - public static final long SMS_CONFIRM_TIMEOUT = T.mins(5).msecs(); + public static final long SMS_CONFIRM_TIMEOUT = T.mins(5L).msecs(); //Storage [MB] public static final long MINIMUM_FREE_SPACE = 200; diff --git a/core/src/main/java/info/nightscout/androidaps/data/Profile.java b/core/src/main/java/info/nightscout/androidaps/data/Profile.java index 0ce7f5d2d6..06eba8d212 100644 --- a/core/src/main/java/info/nightscout/androidaps/data/Profile.java +++ b/core/src/main/java/info/nightscout/androidaps/data/Profile.java @@ -43,7 +43,7 @@ public class Profile { private JSONObject json; private String units; - private double dia; + private double dia; // TODO change to insulinInterface link private TimeZone timeZone; private JSONArray isf; private LongSparseArray isf_v; // oldest at index 0 diff --git a/core/src/main/java/info/nightscout/androidaps/db/ExtendedBolus.java b/core/src/main/java/info/nightscout/androidaps/db/ExtendedBolus.java index 37a160a50d..6459a238c3 100644 --- a/core/src/main/java/info/nightscout/androidaps/db/ExtendedBolus.java +++ b/core/src/main/java/info/nightscout/androidaps/db/ExtendedBolus.java @@ -35,6 +35,7 @@ import info.nightscout.androidaps.utils.Round; * Created by mike on 21.05.2017. */ +@Deprecated @DatabaseTable(tableName = "ExtendedBoluses") public class ExtendedBolus implements Interval, DataPointWithLabelInterface { @@ -335,10 +336,6 @@ public class ExtendedBolus implements Interval, DataPointWithLabelInterface { " " + getRealDuration() + "/" + durationInMinutes + "min"; } - public String toStringShort() { - return "E " + DecimalFormatter.INSTANCE.to2Decimal(absoluteRate()) + "U/h "; - } - public String toStringMedium() { return DecimalFormatter.INSTANCE.to2Decimal(absoluteRate()) + "U/h " + getRealDuration() + "/" + durationInMinutes + "'"; diff --git a/core/src/main/java/info/nightscout/androidaps/db/TemporaryBasal.java b/core/src/main/java/info/nightscout/androidaps/db/TemporaryBasal.java index f38b66f1b8..696947cb14 100644 --- a/core/src/main/java/info/nightscout/androidaps/db/TemporaryBasal.java +++ b/core/src/main/java/info/nightscout/androidaps/db/TemporaryBasal.java @@ -26,6 +26,7 @@ import info.nightscout.androidaps.utils.sharedPreferences.SP; * Created by mike on 21.05.2017. */ +@Deprecated @DatabaseTable(tableName = "TemporaryBasals") public class TemporaryBasal implements Interval, DbObjectBase { @@ -431,7 +432,7 @@ public class TemporaryBasal implements Interval, DbObjectBase { return "null"; Double currentBasalRate = profile.getBasal(); double rate = currentBasalRate + netExtendedRate; - return getCalcuatedPercentageIfNeeded() + DecimalFormatter.INSTANCE.to2Decimal(rate) + "U/h (" + DecimalFormatter.INSTANCE.to2Decimal(netExtendedRate) + "E) @" + + return DecimalFormatter.INSTANCE.to2Decimal(rate) + "U/h (" + DecimalFormatter.INSTANCE.to2Decimal(netExtendedRate) + "E) @" + dateUtil.timeString(date) + " " + getRealDuration() + "/" + durationInMinutes + "'"; } else if (isAbsolute) { @@ -459,47 +460,12 @@ public class TemporaryBasal implements Interval, DbObjectBase { rate = absoluteRate; } - if (sp.getBoolean(R.string.key_danar_visualizeextendedaspercentage, false) && sp.getBoolean(R.string.key_danar_useextended, false)) { - Profile profile = profileFunction.getProfile(); - if (profile != null) { - double basal = profile.getBasal(); - if (basal != 0) { - return Math.round(rate * 100d / basal) + "%"; - } - } - } return DecimalFormatter.INSTANCE.to2Decimal(rate) + "U/h"; } else { // percent return percentRate + "%"; } } - private String getCalcuatedPercentageIfNeeded() { - Profile profile = profileFunction.getProfile(); - - if (profile == null) - return "null"; - - if (isAbsolute || isFakeExtended) { - - double rate; - if (isFakeExtended) { - double currentBasalRate = profile.getBasal(); - rate = currentBasalRate + netExtendedRate; - } else { - rate = absoluteRate; - } - - if (sp.getBoolean(R.string.key_danar_visualizeextendedaspercentage, false) && sp.getBoolean(R.string.key_danar_useextended, false)) { - double basal = profile.getBasal(); - if (basal != 0) { - return Math.round(rate * 100d / basal) + "% "; - } - } - } - return ""; - } - public String toStringVeryShort() { Profile profile = profileFunction.getProfile(); diff --git a/core/src/main/java/info/nightscout/androidaps/dialogs/DialogFragmentWithDate.kt b/core/src/main/java/info/nightscout/androidaps/dialogs/DialogFragmentWithDate.kt index 5e35ef2682..45b69f4a7c 100644 --- a/core/src/main/java/info/nightscout/androidaps/dialogs/DialogFragmentWithDate.kt +++ b/core/src/main/java/info/nightscout/androidaps/dialogs/DialogFragmentWithDate.kt @@ -16,7 +16,7 @@ import info.nightscout.androidaps.core.R import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.utils.DateUtil -import info.nightscout.androidaps.utils.extensions.toVisibility +import info.nightscout.androidaps.extensions.toVisibility import info.nightscout.androidaps.utils.sharedPreferences.SP import java.util.* import javax.inject.Inject diff --git a/core/src/main/java/info/nightscout/androidaps/utils/extensions/BolusCalculatorResultExtension.kt b/core/src/main/java/info/nightscout/androidaps/extensions/BolusCalculatorResultExtension.kt similarity index 86% rename from core/src/main/java/info/nightscout/androidaps/utils/extensions/BolusCalculatorResultExtension.kt rename to core/src/main/java/info/nightscout/androidaps/extensions/BolusCalculatorResultExtension.kt index 64a7cdf38c..d5ffeb9566 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/extensions/BolusCalculatorResultExtension.kt +++ b/core/src/main/java/info/nightscout/androidaps/extensions/BolusCalculatorResultExtension.kt @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.utils.extensions +package info.nightscout.androidaps.extensions import com.google.gson.Gson import info.nightscout.androidaps.Constants @@ -9,7 +9,7 @@ import org.json.JSONObject fun BolusCalculatorResult.toJson(): JSONObject = JSONObject() - .put("eventType", TherapyEvent.Type.BOLUS_WIZARD) + .put("eventType", TherapyEvent.Type.BOLUS_WIZARD.text) .put("created_at", DateUtil.toISOString(timestamp)) .put("bolusCalculatorResult", Gson().toJson(this)) .put("date", timestamp) diff --git a/core/src/main/java/info/nightscout/androidaps/utils/extensions/BolusExtension.kt b/core/src/main/java/info/nightscout/androidaps/extensions/BolusExtension.kt similarity index 96% rename from core/src/main/java/info/nightscout/androidaps/utils/extensions/BolusExtension.kt rename to core/src/main/java/info/nightscout/androidaps/extensions/BolusExtension.kt index 48ba4fb21e..ee61eb1b92 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/extensions/BolusExtension.kt +++ b/core/src/main/java/info/nightscout/androidaps/extensions/BolusExtension.kt @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.utils.extensions +package info.nightscout.androidaps.extensions import info.nightscout.androidaps.data.Iob import info.nightscout.androidaps.database.embedments.InterfaceIDs @@ -18,7 +18,7 @@ fun Bolus.iobCalc(activePlugin: ActivePluginProvider, time: Long, dia: Double): fun Bolus.toJson(): JSONObject = JSONObject() - .put("eventType", if (type == Bolus.Type.SMB) TherapyEvent.Type.CORRECTION_BOLUS else TherapyEvent.Type.MEAL_BOLUS) + .put("eventType", if (type == Bolus.Type.SMB) TherapyEvent.Type.CORRECTION_BOLUS.text else TherapyEvent.Type.MEAL_BOLUS.text) .put("insulin", amount) .put("created_at", DateUtil.toISOString(timestamp)) .put("date", timestamp) diff --git a/core/src/main/java/info/nightscout/androidaps/utils/extensions/CarbsExtension.kt b/core/src/main/java/info/nightscout/androidaps/extensions/CarbsExtension.kt similarity index 95% rename from core/src/main/java/info/nightscout/androidaps/utils/extensions/CarbsExtension.kt rename to core/src/main/java/info/nightscout/androidaps/extensions/CarbsExtension.kt index 223d8cb2e6..aa989abe54 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/extensions/CarbsExtension.kt +++ b/core/src/main/java/info/nightscout/androidaps/extensions/CarbsExtension.kt @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.utils.extensions +package info.nightscout.androidaps.extensions import info.nightscout.androidaps.database.embedments.InterfaceIDs import info.nightscout.androidaps.database.entities.Carbs @@ -9,7 +9,7 @@ import org.json.JSONObject fun Carbs.toJson(): JSONObject = JSONObject() - .put("eventType", if (amount < 12) TherapyEvent.Type.CARBS_CORRECTION else TherapyEvent.Type.MEAL_BOLUS) + .put("eventType", if (amount < 12) TherapyEvent.Type.CARBS_CORRECTION.text else TherapyEvent.Type.MEAL_BOLUS.text) .put("carbs", amount) .put("created_at", DateUtil.toISOString(timestamp)) .put("date", timestamp).also { diff --git a/core/src/main/java/info/nightscout/androidaps/utils/extensions/Concurrency.kt b/core/src/main/java/info/nightscout/androidaps/extensions/Concurrency.kt similarity index 93% rename from core/src/main/java/info/nightscout/androidaps/utils/extensions/Concurrency.kt rename to core/src/main/java/info/nightscout/androidaps/extensions/Concurrency.kt index b958a0ea24..e0ecdf7f37 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/extensions/Concurrency.kt +++ b/core/src/main/java/info/nightscout/androidaps/extensions/Concurrency.kt @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.utils.extensions +package info.nightscout.androidaps.extensions @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "NOTHING_TO_INLINE") diff --git a/core/src/main/java/info/nightscout/androidaps/utils/extensions/DeviceStatusExtension.kt b/core/src/main/java/info/nightscout/androidaps/extensions/DeviceStatusExtension.kt similarity index 99% rename from core/src/main/java/info/nightscout/androidaps/utils/extensions/DeviceStatusExtension.kt rename to core/src/main/java/info/nightscout/androidaps/extensions/DeviceStatusExtension.kt index 97af8a73aa..23e500a2dd 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/extensions/DeviceStatusExtension.kt +++ b/core/src/main/java/info/nightscout/androidaps/extensions/DeviceStatusExtension.kt @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.utils.extensions +package info.nightscout.androidaps.extensions import android.os.Build import info.nightscout.androidaps.database.entities.DeviceStatus diff --git a/core/src/main/java/info/nightscout/androidaps/extensions/ExtendedBolusExtension.kt b/core/src/main/java/info/nightscout/androidaps/extensions/ExtendedBolusExtension.kt new file mode 100644 index 0000000000..7d9092c8e0 --- /dev/null +++ b/core/src/main/java/info/nightscout/androidaps/extensions/ExtendedBolusExtension.kt @@ -0,0 +1,190 @@ +package info.nightscout.androidaps.extensions + +import info.nightscout.androidaps.data.IobTotal +import info.nightscout.androidaps.data.Profile +import info.nightscout.androidaps.database.embedments.InterfaceIDs +import info.nightscout.androidaps.database.entities.Bolus +import info.nightscout.androidaps.database.entities.ExtendedBolus +import info.nightscout.androidaps.database.entities.TemporaryBasal +import info.nightscout.androidaps.database.entities.TherapyEvent +import info.nightscout.androidaps.database.interfaces.end +import info.nightscout.androidaps.interfaces.InsulinInterface +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult +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 kotlin.math.ceil +import kotlin.math.max +import kotlin.math.min +import kotlin.math.round +import kotlin.math.roundToInt + +fun ExtendedBolus.isInProgress(dateUtil: DateUtil): Boolean = + dateUtil._now() in timestamp..timestamp + duration + +val ExtendedBolus.plannedRemainingMinutes: Int + get() = max(round((end - System.currentTimeMillis()) / 1000.0 / 60).toInt(), 0) + +fun ExtendedBolus.toStringFull(dateUtil: DateUtil): String = + "E " + to2Decimal(rate) + "U/h @" + dateUtil.timeString(timestamp) + + " " + getPassedDurationToTimeInMinutes(dateUtil._now()) + "/" + T.msecs(duration).mins() + "min" + +fun ExtendedBolus.toStringMedium(dateUtil: DateUtil): String = + to2Decimal(rate) + "U/h " + getPassedDurationToTimeInMinutes(dateUtil._now()) + "/" + T.msecs(duration).mins() + "'" + +fun ExtendedBolus.toStringTotal(): String = "${to2Decimal(amount)}U ( ${to2Decimal(rate)} U/h )" + +fun ExtendedBolus.getPassedDurationToTimeInMinutes(time: Long): Int = + ((min(time, end) - timestamp) / 60.0 / 1000).roundToInt() + +fun ExtendedBolus.toTemporaryBasal(profile: Profile): TemporaryBasal = + TemporaryBasal( + timestamp = timestamp, + duration = duration, + rate = profile.getBasal(timestamp) + rate, + isAbsolute = true, + isValid = isValid, + interfaceIDs_backing = interfaceIDs_backing, + type = TemporaryBasal.Type.FAKE_EXTENDED + ) + +fun ExtendedBolus.toJson(profile: Profile): JSONObject = + if (isEmulatingTempBasal) + toTemporaryBasal(profile) + .toJson(profile) + .put("extendedEmulated", toRealJson()) + else toRealJson() + +fun ExtendedBolus.toRealJson(): JSONObject = + JSONObject() + .put("created_at", DateUtil.toISOString(timestamp)) + .put("enteredBy", "openaps://" + "AndroidAPS") + .put("eventType", TherapyEvent.Type.COMBO_BOLUS.text) + .put("duration", T.msecs(duration).mins()) + .put("splitNow", 0) + .put("splitExt", 100) + .put("enteredinsulin", amount) + .put("relative", rate) + .put("isEmulatingTempBasal", isEmulatingTempBasal) + .also { + if (interfaceIDs.pumpId != null) it.put("pumpId", interfaceIDs.pumpId) + if (interfaceIDs.endId != null) it.put("endId", interfaceIDs.endId) + 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) + } + +/* + create fake object with nsID and isValid == false + */ +fun extendedBolusFromNsIdForInvalidating(nsId: String): ExtendedBolus = + extendedBolusFromJson( + JSONObject() + .put("mills", 1) + .put("amount", -1.0) + .put("duration", -1.0) + .put("splitNow", 0) + .put("splitExt", 100) + .put("_id", nsId) + .put("isValid", false) + )!! + +fun extendedBolusFromJson(jsonObject: JSONObject): ExtendedBolus? { + val timestamp = JsonHelper.safeGetLongAllowNull(jsonObject, "mills", null) ?: return null + if (JsonHelper.safeGetIntAllowNull(jsonObject, "splitNow") != 0) return null + if (JsonHelper.safeGetIntAllowNull(jsonObject, "splitExt") != 100) return null + val amount = JsonHelper.safeGetDoubleAllowNull(jsonObject, "enteredinsulin") ?: return null + val duration = JsonHelper.safeGetLongAllowNull(jsonObject, "duration") ?: return null + val isValid = JsonHelper.safeGetBoolean(jsonObject, "isValid", true) + val isEmulatingTempBasal = JsonHelper.safeGetBoolean(jsonObject, "isEmulatingTempBasal", false) + val id = JsonHelper.safeGetStringAllowNull(jsonObject, "_id", null) ?: return null + val pumpId = JsonHelper.safeGetLongAllowNull(jsonObject, "pumpId", null) + val endPumpId = JsonHelper.safeGetLongAllowNull(jsonObject, "endId", null) + val pumpType = InterfaceIDs.PumpType.fromString(JsonHelper.safeGetStringAllowNull(jsonObject, "pumpType", null)) + val pumpSerial = JsonHelper.safeGetStringAllowNull(jsonObject, "pumpSerial", null) + + return ExtendedBolus( + timestamp = timestamp, + amount = amount, + duration = duration, + isEmulatingTempBasal = isEmulatingTempBasal, + isValid = isValid + ).also { + it.interfaceIDs.nightscoutId = id + it.interfaceIDs.pumpId = pumpId + it.interfaceIDs.endId = endPumpId + it.interfaceIDs.pumpType = pumpType + it.interfaceIDs.pumpSerial = pumpSerial + } +} + +fun ExtendedBolus.iobCalc(time: Long, profile: Profile, insulinInterface: InsulinInterface): IobTotal { + val result = IobTotal(time) + val realDuration = getPassedDurationToTimeInMinutes(time) + if (realDuration > 0) { + val dia = profile.dia + val diaAgo = time - dia * 60 * 60 * 1000 + val aboutFiveMinIntervals = ceil(realDuration / 5.0).toInt() + val spacing = realDuration / aboutFiveMinIntervals + for (j in 0L until aboutFiveMinIntervals) { + // find middle of the interval + val calcDate = (timestamp + j * spacing * 60 * 1000 + 0.5 * spacing * 60 * 1000).toLong() + if (calcDate > diaAgo && calcDate <= time) { + val tempBolusSize: Double = rate * spacing / 60.0 + val tempBolusPart = Bolus( + timestamp = calcDate, + amount = tempBolusSize, + type = Bolus.Type.NORMAL + ) + val aIOB = insulinInterface.iobCalcForTreatment(tempBolusPart, time, dia) + result.iob += aIOB.iobContrib + result.activity += aIOB.activityContrib + result.extendedBolusInsulin += tempBolusPart.amount + } + } + } + return result +} + +fun ExtendedBolus.iobCalc(time: Long, profile: Profile, lastAutosensResult: AutosensResult, exercise_mode: Boolean, half_basal_exercise_target: Int, isTempTarget: Boolean, insulinInterface: InsulinInterface): IobTotal { + val result = IobTotal(time) + val realDuration = getPassedDurationToTimeInMinutes(time) + var sensitivityRatio = lastAutosensResult.ratio + val normalTarget = 100.0 + if (exercise_mode && isTempTarget && profile.targetMgdl >= normalTarget + 5) { + // w/ target 100, temp target 110 = .89, 120 = 0.8, 140 = 0.67, 160 = .57, and 200 = .44 + // e.g.: Sensitivity ratio set to 0.8 based on temp target of 120; Adjusting basal from 1.65 to 1.35; ISF from 58.9 to 73.6 + val c = half_basal_exercise_target - normalTarget + sensitivityRatio = c / (c + profile.targetMgdl - normalTarget) + } + if (realDuration > 0) { + var netBasalRate: Double + val dia = profile.dia + val diaAgo = time - dia * 60 * 60 * 1000 + val aboutFiveMinIntervals = ceil(realDuration / 5.0).toInt() + val spacing = realDuration / aboutFiveMinIntervals + for (j in 0L until aboutFiveMinIntervals) { + // find middle of the interval + val calcDate = (timestamp + j * spacing * 60 * 1000 + 0.5 * spacing * 60 * 1000).toLong() + val basalRate = profile.getBasal(calcDate) + val basalRateCorrection = basalRate * (sensitivityRatio - 1) + netBasalRate = rate - basalRateCorrection + if (calcDate > diaAgo && calcDate <= time) { + val tempBolusSize = netBasalRate * spacing / 60.0 + val tempBolusPart = Bolus( + timestamp = calcDate, + amount = tempBolusSize, + type = Bolus.Type.NORMAL + ) + val aIOB = insulinInterface.iobCalcForTreatment(tempBolusPart, time, dia) + result.iob += aIOB.iobContrib + result.activity += aIOB.activityContrib + result.extendedBolusInsulin += tempBolusPart.amount + } + } + } + return result +} + diff --git a/core/src/main/java/info/nightscout/androidaps/utils/extensions/FoodExtension.kt b/core/src/main/java/info/nightscout/androidaps/extensions/FoodExtension.kt similarity index 97% rename from core/src/main/java/info/nightscout/androidaps/utils/extensions/FoodExtension.kt rename to core/src/main/java/info/nightscout/androidaps/extensions/FoodExtension.kt index b3620fb71e..dfda0de134 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/extensions/FoodExtension.kt +++ b/core/src/main/java/info/nightscout/androidaps/extensions/FoodExtension.kt @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.utils.extensions +package info.nightscout.androidaps.extensions import info.nightscout.androidaps.database.entities.Food import info.nightscout.androidaps.utils.JsonHelper diff --git a/core/src/main/java/info/nightscout/androidaps/utils/extensions/GlucoseValueExtension.kt b/core/src/main/java/info/nightscout/androidaps/extensions/GlucoseValueExtension.kt similarity index 94% rename from core/src/main/java/info/nightscout/androidaps/utils/extensions/GlucoseValueExtension.kt rename to core/src/main/java/info/nightscout/androidaps/extensions/GlucoseValueExtension.kt index 6a77ecae2a..8ffc9a93c5 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/extensions/GlucoseValueExtension.kt +++ b/core/src/main/java/info/nightscout/androidaps/extensions/GlucoseValueExtension.kt @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.utils.extensions +package info.nightscout.androidaps.extensions import info.nightscout.androidaps.Constants import info.nightscout.androidaps.database.entities.GlucoseValue diff --git a/core/src/main/java/info/nightscout/androidaps/utils/extensions/HexByteArrayConversion.kt b/core/src/main/java/info/nightscout/androidaps/extensions/HexByteArrayConversion.kt similarity index 94% rename from core/src/main/java/info/nightscout/androidaps/utils/extensions/HexByteArrayConversion.kt rename to core/src/main/java/info/nightscout/androidaps/extensions/HexByteArrayConversion.kt index 2d685210e7..8de21e6552 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/extensions/HexByteArrayConversion.kt +++ b/core/src/main/java/info/nightscout/androidaps/extensions/HexByteArrayConversion.kt @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.utils.extensions +package info.nightscout.androidaps.extensions import java.util.* diff --git a/core/src/main/java/info/nightscout/androidaps/utils/extensions/HtmlString.kt b/core/src/main/java/info/nightscout/androidaps/extensions/HtmlString.kt similarity index 86% rename from core/src/main/java/info/nightscout/androidaps/utils/extensions/HtmlString.kt rename to core/src/main/java/info/nightscout/androidaps/extensions/HtmlString.kt index 6dbb621c6a..e72d37e334 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/extensions/HtmlString.kt +++ b/core/src/main/java/info/nightscout/androidaps/extensions/HtmlString.kt @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.utils.extensions +package info.nightscout.androidaps.extensions import androidx.annotation.ColorRes import info.nightscout.androidaps.utils.resources.ResourceHelper diff --git a/core/src/main/java/info/nightscout/androidaps/utils/extensions/JSONObjectExt.kt b/core/src/main/java/info/nightscout/androidaps/extensions/JSONObjectExt.kt similarity index 97% rename from core/src/main/java/info/nightscout/androidaps/utils/extensions/JSONObjectExt.kt rename to core/src/main/java/info/nightscout/androidaps/extensions/JSONObjectExt.kt index 6ddb1920ed..3a42eabe4b 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/extensions/JSONObjectExt.kt +++ b/core/src/main/java/info/nightscout/androidaps/extensions/JSONObjectExt.kt @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.utils.extensions +package info.nightscout.androidaps.extensions import androidx.annotation.StringRes import info.nightscout.androidaps.utils.resources.ResourceHelper diff --git a/core/src/main/java/info/nightscout/androidaps/extensions/PumpStateExtension.kt b/core/src/main/java/info/nightscout/androidaps/extensions/PumpStateExtension.kt new file mode 100644 index 0000000000..f6c6994dfb --- /dev/null +++ b/core/src/main/java/info/nightscout/androidaps/extensions/PumpStateExtension.kt @@ -0,0 +1,62 @@ +package info.nightscout.androidaps.extensions + +import info.nightscout.androidaps.data.Profile +import info.nightscout.androidaps.interfaces.PumpSync +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.DecimalFormatter +import info.nightscout.androidaps.utils.DecimalFormatter.to2Decimal +import info.nightscout.androidaps.utils.T +import kotlin.math.ceil +import kotlin.math.max +import kotlin.math.min +import kotlin.math.roundToInt + +val PumpSync.PumpState.TemporaryBasal.end: Long + get() = timestamp + duration + +val PumpSync.PumpState.TemporaryBasal.plannedRemainingMinutes: Long + get() = max(T.msecs(end - System.currentTimeMillis()).mins(), 0L) + +val PumpSync.PumpState.TemporaryBasal.plannedRemainingMinutesRoundedUp: Int + get() = max(ceil((end - System.currentTimeMillis()) / 1000.0 / 60).toInt(), 0) + +val PumpSync.PumpState.TemporaryBasal.durationInMinutes: Int + get() = T.msecs(duration).mins().toInt() + +fun PumpSync.PumpState.TemporaryBasal.getPassedDurationToTimeInMinutes(time: Long): Int = + ((min(time, end) - timestamp) / 60.0 / 1000).roundToInt() + +fun PumpSync.PumpState.TemporaryBasal.convertedToAbsolute(time: Long, profile: Profile): Double = + if (isAbsolute) rate + else profile.getBasal(time) * rate / 100 + +fun PumpSync.PumpState.TemporaryBasal.toStringFull(dateUtil: DateUtil): String { + return when { + isAbsolute -> { + DecimalFormatter.to2Decimal(rate) + "U/h @" + + dateUtil.timeString(timestamp) + + " " + getPassedDurationToTimeInMinutes(dateUtil._now()) + "/" + durationInMinutes + "'" + } + + else -> { // percent + rate.toString() + "% @" + + dateUtil.timeString(timestamp) + + " " + getPassedDurationToTimeInMinutes(dateUtil._now()) + "/" + durationInMinutes + "'" + } + } +} + +val PumpSync.PumpState.ExtendedBolus.end: Long + get() = timestamp + duration + +val PumpSync.PumpState.ExtendedBolus.plannedRemainingMinutes: Long + get() = max(T.msecs(end - System.currentTimeMillis()).mins(), 0L) + +fun PumpSync.PumpState.ExtendedBolus.getPassedDurationToTimeInMinutes(time: Long): Int = + ((min(time, end) - timestamp) / 60.0 / 1000).roundToInt() + +fun PumpSync.PumpState.ExtendedBolus.toStringFull(dateUtil: DateUtil): String = + "E " + to2Decimal(rate) + "U/h @" + + dateUtil.timeString(timestamp) + + " " + getPassedDurationToTimeInMinutes(dateUtil._now()) + "/" + T.msecs(duration).mins() + "min" + diff --git a/core/src/main/java/info/nightscout/androidaps/extensions/TemporaryBasalExtension.kt b/core/src/main/java/info/nightscout/androidaps/extensions/TemporaryBasalExtension.kt new file mode 100644 index 0000000000..c1d7bcf85d --- /dev/null +++ b/core/src/main/java/info/nightscout/androidaps/extensions/TemporaryBasalExtension.kt @@ -0,0 +1,224 @@ +package info.nightscout.androidaps.extensions + +import info.nightscout.androidaps.data.IobTotal +import info.nightscout.androidaps.data.Profile +import info.nightscout.androidaps.database.embedments.InterfaceIDs +import info.nightscout.androidaps.database.entities.Bolus +import info.nightscout.androidaps.database.entities.TemporaryBasal +import info.nightscout.androidaps.database.entities.TemporaryBasal.Type.Companion.fromString +import info.nightscout.androidaps.database.entities.TherapyEvent +import info.nightscout.androidaps.database.interfaces.end +import info.nightscout.androidaps.interfaces.InsulinInterface +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.DecimalFormatter.to0Decimal +import info.nightscout.androidaps.utils.DecimalFormatter.to2Decimal +import info.nightscout.androidaps.utils.JsonHelper +import info.nightscout.androidaps.utils.T +import org.json.JSONObject +import kotlin.math.ceil +import kotlin.math.max +import kotlin.math.min +import kotlin.math.round +import kotlin.math.roundToInt + +fun TemporaryBasal.getPassedDurationToTimeInMinutes(time: Long): Int = + ((min(time, end) - timestamp) / 60.0 / 1000).roundToInt() + +val TemporaryBasal.plannedRemainingMinutes: Int + get() = max(round((end - System.currentTimeMillis()) / 1000.0 / 60).toInt(), 0) + +fun TemporaryBasal.convertedToAbsolute(time: Long, profile: Profile): Double = + if (isAbsolute) rate + else profile.getBasal(time) * rate / 100 + +fun TemporaryBasal.convertedToPercent(time: Long, profile: Profile): Int = + if (!isAbsolute) rate.toInt() + else (rate / profile.getBasal(time) * 100).toInt() + +fun TemporaryBasal.netExtendedRate(profile: Profile) = rate - profile.getBasal(timestamp) +val TemporaryBasal.durationInMinutes + get() = T.msecs(duration).mins() + +fun TemporaryBasal.toStringFull(profile: Profile, dateUtil: DateUtil): String { + return when { + type == TemporaryBasal.Type.FAKE_EXTENDED -> { + to2Decimal(rate) + "U/h (" + to2Decimal(netExtendedRate(profile)) + "E) @" + + dateUtil.timeString(timestamp) + + " " + getPassedDurationToTimeInMinutes(dateUtil._now()) + "/" + durationInMinutes + "'" + } + + isAbsolute -> { + to2Decimal(rate) + "U/h @" + + dateUtil.timeString(timestamp) + + " " + getPassedDurationToTimeInMinutes(dateUtil._now()) + "/" + durationInMinutes + "'" + } + + else -> { // percent + rate.toString() + "% @" + + dateUtil.timeString(timestamp) + + " " + getPassedDurationToTimeInMinutes(dateUtil._now()) + "/" + durationInMinutes + "'" + } + } +} + +fun TemporaryBasal.toJson(profile: Profile): JSONObject = + JSONObject() + .put("created_at", DateUtil.toISOString(timestamp)) + .put("enteredBy", "openaps://" + "AndroidAPS") + .put("eventType", TherapyEvent.Type.TEMPORARY_BASAL.text) + .put("duration", T.msecs(duration).mins()) + .put("rate", rate) + .put("type", type.name) + .also { + if (isAbsolute) it.put("absolute", rate) + else it.put("percent", convertedToPercent(timestamp, profile) - 100) + if (interfaceIDs.pumpId != null) it.put("pumpId", interfaceIDs.pumpId) + if (interfaceIDs.endId != null) it.put("endId", interfaceIDs.endId) + 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) + } + +/* + create fake object with nsID and isValid == false + */ +fun temporaryBasalFromNsIdForInvalidating(nsId: String): TemporaryBasal = + temporaryBasalFromJson( + JSONObject() + .put("mills", 1) + .put("absolute", -1.0) + .put("duration", -1.0) + .put("_id", nsId) + .put("isValid", false) + )!! + +fun temporaryBasalFromJson(jsonObject: JSONObject): TemporaryBasal? { + val timestamp = JsonHelper.safeGetLongAllowNull(jsonObject, "mills", null) ?: return null + val percent = JsonHelper.safeGetDoubleAllowNull(jsonObject, "percent") + val absolute = JsonHelper.safeGetDoubleAllowNull(jsonObject, "absolute") + val duration = JsonHelper.safeGetLongAllowNull(jsonObject, "duration") ?: return null + val type = fromString(JsonHelper.safeGetString(jsonObject, "type")) + val isValid = JsonHelper.safeGetBoolean(jsonObject, "isValid", true) + val id = JsonHelper.safeGetStringAllowNull(jsonObject, "_id", null) ?: return null + val pumpId = JsonHelper.safeGetLongAllowNull(jsonObject, "pumpId", null) + val endPumpId = JsonHelper.safeGetLongAllowNull(jsonObject, "endId", null) + val pumpType = InterfaceIDs.PumpType.fromString(JsonHelper.safeGetStringAllowNull(jsonObject, "pumpType", null)) + val pumpSerial = JsonHelper.safeGetStringAllowNull(jsonObject, "pumpSerial", null) + + val rate = if (percent != null) percent + 100 + else absolute ?: return null + + return TemporaryBasal( + timestamp = timestamp, + rate = rate, + duration = duration, + type = type, + isAbsolute = absolute != null, + isValid = isValid + ).also { + it.interfaceIDs.nightscoutId = id + it.interfaceIDs.pumpId = pumpId + it.interfaceIDs.endId = endPumpId + it.interfaceIDs.pumpType = pumpType + it.interfaceIDs.pumpSerial = pumpSerial + } +} + +fun TemporaryBasal.toStringShort(): String = + if (isAbsolute || type == TemporaryBasal.Type.FAKE_EXTENDED) to2Decimal(rate) + "U/h" + else "${to0Decimal(rate)}%" + +fun TemporaryBasal.iobCalc(time: Long, profile: Profile, insulinInterface: InsulinInterface): IobTotal { + val result = IobTotal(time) + val realDuration: Int = getPassedDurationToTimeInMinutes(time) + var netBasalAmount = 0.0 + if (realDuration > 0) { + var netBasalRate: Double + val dia = profile.dia + val diaAgo = time - dia * 60 * 60 * 1000 + val aboutFiveMinIntervals = ceil(realDuration / 5.0).toInt() + val tempBolusSpacing = (realDuration / aboutFiveMinIntervals).toDouble() + for (j in 0L until aboutFiveMinIntervals) { + // find middle of the interval + val calcDate = (timestamp + j * tempBolusSpacing * 60 * 1000 + 0.5 * tempBolusSpacing * 60 * 1000).toLong() + val basalRate = profile.getBasal(calcDate) + netBasalRate = if (isAbsolute) { + rate - basalRate + } else { + (rate - 100) / 100.0 * basalRate + } + if (calcDate > diaAgo && calcDate <= time) { + val tempBolusSize = netBasalRate * tempBolusSpacing / 60.0 + netBasalAmount += tempBolusSize + val tempBolusPart = Bolus( + timestamp = calcDate, + amount = tempBolusSize, + type = Bolus.Type.NORMAL + ) + val aIOB = insulinInterface.iobCalcForTreatment(tempBolusPart, time, dia) + result.basaliob += aIOB.iobContrib + result.activity += aIOB.activityContrib + result.netbasalinsulin += tempBolusPart.amount + if (tempBolusPart.amount > 0) { + result.hightempinsulin += tempBolusPart.amount + } + } + result.netRatio = netBasalRate // ratio at the end of interval + } + } + result.netInsulin = netBasalAmount + return result +} + +fun TemporaryBasal.iobCalc(time: Long, profile: Profile, lastAutosensResult: AutosensResult, exercise_mode: Boolean, half_basal_exercise_target: Int, isTempTarget: Boolean, insulinInterface: InsulinInterface): IobTotal { + val result = IobTotal(time) + val realDuration: Double = getPassedDurationToTimeInMinutes(time).toDouble() + var netBasalAmount = 0.0 + var sensitivityRatio = lastAutosensResult.ratio + val normalTarget = 100.0 + if (exercise_mode && isTempTarget && profile.targetMgdl >= normalTarget + 5) { + // w/ target 100, temp target 110 = .89, 120 = 0.8, 140 = 0.67, 160 = .57, and 200 = .44 + // e.g.: Sensitivity ratio set to 0.8 based on temp target of 120; Adjusting basal from 1.65 to 1.35; ISF from 58.9 to 73.6 + val c = half_basal_exercise_target - normalTarget + sensitivityRatio = c / (c + profile.targetMgdl - normalTarget) + } + if (realDuration > 0) { + var netBasalRate: Double + val dia = profile.dia + val diaAgo = time - dia * 60 * 60 * 1000 + val aboutFiveMinIntervals = ceil(realDuration / 5.0).toInt() + val tempBolusSpacing = realDuration / aboutFiveMinIntervals + for (j in 0L until aboutFiveMinIntervals) { + // find middle of the interval + val calcDate = (timestamp + j * tempBolusSpacing * 60 * 1000 + 0.5 * tempBolusSpacing * 60 * 1000).toLong() + var basalRate = profile.getBasal(calcDate) + basalRate *= sensitivityRatio + netBasalRate = if (isAbsolute) { + rate - basalRate + } else { + val abs: Double = rate / 100.0 * profile.getBasal(calcDate) + abs - basalRate + } + if (calcDate > diaAgo && calcDate <= time) { + val tempBolusSize = netBasalRate * tempBolusSpacing / 60.0 + netBasalAmount += tempBolusSize + val tempBolusPart = Bolus( + timestamp = calcDate, + amount = tempBolusSize, + type = Bolus.Type.NORMAL + ) + val aIOB = insulinInterface.iobCalcForTreatment(tempBolusPart, time, dia) + result.basaliob += aIOB.iobContrib + result.activity += aIOB.activityContrib + result.netbasalinsulin += tempBolusPart.amount + if (tempBolusPart.amount > 0) { + result.hightempinsulin += tempBolusPart.amount + } + } + result.netRatio = netBasalRate // ratio at the end of interval + } + } + result.netInsulin = netBasalAmount + return result +} diff --git a/core/src/main/java/info/nightscout/androidaps/utils/extensions/TemporaryTargetExtension.kt b/core/src/main/java/info/nightscout/androidaps/extensions/TemporaryTargetExtension.kt similarity index 98% rename from core/src/main/java/info/nightscout/androidaps/utils/extensions/TemporaryTargetExtension.kt rename to core/src/main/java/info/nightscout/androidaps/extensions/TemporaryTargetExtension.kt index b203453c77..8cbf84f6c8 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/extensions/TemporaryTargetExtension.kt +++ b/core/src/main/java/info/nightscout/androidaps/extensions/TemporaryTargetExtension.kt @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.utils.extensions +package info.nightscout.androidaps.extensions import info.nightscout.androidaps.Constants import info.nightscout.androidaps.core.R diff --git a/core/src/main/java/info/nightscout/androidaps/utils/extensions/TherapyEventExtension.kt b/core/src/main/java/info/nightscout/androidaps/extensions/TherapyEventExtension.kt similarity index 98% rename from core/src/main/java/info/nightscout/androidaps/utils/extensions/TherapyEventExtension.kt rename to core/src/main/java/info/nightscout/androidaps/extensions/TherapyEventExtension.kt index a85d92406a..d83157cd32 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/extensions/TherapyEventExtension.kt +++ b/core/src/main/java/info/nightscout/androidaps/extensions/TherapyEventExtension.kt @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.utils.extensions +package info.nightscout.androidaps.extensions import info.nightscout.androidaps.Constants import info.nightscout.androidaps.core.R diff --git a/core/src/main/java/info/nightscout/androidaps/utils/extensions/TrendArrowIcon.kt b/core/src/main/java/info/nightscout/androidaps/extensions/TrendArrowIcon.kt similarity index 94% rename from core/src/main/java/info/nightscout/androidaps/utils/extensions/TrendArrowIcon.kt rename to core/src/main/java/info/nightscout/androidaps/extensions/TrendArrowIcon.kt index 51bc4e869f..01fbcbe91a 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/extensions/TrendArrowIcon.kt +++ b/core/src/main/java/info/nightscout/androidaps/extensions/TrendArrowIcon.kt @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.utils.extensions +package info.nightscout.androidaps.extensions import info.nightscout.androidaps.core.R import info.nightscout.androidaps.database.entities.GlucoseValue diff --git a/core/src/main/java/info/nightscout/androidaps/utils/extensions/UIUtils.kt b/core/src/main/java/info/nightscout/androidaps/extensions/UIUtils.kt similarity index 83% rename from core/src/main/java/info/nightscout/androidaps/utils/extensions/UIUtils.kt rename to core/src/main/java/info/nightscout/androidaps/extensions/UIUtils.kt index 12aa4c031b..fcde955752 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/extensions/UIUtils.kt +++ b/core/src/main/java/info/nightscout/androidaps/extensions/UIUtils.kt @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.utils.extensions +package info.nightscout.androidaps.extensions import android.os.Handler import android.os.Looper diff --git a/core/src/main/java/info/nightscout/androidaps/utils/extensions/UserEntryExt.kt b/core/src/main/java/info/nightscout/androidaps/extensions/UserEntryExt.kt similarity index 92% rename from core/src/main/java/info/nightscout/androidaps/utils/extensions/UserEntryExt.kt rename to core/src/main/java/info/nightscout/androidaps/extensions/UserEntryExt.kt index c0ce48e35f..f38e9f384d 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/extensions/UserEntryExt.kt +++ b/core/src/main/java/info/nightscout/androidaps/extensions/UserEntryExt.kt @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.utils.extensions +package info.nightscout.androidaps.extensions import info.nightscout.androidaps.core.R import info.nightscout.androidaps.database.entities.UserEntry.* 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 1eb751d224..1e1911b75e 100644 --- a/core/src/main/java/info/nightscout/androidaps/interfaces/DataSyncSelector.kt +++ b/core/src/main/java/info/nightscout/androidaps/interfaces/DataSyncSelector.kt @@ -12,6 +12,8 @@ interface DataSyncSelector { data class PairBolus(val value: Bolus, val updateRecordId: Long) data class PairCarbs(val value: Carbs, val updateRecordId: Long) 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) fun resetToNextFullSync() @@ -54,4 +56,14 @@ interface DataSyncSelector { fun changedDeviceStatuses() : List // Until NS v3 fun processChangedDeviceStatusesCompat(): Boolean + + fun confirmLastTemporaryBasalIdIfGreater(lastSynced: Long) + fun changedTemporaryBasals() : List + // Until NS v3 + fun processChangedTemporaryBasalsCompat(): Boolean + + fun confirmLastExtendedBolusIdIfGreater(lastSynced: Long) + fun changedExtendedBoluses() : List + // Until NS v3 + fun processChangedExtendedBolusesCompat(): Boolean } \ No newline at end of file diff --git a/core/src/main/java/info/nightscout/androidaps/interfaces/DatabaseHelperInterface.kt b/core/src/main/java/info/nightscout/androidaps/interfaces/DatabaseHelperInterface.kt index 0b2415260e..b8fa2b631e 100644 --- a/core/src/main/java/info/nightscout/androidaps/interfaces/DatabaseHelperInterface.kt +++ b/core/src/main/java/info/nightscout/androidaps/interfaces/DatabaseHelperInterface.kt @@ -8,7 +8,6 @@ interface DatabaseHelperInterface { fun resetDatabases() - fun createOrUpdate(extendedBolus: ExtendedBolus): Boolean fun createOrUpdate(profileSwitch: ProfileSwitch) fun createOrUpdate(record: DanaRHistoryRecord) fun createOrUpdate(record: OmnipodHistoryRecord) @@ -22,7 +21,6 @@ interface DatabaseHelperInterface { fun size(table: String): Long fun deleteAllDbRequests() fun deleteDbRequest(id: String): Int - fun delete(tempBasal: TemporaryBasal) fun delete(extendedBolus: ExtendedBolus) fun delete(profileSwitch: ProfileSwitch) fun deleteDbRequestbyMongoId(action: String, _id: String) @@ -30,29 +28,25 @@ interface DatabaseHelperInterface { fun roundDateToSec(date: Long): Long fun createOrUpdateTDD(record: TDD) fun createOrUpdate(tempBasal: TemporaryBasal): Boolean + @Deprecated("Use new DB") fun findTempBasalByPumpId(id: Long): TemporaryBasal? + @Deprecated("Use new DB") fun getTemporaryBasalsDataFromTime(mills: Long, ascending: Boolean): List - fun getExtendedBolusDataFromTime(mills: Long, ascending: Boolean): List fun getProfileSwitchEventsFromTime(from: Long, to: Long, ascending: Boolean): List fun getProfileSwitchEventsFromTime(mills: Long, ascending: Boolean): List fun getAllOmnipodHistoryRecordsFromTimestamp(timestamp: Long, ascending: Boolean): List fun findOmnipodHistoryRecordByPumpId(pumpId: Long): OmnipodHistoryRecord? fun getTDDsForLastXDays(days: Int): List fun getProfileSwitchData(from: Long, ascending: Boolean): List + @Deprecated("Use new DB") fun getExtendedBolusByPumpId(pumpId: Long): ExtendedBolus? - fun getAllExtendedBoluses(): List fun getAllProfileSwitches(): List fun getAllTDDs(): List - fun getAllTemporaryBasals(): List fun getAllOHQueueItems(maxEntries: Long): List fun resetProfileSwitch() // old DB model - fun deleteTempBasalById(_id: String) - fun deleteExtendedBolusById(_id: String) fun deleteProfileSwitchById(_id: String) - fun createTempBasalFromJsonIfNotExists(json: JSONObject) - fun createExtendedBolusFromJsonIfNotExists(json: JSONObject) fun createProfileSwitchFromJsonIfNotExists(trJson: JSONObject) fun getInsightBolusID(pumpSerial: String, bolusID: Int, timestamp: Long): InsightBolusID? diff --git a/core/src/main/java/info/nightscout/androidaps/interfaces/IobCobCalculator.kt b/core/src/main/java/info/nightscout/androidaps/interfaces/IobCobCalculator.kt index 046a44de80..5e31a3bbef 100644 --- a/core/src/main/java/info/nightscout/androidaps/interfaces/IobCobCalculator.kt +++ b/core/src/main/java/info/nightscout/androidaps/interfaces/IobCobCalculator.kt @@ -4,7 +4,9 @@ import androidx.collection.LongSparseArray import info.nightscout.androidaps.data.IobTotal import info.nightscout.androidaps.data.MealData import info.nightscout.androidaps.data.Profile +import info.nightscout.androidaps.database.entities.ExtendedBolus import info.nightscout.androidaps.database.entities.GlucoseValue +import info.nightscout.androidaps.database.entities.TemporaryBasal import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult import info.nightscout.androidaps.plugins.iob.iobCobCalculator.BasalData import info.nightscout.androidaps.plugins.iob.iobCobCalculator.CobInfo @@ -23,7 +25,7 @@ interface IobCobCalculator { fun getLastAutosensData(reason: String): AutosensData? fun getLastAutosensDataSynchronized(reason: String): AutosensData? fun calculateAbsInsulinFromTreatmentsAndTempsSynchronized(fromTime: Long): IobTotal - fun calculateFromTreatmentsAndTempsSynchronized(time: Long, profile: Profile?): IobTotal + fun calculateFromTreatmentsAndTempsSynchronized(time: Long, profile: Profile): IobTotal fun getBasalData(profile: Profile, fromTime: Long): BasalData fun calculateIobArrayForSMB(lastAutosensResult: AutosensResult, exercise_mode: Boolean, half_basal_exercise_target: Int, isTempTarget: Boolean): Array fun iobArrayToString(array: Array): String @@ -71,5 +73,53 @@ interface IobCobCalculator { * @param timestamp timestamp in milliseconds * @return calculated iob */ - fun calculateIobFromBolusToTime(timestamp: Long): IobTotal + fun calculateIobFromBolusToTime(toTime: Long): IobTotal + + /** + * Get running temporary basal at time + * + * @return running temporary basal or null if no tbr is running + */ + fun getTempBasal(timestamp: Long): TemporaryBasal? + + /** + * Get running temporary basal at time + * + * @return running temporary basal or null if no tbr is running + * If pump is faking extended boluses as temporary basals + * return extended converted to temporary basal with type == FAKE_EXTENDED + */ + fun getTempBasalIncludingConvertedExtended(timestamp: Long): TemporaryBasal? + + /** + * Get running extended bolus at time + * + * @return running extended bolus or null if no eb is running + */ + fun getExtendedBolus(timestamp: Long): ExtendedBolus? + + /** + * Calculate IOB of all insulin in the body to the time + * + * Running basal is added to the IOB !!! + * + * @param timestamp + * @return IobTotal + */ + fun calculateAbsoluteIobTempBasals(toTime: Long): IobTotal + + /** + * Calculate IOB from Temporary basals and Extended boluses (if emulation is enabled) to the the time specified + * + * @param time time to calculate to + * @return IobTotal + */ + fun calculateIobToTimeFromTempBasalsIncludingConvertedExtended(toTime: Long): IobTotal + + /** + * Calculate IOB from Temporary basals and Extended boluses (if emulation is enabled) to now + * + * @return IobTotal + */ + fun calculateIobFromTempBasalsIncludingConvertedExtended(): IobTotal } \ No newline at end of file diff --git a/core/src/main/java/info/nightscout/androidaps/interfaces/PumpSync.kt b/core/src/main/java/info/nightscout/androidaps/interfaces/PumpSync.kt index 9a380c2731..f11f5816ff 100644 --- a/core/src/main/java/info/nightscout/androidaps/interfaces/PumpSync.kt +++ b/core/src/main/java/info/nightscout/androidaps/interfaces/PumpSync.kt @@ -1,6 +1,7 @@ package info.nightscout.androidaps.interfaces import info.nightscout.androidaps.data.DetailedBolusInfo +import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.database.entities.TemporaryBasal import info.nightscout.androidaps.plugins.pump.common.defs.PumpType @@ -12,7 +13,7 @@ import info.nightscout.androidaps.plugins.pump.common.defs.PumpType * - for pumps that have a reliable history that can be read and which therefore issue a bolus on the pump, * read the history back and add new bolus entries on the pump, the method [syncBolusWithPumpId] * are used to inform AAPS-core of a new bolus. - * [VirtualPumpPlugin](info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin) is a pump driver that + * [info.nightscout.androidaps.danars.DanaRSPlugin] is a pump driver that * takes this approach. * - for pumps that don't support history or take rather long to complete a bolus, the methods * [addBolusWithTempId] and [syncBolusWithTempId] provide a mechanism to notify AAPS-core of a started @@ -22,6 +23,36 @@ import info.nightscout.androidaps.plugins.pump.common.defs.PumpType */ interface PumpSync { + /* + * GENERAL STATUS + */ + + /** + * Query expected pump state + * + * Driver may query AAPS for expecting state of the pump and use it for sanity check + * or generation of status for NS + * + * TemporaryBasal + * duration in milliseconds + * rate in U/h or % where 100% is equal to no TBR + * + * ExtendedBolus + * duration in milliseconds + * amount in U + * rate in U/h (synthetic only) + * + * @return data from database. + * temporaryBasal (and extendedBolus) is null if there is no record in progress based on data in database + * bolus is null when there is no record in database + */ + data class PumpState(val temporaryBasal: TemporaryBasal?, val extendedBolus: ExtendedBolus?, val bolus: Bolus?, val profile: Profile?) { + data class TemporaryBasal(val timestamp: Long, val duration: Long, val rate: Double, val isAbsolute: Boolean, val type: TemporaryBasalType, val id: Long, val pumpId: Long?) + data class ExtendedBolus(val timestamp: Long, val duration: Long, val amount: Double, val rate: Double) + data class Bolus(val timestamp: Long, val amount: Double) + } + fun expectedPumpState(): PumpState + /* * BOLUSES & CARBS */ @@ -130,8 +161,9 @@ interface PumpSync { * @param pumpId pump id from history if available * @param pumpType pump type like PumpType.ACCU_CHEK_COMBO * @param pumpSerial pump serial number + * @return true if new record is created **/ - fun insertTherapyEventIfNewWithTimestamp(timestamp: Long, type: DetailedBolusInfo.EventType, note: String? = null, pumpId: Long? = null, pumpType: PumpType, pumpSerial: String) + fun insertTherapyEventIfNewWithTimestamp(timestamp: Long, type: DetailedBolusInfo.EventType, note: String? = null, pumpId: Long? = null, pumpType: PumpType, pumpSerial: String) : Boolean /** * Create an announcement @@ -167,6 +199,12 @@ interface PumpSync { PUMP_SUSPEND -> TemporaryBasal.Type.PUMP_SUSPEND SUPERBOLUS -> TemporaryBasal.Type.SUPERBOLUS } + + companion object { + + fun fromDbType(dbType: TemporaryBasal.Type) = values().firstOrNull { it.name == dbType.name } ?: NORMAL + } + } /** @@ -179,6 +217,17 @@ interface PumpSync { * If overlap another running TBR, running is cut off * isValid field is preserved * + * if driver does cut of ended TBR by itself use only [syncTemporaryBasalWithPumpId] + * if driver send another [syncTemporaryBasalWithPumpId] to cut previous by AAPS it's necessary + * to send [syncTemporaryBasalWithPumpId] sorted by timestamp for proper cutting + * + * if driver use combination of start [syncTemporaryBasalWithPumpId] and end [syncStopTemporaryBasalWithPumpId] + * events AAPS does the cutting itself. Events must be sorted by timestamp + * if db record already has endPumpId assigned by [syncStopTemporaryBasalWithPumpId] other updates + * are ignored + * + * see [info.nightscout.androidaps.database.transactions.SyncPumpTemporaryBasalTransaction] + * * @param timestamp timestamp of event from pump history * @param rate TBR rate in U/h or % (value of 100% is equal to no TBR) * @param duration duration in milliseconds @@ -207,6 +256,8 @@ interface PumpSync { * endPumpId is stored to running record * If db record doesn't exist data is ignored and false returned * + * see [info.nightscout.androidaps.database.transactions.SyncPumpCancelTemporaryBasalIfAnyTransaction] + * * @param timestamp timestamp of event from pump history * @param endPumpId pump id of ending event from history * @param pumpType pump type like PumpType.ACCU_CHEK_COMBO @@ -214,4 +265,67 @@ interface PumpSync { * @return true if running record is found and ended by changing duration **/ fun syncStopTemporaryBasalWithPumpId(timestamp: Long, endPumpId: Long, pumpType: PumpType, pumpSerial: String): Boolean + + /** + * Invalidate of temporary basals that failed to start + * EROS specific, replace by setting duration to zero ???? + * + * If exists, isValid is set false + * If db record doesn't exist data is ignored and false returned + * + * + * @param pumpId pump id of ending event from history + * @param pumpType pump type like PumpType.ACCU_CHEK_COMBO + * @param pumpSerial pump serial number + * @return true if running record is found and invalidated + **/ + fun invalidateTemporaryBasal(id: Long): Boolean + + /** + * Synchronization of extended bolus + * + * Search for combination of pumpId, PumpType, pumpSerial + * + * If exists and endId is null (ie. has not been cut off), timestamp, duration, amount is updated + * If overlap another running EB, running is cut off and new record is created + * If db record doesn't exist, new record is created. + * isValid field is preserved + * + * see [info.nightscout.androidaps.database.transactions.SyncPumpExtendedBolusTransaction] + * + * @param timestamp timestamp of event from pump history + * @param amount EB total amount in U + * @param duration duration in milliseconds + * @param pumpId pump id from history + * @param pumpType pump type like PumpType.ACCU_CHEK_COMBO + * @param pumpSerial pump serial number + * @return true if new record is created + **/ + + fun syncExtendedBolusWithPumpId(timestamp: Long, amount: Double, duration: Long, isEmulatingTB: Boolean, pumpId: Long, pumpType: PumpType, pumpSerial: String): Boolean + + /** + * Synchronization of extended bolus end event + * (for pumps having separate event for end of EB or not having history) + * (not useful for pump modifying duration in history log) + * + * Search first for a TBR with combination of endPumpId, pumpType, pumpSerial + * if found assume, some running EB has been already cut off and ignore data. False is returned + * + * Search for running EB with combination of pumpType, pumpSerial + * + * If exists, + * currently running record is cut off by provided timestamp (ie duration and amount is adjusted) + * endPumpId is stored to running record + * If db record doesn't exist data is ignored and false returned + * + * see [info.nightscout.androidaps.database.transactions.SyncPumpCancelExtendedBolusIfAnyTransaction] + * + * @param timestamp timestamp of event from pump history + * @param endPumpId pump id of ending event from history + * @param pumpType pump type like PumpType.ACCU_CHEK_COMBO + * @param pumpSerial pump serial number + * @return true if running record is found and ended by changing duration + **/ + fun syncStopExtendedBolusWithPumpId(timestamp: Long, endPumpId: Long, pumpType: PumpType, pumpSerial: String): Boolean } \ No newline at end of file diff --git a/core/src/main/java/info/nightscout/androidaps/interfaces/TreatmentsInterface.java b/core/src/main/java/info/nightscout/androidaps/interfaces/TreatmentsInterface.java index aedbdce672..e41e39da45 100644 --- a/core/src/main/java/info/nightscout/androidaps/interfaces/TreatmentsInterface.java +++ b/core/src/main/java/info/nightscout/androidaps/interfaces/TreatmentsInterface.java @@ -22,37 +22,11 @@ public interface TreatmentsInterface { TreatmentServiceInterface getService(); - IobTotal getLastCalculationTempBasals(); - - IobTotal getCalculationToTimeTempBasals(long time); - - IobTotal getCalculationToTimeExtendedBoluses(long time); - @Deprecated List getTreatmentsFromHistoryAfterTimestamp(long timestamp); - // real basals (not faked by extended bolus) - boolean isInHistoryRealTempBasalInProgress(); - - TemporaryBasal getRealTempBasalFromHistory(long time); - boolean addToHistoryTempBasal(TemporaryBasal tempBasal); - // basal that can be faked by extended boluses - boolean isTempBasalInProgress(); - - TemporaryBasal getTempBasalFromHistory(long time); - - NonOverlappingIntervals getTemporaryBasalsFromHistory(); - - void removeTempBasal(TemporaryBasal temporaryBasal); - - boolean isInHistoryExtendedBolusInProgress(); - - ExtendedBolus getExtendedBolusFromHistory(long time); - - Intervals getExtendedBolusesFromHistory(); - boolean addToHistoryExtendedBolus(ExtendedBolus extendedBolus); boolean addToHistoryTreatment(DetailedBolusInfo detailedBolusInfo, boolean allowUpdate); @@ -67,8 +41,6 @@ public interface TreatmentsInterface { void doProfileSwitch(final int duration, final int percentage, final int timeShift); - long oldestDataAvailable(); - TreatmentUpdateReturn createOrUpdateMedtronic(Treatment treatment, boolean fromNightScout); } \ No newline at end of file diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/aps/loop/APSResult.kt b/core/src/main/java/info/nightscout/androidaps/plugins/aps/loop/APSResult.kt index 7e8bdf161c..f938e48393 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/aps/loop/APSResult.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/aps/loop/APSResult.kt @@ -7,15 +7,17 @@ import info.nightscout.androidaps.data.IobTotal import info.nightscout.androidaps.database.entities.GlucoseValue import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.Constraint +import info.nightscout.androidaps.interfaces.IobCobCalculator import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.PumpDescription -import info.nightscout.androidaps.interfaces.TreatmentsInterface import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DecimalFormatter import info.nightscout.androidaps.utils.HtmlHelper.fromHtml +import info.nightscout.androidaps.extensions.convertedToAbsolute +import info.nightscout.androidaps.extensions.convertedToPercent import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.sharedPreferences.SP import org.json.JSONException @@ -34,7 +36,7 @@ open class APSResult @Inject constructor(val injector: HasAndroidInjector) { @Inject lateinit var constraintChecker: ConstraintChecker @Inject lateinit var sp: SP @Inject lateinit var activePlugin: ActivePluginProvider - @Inject lateinit var treatmentsPlugin: TreatmentsInterface + @Inject lateinit var iobCobCalculator: IobCobCalculator @Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var dateUtil: DateUtil @@ -316,7 +318,7 @@ open class APSResult @Inject constructor(val injector: HasAndroidInjector) { return false } val now = System.currentTimeMillis() - val activeTemp = treatmentsPlugin.getTempBasalFromHistory(now) + val activeTemp = iobCobCalculator.getTempBasalIncludingConvertedExtended(now) val pump = activePlugin.activePump val profile = profileFunction.getProfile() if (profile == null) { @@ -328,7 +330,7 @@ open class APSResult @Inject constructor(val injector: HasAndroidInjector) { aapsLogger.debug(LTag.APS, "FALSE: No temp running, asking cancel temp") return false } - if (activeTemp != null && abs(percent - activeTemp.tempBasalConvertedToPercent(now, profile)) < pump.pumpDescription.basalStep) { + if (activeTemp != null && abs(percent - activeTemp.convertedToPercent(now, profile)) < pump.pumpDescription.basalStep) { aapsLogger.debug(LTag.APS, "FALSE: Temp equal") return false } @@ -351,7 +353,7 @@ open class APSResult @Inject constructor(val injector: HasAndroidInjector) { val lowThreshold = 1 - percentMinChangeChange val highThreshold = 1 + percentMinChangeChange var change = percent / 100.0 - if (activeTemp != null) change = percent / activeTemp.tempBasalConvertedToPercent(now, profile).toDouble() + if (activeTemp != null) change = percent / activeTemp.convertedToPercent(now, profile).toDouble() if (change < lowThreshold || change > highThreshold) { aapsLogger.debug(LTag.APS, "TRUE: Outside allowed range " + change * 100.0 + "%") true @@ -364,7 +366,7 @@ open class APSResult @Inject constructor(val injector: HasAndroidInjector) { aapsLogger.debug(LTag.APS, "FALSE: No temp running, asking cancel temp") return false } - if (activeTemp != null && abs(rate - activeTemp.tempBasalConvertedToAbsolute(now, profile)) < pump.pumpDescription.basalStep) { + if (activeTemp != null && abs(rate - activeTemp.convertedToAbsolute(now, profile)) < pump.pumpDescription.basalStep) { aapsLogger.debug(LTag.APS, "FALSE: Temp equal") return false } @@ -387,7 +389,7 @@ open class APSResult @Inject constructor(val injector: HasAndroidInjector) { val lowThreshold = 1 - percentMinChangeChange val highThreshold = 1 + percentMinChangeChange var change = rate / profile.basal - if (activeTemp != null) change = rate / activeTemp.tempBasalConvertedToAbsolute(now, profile) + if (activeTemp != null) change = rate / activeTemp.convertedToAbsolute(now, profile) if (change < lowThreshold || change > highThreshold) { aapsLogger.debug(LTag.APS, "TRUE: Outside allowed range " + change * 100.0 + "%") true diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/activities/PrefImportListActivity.kt b/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/activities/PrefImportListActivity.kt index f4cbc1dc91..77c361d869 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/activities/PrefImportListActivity.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/activities/PrefImportListActivity.kt @@ -19,7 +19,7 @@ import info.nightscout.androidaps.plugins.general.maintenance.PrefsFileContract import info.nightscout.androidaps.plugins.general.maintenance.PrefsFormatsHandler import info.nightscout.androidaps.plugins.general.maintenance.formats.PrefsMetadataKey import info.nightscout.androidaps.plugins.general.maintenance.formats.PrefsStatus -import info.nightscout.androidaps.utils.extensions.toVisibility +import info.nightscout.androidaps.extensions.toVisibility import info.nightscout.androidaps.utils.locale.LocaleHelper import info.nightscout.androidaps.utils.resources.ResourceHelper import javax.inject.Inject diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/formats/EncryptedPrefsFormat.kt b/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/formats/EncryptedPrefsFormat.kt index 2cc83d410c..532b4eab00 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/formats/EncryptedPrefsFormat.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/formats/EncryptedPrefsFormat.kt @@ -2,8 +2,8 @@ package info.nightscout.androidaps.plugins.general.maintenance.formats import info.nightscout.androidaps.core.R import info.nightscout.androidaps.utils.CryptoUtil -import info.nightscout.androidaps.utils.extensions.hexStringToByteArray -import info.nightscout.androidaps.utils.extensions.toHex +import info.nightscout.androidaps.extensions.hexStringToByteArray +import info.nightscout.androidaps.extensions.toHex import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.storage.Storage import org.json.JSONException diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSUpload.java b/core/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSUpload.java index b5c2a664da..e93a671301 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSUpload.java +++ b/core/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSUpload.java @@ -7,16 +7,11 @@ import javax.inject.Inject; import javax.inject.Singleton; import info.nightscout.androidaps.core.R; -import info.nightscout.androidaps.data.DetailedBolusInfo; -import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.database.entities.TherapyEvent; import info.nightscout.androidaps.db.DbRequest; -import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.ProfileSwitch; -import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.interfaces.UploadQueueInterface; import info.nightscout.androidaps.logging.AAPSLogger; -import info.nightscout.androidaps.plugins.configBuilder.RunningConfiguration; import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.sharedPreferences.SP; @@ -29,159 +24,16 @@ public class NSUpload { private final AAPSLogger aapsLogger; private final SP sp; private final UploadQueueInterface uploadQueue; - private final RunningConfiguration runningConfiguration; - private final DateUtil dateUtil; @Inject public NSUpload( AAPSLogger aapsLogger, SP sp, - UploadQueueInterface uploadQueue, - RunningConfiguration runningConfiguration, - DateUtil dateUtil + UploadQueueInterface uploadQueue ) { this.aapsLogger = aapsLogger; this.sp = sp; this.uploadQueue = uploadQueue; - this.runningConfiguration = runningConfiguration; - this.dateUtil = dateUtil; - } - - public void uploadTempBasalStartAbsolute(TemporaryBasal temporaryBasal, Double originalExtendedAmount) { - try { - JSONObject data = new JSONObject(); - data.put("eventType", TherapyEvent.Type.TEMPORARY_BASAL.getText()); - data.put("duration", temporaryBasal.durationInMinutes); - data.put("absolute", temporaryBasal.absoluteRate); - data.put("rate", temporaryBasal.absoluteRate); - if (temporaryBasal.pumpId != 0) - data.put("pumpId", temporaryBasal.pumpId); - data.put("created_at", DateUtil.toISOString(temporaryBasal.date)); - data.put("enteredBy", "openaps://" + "AndroidAPS"); - if (originalExtendedAmount != null) - data.put("originalExtendedAmount", originalExtendedAmount); // for back synchronization - uploadQueue.add(new DbRequest("dbAdd", "treatments", data, temporaryBasal.date)); - } catch (JSONException e) { - aapsLogger.error("Unhandled exception", e); - } - } - - public void uploadTempBasalStartPercent(TemporaryBasal temporaryBasal, Profile profile) { - try { - boolean useAbsolute = sp.getBoolean(R.string.key_ns_sync_use_absolute, false); - double absoluteRate = 0; - if (profile != null) { - absoluteRate = profile.getBasal(temporaryBasal.date) * temporaryBasal.percentRate / 100d; - } - if (useAbsolute) { - TemporaryBasal t = temporaryBasal.clone(); - t.isAbsolute = true; - if (profile != null) { - t.absoluteRate = absoluteRate; - uploadTempBasalStartAbsolute(t, null); - } - } else { - JSONObject data = new JSONObject(); - data.put("eventType", TherapyEvent.Type.TEMPORARY_BASAL.getText()); - data.put("duration", temporaryBasal.durationInMinutes); - data.put("percent", temporaryBasal.percentRate - 100); - if (profile != null) - data.put("rate", absoluteRate); - if (temporaryBasal.pumpId != 0) - data.put("pumpId", temporaryBasal.pumpId); - data.put("created_at", DateUtil.toISOString(temporaryBasal.date)); - data.put("enteredBy", "openaps://" + "AndroidAPS"); - uploadQueue.add(new DbRequest("dbAdd", "treatments", data, temporaryBasal.date)); - } - } catch (JSONException e) { - aapsLogger.error("Unhandled exception", e); - } - } - - public void uploadTempBasalEnd(long time, boolean isFakedTempBasal, long pumpId) { - try { - JSONObject data = new JSONObject(); - data.put("eventType", TherapyEvent.Type.TEMPORARY_BASAL.getText()); - data.put("created_at", DateUtil.toISOString(time)); - data.put("enteredBy", "openaps://" + "AndroidAPS"); - if (isFakedTempBasal) - data.put("isFakedTempBasal", isFakedTempBasal); - if (pumpId != 0) - data.put("pumpId", pumpId); - uploadQueue.add(new DbRequest("dbAdd", "treatments", data, time)); - } catch (JSONException e) { - aapsLogger.error("Unhandled exception", e); - } - } - - public void uploadExtendedBolus(ExtendedBolus extendedBolus) { - try { - JSONObject data = new JSONObject(); - data.put("eventType", TherapyEvent.Type.COMBO_BOLUS.getText()); - data.put("duration", extendedBolus.durationInMinutes); - data.put("splitNow", 0); - data.put("splitExt", 100); - data.put("enteredinsulin", extendedBolus.insulin); - data.put("relative", extendedBolus.insulin / extendedBolus.durationInMinutes * 60); // U/h - if (extendedBolus.pumpId != 0) - data.put("pumpId", extendedBolus.pumpId); - data.put("created_at", DateUtil.toISOString(extendedBolus.date)); - data.put("enteredBy", "openaps://" + "AndroidAPS"); - uploadQueue.add(new DbRequest("dbAdd", "treatments", data, extendedBolus.date)); - } catch (JSONException e) { - aapsLogger.error("Unhandled exception", e); - } - } - - public void uploadExtendedBolusEnd(long time, long pumpId) { - try { - JSONObject data = new JSONObject(); - data.put("eventType", TherapyEvent.Type.COMBO_BOLUS.getText()); - data.put("duration", 0); - data.put("splitNow", 0); - data.put("splitExt", 100); - data.put("enteredinsulin", 0); - data.put("relative", 0); - data.put("created_at", DateUtil.toISOString(time)); - data.put("enteredBy", "openaps://" + "AndroidAPS"); - if (pumpId != 0) - data.put("pumpId", pumpId); - uploadQueue.add(new DbRequest("dbAdd", "treatments", data, time)); - } catch (JSONException e) { - aapsLogger.error("Unhandled exception", e); - } - } - - - public void uploadTreatmentRecord(DetailedBolusInfo detailedBolusInfo) { - throw new IllegalStateException("DO NOT USE"); -/* - JSONObject data = new JSONObject(); - try { - data.put("eventType", detailedBolusInfo.eventType); - if (detailedBolusInfo.insulin != 0d) data.put("insulin", detailedBolusInfo.insulin); - if (detailedBolusInfo.carbs != 0d) data.put("carbs", (int) detailedBolusInfo.carbs); - data.put("created_at", DateUtil.toISOString(detailedBolusInfo.timestamp)); - data.put("date", detailedBolusInfo.timestamp); - data.put("isSMB", detailedBolusInfo.isSMB); - if (detailedBolusInfo.pumpId != 0) - data.put("pumpId", detailedBolusInfo.pumpId); - if (detailedBolusInfo.glucose != 0d) - data.put("glucose", detailedBolusInfo.glucose); - if (!detailedBolusInfo.glucoseType.equals("")) - data.put("glucoseType", detailedBolusInfo.glucoseType); - if (detailedBolusInfo.boluscalc != null) - data.put("boluscalc", detailedBolusInfo.boluscalc); - if (detailedBolusInfo.carbTime != 0) - data.put("preBolus", detailedBolusInfo.carbTime); - if (StringUtils.isNotEmpty(detailedBolusInfo.notes())) { - data.put("notes", detailedBolusInfo.notes()); - } - } catch (JSONException e) { - aapsLogger.error("Unhandled exception", e); - } - uploadCareportalEntryToNS(data, detailedBolusInfo.timestamp); - */ } public void uploadProfileSwitch(ProfileSwitch profileSwitch, long nsClientId) { diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/Notification.kt b/core/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/Notification.kt index 7858abeffe..1e2711dc78 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/Notification.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/Notification.kt @@ -121,6 +121,7 @@ open class Notification { const val OMNIPOD_UNKNOWN_TBR = 68 const val OMNIPOD_STARTUP_STATUS_REFRESH_FAILED = 69 const val OMNIPOD_TIME_OUT_OF_SYNC = 70 + const val UNSUPPORTED_ACTION_IN_PUMP = 71 const val USER_MESSAGE = 1000 diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/PumpSyncImplementation.kt b/core/src/main/java/info/nightscout/androidaps/plugins/pump/PumpSyncImplementation.kt index 039f4a8b1f..280d6482c7 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/pump/PumpSyncImplementation.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/pump/PumpSyncImplementation.kt @@ -2,27 +2,71 @@ package info.nightscout.androidaps.plugins.pump import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.database.AppRepository +import info.nightscout.androidaps.database.ValueWrapper import info.nightscout.androidaps.database.embedments.InterfaceIDs import info.nightscout.androidaps.database.entities.Bolus import info.nightscout.androidaps.database.entities.Carbs +import info.nightscout.androidaps.database.entities.ExtendedBolus import info.nightscout.androidaps.database.entities.TemporaryBasal import info.nightscout.androidaps.database.entities.TherapyEvent import info.nightscout.androidaps.database.transactions.* +import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.PumpSync import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.pump.common.defs.PumpType +import info.nightscout.androidaps.utils.DateUtil import io.reactivex.disposables.CompositeDisposable import io.reactivex.rxkotlin.plusAssign import javax.inject.Inject class PumpSyncImplementation @Inject constructor( private val aapsLogger: AAPSLogger, + private val dateUtil: DateUtil, + private val profileFunction: ProfileFunction, private val repository: AppRepository ) : PumpSync { private val disposable = CompositeDisposable() + override fun expectedPumpState(): PumpSync.PumpState { + val bolus = repository.getLastBolusRecord() + val temporaryBasal = repository.getTemporaryBasalActiveAt(dateUtil._now()).blockingGet() + val extendedBolus = repository.getExtendedBolusActiveAt(dateUtil._now()).blockingGet() + + return PumpSync.PumpState( + temporaryBasal = + if (temporaryBasal is ValueWrapper.Existing) + PumpSync.PumpState.TemporaryBasal( + id = temporaryBasal.value.id, + timestamp = temporaryBasal.value.timestamp, + duration = temporaryBasal.value.duration, + rate = temporaryBasal.value.rate, + isAbsolute = temporaryBasal.value.isAbsolute, + type = PumpSync.TemporaryBasalType.fromDbType(temporaryBasal.value.type), + pumpId = temporaryBasal.value.interfaceIDs.pumpId + ) + else null, + extendedBolus = + if (extendedBolus is ValueWrapper.Existing) + PumpSync.PumpState.ExtendedBolus( + timestamp = extendedBolus.value.timestamp, + duration = extendedBolus.value.duration, + amount = extendedBolus.value.amount, + rate = extendedBolus.value.rate + ) + else null, + bolus = + bolus?.let { + PumpSync.PumpState.Bolus( + timestamp = bolus.timestamp, + amount = bolus.amount + ) + }, + profile = profileFunction.getProfile() + ) + } + override fun addBolusWithTempId(timestamp: Long, amount: Double, temporaryId: Long, type: DetailedBolusInfo.BolusType, pumpType: PumpType, pumpSerial: String): Boolean { val bolus = Bolus( timestamp = timestamp, @@ -104,7 +148,7 @@ class PumpSyncImplementation @Inject constructor( } } - override fun insertTherapyEventIfNewWithTimestamp(timestamp: Long, type: DetailedBolusInfo.EventType, note: String?, pumpId: Long?, pumpType: PumpType, pumpSerial: String) { + override fun insertTherapyEventIfNewWithTimestamp(timestamp: Long, type: DetailedBolusInfo.EventType, note: String?, pumpId: Long?, pumpType: PumpType, pumpSerial: String): Boolean { val therapyEvent = TherapyEvent( timestamp = timestamp, type = type.toDBbEventType(), @@ -119,11 +163,15 @@ class PumpSyncImplementation @Inject constructor( pumpType = pumpType.toDbPumpType(), pumpSerial = pumpSerial) ) - disposable += repository.runTransactionForResult(InsertIfNewByTimestampTherapyEventTransaction(therapyEvent)) - .subscribe( - { result -> result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted therapy event $it") } }, - { aapsLogger.error(LTag.DATABASE, "Error while saving therapy event", it) } - ) + repository.runTransactionForResult(InsertIfNewByTimestampTherapyEventTransaction(therapyEvent)) + .doOnError { + aapsLogger.error(LTag.DATABASE, "Error while saving therapy event", it) + } + .blockingGet() + .also { result -> + result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted therapy event $it") } + return result.inserted.size > 0 + } } override fun insertAnnouncement(error: String, pumpId: Long?, pumpType: PumpType, pumpSerial: String) { @@ -169,4 +217,51 @@ class PumpSyncImplementation @Inject constructor( return result.updated.size > 0 } } + + override fun invalidateTemporaryBasal(id: Long): Boolean { + repository.runTransactionForResult(InvalidateTemporaryBasalTransaction(id)) + .doOnError { aapsLogger.error(LTag.DATABASE, "Error while invalidating temporary basal", it) } + .blockingGet() + .also { result -> + result.invalidated.forEach { + aapsLogger.debug(LTag.DATABASE, "Invalidated temporary basal $it") + } + return result.invalidated.size > 0 + } + } + + override fun syncExtendedBolusWithPumpId(timestamp: Long, amount: Double, duration: Long, isEmulatingTB: Boolean, pumpId: Long, pumpType: PumpType, pumpSerial: String): Boolean { + val extendedBolus = ExtendedBolus( + timestamp = timestamp, + amount = amount, + duration = duration, + isEmulatingTempBasal = isEmulatingTB, + interfaceIDs_backing = InterfaceIDs( + pumpId = pumpId, + pumpType = pumpType.toDbPumpType(), + pumpSerial = pumpSerial + ) + ) + repository.runTransactionForResult(SyncPumpExtendedBolusTransaction(extendedBolus)) + .doOnError { aapsLogger.error(LTag.DATABASE, "Error while extended bolus", it) } + .blockingGet() + .also { result -> + result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted extended bolus $it") } + result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated extended bolus $it") } + return result.inserted.size > 0 + } + } + + override fun syncStopExtendedBolusWithPumpId(timestamp: Long, endPumpId: Long, pumpType: PumpType, pumpSerial: String): Boolean { + repository.runTransactionForResult(SyncPumpCancelExtendedBolusIfAnyTransaction(timestamp, endPumpId, pumpType.toDbPumpType(), pumpSerial)) + .doOnError { aapsLogger.error(LTag.DATABASE, "Error while saving extended bolus", it) } + .blockingGet() + .also { result -> + result.updated.forEach { + aapsLogger.debug(LTag.DATABASE, "Updated extended bolus $it") + } + return result.updated.size > 0 + } + } + } \ No newline at end of file diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/bolusInfo/DetailedBolusInfoStorage.kt b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/bolusInfo/DetailedBolusInfoStorage.kt index b4cf7914ef..062d41191f 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/bolusInfo/DetailedBolusInfoStorage.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/bolusInfo/DetailedBolusInfoStorage.kt @@ -27,7 +27,7 @@ class DetailedBolusInfoStorage @Inject constructor( // Look for info with bolus for (i in store.indices) { val d = store[i] - aapsLogger.debug(LTag.PUMP, "Existing bolus info: " + store[i]) + //aapsLogger.debug(LTag.PUMP, "Existing bolus info: " + store[i]) if (bolusTime > d.timestamp - T.mins(1).msecs() && bolusTime < d.timestamp + T.mins(1).msecs() && abs(store[i].insulin - bolus) < 0.01) { aapsLogger.debug(LTag.PUMP, "Using & removing bolus info: ${store[i]}") store.removeAt(i) @@ -53,7 +53,7 @@ class DetailedBolusInfoStorage @Inject constructor( } } //Not found - aapsLogger.debug(LTag.PUMP, "Bolus info not found") + //aapsLogger.debug(LTag.PUMP, "Bolus info not found") return null } } \ No newline at end of file diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/bolusInfo/TemporaryBasalStorage.kt b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/bolusInfo/TemporaryBasalStorage.kt new file mode 100644 index 0000000000..0a5ac50f67 --- /dev/null +++ b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/bolusInfo/TemporaryBasalStorage.kt @@ -0,0 +1,59 @@ +package info.nightscout.androidaps.plugins.pump.common.bolusInfo + +import info.nightscout.androidaps.interfaces.PumpSync +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.utils.T +import java.util.* +import javax.inject.Inject +import javax.inject.Singleton +import kotlin.math.abs + +@Singleton +class TemporaryBasalStorage @Inject constructor( + val aapsLogger: AAPSLogger +) { + + val store = ArrayList() + + @Synchronized + fun add(temporaryBasal: PumpSync.PumpState.TemporaryBasal) { + aapsLogger.debug("Stored temporary basal info: $temporaryBasal") + store.add(temporaryBasal) + } + + @Synchronized + fun findTemporaryBasal(time: Long, rate: Double): PumpSync.PumpState.TemporaryBasal? { + // Look for info with temporary basal + for (i in store.indices) { + val d = store[i] + //aapsLogger.debug(LTag.PUMP, "Existing temporary basal info: " + store[i]) + if (time > d.timestamp - T.mins(1).msecs() && time < d.timestamp + T.mins(1).msecs() && abs(store[i].rate - rate) < 0.01) { + aapsLogger.debug(LTag.PUMP, "Using & removing temporary basal info: ${store[i]}") + store.removeAt(i) + return d + } + } + // If not found use time only + for (i in store.indices) { + val d = store[i] + if (time > d.timestamp - T.mins(1).msecs() && time < d.timestamp + T.mins(1).msecs() && rate <= store[i].rate + 0.01) { + aapsLogger.debug(LTag.PUMP, "Using TIME-ONLY & removing temporary basal info: ${store[i]}") + store.removeAt(i) + return d + } + } + // If not found, use last record if amount is the same + if (store.size > 0) { + val d = store[store.size - 1] + if (abs(d.rate - rate) < 0.01) { + aapsLogger.debug(LTag.PUMP, "Using LAST & removing temporary basal info: $d") + store.removeAt(store.size - 1) + return d + } + } + //Not found + //aapsLogger.debug(LTag.PUMP, "Temporary basal info not found") + return null + } +} \ No newline at end of file diff --git a/core/src/main/java/info/nightscout/androidaps/utils/CryptoUtil.kt b/core/src/main/java/info/nightscout/androidaps/utils/CryptoUtil.kt index e78b112615..563db53270 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/CryptoUtil.kt +++ b/core/src/main/java/info/nightscout/androidaps/utils/CryptoUtil.kt @@ -1,7 +1,7 @@ package info.nightscout.androidaps.utils import info.nightscout.androidaps.logging.AAPSLogger -import info.nightscout.androidaps.utils.extensions.toHex +import info.nightscout.androidaps.extensions.toHex import org.spongycastle.util.encoders.Base64 import java.nio.ByteBuffer import java.security.MessageDigest diff --git a/core/src/main/java/info/nightscout/androidaps/utils/DateUtil.java b/core/src/main/java/info/nightscout/androidaps/utils/DateUtil.java index 61f669e196..fde7122293 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/DateUtil.java +++ b/core/src/main/java/info/nightscout/androidaps/utils/DateUtil.java @@ -271,7 +271,7 @@ public class DateUtil { public static boolean isCloseToNow(long date) { long diff = Math.abs(date - now()); - return diff < T.mins(2).msecs(); + return diff < T.mins(2L).msecs(); } public static boolean isOlderThan(long date, long minutes) { diff --git a/core/src/main/java/info/nightscout/androidaps/utils/T.java b/core/src/main/java/info/nightscout/androidaps/utils/T.java deleted file mode 100644 index 5671f0725c..0000000000 --- a/core/src/main/java/info/nightscout/androidaps/utils/T.java +++ /dev/null @@ -1,79 +0,0 @@ -package info.nightscout.androidaps.utils; - -/** - * Created by mike on 26.03.2018. - */ - -public class T { - private long time; // in msec - - public static T now() { - T t = new T(); - t.time = System.currentTimeMillis(); - return t; - } - - public static T msecs(long msec) { - T t = new T(); - t.time = msec; - return t; - } - - public static T secs(long sec) { - T t = new T(); - t.time = sec * 1000L; - return t; - } - - public static T mins(long min) { - T t = new T(); - t.time = min * 60 * 1000L; - return t; - } - - public static T hours(long hour) { - T t = new T(); - t.time = hour * 60 * 60 * 1000L; - return t; - } - - public static T days(long day) { - T t = new T(); - t.time = day * 24 * 60 * 60 * 1000L; - return t; - } - - public static T months(long month) { - T t = new T(); - t.time = month * 31 * 24 * 60 * 60 * 1000L; - return t; - } - - public long msecs() { - return time; - } - - public long secs() { - return time / 1000L; - } - - public long mins() { - return time / 60 / 1000L; - } - - public long hours() { - return time / 60 / 60 / 1000L; - } - - public long days() { - return time / 24 / 60 / 60 / 1000L; - } - - public T plus(T plus) { - return T.msecs(time + plus.time); - } - - public T minus(T minus) { - return T.msecs(time - minus.time); - } -} diff --git a/core/src/main/java/info/nightscout/androidaps/utils/T.kt b/core/src/main/java/info/nightscout/androidaps/utils/T.kt new file mode 100644 index 0000000000..29915386f1 --- /dev/null +++ b/core/src/main/java/info/nightscout/androidaps/utils/T.kt @@ -0,0 +1,25 @@ +package info.nightscout.androidaps.utils + +@Suppress("SpellCheckingInspection") +class T(val time: Long = 0L) { + + fun msecs(): Long = time + fun secs(): Long = time / 1000L + fun mins(): Long = time / 60 / 1000L + fun hours(): Long = time / 60 / 60 / 1000L + fun days(): Long = time / 24 / 60 / 60 / 1000L + + operator fun plus(plus: T): T = T(time + plus.time) + operator fun minus(minus: T): T = T(time - minus.time) + + companion object { + + @JvmStatic fun now(): T = T(System.currentTimeMillis()) + @JvmStatic fun msecs(msec: Long): T = T(msec) + @JvmStatic fun secs(sec: Long): T = T(sec * 1000L) + @JvmStatic fun mins(min: Long): T = T(min * 60 * 1000L) + @JvmStatic fun hours(hour: Long): T = T(hour * 60 * 60 * 1000L) + @JvmStatic fun days(day: Long): T = T(day * 24 * 60 * 60 * 1000L) + @JvmStatic fun months(month: Long): T = T(month * 31 * 24 * 60 * 60 * 1000L) + } +} \ No newline at end of file diff --git a/core/src/main/java/info/nightscout/androidaps/utils/WarnColors.kt b/core/src/main/java/info/nightscout/androidaps/utils/WarnColors.kt index c1b072234f..e61b6bd327 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/WarnColors.kt +++ b/core/src/main/java/info/nightscout/androidaps/utils/WarnColors.kt @@ -4,7 +4,7 @@ import android.graphics.Color import android.widget.TextView import info.nightscout.androidaps.core.R import info.nightscout.androidaps.database.entities.TherapyEvent -import info.nightscout.androidaps.utils.extensions.isOlderThan +import info.nightscout.androidaps.extensions.isOlderThan import info.nightscout.androidaps.utils.resources.ResourceHelper import javax.inject.Inject import javax.inject.Singleton diff --git a/core/src/main/java/info/nightscout/androidaps/utils/alertDialogs/OKDialog.kt b/core/src/main/java/info/nightscout/androidaps/utils/alertDialogs/OKDialog.kt index 373935fb94..76e64ebaf3 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/alertDialogs/OKDialog.kt +++ b/core/src/main/java/info/nightscout/androidaps/utils/alertDialogs/OKDialog.kt @@ -7,7 +7,7 @@ import android.os.SystemClock import android.text.Spanned import androidx.fragment.app.FragmentActivity import info.nightscout.androidaps.core.R -import info.nightscout.androidaps.utils.extensions.runOnUiThread +import info.nightscout.androidaps.extensions.runOnUiThread object OKDialog { diff --git a/core/src/main/java/info/nightscout/androidaps/utils/alertDialogs/WarningDialog.kt b/core/src/main/java/info/nightscout/androidaps/utils/alertDialogs/WarningDialog.kt index 2894f1b8d4..38f3314667 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/alertDialogs/WarningDialog.kt +++ b/core/src/main/java/info/nightscout/androidaps/utils/alertDialogs/WarningDialog.kt @@ -6,7 +6,7 @@ import android.content.DialogInterface import android.os.SystemClock import androidx.annotation.StringRes import info.nightscout.androidaps.core.R -import info.nightscout.androidaps.utils.extensions.runOnUiThread +import info.nightscout.androidaps.extensions.runOnUiThread // if you need error dialog - duplicate to ErrorDialog and make it and use: AppThemeErrorDialog & R.drawable.ic_header_error instead diff --git a/core/src/main/java/info/nightscout/androidaps/utils/protection/BiometricCheck.kt b/core/src/main/java/info/nightscout/androidaps/utils/protection/BiometricCheck.kt index b74b3377dc..fe46155c8b 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/protection/BiometricCheck.kt +++ b/core/src/main/java/info/nightscout/androidaps/utils/protection/BiometricCheck.kt @@ -5,7 +5,7 @@ import androidx.biometric.BiometricPrompt.* import androidx.fragment.app.FragmentActivity import info.nightscout.androidaps.core.R import info.nightscout.androidaps.utils.ToastUtils -import info.nightscout.androidaps.utils.extensions.runOnUiThread +import info.nightscout.androidaps.extensions.runOnUiThread import java.util.concurrent.Executors object BiometricCheck { diff --git a/core/src/main/java/info/nightscout/androidaps/utils/ui/UIRunnable.kt b/core/src/main/java/info/nightscout/androidaps/utils/ui/UIRunnable.kt index d3860ac53b..36f44f6693 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/ui/UIRunnable.kt +++ b/core/src/main/java/info/nightscout/androidaps/utils/ui/UIRunnable.kt @@ -1,6 +1,6 @@ package info.nightscout.androidaps.utils.ui -import info.nightscout.androidaps.utils.extensions.runOnUiThread +import info.nightscout.androidaps.extensions.runOnUiThread class UIRunnable (val runnable: Runnable) : Runnable { override fun run() { diff --git a/core/src/main/java/info/nightscout/androidaps/utils/ui/WeekdayPicker.kt b/core/src/main/java/info/nightscout/androidaps/utils/ui/WeekdayPicker.kt index e3352ec94d..e76dc1b2e1 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/ui/WeekdayPicker.kt +++ b/core/src/main/java/info/nightscout/androidaps/utils/ui/WeekdayPicker.kt @@ -7,7 +7,7 @@ import android.widget.Checkable import androidx.appcompat.widget.AppCompatCheckedTextView import androidx.constraintlayout.widget.ConstraintLayout import info.nightscout.androidaps.core.databinding.WeekdayPickerBinding -import info.nightscout.androidaps.utils.extensions.toVisibility +import info.nightscout.androidaps.extensions.toVisibility import java.util.* class WeekdayPicker @JvmOverloads constructor( diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 7ccc01f2af..7aeae44c0a 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -8,7 +8,6 @@ absorption_maxtime openapsama_min_5m_carbimpact absorption_cutoff - danar_visualizeextendedaspercentage" danar_useextended eatingsoon_duration eatingsoon_target diff --git a/core/src/test/java/info/nightscout/androidaps/TestPumpPlugin.kt b/core/src/test/java/info/nightscout/androidaps/TestPumpPlugin.kt index d104302084..bfc9e86370 100644 --- a/core/src/test/java/info/nightscout/androidaps/TestPumpPlugin.kt +++ b/core/src/test/java/info/nightscout/androidaps/TestPumpPlugin.kt @@ -6,6 +6,7 @@ import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.interfaces.PumpDescription import info.nightscout.androidaps.interfaces.PumpInterface +import info.nightscout.androidaps.interfaces.PumpSync import info.nightscout.androidaps.plugins.common.ManufacturerType import info.nightscout.androidaps.plugins.pump.common.defs.PumpType import info.nightscout.androidaps.utils.TimeChangeType @@ -50,8 +51,8 @@ class TestPumpPlugin(val injector: HasAndroidInjector) : PumpInterface { override val batteryLevel: Int = 0 override fun deliverTreatment(detailedBolusInfo: DetailedBolusInfo): PumpEnactResult = PumpEnactResult(injector).success(true) override fun stopBolusDelivering() {} - override fun setTempBasalAbsolute(absoluteRate: Double, durationInMinutes: Int, profile: Profile, enforceNew: Boolean): PumpEnactResult = PumpEnactResult(injector).success(true) - override fun setTempBasalPercent(percent: Int, durationInMinutes: Int, profile: Profile, enforceNew: Boolean): PumpEnactResult = PumpEnactResult(injector).success(true) + override fun setTempBasalAbsolute(absoluteRate: Double, durationInMinutes: Int, profile: Profile, enforceNew: Boolean, tbrType: PumpSync.TemporaryBasalType): PumpEnactResult = PumpEnactResult(injector).success(true) + override fun setTempBasalPercent(percent: Int, durationInMinutes: Int, profile: Profile, enforceNew: Boolean, tbrType: PumpSync.TemporaryBasalType): PumpEnactResult = PumpEnactResult(injector).success(true) override fun setExtendedBolus(insulin: Double, durationInMinutes: Int): PumpEnactResult = PumpEnactResult(injector).success(true) override fun cancelTempBasal(enforceNew: Boolean): PumpEnactResult = PumpEnactResult(injector).success(true) override fun cancelExtendedBolus(): PumpEnactResult = PumpEnactResult(injector).success(true) diff --git a/core/src/test/java/info/nightscout/androidaps/plugins/aps/loop/APSResultTest.kt b/core/src/test/java/info/nightscout/androidaps/plugins/aps/loop/APSResultTest.kt index 159659f4de..40a6cd3c20 100644 --- a/core/src/test/java/info/nightscout/androidaps/plugins/aps/loop/APSResultTest.kt +++ b/core/src/test/java/info/nightscout/androidaps/plugins/aps/loop/APSResultTest.kt @@ -4,8 +4,9 @@ import dagger.android.AndroidInjector import dagger.android.HasAndroidInjector import info.nightscout.androidaps.TestBaseWithProfile import info.nightscout.androidaps.TestPumpPlugin -import info.nightscout.androidaps.db.TemporaryBasal +import info.nightscout.androidaps.database.entities.TemporaryBasal import info.nightscout.androidaps.interfaces.Constraint +import info.nightscout.androidaps.interfaces.IobCobCalculator import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.pump.common.defs.PumpType import info.nightscout.androidaps.utils.JsonHelper.safeGetDouble @@ -26,6 +27,7 @@ class APSResultTest : TestBaseWithProfile() { @Mock lateinit var constraintChecker: ConstraintChecker @Mock lateinit var sp: SP + @Mock lateinit var iobCobCalculator: IobCobCalculator private lateinit var testPumpPlugin: TestPumpPlugin private val injector = HasAndroidInjector { AndroidInjector { } } @@ -41,7 +43,7 @@ class APSResultTest : TestBaseWithProfile() { it.constraintChecker = constraintChecker it.sp = sp it.activePlugin = activePluginProvider - it.treatmentsPlugin = treatmentsInterface + it.iobCobCalculator = iobCobCalculator it.profileFunction = profileFunction it.resourceHelper = resourceHelper } @@ -54,7 +56,7 @@ class APSResultTest : TestBaseWithProfile() { // closed loop mode return original request closedLoopEnabled.set(aapsLogger, true) - `when`(treatmentsInterface.getTempBasalFromHistory(ArgumentMatchers.anyLong())).thenReturn(null) + `when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(ArgumentMatchers.anyLong())).thenReturn(null) apsResult.tempBasalRequested(false) Assert.assertEquals(false, apsResult.isChangeRequested) apsResult.tempBasalRequested(true).percent(200).duration(30) @@ -63,46 +65,46 @@ class APSResultTest : TestBaseWithProfile() { // open loop closedLoopEnabled.set(aapsLogger, false) // no change requested - `when`(treatmentsInterface.getTempBasalFromHistory(ArgumentMatchers.anyLong())).thenReturn(null) + `when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(ArgumentMatchers.anyLong())).thenReturn(null) apsResult.tempBasalRequested(false) Assert.assertEquals(false, apsResult.isChangeRequested) // request 100% when no temp is running - `when`(treatmentsInterface.getTempBasalFromHistory(ArgumentMatchers.anyLong())).thenReturn(null) + `when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(ArgumentMatchers.anyLong())).thenReturn(null) apsResult.tempBasalRequested(true).percent(100).duration(30) Assert.assertEquals(false, apsResult.isChangeRequested) // request equal temp - `when`(treatmentsInterface.getTempBasalFromHistory(ArgumentMatchers.anyLong())).thenReturn(TemporaryBasal(injector).percent(70).duration(30)) + `when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(ArgumentMatchers.anyLong())).thenReturn(TemporaryBasal(timestamp = 0, rate = 70.0, duration = 30, isAbsolute = false, type = TemporaryBasal.Type.NORMAL)) apsResult.tempBasalRequested(true).percent(70).duration(30) Assert.assertEquals(false, apsResult.isChangeRequested) // request zero temp - `when`(treatmentsInterface.getTempBasalFromHistory(ArgumentMatchers.anyLong())).thenReturn(TemporaryBasal(injector).percent(10).duration(30)) + `when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(ArgumentMatchers.anyLong())).thenReturn(TemporaryBasal(timestamp = 0, rate = 10.0, duration = 30, isAbsolute = false, type = TemporaryBasal.Type.NORMAL)) apsResult.tempBasalRequested(true).percent(0).duration(30) Assert.assertEquals(true, apsResult.isChangeRequested) // request high temp - `when`(treatmentsInterface.getTempBasalFromHistory(ArgumentMatchers.anyLong())).thenReturn(TemporaryBasal(injector).percent(190).duration(30)) + `when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(ArgumentMatchers.anyLong())).thenReturn(TemporaryBasal(timestamp = 0, rate = 190.0, duration = 30, isAbsolute = false, type = TemporaryBasal.Type.NORMAL)) apsResult.tempBasalRequested(true).percent(200).duration(30) Assert.assertEquals(true, apsResult.isChangeRequested) // request slightly different temp - `when`(treatmentsInterface.getTempBasalFromHistory(ArgumentMatchers.anyLong())).thenReturn(TemporaryBasal(injector).percent(70).duration(30)) + `when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(ArgumentMatchers.anyLong())).thenReturn(TemporaryBasal(timestamp = 0, rate = 70.0, duration = 30, isAbsolute = false, type = TemporaryBasal.Type.NORMAL)) apsResult.tempBasalRequested(true).percent(80).duration(30) Assert.assertEquals(false, apsResult.isChangeRequested) // request different temp - `when`(treatmentsInterface.getTempBasalFromHistory(ArgumentMatchers.anyLong())).thenReturn(TemporaryBasal(injector).percent(70).duration(30)) + `when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(ArgumentMatchers.anyLong())).thenReturn(TemporaryBasal(timestamp = 0, rate = 70.0, duration = 30, isAbsolute = false, type = TemporaryBasal.Type.NORMAL)) apsResult.tempBasalRequested(true).percent(120).duration(30) Assert.assertEquals(true, apsResult.isChangeRequested) // it should work with absolute temps too // request different temp - `when`(treatmentsInterface.getTempBasalFromHistory(ArgumentMatchers.anyLong())).thenReturn(TemporaryBasal(injector).absolute(1.0).duration(30)) + `when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(ArgumentMatchers.anyLong())).thenReturn(TemporaryBasal(timestamp = 0, rate = 1.0, duration = 30, isAbsolute = true, type = TemporaryBasal.Type.NORMAL)) apsResult.tempBasalRequested(true).percent(100).duration(30) Assert.assertEquals(false, apsResult.isChangeRequested) - `when`(treatmentsInterface.getTempBasalFromHistory(ArgumentMatchers.anyLong())).thenReturn(TemporaryBasal(injector).absolute(2.0).duration(30)) + `when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(ArgumentMatchers.anyLong())).thenReturn(TemporaryBasal(timestamp = 0, rate = 2.0, duration = 30, isAbsolute = true, type = TemporaryBasal.Type.NORMAL)) apsResult.tempBasalRequested(true).percent(50).duration(30) Assert.assertEquals(true, apsResult.isChangeRequested) @@ -113,44 +115,44 @@ class APSResultTest : TestBaseWithProfile() { // open loop closedLoopEnabled.set(aapsLogger, false) // request 100% when no temp is running - `when`(treatmentsInterface.getTempBasalFromHistory(ArgumentMatchers.anyLong())).thenReturn(null) + `when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(ArgumentMatchers.anyLong())).thenReturn(null) apsResult.tempBasalRequested(true).rate(1.0).duration(30) Assert.assertEquals(false, apsResult.isChangeRequested) // request equal temp - `when`(treatmentsInterface.getTempBasalFromHistory(ArgumentMatchers.anyLong())).thenReturn(TemporaryBasal(injector).absolute(2.0).duration(30)) + `when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(ArgumentMatchers.anyLong())).thenReturn(TemporaryBasal(timestamp = 0, rate = 2.0, duration = 30, isAbsolute = true, type = TemporaryBasal.Type.NORMAL)) apsResult.tempBasalRequested(true).rate(2.0).duration(30) Assert.assertEquals(false, apsResult.isChangeRequested) - `when`(treatmentsInterface.getTempBasalFromHistory(ArgumentMatchers.anyLong())).thenReturn(TemporaryBasal(injector).percent(200).duration(30)) + `when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(ArgumentMatchers.anyLong())).thenReturn(TemporaryBasal(timestamp = 0, rate = 200.0, duration = 30, isAbsolute = false, type = TemporaryBasal.Type.NORMAL)) apsResult.tempBasalRequested(true).rate(2.0).duration(30) Assert.assertEquals(false, apsResult.isChangeRequested) // request zero temp - `when`(treatmentsInterface.getTempBasalFromHistory(ArgumentMatchers.anyLong())).thenReturn(TemporaryBasal(injector).absolute(0.1).duration(30)) + `when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(ArgumentMatchers.anyLong())).thenReturn(TemporaryBasal(timestamp = 0, rate = 0.1, duration = 30, isAbsolute = true, type = TemporaryBasal.Type.NORMAL)) apsResult.tempBasalRequested(true).rate(0.0).duration(30) Assert.assertEquals(true, apsResult.isChangeRequested) // request high temp - `when`(treatmentsInterface.getTempBasalFromHistory(ArgumentMatchers.anyLong())).thenReturn(TemporaryBasal(injector).absolute(34.9).duration(30)) + `when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(ArgumentMatchers.anyLong())).thenReturn(TemporaryBasal(timestamp = 0, rate = 34.9, duration = 30, isAbsolute = true, type = TemporaryBasal.Type.NORMAL)) apsResult.tempBasalRequested(true).rate(35.0).duration(30) Assert.assertEquals(true, apsResult.isChangeRequested) // request slightly different temp - `when`(treatmentsInterface.getTempBasalFromHistory(ArgumentMatchers.anyLong())).thenReturn(TemporaryBasal(injector).absolute(1.1).duration(30)) + `when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(ArgumentMatchers.anyLong())).thenReturn(TemporaryBasal(timestamp = 0, rate = 1.1, duration = 30, isAbsolute = true, type = TemporaryBasal.Type.NORMAL)) apsResult.tempBasalRequested(true).rate(1.2).duration(30) Assert.assertEquals(false, apsResult.isChangeRequested) // request different temp - `when`(treatmentsInterface.getTempBasalFromHistory(ArgumentMatchers.anyLong())).thenReturn(TemporaryBasal(injector).absolute(1.1).duration(30)) + `when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(ArgumentMatchers.anyLong())).thenReturn(TemporaryBasal(timestamp = 0, rate = 1.1, duration = 30, isAbsolute = true, type = TemporaryBasal.Type.NORMAL)) apsResult.tempBasalRequested(true).rate(1.5).duration(30) Assert.assertEquals(true, apsResult.isChangeRequested) // it should work with percent temps too // request different temp - `when`(treatmentsInterface.getTempBasalFromHistory(ArgumentMatchers.anyLong())).thenReturn(TemporaryBasal(injector).percent(110).duration(30)) + `when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(ArgumentMatchers.anyLong())).thenReturn(TemporaryBasal(timestamp = 0, rate = 110.0, duration = 30, isAbsolute = false, type = TemporaryBasal.Type.NORMAL)) apsResult.tempBasalRequested(true).rate(1.1).duration(30) Assert.assertEquals(false, apsResult.isChangeRequested) - `when`(treatmentsInterface.getTempBasalFromHistory(ArgumentMatchers.anyLong())).thenReturn(TemporaryBasal(injector).percent(200).duration(30)) + `when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(ArgumentMatchers.anyLong())).thenReturn(TemporaryBasal(timestamp = 0, rate = 200.0, duration = 30, isAbsolute = false, type = TemporaryBasal.Type.NORMAL)) apsResult.tempBasalRequested(true).rate(0.5).duration(30) Assert.assertEquals(true, apsResult.isChangeRequested) } @@ -162,7 +164,7 @@ class APSResultTest : TestBaseWithProfile() { it.constraintChecker = constraintChecker it.sp = sp it.activePlugin = activePluginProvider - it.treatmentsPlugin = treatmentsInterface + it.iobCobCalculator = iobCobCalculator it.profileFunction = profileFunction it.resourceHelper = resourceHelper } @@ -179,7 +181,7 @@ class APSResultTest : TestBaseWithProfile() { it.constraintChecker = constraintChecker it.sp = sp it.activePlugin = activePluginProvider - it.treatmentsPlugin = treatmentsInterface + it.iobCobCalculator = iobCobCalculator it.profileFunction = profileFunction it.resourceHelper = resourceHelper } diff --git a/core/src/test/java/info/nightscout/androidaps/pump/bolusInfo/DetailedBolusInfoStorageTest.kt b/core/src/test/java/info/nightscout/androidaps/pump/bolusInfo/DetailedBolusInfoStorageTest.kt index 4a70420302..7e0eb236c1 100644 --- a/core/src/test/java/info/nightscout/androidaps/pump/bolusInfo/DetailedBolusInfoStorageTest.kt +++ b/core/src/test/java/info/nightscout/androidaps/pump/bolusInfo/DetailedBolusInfoStorageTest.kt @@ -7,10 +7,7 @@ import org.junit.Assert.assertEquals import org.junit.Assert.assertNull import org.junit.Before import org.junit.Test -import org.junit.runner.RunWith -import org.powermock.modules.junit4.PowerMockRunner -@RunWith(PowerMockRunner::class) class DetailedBolusInfoStorageTest : TestBase() { private val info1 = DetailedBolusInfo() diff --git a/core/src/test/java/info/nightscout/androidaps/pump/bolusInfo/TemporaryBasalStorageTest.kt b/core/src/test/java/info/nightscout/androidaps/pump/bolusInfo/TemporaryBasalStorageTest.kt new file mode 100644 index 0000000000..d54568e4ae --- /dev/null +++ b/core/src/test/java/info/nightscout/androidaps/pump/bolusInfo/TemporaryBasalStorageTest.kt @@ -0,0 +1,79 @@ +package info.nightscout.androidaps.pump.bolusInfo + +import info.nightscout.androidaps.TestBase +import info.nightscout.androidaps.interfaces.PumpSync +import info.nightscout.androidaps.plugins.pump.common.bolusInfo.TemporaryBasalStorage +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNull +import org.junit.Before +import org.junit.Test + +class TemporaryBasalStorageTest : TestBase() { + + private val info1 = PumpSync.PumpState.TemporaryBasal(1000000, 1000, 3.0, false, PumpSync.TemporaryBasalType.NORMAL, 0L, 0L) + private val info2 = PumpSync.PumpState.TemporaryBasal(1000001, 1000, 4.0, false, PumpSync.TemporaryBasalType.NORMAL, 0L, 0L) + private val info3 = PumpSync.PumpState.TemporaryBasal(2000000, 1000, 5.0, false, PumpSync.TemporaryBasalType.NORMAL, 0L, 0L) + + private lateinit var temporaryBasalStorage: TemporaryBasalStorage + + @Before + fun prepare() { + temporaryBasalStorage = TemporaryBasalStorage(aapsLogger) + } + + private fun setUp() { + temporaryBasalStorage.store.clear() + temporaryBasalStorage.add(info1) + temporaryBasalStorage.add(info2) + temporaryBasalStorage.add(info3) + } + + @Test + fun add() { + temporaryBasalStorage.store.clear() + assertEquals(0, temporaryBasalStorage.store.size) + temporaryBasalStorage.add(info1) + assertEquals(1, temporaryBasalStorage.store.size) + } + + @Test + fun findTemporaryBasal() { + + // Look for exact bolus + setUp() + var d = temporaryBasalStorage.findTemporaryBasal(1000000, 4.0) + assertEquals(4.0, d!!.rate, 0.01) + assertEquals(2, temporaryBasalStorage.store.size) + // Look for exact bolus + setUp() + d = temporaryBasalStorage.findTemporaryBasal(1000000, 3.0) + assertEquals(3.0, d!!.rate, 0.01) + assertEquals(2, temporaryBasalStorage.store.size) + // With less rate (bolus not delivered completely). Should return first one matching date + setUp() + d = temporaryBasalStorage.findTemporaryBasal(1000500, 2.0) + assertEquals(3.0, d!!.rate, 0.01) + assertEquals(2, temporaryBasalStorage.store.size) + // With less rate (bolus not delivered completely). Should return first one matching date + setUp() + d = temporaryBasalStorage.findTemporaryBasal(1000500, 3.5) + assertEquals(4.0, d!!.rate, 0.01) + assertEquals(2, temporaryBasalStorage.store.size) + // With more rate should return null + setUp() + d = temporaryBasalStorage.findTemporaryBasal(1000500, 4.5) + assertNull(d) + assertEquals(3, temporaryBasalStorage.store.size) + // With more than one minute off should return null + setUp() + d = temporaryBasalStorage.findTemporaryBasal(1070000, 4.0) + assertNull(d) + assertEquals(3, temporaryBasalStorage.store.size) + // Use last, if bolus size is the same + setUp() + d = temporaryBasalStorage.findTemporaryBasal(1070000, 5.0) + assertEquals(5.0, d!!.rate, 0.01) + assertEquals(2, temporaryBasalStorage.store.size) + + } +} \ No newline at end of file diff --git a/dana/src/main/java/info/nightscout/androidaps/dana/DanaFragment.kt b/dana/src/main/java/info/nightscout/androidaps/dana/DanaFragment.kt index b6ffdf0980..39e90d24d2 100644 --- a/dana/src/main/java/info/nightscout/androidaps/dana/DanaFragment.kt +++ b/dana/src/main/java/info/nightscout/androidaps/dana/DanaFragment.kt @@ -30,7 +30,7 @@ import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.WarnColors import info.nightscout.androidaps.utils.alertDialogs.OKDialog -import info.nightscout.androidaps.utils.extensions.toVisibility +import info.nightscout.androidaps.extensions.toVisibility import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.sharedPreferences.SP @@ -102,7 +102,7 @@ class DanaFragment : DaggerFragment() { binding.userOptions.setOnClickListener { startActivity(Intent(context, info.nightscout.androidaps.dana.activities.DanaUserOptionsActivity::class.java)) } binding.btconnection.setOnClickListener { aapsLogger.debug(LTag.PUMP, "Clicked connect to pump") - danaPump.lastConnection = 0 + danaPump.reset() commandQueue.readStatus("Clicked connect to pump", null) } if (activePlugin.activePump.pumpDescription.pumpType == PumpType.DANA_RS) @@ -208,16 +208,8 @@ class DanaFragment : DaggerFragment() { warnColors.setColor(binding.dailyunits, pump.dailyTotalUnits, pump.maxDailyTotalUnits * 0.75, pump.maxDailyTotalUnits * 0.9) binding.basabasalrate.text = "( " + (pump.activeProfile + 1) + " ) " + resourceHelper.gs(R.string.pump_basebasalrate, plugin.baseBasalRate) // DanaRPlugin, DanaRKoreanPlugin - if (activePlugin.activePump.isFakingTempsByExtendedBoluses) { - binding.tempbasal.text = activePlugin.activeTreatments.getRealTempBasalFromHistory(System.currentTimeMillis())?.toStringFull() - ?: "" - } else { - // v2 plugin - binding.tempbasal.text = activePlugin.activeTreatments.getTempBasalFromHistory(System.currentTimeMillis())?.toStringFull() - ?: "" - } - binding.extendedbolus.text = activePlugin.activeTreatments.getExtendedBolusFromHistory(System.currentTimeMillis())?.toString() - ?: "" + binding.tempbasal.text = danaPump.temporaryBasalToString() + binding.extendedbolus.text = danaPump.extendedBolusToString() binding.reservoir.text = resourceHelper.gs(R.string.reservoirvalue, pump.reservoirRemainingUnits, 300) warnColors.setColorInverse(binding.reservoir, pump.reservoirRemainingUnits, 50.0, 20.0) binding.battery.text = "{fa-battery-" + pump.batteryRemaining / 25 + "}" diff --git a/dana/src/main/java/info/nightscout/androidaps/dana/DanaPump.kt b/dana/src/main/java/info/nightscout/androidaps/dana/DanaPump.kt index 60b68cbcd1..5713c7788b 100644 --- a/dana/src/main/java/info/nightscout/androidaps/dana/DanaPump.kt +++ b/dana/src/main/java/info/nightscout/androidaps/dana/DanaPump.kt @@ -4,10 +4,13 @@ import dagger.android.HasAndroidInjector import info.nightscout.androidaps.Constants import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.interfaces.ProfileStore +import info.nightscout.androidaps.interfaces.PumpSync import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress import info.nightscout.androidaps.plugins.pump.common.defs.PumpType +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.DecimalFormatter import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.sharedPreferences.SP import org.joda.time.DateTime @@ -19,11 +22,15 @@ import java.text.DecimalFormat import java.util.concurrent.TimeUnit import javax.inject.Inject import javax.inject.Singleton +import kotlin.math.max +import kotlin.math.min +import kotlin.math.roundToInt @Singleton class DanaPump @Inject constructor( private val aapsLogger: AAPSLogger, private val sp: SP, + private val dateUtil: DateUtil, private val injector: HasAndroidInjector ) { @@ -44,6 +51,8 @@ class DanaPump @Inject constructor( var lastConnection: Long = 0 var lastSettingsRead: Long = 0 + @JvmField var lastHistoryFetched: Long = 0 + @JvmField var historyDoneReceived: Boolean = false // true when last history message is received // Info var serialNumber = "" @@ -108,20 +117,105 @@ class DanaPump @Inject constructor( var lastBolusTime: Long = 0 var lastBolusAmount = 0.0 var currentBasal = 0.0 - var isTempBasalInProgress = false - var tempBasalPercent = 0 - var tempBasalRemainingMin = 0 - var tempBasalTotalSec = 0 + + /* + * TEMP BASALS + */ + var tempBasalStart: Long = 0 - var isDualBolusInProgress = false - var isExtendedInProgress = false - var extendedBolusMinutes = 0 - var extendedBolusAmount = 0.0 - var extendedBolusAbsoluteRate = 0.0 - var extendedBolusSoFarInMinutes = 0 + var tempBasalDuration: Long = 0 // in milliseconds + var tempBasalPercent = 0 + + var tempBasalTotalSec: Long + set(durationInSec) { + tempBasalDuration = T.secs(durationInSec).msecs() + } + get() = T.msecs(tempBasalDuration).mins() + var isTempBasalInProgress: Boolean + get() = tempBasalStart != 0L && dateUtil._now() in tempBasalStart..tempBasalStart + tempBasalDuration + set(isRunning) { + if (isRunning) throw IllegalArgumentException("Use to cancel TBR only") + else { + tempBasalStart = 0L + tempBasalDuration = 0L + tempBasalPercent = 0 + } + } + val tempBasalRemainingMin: Int + get() = max(T.msecs(tempBasalStart + tempBasalDuration - dateUtil._now()).mins().toInt(), 0) + + fun temporaryBasalToString(): String { + if (!isTempBasalInProgress) return "" + + val passedMin = ((min(dateUtil._now(), tempBasalStart + tempBasalDuration) - tempBasalStart) / 60.0 / 1000).roundToInt() + return tempBasalPercent.toString() + "% @" + + dateUtil.timeString(tempBasalStart) + + " " + passedMin + "/" + T.msecs(tempBasalDuration).mins() + "'" + } + + fun fromTemporaryBasal(tbr: PumpSync.PumpState.TemporaryBasal?) { + if (tbr == null) { + tempBasalStart = 0 + tempBasalDuration = 0 + tempBasalPercent = 0 + } else { + tempBasalStart = tbr.timestamp + tempBasalDuration = tbr.duration + tempBasalPercent = tbr.rate.toInt() + } + } + + /* + * EXTENDED BOLUSES + */ + var extendedBolusStart: Long = 0 - var extendedBolusRemainingMinutes = 0 - var extendedBolusDeliveredSoFar = 0.0 //RS only = 0.0 + var extendedBolusDuration: Long = 0 + var extendedBolusAmount = 0.0 + + var isExtendedInProgress: Boolean + get() = extendedBolusStart != 0L && dateUtil._now() in extendedBolusStart..extendedBolusStart + extendedBolusDuration + set(isRunning) { + if (isRunning) throw IllegalArgumentException("Use to cancel EB only") + else { + extendedBolusStart = 0L + extendedBolusDuration = 0L + extendedBolusAmount = 0.0 + } + } + val extendedBolusPassedMinutes: Int + get() = T.msecs(max(0, dateUtil._now() - extendedBolusStart)).mins().toInt() + val extendedBolusRemainingMinutes: Int + get() = max(T.msecs(extendedBolusStart + extendedBolusDuration - dateUtil._now()).mins().toInt(), 0) + private val extendedBolusDurationInMinutes: Int + get() = T.msecs(extendedBolusDuration).mins().toInt() + var extendedBolusAbsoluteRate: Double + get() = extendedBolusAmount * T.hours(1).msecs() / extendedBolusDuration + set(rate) { + extendedBolusAmount = rate * extendedBolusDuration / T.hours(1).msecs() + } + + fun extendedBolusToString(): String { + if (!isExtendedInProgress) return "" + + return "E " + DecimalFormatter.to2Decimal(extendedBolusAbsoluteRate) + "U/h @" + + dateUtil.timeString(extendedBolusStart) + + " " + extendedBolusPassedMinutes + "/" + extendedBolusDurationInMinutes + "'" + } + + fun fromExtendedBolus(eb: PumpSync.PumpState.ExtendedBolus?) { + if (eb == null) { + extendedBolusStart = 0 + extendedBolusDuration = 0 + extendedBolusAmount = 0.0 + } else { + extendedBolusStart = eb.timestamp + extendedBolusDuration = eb.duration + extendedBolusAmount = eb.amount + } + } + + var isDualBolusInProgress = false // Profile R,RSv1 var units = 0 @@ -179,7 +273,6 @@ class DanaPump @Inject constructor( } var bolusStartErrorCode: Int = 0 // last start bolus erroCode - var historyDoneReceived: Boolean = false // true when last history message is received var bolusingTreatment: EventOverviewBolusProgress.Treatment? = null // actually delivered treatment var bolusAmountToBeDelivered = 0.0 // amount to be delivered var bolusProgressLastTimeStamp: Long = 0 // timestamp of last bolus progress message @@ -188,7 +281,7 @@ class DanaPump @Inject constructor( var bolusDone = false // success end var lastEventTimeLoaded: Long = 0 // timestamp of last received event - val lastKnownHistoryId: Int = 0 // hwver 7+, 1-2000 + // val lastKnownHistoryId: Int = 0 // hwver 7+, 1-2000 fun createConvertedProfile(): ProfileStore? { pumpProfiles?.let { @@ -279,6 +372,7 @@ class DanaPump @Inject constructor( aapsLogger.debug(LTag.PUMP, "DanaRPump reset") lastConnection = 0 lastSettingsRead = 0 + lastHistoryFetched = 0 } fun modelFriendlyName(): String = diff --git a/dana/src/main/res/values/strings.xml b/dana/src/main/res/values/strings.xml index c6ec142c94..131e23c744 100644 --- a/dana/src/main/res/values/strings.xml +++ b/dana/src/main/res/values/strings.xml @@ -120,7 +120,6 @@ Pump password (v1 only) Pump password Use extended boluses for >200%% - Visualize extended bolus as %% Bolus speed Selected pump Log reservoir change diff --git a/dana/src/test/java/info/nightscout/androidaps/dana/DanaPumpTest.kt b/dana/src/test/java/info/nightscout/androidaps/dana/DanaPumpTest.kt index 69d35cc180..fe5e5e61df 100644 --- a/dana/src/test/java/info/nightscout/androidaps/dana/DanaPumpTest.kt +++ b/dana/src/test/java/info/nightscout/androidaps/dana/DanaPumpTest.kt @@ -18,7 +18,7 @@ class DanaPumpTest : TestBaseWithProfile() { @Before fun setup() { - sut = DanaPump(aapsLogger, sp, profileInjector) + sut = DanaPump(aapsLogger, sp, dateUtil, profileInjector) } @Test diff --git a/danar/src/main/java/info/nightscout/androidaps/danaRKorean/DanaRKoreanPlugin.java b/danar/src/main/java/info/nightscout/androidaps/danaRKorean/DanaRKoreanPlugin.java index acb9ea580c..5515253904 100644 --- a/danar/src/main/java/info/nightscout/androidaps/danaRKorean/DanaRKoreanPlugin.java +++ b/danar/src/main/java/info/nightscout/androidaps/danaRKorean/DanaRKoreanPlugin.java @@ -19,8 +19,6 @@ import info.nightscout.androidaps.danar.R; import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.PumpEnactResult; -import info.nightscout.androidaps.db.ExtendedBolus; -import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.interfaces.ActivePluginProvider; @@ -96,7 +94,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin { boolean previousValue = useExtendedBoluses; useExtendedBoluses = sp.getBoolean(R.string.key_danar_useextended, false); - if (useExtendedBoluses != previousValue && activePlugin.getActiveTreatments().isInHistoryExtendedBolusInProgress()) { + if (useExtendedBoluses != previousValue && pumpSync.expectedPumpState().getExtendedBolus() != null) { sExecutionService.extendedBolusStop(); } } @@ -225,18 +223,14 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin { final boolean doHighTemp = absoluteRate > getBaseBasalRate() && !useExtendedBoluses; final boolean doExtendedTemp = absoluteRate > getBaseBasalRate() && useExtendedBoluses; - long now = System.currentTimeMillis(); - TemporaryBasal activeTemp = activePlugin.getActiveTreatments().getRealTempBasalFromHistory(now); - ExtendedBolus activeExtended = activePlugin.getActiveTreatments().getExtendedBolusFromHistory(now); - if (doTempOff) { // If extended in progress - if (activeExtended != null && useExtendedBoluses) { + if (danaPump.isExtendedInProgress() && useExtendedBoluses) { aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Stopping extended bolus (doTempOff)"); return cancelExtendedBolus(); } // If temp in progress - if (activeTemp != null) { + if (danaPump.isTempBasalInProgress()) { aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Stopping temp basal (doTempOff)"); return cancelRealTempBasal(); } @@ -257,7 +251,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin { aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Calculated percent rate: " + percentRate); // If extended in progress - if (activeExtended != null && useExtendedBoluses) { + if (danaPump.isExtendedInProgress() && useExtendedBoluses) { aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Stopping extended bolus (doLowTemp || doHighTemp)"); result = cancelExtendedBolus(); if (!result.getSuccess()) { @@ -266,14 +260,14 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin { } } // Check if some temp is already in progress - if (activeTemp != null) { + if (danaPump.isTempBasalInProgress()) { // Correct basal already set ? - aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: currently running: " + activeTemp.toString()); - if (activeTemp.percentRate == percentRate && activeTemp.getPlannedRemainingMinutes() > 4) { + aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: currently running: " + danaPump.getTempBasalPercent() + "%"); + if (danaPump.getTempBasalPercent() == percentRate && danaPump.getTempBasalRemainingMin() > 4) { if (enforceNew) { cancelTempBasal(true); } else { - result.success(true).percent(percentRate).enacted(false).duration(activeTemp.getPlannedRemainingMinutes()).isPercent(true).isTempCancel(false); + result.success(true).percent(percentRate).enacted(false).duration(danaPump.getTempBasalRemainingMin()).isPercent(true).isTempCancel(false); aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Correct temp basal already set (doLowTemp || doHighTemp)"); return result; } @@ -285,7 +279,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin { } if (doExtendedTemp) { // Check if some temp is already in progress - if (activeTemp != null) { + if (danaPump.isTempBasalInProgress()) { aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Stopping temp basal (doExtendedTemp)"); result = cancelRealTempBasal(); // Check for proper result @@ -304,11 +298,11 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin { extendedRateToSet = Round.roundTo(extendedRateToSet, pumpDescription.getExtendedBolusStep() * 2); // *2 because of half hours // What is current rate of extended bolusing in u/h? - aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Extended bolus in progress: " + (activeExtended != null) + " rate: " + danaPump.getExtendedBolusAbsoluteRate() + "U/h duration remaining: " + danaPump.getExtendedBolusRemainingMinutes() + "min"); + aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Extended bolus in progress: " + (danaPump.isExtendedInProgress()) + " rate: " + danaPump.getExtendedBolusAbsoluteRate() + "U/h duration remaining: " + danaPump.getExtendedBolusRemainingMinutes() + "min"); aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Rate to set: " + extendedRateToSet + "U/h"); // Compare with extended rate in progress - if (activeExtended != null && Math.abs(danaPump.getExtendedBolusAbsoluteRate() - extendedRateToSet) < getPumpDescription().getExtendedBolusStep()) { + if (danaPump.isExtendedInProgress() && Math.abs(danaPump.getExtendedBolusAbsoluteRate() - extendedRateToSet) < getPumpDescription().getExtendedBolusStep()) { // correct extended already set result.success(true).absolute(danaPump.getExtendedBolusAbsoluteRate()).enacted(false).duration(danaPump.getExtendedBolusRemainingMinutes()).isPercent(false).isTempCancel(false); aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Correct extended already set"); @@ -335,9 +329,9 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin { @NonNull @Override public PumpEnactResult cancelTempBasal(boolean force) { - if (activePlugin.getActiveTreatments().isInHistoryRealTempBasalInProgress()) + if (danaPump.isTempBasalInProgress()) return cancelRealTempBasal(); - if (activePlugin.getActiveTreatments().isInHistoryExtendedBolusInProgress() && useExtendedBoluses) { + if (danaPump.isExtendedInProgress() && useExtendedBoluses) { return cancelExtendedBolus(); } PumpEnactResult result = new PumpEnactResult(getInjector()); @@ -352,17 +346,12 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin { private PumpEnactResult cancelRealTempBasal() { PumpEnactResult result = new PumpEnactResult(getInjector()); - TemporaryBasal runningTB = activePlugin.getActiveTreatments().getTempBasalFromHistory(System.currentTimeMillis()); - if (runningTB != null) { + if (danaPump.isTempBasalInProgress()) { sExecutionService.tempBasalStop(); result.enacted(true).isTempCancel(true); - } - if (!danaPump.isTempBasalInProgress()) { + } else { result.success(true).isTempCancel(true).comment(R.string.ok); aapsLogger.debug(LTag.PUMP, "cancelRealTempBasal: OK"); - } else { - result.success(false).comment(R.string.danar_valuenotsetproperly).isTempCancel(true); - aapsLogger.error("cancelRealTempBasal: Failed to cancel temp basal"); } return result; } diff --git a/danar/src/main/java/info/nightscout/androidaps/danaRKorean/comm/MsgStatus_k.kt b/danar/src/main/java/info/nightscout/androidaps/danaRKorean/comm/MsgStatus_k.kt index 0f0815bd93..0138c65ee3 100644 --- a/danar/src/main/java/info/nightscout/androidaps/danaRKorean/comm/MsgStatus_k.kt +++ b/danar/src/main/java/info/nightscout/androidaps/danaRKorean/comm/MsgStatus_k.kt @@ -15,9 +15,9 @@ class MsgStatus_k( override fun handleMessage(bytes: ByteArray) { danaPump.dailyTotalUnits = intFromBuff(bytes, 0, 3) / 750.0 - danaPump.isExtendedInProgress = intFromBuff(bytes, 3, 1) == 1 - danaPump.extendedBolusMinutes = intFromBuff(bytes, 4, 2) - danaPump.extendedBolusAmount = intFromBuff(bytes, 6, 2) / 100.0 + val isExtendedInProgress = intFromBuff(bytes, 3, 1) == 1 + val extendedBolusMinutes = intFromBuff(bytes, 4, 2) + val extendedBolusAmount = intFromBuff(bytes, 6, 2) / 100.0 //val lastBolusAmount = intFromBuff(bytes, 13, 2) / 100.0 //if (lastBolusAmount != 0d) { // pump.lastBolusTime = dateTimeFromBuff(bytes, 8); @@ -25,9 +25,9 @@ class MsgStatus_k( //} danaPump.iob = intFromBuff(bytes, 15, 2) / 100.0 aapsLogger.debug(LTag.PUMPCOMM, "Daily total: " + danaPump.dailyTotalUnits) - aapsLogger.debug(LTag.PUMPCOMM, "Is extended bolus running: " + danaPump.isExtendedInProgress) - aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus min: " + danaPump.extendedBolusMinutes) - aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus amount: " + danaPump.extendedBolusAmount) + aapsLogger.debug(LTag.PUMPCOMM, "Is extended bolus running: $isExtendedInProgress") + aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus min: $extendedBolusMinutes") + aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus amount: $extendedBolusAmount") //aapsLogger.debug(LTag.PUMPCOMM, "Last bolus time: " + pump.lastBolusTime); //aapsLogger.debug(LTag.PUMPCOMM, "Last bolus amount: " + pump.lastBolusAmount); aapsLogger.debug(LTag.PUMPCOMM, "IOB: " + danaPump.iob) diff --git a/danar/src/main/java/info/nightscout/androidaps/danaRKorean/services/DanaRKoreanExecutionService.java b/danar/src/main/java/info/nightscout/androidaps/danaRKorean/services/DanaRKoreanExecutionService.java index 2d7ea60435..735eaa3c77 100644 --- a/danar/src/main/java/info/nightscout/androidaps/danaRKorean/services/DanaRKoreanExecutionService.java +++ b/danar/src/main/java/info/nightscout/androidaps/danaRKorean/services/DanaRKoreanExecutionService.java @@ -171,7 +171,7 @@ public class DanaRKoreanExecutionService extends AbstractDanaRExecutionService { rxBus.send(new EventPumpStatusChanged(resourceHelper.gs(R.string.gettingpumptime))); mSerialIOThread.sendMessage(new MsgSettingPumpTime(injector)); if (danaPump.getPumpTime() == 0) { - // initial handshake was not successfull + // initial handshake was not successful // deinitialize pump danaPump.reset(); rxBus.send(new EventDanaRNewStatus()); @@ -182,7 +182,7 @@ public class DanaRKoreanExecutionService extends AbstractDanaRExecutionService { aapsLogger.debug(LTag.PUMP, "Pump time difference: " + timeDiff + " seconds"); if (Math.abs(timeDiff) > 10) { waitForWholeMinute(); // Dana can set only whole minute - // add 10sec to be sure we are over minute (will be cutted off anyway) + // add 10sec to be sure we are over minute (will be cut off anyway) mSerialIOThread.sendMessage(new MsgSetTime(injector, DateUtil.now() + T.secs(10).msecs())); mSerialIOThread.sendMessage(new MsgSettingPumpTime(injector)); timeDiff = (danaPump.getPumpTime() - System.currentTimeMillis()) / 1000L; @@ -203,6 +203,8 @@ public class DanaRKoreanExecutionService extends AbstractDanaRExecutionService { lastApproachingDailyLimit = System.currentTimeMillis(); } } + + doSanityCheck(); } catch (Exception e) { aapsLogger.error("Unhandled exception", e); } diff --git a/danar/src/main/java/info/nightscout/androidaps/danaRv2/DanaRv2Plugin.java b/danar/src/main/java/info/nightscout/androidaps/danaRv2/DanaRv2Plugin.java index 25d4af08f5..cdec52119c 100644 --- a/danar/src/main/java/info/nightscout/androidaps/danaRv2/DanaRv2Plugin.java +++ b/danar/src/main/java/info/nightscout/androidaps/danaRv2/DanaRv2Plugin.java @@ -19,7 +19,6 @@ import info.nightscout.androidaps.danar.R; import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.PumpEnactResult; -import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.interfaces.ActivePluginProvider; import info.nightscout.androidaps.interfaces.CommandQueueProvider; @@ -31,6 +30,7 @@ import info.nightscout.androidaps.plugins.bus.RxBusWrapper; import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker; import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress; import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInfoStorage; +import info.nightscout.androidaps.plugins.pump.common.bolusInfo.TemporaryBasalStorage; import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.FabricPrivacy; @@ -50,10 +50,10 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin { private final ResourceHelper resourceHelper; private final ConstraintChecker constraintChecker; private final DetailedBolusInfoStorage detailedBolusInfoStorage; + private final TemporaryBasalStorage temporaryBasalStorage; private final FabricPrivacy fabricPrivacy; public long lastEventTimeLoaded = 0; - public boolean eventsLoadingDone = false; @Inject public DanaRv2Plugin( @@ -69,6 +69,7 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin { SP sp, CommandQueueProvider commandQueue, DetailedBolusInfoStorage detailedBolusInfoStorage, + TemporaryBasalStorage temporaryBasalStorage, DateUtil dateUtil, FabricPrivacy fabricPrivacy, PumpSync pumpSync @@ -79,6 +80,7 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin { this.resourceHelper = resourceHelper; this.constraintChecker = constraintChecker; this.detailedBolusInfoStorage = detailedBolusInfoStorage; + this.temporaryBasalStorage = temporaryBasalStorage; this.fabricPrivacy = fabricPrivacy; getPluginDescription().description(R.string.description_pump_dana_r_v2); @@ -230,7 +232,7 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin { if (doTempOff) { // If temp in progress - if (activePlugin.getActiveTreatments().isTempBasalInProgress()) { + if (danaPump.isTempBasalInProgress()) { aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Stopping temp basal (doTempOff)"); return cancelTempBasal(false); } @@ -248,17 +250,17 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin { if (percentRate > 500) // Special high temp 500/15min percentRate = 500; // Check if some temp is already in progress - TemporaryBasal activeTemp = activePlugin.getActiveTreatments().getTempBasalFromHistory(System.currentTimeMillis()); - if (activeTemp != null) { + if (danaPump.isTempBasalInProgress()) { // Correct basal already set ? - if (activeTemp.percentRate == percentRate && activeTemp.getPlannedRemainingMinutes() > 4) { + if (danaPump.getTempBasalPercent() == percentRate && danaPump.getTempBasalRemainingMin() > 4) { if (!enforceNew) { - result.success(true).percent(percentRate).enacted(false).duration(activeTemp.getPlannedRemainingMinutes()).isPercent(true).isTempCancel(false); + result.success(true).percent(percentRate).enacted(false).duration(danaPump.getTempBasalRemainingMin()).isPercent(true).isTempCancel(false); aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Correct temp basal already set (doLowTemp || doHighTemp)"); return result; } } } + temporaryBasalStorage.add(new PumpSync.PumpState.TemporaryBasal(dateUtil._now(), T.mins(durationInMinutes).msecs(), percentRate, false, tbrType, 0L, 0L)); // Convert duration from minutes to hours aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Setting temp basal " + percentRate + "% for " + durationInMinutes + " minutes (doLowTemp || doHighTemp)"); if (percentRate == 0 && durationInMinutes > 30) { @@ -292,13 +294,12 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin { } if (percent > getPumpDescription().getMaxTempPercent()) percent = getPumpDescription().getMaxTempPercent(); - long now = System.currentTimeMillis(); - TemporaryBasal activeTemp = activePlugin.getActiveTreatments().getRealTempBasalFromHistory(now); - if (activeTemp != null && activeTemp.percentRate == percent && activeTemp.getPlannedRemainingMinutes() > 4 && !enforceNew) { + if (danaPump.isTempBasalInProgress() && danaPump.getTempBasalPercent() == percent && danaPump.getTempBasalRemainingMin() > 4 && !enforceNew) { result.enacted(false).success(true).isTempCancel(false).comment(R.string.ok).duration(pump.getTempBasalRemainingMin()).percent(pump.getTempBasalPercent()).isPercent(true); aapsLogger.debug(LTag.PUMP, "setTempBasalPercent: Correct value already set"); return result; } + temporaryBasalStorage.add(new PumpSync.PumpState.TemporaryBasal(dateUtil._now(), T.mins(durationInMinutes).msecs(), percent, false, tbrType, 0L, 0L)); boolean connectionOK; if (durationInMinutes == 15 || durationInMinutes == 30) { connectionOK = sExecutionService.tempBasalShortDuration(percent, durationInMinutes); @@ -333,17 +334,12 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin { @NonNull @Override public PumpEnactResult cancelTempBasal(boolean force) { PumpEnactResult result = new PumpEnactResult(getInjector()); - TemporaryBasal runningTB = activePlugin.getActiveTreatments().getTempBasalFromHistory(System.currentTimeMillis()); - if (runningTB != null) { + if (danaPump.isTempBasalInProgress()) { sExecutionService.tempBasalStop(); result.enacted(true).isTempCancel(true); - } - if (!danaPump.isTempBasalInProgress()) { + } else { result.success(true).isTempCancel(true).comment(R.string.ok); aapsLogger.debug(LTag.PUMP, "cancelRealTempBasal: OK"); - } else { - result.success(false).comment(R.string.danar_valuenotsetproperly).isTempCancel(true); - aapsLogger.error("cancelRealTempBasal: Failed to cancel temp basal"); } return result; } diff --git a/danar/src/main/java/info/nightscout/androidaps/danaRv2/comm/MessageHashTableRv2.kt b/danar/src/main/java/info/nightscout/androidaps/danaRv2/comm/MessageHashTableRv2.kt index 89764534d6..05ca40da1d 100644 --- a/danar/src/main/java/info/nightscout/androidaps/danaRv2/comm/MessageHashTableRv2.kt +++ b/danar/src/main/java/info/nightscout/androidaps/danaRv2/comm/MessageHashTableRv2.kt @@ -19,8 +19,8 @@ class MessageHashTableRv2 @Inject constructor( put(MsgBolusStartWithSpeed(injector, 0.0, 0)) // 0x0104 CMD_MEALINS_START_DATA_SPEED put(MsgBolusProgress(injector)) // 0x0202 CMD_PUMP_THIS_REMAINDER_MEAL_INS put(MsgStatusProfile(injector)) // 0x0204 CMD_PUMP_CALCULATION_SETTING - put(MsgStatusTempBasal_v2(injector)) // 0x0205 CMD_PUMP_EXERCISE_MODE - put(MsgStatusBolusExtended_v2(injector)) // 0x0207 CMD_PUMP_EXPANS_INS_I + put(MsgStatusTempBasal(injector)) // 0x0205 CMD_PUMP_EXERCISE_MODE + put(MsgStatusBolusExtended(injector)) // 0x0207 CMD_PUMP_EXPANS_INS_I put(MsgStatusBasic(injector)) // 0x020A CMD_PUMP_INITVIEW_I put(MsgStatus(injector)) // 0x020B CMD_PUMP_STATUS put(MsgInitConnStatusTime(injector)) // 0x0301 CMD_PUMPINIT_TIME_INFO diff --git a/danar/src/main/java/info/nightscout/androidaps/danaRv2/comm/MsgHistoryEvents_v2.kt b/danar/src/main/java/info/nightscout/androidaps/danaRv2/comm/MsgHistoryEvents_v2.kt index 5c939bda8d..34ebfb0787 100644 --- a/danar/src/main/java/info/nightscout/androidaps/danaRv2/comm/MsgHistoryEvents_v2.kt +++ b/danar/src/main/java/info/nightscout/androidaps/danaRv2/comm/MsgHistoryEvents_v2.kt @@ -3,20 +3,23 @@ package info.nightscout.androidaps.danaRv2.comm import dagger.android.HasAndroidInjector import info.nightscout.androidaps.danar.R import info.nightscout.androidaps.danar.comm.MessageBase -import info.nightscout.androidaps.db.ExtendedBolus -import info.nightscout.androidaps.db.Source -import info.nightscout.androidaps.db.TemporaryBasal import info.nightscout.androidaps.events.EventPumpStatusChanged import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.pump.common.defs.PumpType import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.T import java.util.* class MsgHistoryEvents_v2 constructor( - private val injector: HasAndroidInjector, + injector: HasAndroidInjector, var from: Long = 0 ) : MessageBase(injector) { + companion object { + + var messageBuffer = arrayListOf() // for reversing order of incoming messages + } + init { SetCommand(0xE003) if (from > DateUtil.now()) { @@ -34,57 +37,84 @@ class MsgHistoryEvents_v2 constructor( gfrom.timeInMillis = from AddParamDate(gfrom) } - danaRv2Plugin.eventsLoadingDone = false - aapsLogger.debug(LTag.PUMPBTCOMM, "New message") + aapsLogger.debug(LTag.PUMPCOMM, "Loading event history from: " + dateUtil.dateAndTimeString(from)) + danaPump.historyDoneReceived = false + messageBuffer = arrayListOf() } - override fun handleMessage(bytes: ByteArray) { + override fun handleMessage(data: ByteArray) { + val recordCode = intFromBuff(data, 0, 1).toByte() + // Last record + if (recordCode == 0xFF.toByte()) { + aapsLogger.debug(LTag.PUMPCOMM, "Last record received") + + val array: Array = messageBuffer.toTypedArray() + val sorted = array.sortedArrayWith { s1: ByteArray, s2: ByteArray -> (dateTime(s1) - dateTime(s2)).toInt() } + for (message in sorted) processMessage(message) + danaPump.historyDoneReceived = true + } else messageBuffer.add(data) + } + + fun dateTime(data: ByteArray): Long = + dateTimeSecFromBuff(data, 1) // 6 bytes + + fun processMessage(bytes: ByteArray) { val recordCode = intFromBuff(bytes, 0, 1).toByte() // Last record if (recordCode == 0xFF.toByte()) { - danaRv2Plugin.eventsLoadingDone = true return } - danaRv2Plugin.eventsLoadingDone = false val datetime = dateTimeSecFromBuff(bytes, 1) // 6 bytes val param1 = intFromBuff(bytes, 7, 2) val param2 = intFromBuff(bytes, 9, 2) - val temporaryBasal = TemporaryBasal(injector) - .date(datetime) - .source(Source.PUMP) - .pumpId(datetime) - val extendedBolus = ExtendedBolus(injector) - .date(datetime) - .source(Source.PUMP) - .pumpId(datetime) val status: String when (recordCode.toInt()) { info.nightscout.androidaps.dana.DanaPump.TEMPSTART -> { aapsLogger.debug(LTag.PUMPBTCOMM, "EVENT TEMPSTART (" + recordCode + ") " + dateUtil.dateAndTimeString(datetime) + " (" + datetime + ")" + " Ratio: " + param1 + "% Duration: " + param2 + "min") - temporaryBasal.percentRate = param1 - temporaryBasal.durationInMinutes = param2 - activePlugin.activeTreatments.addToHistoryTempBasal(temporaryBasal) + val temporaryBasalInfo = temporaryBasalStorage.findTemporaryBasal(datetime, param1.toDouble()) + pumpSync.syncTemporaryBasalWithPumpId( + timestamp = datetime, + rate = param1.toDouble(), + duration = T.mins(param2.toLong()).msecs(), + isAbsolute = false, + type = temporaryBasalInfo?.type, + pumpId = datetime, + pumpType = PumpType.DANA_RV2, + pumpSerial = danaPump.serialNumber) status = "TEMPSTART " + dateUtil.timeString(datetime) } info.nightscout.androidaps.dana.DanaPump.TEMPSTOP -> { aapsLogger.debug(LTag.PUMPBTCOMM, "EVENT TEMPSTOP (" + recordCode + ") " + dateUtil.dateAndTimeString(datetime)) - activePlugin.activeTreatments.addToHistoryTempBasal(temporaryBasal) + pumpSync.syncStopTemporaryBasalWithPumpId( + timestamp = datetime, + endPumpId = datetime, + pumpType = PumpType.DANA_RV2, + pumpSerial = danaPump.serialNumber) status = "TEMPSTOP " + dateUtil.timeString(datetime) } info.nightscout.androidaps.dana.DanaPump.EXTENDEDSTART -> { - aapsLogger.debug(LTag.PUMPBTCOMM, "EVENT EXTENDEDSTART (" + recordCode + ") " + dateUtil.dateAndTimeString(datetime) + " (" + datetime + ")" + " Amount: " + param1 / 100.0 + "U Duration: " + param2 + "min") - extendedBolus.insulin = param1 / 100.0 - extendedBolus.durationInMinutes = param2 - activePlugin.activeTreatments.addToHistoryExtendedBolus(extendedBolus) + val newRecord = pumpSync.syncExtendedBolusWithPumpId( + timestamp = datetime, + amount = param1 / 100.0, + duration = T.mins(param2.toLong()).msecs(), + isEmulatingTB = false, + pumpId = datetime, + pumpType = PumpType.DANA_RV2, + pumpSerial = danaPump.serialNumber) + aapsLogger.debug(LTag.PUMPBTCOMM, (if (newRecord) "**NEW** " else "") + "EVENT EXTENDEDSTART (" + recordCode + ") " + dateUtil.dateAndTimeString(datetime) + " (" + datetime + ")" + " Amount: " + param1 / 100.0 + "U Duration: " + param2 + "min") status = "EXTENDEDSTART " + dateUtil.timeString(datetime) } info.nightscout.androidaps.dana.DanaPump.EXTENDEDSTOP -> { - aapsLogger.debug(LTag.PUMPBTCOMM, "EVENT EXTENDEDSTOP (" + recordCode + ") " + dateUtil.dateAndTimeString(datetime) + " (" + datetime + ")" + " Delivered: " + param1 / 100.0 + "U RealDuration: " + param2 + "min") - activePlugin.activeTreatments.addToHistoryExtendedBolus(extendedBolus) + val newRecord = pumpSync.syncStopExtendedBolusWithPumpId( + timestamp = datetime, + endPumpId = datetime, + pumpType = PumpType.DANA_RV2, + pumpSerial = danaPump.serialNumber) + aapsLogger.debug(LTag.PUMPBTCOMM, (if (newRecord) "**NEW** " else "") + "EVENT EXTENDEDSTOP (" + recordCode + ") " + dateUtil.dateAndTimeString(datetime) + " (" + datetime + ")" + " Delivered: " + param1 / 100.0 + "U RealDuration: " + param2 + "min") status = "EXTENDEDSTOP " + dateUtil.timeString(datetime) } @@ -115,16 +145,25 @@ class MsgHistoryEvents_v2 constructor( } info.nightscout.androidaps.dana.DanaPump.DUALEXTENDEDSTART -> { - aapsLogger.debug(LTag.PUMPBTCOMM, "EVENT DUALEXTENDEDSTART (" + recordCode + ") " + dateUtil.dateAndTimeString(datetime) + " (" + datetime + ")" + " Amount: " + param1 / 100.0 + "U Duration: " + param2 + "min") - extendedBolus.insulin = param1 / 100.0 - extendedBolus.durationInMinutes = param2 - activePlugin.activeTreatments.addToHistoryExtendedBolus(extendedBolus) + val newRecord = pumpSync.syncExtendedBolusWithPumpId( + timestamp = datetime, + amount = param1 / 100.0, + duration = T.mins(param2.toLong()).msecs(), + isEmulatingTB = false, + pumpId = datetime, + pumpType = PumpType.DANA_RV2, + pumpSerial = danaPump.serialNumber) + aapsLogger.debug(LTag.PUMPBTCOMM, (if (newRecord) "**NEW** " else "") + "EVENT DUALEXTENDEDSTART (" + recordCode + ") " + dateUtil.dateAndTimeString(datetime) + " (" + datetime + ")" + " Amount: " + param1 / 100.0 + "U Duration: " + param2 + "min") status = "DUALEXTENDEDSTART " + dateUtil.timeString(datetime) } info.nightscout.androidaps.dana.DanaPump.DUALEXTENDEDSTOP -> { - aapsLogger.debug(LTag.PUMPBTCOMM, "EVENT DUALEXTENDEDSTOP (" + recordCode + ") " + dateUtil.dateAndTimeString(datetime) + " (" + datetime + ")" + " Delivered: " + param1 / 100.0 + "U RealDuration: " + param2 + "min") - activePlugin.activeTreatments.addToHistoryExtendedBolus(extendedBolus) + val newRecord = pumpSync.syncStopExtendedBolusWithPumpId( + timestamp = datetime, + endPumpId = datetime, + pumpType = PumpType.DANA_RV2, + pumpSerial = danaPump.serialNumber) + aapsLogger.debug(LTag.PUMPBTCOMM, (if (newRecord) "**NEW** " else "") + "EVENT DUALEXTENDEDSTOP (" + recordCode + ") " + dateUtil.dateAndTimeString(datetime) + " (" + datetime + ")" + " Delivered: " + param1 / 100.0 + "U RealDuration: " + param2 + "min") status = "DUALEXTENDEDSTOP " + dateUtil.timeString(datetime) } @@ -169,7 +208,7 @@ class MsgHistoryEvents_v2 constructor( status = "UNKNOWN " + dateUtil.timeString(datetime) } } - if (datetime > danaRv2Plugin.lastEventTimeLoaded) danaRv2Plugin.lastEventTimeLoaded = datetime + if (datetime > danaPump.lastEventTimeLoaded) danaPump.lastEventTimeLoaded = datetime rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.processinghistory) + ": " + status)) } } \ No newline at end of file diff --git a/danar/src/main/java/info/nightscout/androidaps/danaRv2/comm/MsgStatusBolusExtended_v2.kt b/danar/src/main/java/info/nightscout/androidaps/danaRv2/comm/MsgStatusBolusExtended_v2.kt deleted file mode 100644 index f0afbabcb2..0000000000 --- a/danar/src/main/java/info/nightscout/androidaps/danaRv2/comm/MsgStatusBolusExtended_v2.kt +++ /dev/null @@ -1,49 +0,0 @@ -package info.nightscout.androidaps.danaRv2.comm - -import dagger.android.HasAndroidInjector -import info.nightscout.androidaps.danar.comm.MessageBase -import info.nightscout.androidaps.logging.LTag -import kotlin.math.ceil - -class MsgStatusBolusExtended_v2( - injector: HasAndroidInjector -) : MessageBase(injector) { - - init { - SetCommand(0x0207) - aapsLogger.debug(LTag.PUMPCOMM, "New message") - } - - override fun handleMessage(bytes: ByteArray) { - val isExtendedInProgress = intFromBuff(bytes, 0, 1) == 1 - val extendedBolusHalfHours = intFromBuff(bytes, 1, 1) - val extendedBolusMinutes = extendedBolusHalfHours * 30 - val extendedBolusAmount = intFromBuff(bytes, 2, 2) / 100.0 - val extendedBolusSoFarInSecs = intFromBuff(bytes, 4, 3) - // This is available only on korean, but not needed now -// int extendedBolusDeliveryPulse = intFromBuff(bytes, 7, 2); -// int isEasyUIUserSleep = intFromBuff(bytes, 9, 1); - val extendedBolusSoFarInMinutes = extendedBolusSoFarInSecs / 60 - val extendedBolusAbsoluteRate = if (isExtendedInProgress) extendedBolusAmount / extendedBolusMinutes * 60 else 0.0 - val extendedBolusStart = if (isExtendedInProgress) getDateFromSecAgo(extendedBolusSoFarInSecs) else 0 - val extendedBolusRemainingMinutes = extendedBolusMinutes - extendedBolusSoFarInMinutes - danaPump.isExtendedInProgress = isExtendedInProgress - danaPump.extendedBolusMinutes = extendedBolusMinutes - danaPump.extendedBolusAmount = extendedBolusAmount - danaPump.extendedBolusSoFarInMinutes = extendedBolusSoFarInMinutes - danaPump.extendedBolusAbsoluteRate = extendedBolusAbsoluteRate - danaPump.extendedBolusStart = extendedBolusStart - danaPump.extendedBolusRemainingMinutes = extendedBolusRemainingMinutes - aapsLogger.debug(LTag.PUMPCOMM, "Is extended bolus running: $isExtendedInProgress") - aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus min: $extendedBolusMinutes") - aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus amount: $extendedBolusAmount") - aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus so far in minutes: $extendedBolusSoFarInMinutes") - aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus absolute rate: $extendedBolusAbsoluteRate") - aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus start: $extendedBolusStart") - aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus remaining minutes: $extendedBolusRemainingMinutes") - } - - private fun getDateFromSecAgo(tempBasalAgoSecs: Int): Long { - return (ceil(System.currentTimeMillis() / 1000.0) - tempBasalAgoSecs).toLong() * 1000 - } -} \ No newline at end of file diff --git a/danar/src/main/java/info/nightscout/androidaps/danaRv2/comm/MsgStatusTempBasal_v2.kt b/danar/src/main/java/info/nightscout/androidaps/danaRv2/comm/MsgStatusTempBasal_v2.kt deleted file mode 100644 index 53f2c81e1d..0000000000 --- a/danar/src/main/java/info/nightscout/androidaps/danaRv2/comm/MsgStatusTempBasal_v2.kt +++ /dev/null @@ -1,42 +0,0 @@ -package info.nightscout.androidaps.danaRv2.comm - -import dagger.android.HasAndroidInjector -import info.nightscout.androidaps.danar.comm.MessageBase -import info.nightscout.androidaps.logging.LTag -import kotlin.math.ceil - -class MsgStatusTempBasal_v2( - injector: HasAndroidInjector -) : MessageBase(injector) { - - init { - SetCommand(0x0205) - aapsLogger.debug(LTag.PUMPCOMM, "New message") - } - - override fun handleMessage(bytes: ByteArray) { - val isTempBasalInProgress = intFromBuff(bytes, 0, 1) and 0x01 == 0x01 - val isAPSTempBasalInProgress = intFromBuff(bytes, 0, 1) and 0x02 == 0x02 - var tempBasalPercent = intFromBuff(bytes, 1, 1) - if (tempBasalPercent > 200) tempBasalPercent = (tempBasalPercent - 200) * 10 - val tempBasalTotalSec: Int = if (intFromBuff(bytes, 2, 1) == 150) 15 * 60 else if (intFromBuff(bytes, 2, 1) == 160) 30 * 60 else intFromBuff(bytes, 2, 1) * 60 * 60 - val tempBasalRunningSeconds = intFromBuff(bytes, 3, 3) - val tempBasalRemainingMin = (tempBasalTotalSec - tempBasalRunningSeconds) / 60 - val tempBasalStart = if (isTempBasalInProgress) getDateFromTempBasalSecAgo(tempBasalRunningSeconds) else 0 - danaPump.isTempBasalInProgress = isTempBasalInProgress - danaPump.tempBasalPercent = tempBasalPercent - danaPump.tempBasalRemainingMin = tempBasalRemainingMin - danaPump.tempBasalTotalSec = tempBasalTotalSec - danaPump.tempBasalStart = tempBasalStart - aapsLogger.debug(LTag.PUMPCOMM, "Is temp basal running: $isTempBasalInProgress") - aapsLogger.debug(LTag.PUMPCOMM, "Is APS temp basal running: $isAPSTempBasalInProgress") - aapsLogger.debug(LTag.PUMPCOMM, "Current temp basal percent: $tempBasalPercent") - aapsLogger.debug(LTag.PUMPCOMM, "Current temp basal remaining min: $tempBasalRemainingMin") - aapsLogger.debug(LTag.PUMPCOMM, "Current temp basal total sec: $tempBasalTotalSec") - aapsLogger.debug(LTag.PUMPCOMM, "Current temp basal start: " + dateUtil.dateAndTimeString(tempBasalStart)) - } - - private fun getDateFromTempBasalSecAgo(tempBasalAgoSecs: Int): Long { - return (ceil(System.currentTimeMillis() / 1000.0) - tempBasalAgoSecs).toLong() * 1000 - } -} \ No newline at end of file diff --git a/danar/src/main/java/info/nightscout/androidaps/danaRv2/services/DanaRv2ExecutionService.java b/danar/src/main/java/info/nightscout/androidaps/danaRv2/services/DanaRv2ExecutionService.java index 17384b1161..a88a52346f 100644 --- a/danar/src/main/java/info/nightscout/androidaps/danaRv2/services/DanaRv2ExecutionService.java +++ b/danar/src/main/java/info/nightscout/androidaps/danaRv2/services/DanaRv2ExecutionService.java @@ -20,9 +20,6 @@ import info.nightscout.androidaps.danaRv2.comm.MsgCheckValue_v2; import info.nightscout.androidaps.danaRv2.comm.MsgHistoryEvents_v2; import info.nightscout.androidaps.danaRv2.comm.MsgSetAPSTempBasalStart_v2; import info.nightscout.androidaps.danaRv2.comm.MsgSetHistoryEntry_v2; -import info.nightscout.androidaps.danaRv2.comm.MsgStatusBolusExtended_v2; -import info.nightscout.androidaps.danaRv2.comm.MsgStatusTempBasal_v2; -import info.nightscout.androidaps.danar.DanaRPlugin; import info.nightscout.androidaps.danar.R; import info.nightscout.androidaps.danar.SerialIOThread; import info.nightscout.androidaps.danar.comm.MessageBase; @@ -49,6 +46,8 @@ import info.nightscout.androidaps.danar.comm.MsgSettingShippingInfo; import info.nightscout.androidaps.danar.comm.MsgSettingUserOptions; import info.nightscout.androidaps.danar.comm.MsgStatus; import info.nightscout.androidaps.danar.comm.MsgStatusBasic; +import info.nightscout.androidaps.danar.comm.MsgStatusBolusExtended; +import info.nightscout.androidaps.danar.comm.MsgStatusTempBasal; import info.nightscout.androidaps.danar.services.AbstractDanaRExecutionService; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.PumpEnactResult; @@ -58,18 +57,15 @@ import info.nightscout.androidaps.events.EventProfileNeedsUpdate; import info.nightscout.androidaps.events.EventPumpStatusChanged; import info.nightscout.androidaps.interfaces.ActivePluginProvider; import info.nightscout.androidaps.interfaces.CommandQueueProvider; -import info.nightscout.androidaps.interfaces.ConfigBuilderInterface; import info.nightscout.androidaps.interfaces.ProfileFunction; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpSync; import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.logging.LTag; import info.nightscout.androidaps.plugins.bus.RxBusWrapper; -import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker; import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress; import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; -import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInfoStorage; import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; import info.nightscout.androidaps.queue.Callback; import info.nightscout.androidaps.queue.commands.Command; @@ -83,25 +79,18 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { @Inject AAPSLogger aapsLogger; @Inject RxBusWrapper rxBus; @Inject ResourceHelper resourceHelper; - @Inject ConstraintChecker constraintChecker; @Inject DanaPump danaPump; - @Inject DanaRPlugin danaRPlugin; @Inject DanaRKoreanPlugin danaRKoreanPlugin; @Inject DanaRv2Plugin danaRv2Plugin; @Inject ActivePluginProvider activePlugin; - @Inject ConfigBuilderInterface configBuilderPlugin; @Inject CommandQueueProvider commandQueue; @Inject Context context; @Inject MessageHashTableRv2 messageHashTableRv2; - @Inject DetailedBolusInfoStorage detailedBolusInfoStorage; - @Inject ActivePluginProvider activePluginProvider; @Inject ProfileFunction profileFunction; @Inject PumpSync pumpSync; @Inject SP sp; @Inject DateUtil dateUtil; - private long lastHistoryFetched = 0; - public DanaRv2ExecutionService() { } @@ -157,8 +146,8 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { rxBus.send(new EventPumpStatusChanged(resourceHelper.gs(R.string.gettingpumpstatus))); MsgStatus statusMsg = new MsgStatus(injector); MsgStatusBasic statusBasicMsg = new MsgStatusBasic(injector); - MsgStatusTempBasal_v2 tempStatusMsg = new MsgStatusTempBasal_v2(injector); - MsgStatusBolusExtended_v2 exStatusMsg = new MsgStatusBolusExtended_v2(injector); + MsgStatusTempBasal tempStatusMsg = new MsgStatusTempBasal(injector); + MsgStatusBolusExtended exStatusMsg = new MsgStatusBolusExtended(injector); MsgCheckValue_v2 checkValue = new MsgCheckValue_v2(injector); if (danaPump.isNewPump()) { @@ -191,8 +180,8 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { rxBus.send(new EventPumpStatusChanged(resourceHelper.gs(R.string.gettingpumptime))); mSerialIOThread.sendMessage(new MsgSettingPumpTime(injector)); if (danaPump.getPumpTime() == 0) { - // initial handshake was not successfull - // deinitialize pump + // initial handshake was not successful + // de-initialize pump danaPump.reset(); rxBus.send(new EventDanaRNewStatus()); rxBus.send(new EventInitializationChanged()); @@ -266,7 +255,7 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { } rxBus.send(new EventPumpStatusChanged(resourceHelper.gs(R.string.settingtempbasal))); mSerialIOThread.sendMessage(new MsgSetTempBasalStart(injector, percent, durationInHours)); - mSerialIOThread.sendMessage(new MsgStatusTempBasal_v2(injector)); + mSerialIOThread.sendMessage(new MsgStatusTempBasal(injector)); loadEvents(); rxBus.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)); return true; @@ -281,7 +270,7 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { } rxBus.send(new EventPumpStatusChanged(resourceHelper.gs(R.string.settingtempbasal))); mSerialIOThread.sendMessage(new MsgSetAPSTempBasalStart_v2(injector, percent, durationInMinutes == 15, durationInMinutes == 30)); - mSerialIOThread.sendMessage(new MsgStatusTempBasal_v2(injector)); + mSerialIOThread.sendMessage(new MsgStatusTempBasal(injector)); loadEvents(); rxBus.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)); return true; @@ -301,7 +290,7 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { } rxBus.send(new EventPumpStatusChanged(resourceHelper.gs(R.string.settingtempbasal))); mSerialIOThread.sendMessage(new MsgSetAPSTempBasalStart_v2(injector, percent, durationInMinutes == 15, durationInMinutes == 30)); - mSerialIOThread.sendMessage(new MsgStatusTempBasal_v2(injector)); + mSerialIOThread.sendMessage(new MsgStatusTempBasal(injector)); loadEvents(); rxBus.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)); return true; @@ -311,7 +300,7 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { if (!isConnected()) return false; rxBus.send(new EventPumpStatusChanged(resourceHelper.gs(R.string.stoppingtempbasal))); mSerialIOThread.sendMessage(new MsgSetTempBasalStop(injector)); - mSerialIOThread.sendMessage(new MsgStatusTempBasal_v2(injector)); + mSerialIOThread.sendMessage(new MsgStatusTempBasal(injector)); loadEvents(); rxBus.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)); return true; @@ -321,7 +310,7 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { if (!isConnected()) return false; rxBus.send(new EventPumpStatusChanged(resourceHelper.gs(R.string.settingextendedbolus))); mSerialIOThread.sendMessage(new MsgSetExtendedBolusStart(injector, insulin, (byte) (durationInHalfHours & 0xFF))); - mSerialIOThread.sendMessage(new MsgStatusBolusExtended_v2(injector)); + mSerialIOThread.sendMessage(new MsgStatusBolusExtended(injector)); loadEvents(); rxBus.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)); return true; @@ -331,7 +320,7 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { if (!isConnected()) return false; rxBus.send(new EventPumpStatusChanged(resourceHelper.gs(R.string.stoppingextendedbolus))); mSerialIOThread.sendMessage(new MsgSetExtendedBolusStop(injector)); - mSerialIOThread.sendMessage(new MsgStatusBolusExtended_v2(injector)); + mSerialIOThread.sendMessage(new MsgStatusBolusExtended(injector)); loadEvents(); rxBus.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)); return true; @@ -358,7 +347,7 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { mSerialIOThread.sendMessage(msg); MsgSetHistoryEntry_v2 msgSetHistoryEntry_v2 = new MsgSetHistoryEntry_v2(injector, DanaPump.CARBS, carbtime, carbs, 0); mSerialIOThread.sendMessage(msgSetHistoryEntry_v2); - lastHistoryFetched = Math.min(lastHistoryFetched, carbtime - T.mins(1).msecs()); + danaPump.lastHistoryFetched = Math.min(danaPump.lastHistoryFetched, carbtime - T.mins(1).msecs()); } final long bolusStart = System.currentTimeMillis(); @@ -427,7 +416,7 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { mSerialIOThread.sendMessage(msg); MsgSetHistoryEntry_v2 msgSetHistoryEntry_v2 = new MsgSetHistoryEntry_v2(injector, DanaPump.CARBS, time, amount, 0); mSerialIOThread.sendMessage(msgSetHistoryEntry_v2); - lastHistoryFetched = Math.min(lastHistoryFetched, time - T.mins(1).msecs()); + danaPump.lastHistoryFetched = Math.min(danaPump.lastHistoryFetched, time - T.mins(1).msecs()); return true; } @@ -442,18 +431,18 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { if (!isConnected()) return new PumpEnactResult(injector).success(false); SystemClock.sleep(300); - MsgHistoryEvents_v2 msg = new MsgHistoryEvents_v2(injector, lastHistoryFetched); - aapsLogger.debug(LTag.PUMP, "Loading event history from: " + dateUtil.dateAndTimeString(lastHistoryFetched)); + MsgHistoryEvents_v2 msg = new MsgHistoryEvents_v2(injector, danaPump.lastHistoryFetched); + aapsLogger.debug(LTag.PUMP, "Loading event history from: " + dateUtil.dateAndTimeString(danaPump.lastHistoryFetched)); mSerialIOThread.sendMessage(msg); - while (!danaRv2Plugin.eventsLoadingDone && mRfcommSocket.isConnected()) { + while (!danaPump.historyDoneReceived && mRfcommSocket.isConnected()) { SystemClock.sleep(100); } SystemClock.sleep(200); if (danaRv2Plugin.lastEventTimeLoaded != 0) - lastHistoryFetched = danaRv2Plugin.lastEventTimeLoaded - T.mins(1).msecs(); + danaPump.lastHistoryFetched = danaRv2Plugin.lastEventTimeLoaded - T.mins(1).msecs(); else - lastHistoryFetched = 0; + danaPump.lastHistoryFetched = 0; danaPump.setLastConnection(System.currentTimeMillis()); return new PumpEnactResult(injector).success(true); } diff --git a/danar/src/main/java/info/nightscout/androidaps/danar/AbstractDanaRPlugin.java b/danar/src/main/java/info/nightscout/androidaps/danar/AbstractDanaRPlugin.java index 971bb33221..b5ac839e33 100644 --- a/danar/src/main/java/info/nightscout/androidaps/danar/AbstractDanaRPlugin.java +++ b/danar/src/main/java/info/nightscout/androidaps/danar/AbstractDanaRPlugin.java @@ -15,10 +15,9 @@ import info.nightscout.androidaps.dana.comm.RecordTypes; import info.nightscout.androidaps.danar.services.AbstractDanaRExecutionService; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.PumpEnactResult; -import info.nightscout.androidaps.db.ExtendedBolus; -import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.events.EventConfigBuilderChange; import info.nightscout.androidaps.events.EventPreferenceChange; +import info.nightscout.androidaps.extensions.PumpStateExtensionKt; import info.nightscout.androidaps.interfaces.ActivePluginProvider; import info.nightscout.androidaps.interfaces.CommandQueueProvider; import info.nightscout.androidaps.interfaces.Constraint; @@ -219,7 +218,6 @@ public abstract class AbstractDanaRPlugin extends PumpPluginBase implements Pump @NonNull @Override public PumpEnactResult setTempBasalPercent(int percent, int durationInMinutes, @NonNull Profile profile, boolean enforceNew, @NonNull PumpSync.TemporaryBasalType tbrType) { - DanaPump pump = danaPump; PumpEnactResult result = new PumpEnactResult(getInjector()); percent = constraintChecker.applyBasalPercentConstraints(new Constraint<>(percent), profile).value(); if (percent < 0) { @@ -229,28 +227,36 @@ public abstract class AbstractDanaRPlugin extends PumpPluginBase implements Pump } if (percent > getPumpDescription().getMaxTempPercent()) percent = getPumpDescription().getMaxTempPercent(); - long now = System.currentTimeMillis(); - TemporaryBasal activeTemp = activePlugin.getActiveTreatments().getRealTempBasalFromHistory(now); - if (activeTemp != null && activeTemp.percentRate == percent && activeTemp.getPlannedRemainingMinutes() > 4 && !enforceNew) { + if (danaPump.isTempBasalInProgress() && danaPump.getTempBasalPercent() == percent && danaPump.getTempBasalRemainingMin() > 4 && !enforceNew) { result.enacted(false).success(true).isTempCancel(false) .comment(R.string.ok) - .duration(pump.getTempBasalRemainingMin()) - .percent(pump.getTempBasalPercent()) + .duration(danaPump.getTempBasalRemainingMin()) + .percent(danaPump.getTempBasalPercent()) .isPercent(true); getAapsLogger().debug(LTag.PUMP, "setTempBasalPercent: Correct value already set"); return result; } int durationInHours = Math.max(durationInMinutes / 60, 1); boolean connectionOK = sExecutionService.tempBasal(percent, durationInHours); - if (connectionOK && pump.isTempBasalInProgress() && pump.getTempBasalPercent() == percent) { + if (connectionOK && danaPump.isTempBasalInProgress() && danaPump.getTempBasalPercent() == percent) { result.enacted(true) .success(true) .comment(R.string.ok) .isTempCancel(false) - .duration(pump.getTempBasalRemainingMin()) - .percent(pump.getTempBasalPercent()) + .duration((int) danaPump.getTempBasalDuration()) + .percent(danaPump.getTempBasalPercent()) .isPercent(true); getAapsLogger().debug(LTag.PUMP, "setTempBasalPercent: OK"); + pumpSync.syncTemporaryBasalWithPumpId( + danaPump.getTempBasalStart(), + danaPump.getTempBasalPercent(), + danaPump.getTempBasalDuration(), + false, + tbrType, + danaPump.getTempBasalStart(), + getPumpDescription().getPumpType(), + serialNumber() + ); return result; } result.enacted(false).success(false).comment(R.string.tempbasaldeliveryerror); @@ -260,36 +266,34 @@ public abstract class AbstractDanaRPlugin extends PumpPluginBase implements Pump @NonNull @Override public PumpEnactResult setExtendedBolus(double insulin, int durationInMinutes) { - DanaPump pump = danaPump; insulin = constraintChecker.applyExtendedBolusConstraints(new Constraint<>(insulin)).value(); // needs to be rounded int durationInHalfHours = Math.max(durationInMinutes / 30, 1); insulin = Round.roundTo(insulin, getPumpDescription().getExtendedBolusStep()); PumpEnactResult result = new PumpEnactResult(getInjector()); - ExtendedBolus runningEB = activePlugin.getActiveTreatments().getExtendedBolusFromHistory(System.currentTimeMillis()); - if (runningEB != null && Math.abs(runningEB.insulin - insulin) < getPumpDescription().getExtendedBolusStep()) { + if (danaPump.isExtendedInProgress() && Math.abs(danaPump.getExtendedBolusAmount() - insulin) < getPumpDescription().getExtendedBolusStep()) { result.enacted(false) .success(true) .comment(R.string.ok) - .duration(pump.getExtendedBolusRemainingMinutes()) - .absolute(pump.getExtendedBolusAbsoluteRate()) + .duration(danaPump.getExtendedBolusRemainingMinutes()) + .absolute(danaPump.getExtendedBolusAbsoluteRate()) .isPercent(false) .isTempCancel(false); - getAapsLogger().debug(LTag.PUMP, "setExtendedBolus: Correct extended bolus already set. Current: " + pump.getExtendedBolusAmount() + " Asked: " + insulin); + getAapsLogger().debug(LTag.PUMP, "setExtendedBolus: Correct extended bolus already set. Current: " + danaPump.getExtendedBolusAmount() + " Asked: " + insulin); return result; } boolean connectionOK = sExecutionService.extendedBolus(insulin, durationInHalfHours); - if (connectionOK && pump.isExtendedInProgress() && Math.abs(pump.getExtendedBolusAmount() - insulin) < getPumpDescription().getExtendedBolusStep()) { + if (connectionOK && danaPump.isExtendedInProgress() && Math.abs(danaPump.getExtendedBolusAmount() - insulin) < getPumpDescription().getExtendedBolusStep()) { result.enacted(true) .success(true) .comment(R.string.ok) .isTempCancel(false) - .duration(pump.getExtendedBolusRemainingMinutes()) - .absolute(pump.getExtendedBolusAbsoluteRate()) + .duration(danaPump.getExtendedBolusRemainingMinutes()) + .absolute(danaPump.getExtendedBolusAbsoluteRate()) .isPercent(false); if (!sp.getBoolean("danar_useextended", false)) - result.bolusDelivered(pump.getExtendedBolusAmount()); + result.bolusDelivered(danaPump.getExtendedBolusAmount()); getAapsLogger().debug(LTag.PUMP, "setExtendedBolus: OK"); return result; } @@ -301,17 +305,12 @@ public abstract class AbstractDanaRPlugin extends PumpPluginBase implements Pump @NonNull @Override public PumpEnactResult cancelExtendedBolus() { PumpEnactResult result = new PumpEnactResult(getInjector()); - ExtendedBolus runningEB = activePlugin.getActiveTreatments().getExtendedBolusFromHistory(System.currentTimeMillis()); - if (runningEB != null) { + if (danaPump.isExtendedInProgress()) { sExecutionService.extendedBolusStop(); result.enacted(true).isTempCancel(true); - } - if (!danaPump.isExtendedInProgress()) { + } else { result.success(true).comment(R.string.ok); getAapsLogger().debug(LTag.PUMP, "cancelExtendedBolus: OK"); - } else { - result.success(false).comment(R.string.danar_valuenotsetproperly); - getAapsLogger().error("cancelExtendedBolus: Failed to cancel extended bolus"); } return result; } @@ -374,17 +373,16 @@ public abstract class AbstractDanaRPlugin extends PumpPluginBase implements Pump extended.put("LastBolus", dateUtil.dateAndTimeString(pump.getLastBolusTime())); extended.put("LastBolusAmount", pump.getLastBolusAmount()); } - TemporaryBasal tb = activePlugin.getActiveTreatments().getRealTempBasalFromHistory(now); - if (tb != null) { - extended.put("TempBasalAbsoluteRate", tb.tempBasalConvertedToAbsolute(now, profile)); - extended.put("TempBasalStart", dateUtil.dateAndTimeString(tb.date)); - extended.put("TempBasalRemaining", tb.getPlannedRemainingMinutes()); + PumpSync.PumpState pumpState = pumpSync.expectedPumpState(); + if (pumpState.getTemporaryBasal() != null) { + extended.put("TempBasalAbsoluteRate", PumpStateExtensionKt.convertedToAbsolute(pumpState.getTemporaryBasal(), now, profile)); + extended.put("TempBasalStart", dateUtil.dateAndTimeString(pumpState.getTemporaryBasal().getTimestamp())); + extended.put("TempBasalRemaining", PumpStateExtensionKt.getPlannedRemainingMinutes(pumpState.getTemporaryBasal())); } - ExtendedBolus eb = activePlugin.getActiveTreatments().getExtendedBolusFromHistory(now); - if (eb != null) { - extended.put("ExtendedBolusAbsoluteRate", eb.absoluteRate()); - extended.put("ExtendedBolusStart", dateUtil.dateAndTimeString(eb.date)); - extended.put("ExtendedBolusRemaining", eb.getPlannedRemainingMinutes()); + if (pumpState.getExtendedBolus() != null) { + extended.put("ExtendedBolusAbsoluteRate", pumpState.getExtendedBolus().getRate()); + extended.put("ExtendedBolusStart", dateUtil.dateAndTimeString(pumpState.getExtendedBolus().getTimestamp())); + extended.put("ExtendedBolusRemaining", PumpStateExtensionKt.getPlannedRemainingMinutes(pumpState.getExtendedBolus())); } extended.put("BaseBasalRate", getBaseBasalRate()); try { @@ -463,29 +461,27 @@ public abstract class AbstractDanaRPlugin extends PumpPluginBase implements Pump // Reply for sms communicator @NonNull public String shortStatus(boolean veryShort) { - DanaPump pump = danaPump; String ret = ""; - if (pump.getLastConnection() != 0) { - long agoMilliseconds = System.currentTimeMillis() - pump.getLastConnection(); + if (danaPump.getLastConnection() != 0) { + long agoMilliseconds = System.currentTimeMillis() - danaPump.getLastConnection(); int agoMin = (int) (agoMilliseconds / 60d / 1000d); ret += "LastConn: " + agoMin + " min ago\n"; } - if (pump.getLastBolusTime() != 0) { - ret += "LastBolus: " + DecimalFormatter.INSTANCE.to2Decimal(pump.getLastBolusAmount()) + "U @" + android.text.format.DateFormat.format("HH:mm", pump.getLastBolusTime()) + "\n"; + if (danaPump.getLastBolusTime() != 0) { + ret += "LastBolus: " + DecimalFormatter.INSTANCE.to2Decimal(danaPump.getLastBolusAmount()) + "U @" + android.text.format.DateFormat.format("HH:mm", danaPump.getLastBolusTime()) + "\n"; } - TemporaryBasal activeTemp = activePlugin.getActiveTreatments().getRealTempBasalFromHistory(System.currentTimeMillis()); - if (activeTemp != null) { - ret += "Temp: " + activeTemp.toStringFull() + "\n"; + PumpSync.PumpState pumpState = pumpSync.expectedPumpState(); + if (pumpState.getTemporaryBasal() != null) { + ret += "Temp: " + PumpStateExtensionKt.toStringFull(pumpState.getTemporaryBasal(), dateUtil) + "\n"; } - ExtendedBolus activeExtendedBolus = activePlugin.getActiveTreatments().getExtendedBolusFromHistory(System.currentTimeMillis()); - if (activeExtendedBolus != null) { - ret += "Extended: " + activeExtendedBolus.toString() + "\n"; + if (pumpState.getExtendedBolus() != null) { + ret += "Extended: " + PumpStateExtensionKt.toStringFull(pumpState.getExtendedBolus(), dateUtil) + "\n"; } if (!veryShort) { - ret += "TDD: " + DecimalFormatter.INSTANCE.to0Decimal(pump.getDailyTotalUnits()) + " / " + pump.getMaxDailyTotalUnits() + " U\n"; + ret += "TDD: " + DecimalFormatter.INSTANCE.to0Decimal(danaPump.getDailyTotalUnits()) + " / " + danaPump.getMaxDailyTotalUnits() + " U\n"; } - ret += "Reserv: " + DecimalFormatter.INSTANCE.to0Decimal(pump.getReservoirRemainingUnits()) + "U\n"; - ret += "Batt: " + pump.getBatteryRemaining() + "\n"; + ret += "Reserv: " + DecimalFormatter.INSTANCE.to0Decimal(danaPump.getReservoirRemainingUnits()) + "U\n"; + ret += "Batt: " + danaPump.getBatteryRemaining() + "\n"; return ret; } // TODO: daily total constraint diff --git a/danar/src/main/java/info/nightscout/androidaps/danar/DanaRPlugin.java b/danar/src/main/java/info/nightscout/androidaps/danar/DanaRPlugin.java index 075c87f4e2..8a5b785d2a 100644 --- a/danar/src/main/java/info/nightscout/androidaps/danar/DanaRPlugin.java +++ b/danar/src/main/java/info/nightscout/androidaps/danar/DanaRPlugin.java @@ -17,8 +17,6 @@ import info.nightscout.androidaps.danar.services.DanaRExecutionService; import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.PumpEnactResult; -import info.nightscout.androidaps.db.ExtendedBolus; -import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.interfaces.ActivePluginProvider; @@ -91,7 +89,7 @@ public class DanaRPlugin extends AbstractDanaRPlugin { boolean previousValue = useExtendedBoluses; useExtendedBoluses = sp.getBoolean(R.string.key_danar_useextended, false); - if (useExtendedBoluses != previousValue && activePlugin.getActiveTreatments().isInHistoryExtendedBolusInProgress()) { + if (useExtendedBoluses != previousValue && pumpSync.expectedPumpState().getExtendedBolus() != null) { sExecutionService.extendedBolusStop(); } } @@ -217,18 +215,14 @@ public class DanaRPlugin extends AbstractDanaRPlugin { final boolean doHighTemp = absoluteRate > getBaseBasalRate() && !useExtendedBoluses; final boolean doExtendedTemp = absoluteRate > getBaseBasalRate() && useExtendedBoluses; - long now = System.currentTimeMillis(); - TemporaryBasal activeTemp = activePlugin.getActiveTreatments().getRealTempBasalFromHistory(now); - ExtendedBolus activeExtended = activePlugin.getActiveTreatments().getExtendedBolusFromHistory(now); - if (doTempOff) { // If extended in progress - if (activeExtended != null && useExtendedBoluses) { + if (danaPump.isExtendedInProgress() && useExtendedBoluses) { aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Stopping extended bolus (doTempOff)"); return cancelExtendedBolus(); } // If temp in progress - if (activeTemp != null) { + if (danaPump.isTempBasalInProgress()) { aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Stopping temp basal (doTempOff)"); return cancelRealTempBasal(); } @@ -249,7 +243,7 @@ public class DanaRPlugin extends AbstractDanaRPlugin { aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Calculated percent rate: " + percentRate); // If extended in progress - if (activeExtended != null && useExtendedBoluses) { + if (danaPump.isExtendedInProgress() && useExtendedBoluses) { aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Stopping extended bolus (doLowTemp || doHighTemp)"); result = cancelExtendedBolus(); if (!result.getSuccess()) { @@ -258,14 +252,14 @@ public class DanaRPlugin extends AbstractDanaRPlugin { } } // Check if some temp is already in progress - if (activeTemp != null) { + if (danaPump.isTempBasalInProgress()) { // Correct basal already set ? - aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: currently running: " + activeTemp.toString()); - if (activeTemp.percentRate == percentRate && activeTemp.getPlannedRemainingMinutes() > 4) { + aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: currently running: " + danaPump.temporaryBasalToString()); + if (danaPump.getTempBasalPercent() == percentRate && danaPump.getTempBasalRemainingMin() > 4) { if (enforceNew) { cancelTempBasal(true); } else { - result.success(true).percent(percentRate).enacted(false).duration(activeTemp.getPlannedRemainingMinutes()).isPercent(true).isTempCancel(false); + result.success(true).percent(percentRate).enacted(false).duration(danaPump.getTempBasalRemainingMin()).isPercent(true).isTempCancel(false); aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Correct temp basal already set (doLowTemp || doHighTemp)"); return result; } @@ -277,7 +271,7 @@ public class DanaRPlugin extends AbstractDanaRPlugin { } if (doExtendedTemp) { // Check if some temp is already in progress - if (activeTemp != null) { + if (danaPump.isTempBasalInProgress()) { aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Stopping temp basal (doExtendedTemp)"); result = cancelRealTempBasal(); // Check for proper result @@ -296,11 +290,11 @@ public class DanaRPlugin extends AbstractDanaRPlugin { extendedRateToSet = Round.roundTo(extendedRateToSet, pumpDescription.getExtendedBolusStep() * 2); // *2 because of half hours // What is current rate of extended bolusing in u/h? - aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Extended bolus in progress: " + (activeExtended != null) + " rate: " + danaPump.getExtendedBolusAbsoluteRate() + "U/h duration remaining: " + danaPump.getExtendedBolusRemainingMinutes() + "min"); + aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Extended bolus in progress: " + (danaPump.isExtendedInProgress()) + " rate: " + danaPump.getExtendedBolusAbsoluteRate() + "U/h duration remaining: " + danaPump.getExtendedBolusRemainingMinutes() + "min"); aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Rate to set: " + extendedRateToSet + "U/h"); // Compare with extended rate in progress - if (activeExtended != null && Math.abs(danaPump.getExtendedBolusAbsoluteRate() - extendedRateToSet) < getPumpDescription().getExtendedBolusStep()) { + if (danaPump.isExtendedInProgress() && Math.abs(danaPump.getExtendedBolusAbsoluteRate() - extendedRateToSet) < getPumpDescription().getExtendedBolusStep()) { // correct extended already set result.success(true).absolute(danaPump.getExtendedBolusAbsoluteRate()).enacted(false).duration(danaPump.getExtendedBolusRemainingMinutes()).isPercent(false).isTempCancel(false); aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Correct extended already set"); @@ -327,9 +321,9 @@ public class DanaRPlugin extends AbstractDanaRPlugin { @NonNull @Override public PumpEnactResult cancelTempBasal(boolean force) { - if (activePlugin.getActiveTreatments().isInHistoryRealTempBasalInProgress()) + if (danaPump.isTempBasalInProgress()) return cancelRealTempBasal(); - if (activePlugin.getActiveTreatments().isInHistoryExtendedBolusInProgress() && useExtendedBoluses) { + if (danaPump.isExtendedInProgress() && useExtendedBoluses) { return cancelExtendedBolus(); } PumpEnactResult result = new PumpEnactResult(getInjector()); @@ -344,17 +338,12 @@ public class DanaRPlugin extends AbstractDanaRPlugin { private PumpEnactResult cancelRealTempBasal() { PumpEnactResult result = new PumpEnactResult(getInjector()); - TemporaryBasal runningTB = activePlugin.getActiveTreatments().getTempBasalFromHistory(System.currentTimeMillis()); - if (runningTB != null) { + if (danaPump.isTempBasalInProgress()) { sExecutionService.tempBasalStop(); result.enacted(true).isTempCancel(true); - } - if (!danaPump.isTempBasalInProgress()) { + } else { result.success(true).isTempCancel(true).comment(R.string.ok); aapsLogger.debug(LTag.PUMP, "cancelRealTempBasal: OK"); - } else { - result.success(false).comment(R.string.danar_valuenotsetproperly).isTempCancel(true); - aapsLogger.error("cancelRealTempBasal: Failed to cancel temp basal"); } return result; } diff --git a/danar/src/main/java/info/nightscout/androidaps/danar/comm/MessageBase.java b/danar/src/main/java/info/nightscout/androidaps/danar/comm/MessageBase.java index aab2402847..df769ce431 100644 --- a/danar/src/main/java/info/nightscout/androidaps/danar/comm/MessageBase.java +++ b/danar/src/main/java/info/nightscout/androidaps/danar/comm/MessageBase.java @@ -27,6 +27,7 @@ import info.nightscout.androidaps.logging.LTag; import info.nightscout.androidaps.plugins.bus.RxBusWrapper; import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker; import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInfoStorage; +import info.nightscout.androidaps.plugins.pump.common.bolusInfo.TemporaryBasalStorage; import info.nightscout.androidaps.utils.CRC; import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.resources.ResourceHelper; @@ -50,6 +51,7 @@ public class MessageBase { @Inject public ConfigBuilderInterface configBuilder; @Inject public CommandQueueProvider commandQueue; @Inject public DetailedBolusInfoStorage detailedBolusInfoStorage; + @Inject public TemporaryBasalStorage temporaryBasalStorage; @Inject public ConstraintChecker constraintChecker; @Inject public PumpSync pumpSync; @Inject public DatabaseHelperInterface databaseHelper; diff --git a/danar/src/main/java/info/nightscout/androidaps/danar/comm/MsgStatus.kt b/danar/src/main/java/info/nightscout/androidaps/danar/comm/MsgStatus.kt index 92100e07b1..5e17e5d501 100644 --- a/danar/src/main/java/info/nightscout/androidaps/danar/comm/MsgStatus.kt +++ b/danar/src/main/java/info/nightscout/androidaps/danar/comm/MsgStatus.kt @@ -14,9 +14,9 @@ class MsgStatus( override fun handleMessage(bytes: ByteArray) { danaPump.dailyTotalUnits = intFromBuff(bytes, 0, 3) / 750.0 - danaPump.isExtendedInProgress = intFromBuff(bytes, 3, 1) == 1 - danaPump.extendedBolusMinutes = intFromBuff(bytes, 4, 2) - danaPump.extendedBolusAmount = intFromBuff(bytes, 6, 2) / 100.0 + val isExtendedInProgress = intFromBuff(bytes, 3, 1) == 1 + val extendedBolusMinutes = intFromBuff(bytes, 4, 2) + val extendedBolusAmount = intFromBuff(bytes, 6, 2) / 100.0 val lastBolusAmount = intFromBuff(bytes, 13, 2) / 100.0 if (lastBolusAmount != 0.0) { danaPump.lastBolusTime = dateTimeFromBuff(bytes, 8) @@ -24,9 +24,9 @@ class MsgStatus( } danaPump.iob = intFromBuff(bytes, 15, 2) / 100.0 aapsLogger.debug(LTag.PUMPCOMM, "Daily total: " + danaPump.dailyTotalUnits) - aapsLogger.debug(LTag.PUMPCOMM, "Is extended bolus running: " + danaPump.isExtendedInProgress) - aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus min: " + danaPump.extendedBolusMinutes) - aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus amount: " + danaPump.extendedBolusAmount) + aapsLogger.debug(LTag.PUMPCOMM, "Is extended bolus running: $isExtendedInProgress") + aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus min: $extendedBolusMinutes") + aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus amount: $extendedBolusAmount") aapsLogger.debug(LTag.PUMPCOMM, "Last bolus time: " + danaPump.lastBolusTime) aapsLogger.debug(LTag.PUMPCOMM, "Last bolus amount: " + danaPump.lastBolusAmount) aapsLogger.debug(LTag.PUMPCOMM, "IOB: " + danaPump.iob) diff --git a/danar/src/main/java/info/nightscout/androidaps/danar/comm/MsgStatusBolusExtended.kt b/danar/src/main/java/info/nightscout/androidaps/danar/comm/MsgStatusBolusExtended.kt index 2daf290d93..bf95b17c80 100644 --- a/danar/src/main/java/info/nightscout/androidaps/danar/comm/MsgStatusBolusExtended.kt +++ b/danar/src/main/java/info/nightscout/androidaps/danar/comm/MsgStatusBolusExtended.kt @@ -1,9 +1,8 @@ package info.nightscout.androidaps.danar.comm import dagger.android.HasAndroidInjector -import info.nightscout.androidaps.db.ExtendedBolus -import info.nightscout.androidaps.db.Source import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.utils.T import kotlin.math.ceil class MsgStatusBolusExtended( @@ -18,7 +17,7 @@ class MsgStatusBolusExtended( override fun handleMessage(bytes: ByteArray) { val isExtendedInProgress = intFromBuff(bytes, 0, 1) == 1 val extendedBolusHalfHours = intFromBuff(bytes, 1, 1) - val extendedBolusMinutes = extendedBolusHalfHours * 30 + val extendedBolusMinutes = extendedBolusHalfHours * 30L val extendedBolusAmount = intFromBuff(bytes, 2, 2) / 100.0 val extendedBolusSoFarInSecs = intFromBuff(bytes, 4, 3) // This is available only on korean, but not needed now @@ -28,14 +27,9 @@ class MsgStatusBolusExtended( val extendedBolusAbsoluteRate = if (isExtendedInProgress) extendedBolusAmount / extendedBolusMinutes * 60 else 0.0 val extendedBolusStart = if (isExtendedInProgress) getDateFromSecAgo(extendedBolusSoFarInSecs) else 0 val extendedBolusRemainingMinutes = extendedBolusMinutes - extendedBolusSoFarInMinutes - danaPump.isExtendedInProgress = isExtendedInProgress - danaPump.extendedBolusMinutes = extendedBolusMinutes + danaPump.extendedBolusDuration = T.mins(extendedBolusMinutes).msecs() danaPump.extendedBolusAmount = extendedBolusAmount - danaPump.extendedBolusSoFarInMinutes = extendedBolusSoFarInMinutes - danaPump.extendedBolusAbsoluteRate = extendedBolusAbsoluteRate danaPump.extendedBolusStart = extendedBolusStart - danaPump.extendedBolusRemainingMinutes = extendedBolusRemainingMinutes - updateExtendedBolusInDB() aapsLogger.debug(LTag.PUMPCOMM, "Is extended bolus running: $isExtendedInProgress") aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus min: $extendedBolusMinutes") aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus amount: $extendedBolusAmount") @@ -48,39 +42,4 @@ class MsgStatusBolusExtended( private fun getDateFromSecAgo(tempBasalAgoSecs: Int): Long { return (ceil(System.currentTimeMillis() / 1000.0) - tempBasalAgoSecs).toLong() * 1000 } - - private fun updateExtendedBolusInDB() { - val now = System.currentTimeMillis() - val extendedBolus = activePlugin.activeTreatments.getExtendedBolusFromHistory(System.currentTimeMillis()) - if (extendedBolus != null) { - if (danaPump.isExtendedInProgress) { - if (extendedBolus.absoluteRate() != danaPump.extendedBolusAbsoluteRate) { // Close current extended - val exStop = ExtendedBolus(injector, danaPump.extendedBolusStart - 1000) - exStop.source = Source.USER - activePlugin.activeTreatments.addToHistoryExtendedBolus(exStop) - // Create new - val newExtended = ExtendedBolus(injector) - .date(danaPump.extendedBolusStart) - .insulin(danaPump.extendedBolusAmount) - .durationInMinutes(danaPump.extendedBolusMinutes) - .source(Source.USER) - activePlugin.activeTreatments.addToHistoryExtendedBolus(newExtended) - } - } else { - // Close current temp basal - val exStop = ExtendedBolus(injector, now) - .source(Source.USER) - activePlugin.activeTreatments.addToHistoryExtendedBolus(exStop) - } - } else { - if (danaPump.isExtendedInProgress) { // Create new - val newExtended = ExtendedBolus(injector) - .date(danaPump.extendedBolusStart) - .insulin(danaPump.extendedBolusAmount) - .durationInMinutes(danaPump.extendedBolusMinutes) - .source(Source.USER) - activePlugin.activeTreatments.addToHistoryExtendedBolus(newExtended) - } - } - } } \ No newline at end of file diff --git a/danar/src/main/java/info/nightscout/androidaps/danar/comm/MsgStatusTempBasal.kt b/danar/src/main/java/info/nightscout/androidaps/danar/comm/MsgStatusTempBasal.kt index c354da3bb0..b71099dd1b 100644 --- a/danar/src/main/java/info/nightscout/androidaps/danar/comm/MsgStatusTempBasal.kt +++ b/danar/src/main/java/info/nightscout/androidaps/danar/comm/MsgStatusTempBasal.kt @@ -1,9 +1,8 @@ package info.nightscout.androidaps.danar.comm import dagger.android.HasAndroidInjector -import info.nightscout.androidaps.db.Source -import info.nightscout.androidaps.db.TemporaryBasal import info.nightscout.androidaps.logging.LTag +import kotlin.math.abs import kotlin.math.ceil class MsgStatusTempBasal( @@ -24,53 +23,24 @@ class MsgStatusTempBasal( val tempBasalRunningSeconds = intFromBuff(bytes, 3, 3) val tempBasalRemainingMin = (tempBasalTotalSec - tempBasalRunningSeconds) / 60 val tempBasalStart = if (isTempBasalInProgress) getDateFromTempBasalSecAgo(tempBasalRunningSeconds) else 0 - danaPump.isTempBasalInProgress = isTempBasalInProgress - danaPump.tempBasalPercent = tempBasalPercent - danaPump.tempBasalRemainingMin = tempBasalRemainingMin - danaPump.tempBasalTotalSec = tempBasalTotalSec - danaPump.tempBasalStart = tempBasalStart - updateTempBasalInDB() + if (isTempBasalInProgress && !isWithin3Sec(tempBasalStart)) { + danaPump.tempBasalStart = tempBasalStart + danaPump.tempBasalPercent = tempBasalPercent + danaPump.tempBasalTotalSec = tempBasalTotalSec.toLong() + } + if (!isTempBasalInProgress) danaPump.isTempBasalInProgress = false aapsLogger.debug(LTag.PUMPCOMM, "Is temp basal running: $isTempBasalInProgress") aapsLogger.debug(LTag.PUMPCOMM, "Is APS temp basal running: $isAPSTempBasalInProgress") aapsLogger.debug(LTag.PUMPCOMM, "Current temp basal percent: $tempBasalPercent") aapsLogger.debug(LTag.PUMPCOMM, "Current temp basal remaining min: $tempBasalRemainingMin") aapsLogger.debug(LTag.PUMPCOMM, "Current temp basal total sec: $tempBasalTotalSec") - aapsLogger.debug(LTag.PUMPCOMM, "Current temp basal start: $tempBasalStart") + aapsLogger.debug(LTag.PUMPCOMM, "Current temp basal start: " + dateUtil.dateAndTimeString(tempBasalStart)) } private fun getDateFromTempBasalSecAgo(tempBasalAgoSecs: Int): Long { return (ceil(System.currentTimeMillis() / 1000.0) - tempBasalAgoSecs).toLong() * 1000 } - private fun updateTempBasalInDB() { - val now = System.currentTimeMillis() - if (activePlugin.activeTreatments.isInHistoryRealTempBasalInProgress) { - val tempBasal = activePlugin.activeTreatments.getRealTempBasalFromHistory(System.currentTimeMillis()) - if (danaPump.isTempBasalInProgress) { - if (tempBasal.percentRate != danaPump.tempBasalPercent) { // Close current temp basal - val tempStop = TemporaryBasal(injector).date(danaPump.tempBasalStart - 1000).source(Source.USER) - activePlugin.activeTreatments.addToHistoryTempBasal(tempStop) - // Create new - val newTempBasal = TemporaryBasal(injector) - .date(danaPump.tempBasalStart) - .percent(danaPump.tempBasalPercent) - .duration(danaPump.tempBasalTotalSec / 60) - .source(Source.USER) - activePlugin.activeTreatments.addToHistoryTempBasal(newTempBasal) - } - } else { // Close current temp basal - val tempStop = TemporaryBasal(injector).date(now).source(Source.USER) - activePlugin.activeTreatments.addToHistoryTempBasal(tempStop) - } - } else { - if (danaPump.isTempBasalInProgress) { // Create new - val newTempBasal = TemporaryBasal(injector) - .date(danaPump.tempBasalStart) - .percent(danaPump.tempBasalPercent) - .duration(danaPump.tempBasalTotalSec / 60) - .source(Source.USER) - activePlugin.activeTreatments.addToHistoryTempBasal(newTempBasal) - } - } - } + // because there is no fixed timestamp of start allow update of tbr only if tbr start differs more + private fun isWithin3Sec(newStart: Long) = abs(newStart - danaPump.tempBasalStart) < 3000 } \ No newline at end of file diff --git a/danar/src/main/java/info/nightscout/androidaps/danar/di/DanaRCommModule.kt b/danar/src/main/java/info/nightscout/androidaps/danar/di/DanaRCommModule.kt index f9c9b58f8d..6c157f6efb 100644 --- a/danar/src/main/java/info/nightscout/androidaps/danar/di/DanaRCommModule.kt +++ b/danar/src/main/java/info/nightscout/androidaps/danar/di/DanaRCommModule.kt @@ -3,7 +3,11 @@ package info.nightscout.androidaps.danar.di import dagger.Module import dagger.android.ContributesAndroidInjector import info.nightscout.androidaps.danaRKorean.comm.* -import info.nightscout.androidaps.danaRv2.comm.* +import info.nightscout.androidaps.danaRv2.comm.MsgCheckValue_v2 +import info.nightscout.androidaps.danaRv2.comm.MsgHistoryEvents_v2 +import info.nightscout.androidaps.danaRv2.comm.MsgSetAPSTempBasalStart_v2 +import info.nightscout.androidaps.danaRv2.comm.MsgSetHistoryEntry_v2 +import info.nightscout.androidaps.danaRv2.comm.MsgStatusAPS_v2 import info.nightscout.androidaps.danar.comm.* @Module @@ -69,8 +73,6 @@ abstract class DanaRCommModule { @ContributesAndroidInjector abstract fun contributesMsgSetAPSTempBasalStart_v2(): MsgSetAPSTempBasalStart_v2 @ContributesAndroidInjector abstract fun contributesMsgSetHistoryEntry_v2(): MsgSetHistoryEntry_v2 @ContributesAndroidInjector abstract fun contributesMsgStatusAPS_v2(): MsgStatusAPS_v2 - @ContributesAndroidInjector abstract fun contributesMsgStatusBolusExtended_v2(): MsgStatusBolusExtended_v2 - @ContributesAndroidInjector abstract fun contributesMsgStatusTempBasal_v2(): MsgStatusTempBasal_v2 @ContributesAndroidInjector abstract fun contributesMsgCheckValue_k(): MsgCheckValue_k @ContributesAndroidInjector abstract fun contributesMsgInitConnStatusBasic_k(): MsgInitConnStatusBasic_k diff --git a/danar/src/main/java/info/nightscout/androidaps/danar/services/AbstractDanaRExecutionService.java b/danar/src/main/java/info/nightscout/androidaps/danar/services/AbstractDanaRExecutionService.java index 4ee619fdff..12a4c16b3a 100644 --- a/danar/src/main/java/info/nightscout/androidaps/danar/services/AbstractDanaRExecutionService.java +++ b/danar/src/main/java/info/nightscout/androidaps/danar/services/AbstractDanaRExecutionService.java @@ -38,11 +38,15 @@ import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.events.EventBTChange; import info.nightscout.androidaps.events.EventPumpStatusChanged; +import info.nightscout.androidaps.interfaces.ActivePluginProvider; import info.nightscout.androidaps.interfaces.DatabaseHelperInterface; +import info.nightscout.androidaps.interfaces.PumpSync; import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.logging.LTag; import info.nightscout.androidaps.plugins.bus.RxBusWrapper; +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.FabricPrivacy; import info.nightscout.androidaps.utils.ToastUtils; @@ -67,6 +71,8 @@ public abstract class AbstractDanaRExecutionService extends DaggerService { @Inject DateUtil dateUtil; @Inject DatabaseHelperInterface databaseHelper; @Inject AapsSchedulers aapsSchedulers; + @Inject PumpSync pumpSync; + @Inject ActivePluginProvider activePlugin; private final CompositeDisposable disposable = new CompositeDisposable(); @@ -258,11 +264,11 @@ public abstract class AbstractDanaRExecutionService extends DaggerService { msg = new MsgHistorySuspend(injector); break; } - danaPump.setHistoryDoneReceived(false); + danaPump.historyDoneReceived = false; mSerialIOThread.sendMessage(new MsgPCCommStart(injector)); SystemClock.sleep(400); mSerialIOThread.sendMessage(msg); - while (!danaPump.getHistoryDoneReceived() && mRfcommSocket.isConnected()) { + while (!danaPump.historyDoneReceived && mRfcommSocket.isConnected()) { SystemClock.sleep(100); } SystemClock.sleep(200); @@ -281,4 +287,101 @@ public abstract class AbstractDanaRExecutionService extends DaggerService { SystemClock.sleep(Math.min(timeToWholeMinute, 100)); } } + + protected void doSanityCheck() { + PumpSync.PumpState pumpState = pumpSync.expectedPumpState(); + + // Temporary basal + if (pumpState.getTemporaryBasal() != null) { + if (danaPump.isTempBasalInProgress()) { + if (pumpState.getTemporaryBasal().getRate() != danaPump.getTempBasalPercent() + || pumpState.getTemporaryBasal().getTimestamp() != danaPump.getTempBasalStart() + ) { // Close current temp basal + Notification notification = new Notification(Notification.UNSUPPORTED_ACTION_IN_PUMP, resourceHelper.gs(R.string.unsupported_action_in_pump), Notification.URGENT); + rxBus.send(new EventNewNotification(notification)); + aapsLogger.error(LTag.PUMP, "Different temporary basal found running AAPS: " + (pumpState.getTemporaryBasal() + " DanaPump " + danaPump.temporaryBasalToString())); + pumpSync.syncTemporaryBasalWithPumpId( + danaPump.getTempBasalStart(), + danaPump.getTempBasalPercent(), danaPump.getTempBasalDuration(), + false, + PumpSync.TemporaryBasalType.NORMAL, + danaPump.getTempBasalStart(), + activePlugin.getActivePump().model(), + activePlugin.getActivePump().serialNumber() + ); + } + } else { + pumpSync.syncStopTemporaryBasalWithPumpId( + dateUtil._now(), + dateUtil._now(), + activePlugin.getActivePump().model(), + activePlugin.getActivePump().serialNumber() + ); + Notification notification = new Notification(Notification.UNSUPPORTED_ACTION_IN_PUMP, resourceHelper.gs(R.string.unsupported_action_in_pump), Notification.URGENT); + rxBus.send(new EventNewNotification(notification)); + aapsLogger.error(LTag.PUMP, "Temporary basal should not be running. Sending stop to AAPS"); + } + } else { + if (danaPump.isTempBasalInProgress()) { // Create new + pumpSync.syncTemporaryBasalWithPumpId( + danaPump.getTempBasalStart(), + danaPump.getTempBasalPercent(), danaPump.getTempBasalDuration(), + false, + PumpSync.TemporaryBasalType.NORMAL, + danaPump.getTempBasalStart(), + activePlugin.getActivePump().model(), + activePlugin.getActivePump().serialNumber() + ); + Notification notification = new Notification(Notification.UNSUPPORTED_ACTION_IN_PUMP, resourceHelper.gs(R.string.unsupported_action_in_pump), Notification.URGENT); + rxBus.send(new EventNewNotification(notification)); + aapsLogger.error(LTag.PUMP, "Temporary basal should be running: DanaPump " + danaPump.temporaryBasalToString()); + } + } + // Extended bolus + if (pumpState.getExtendedBolus() != null) { + if (danaPump.isExtendedInProgress()) { + if (pumpState.getExtendedBolus().getRate() != danaPump.getExtendedBolusAbsoluteRate() + || pumpState.getExtendedBolus().getTimestamp() != danaPump.getExtendedBolusStart()) { // Close current extended + Notification notification = new Notification(Notification.UNSUPPORTED_ACTION_IN_PUMP, resourceHelper.gs(R.string.unsupported_action_in_pump), Notification.URGENT); + rxBus.send(new EventNewNotification(notification)); + aapsLogger.error(LTag.PUMP, "Different extended bolus found running AAPS: " + (pumpState.getExtendedBolus() + " DanaPump " + danaPump.extendedBolusToString())); + pumpSync.syncExtendedBolusWithPumpId( + danaPump.getExtendedBolusStart(), + danaPump.getExtendedBolusAmount(), + danaPump.getExtendedBolusDuration(), + activePlugin.getActivePump().isFakingTempsByExtendedBoluses(), + danaPump.getTempBasalStart(), + activePlugin.getActivePump().model(), + activePlugin.getActivePump().serialNumber() + ); + } + } else { + pumpSync.syncStopExtendedBolusWithPumpId( + dateUtil._now(), + dateUtil._now(), + activePlugin.getActivePump().model(), + activePlugin.getActivePump().serialNumber() + ); + Notification notification = new Notification(Notification.UNSUPPORTED_ACTION_IN_PUMP, resourceHelper.gs(R.string.unsupported_action_in_pump), Notification.URGENT); + rxBus.send(new EventNewNotification(notification)); + aapsLogger.error(LTag.PUMP, "Extended bolus should not be running. Sending stop to AAPS"); + } + } else { + if (danaPump.isExtendedInProgress()) { // Create new + Notification notification = new Notification(Notification.UNSUPPORTED_ACTION_IN_PUMP, resourceHelper.gs(R.string.unsupported_action_in_pump), Notification.URGENT); + rxBus.send(new EventNewNotification(notification)); + aapsLogger.error(LTag.PUMP, "Extended bolus should not be running: DanaPump " + danaPump.extendedBolusToString()); + pumpSync.syncExtendedBolusWithPumpId( + danaPump.getExtendedBolusStart(), + danaPump.getExtendedBolusAmount(), + danaPump.getExtendedBolusDuration(), + activePlugin.getActivePump().isFakingTempsByExtendedBoluses(), + danaPump.getTempBasalStart(), + activePlugin.getActivePump().model(), + activePlugin.getActivePump().serialNumber() + ); + } + } + + } } diff --git a/danar/src/main/java/info/nightscout/androidaps/danar/services/DanaRExecutionService.java b/danar/src/main/java/info/nightscout/androidaps/danar/services/DanaRExecutionService.java index ddbca639e2..136a98bb34 100644 --- a/danar/src/main/java/info/nightscout/androidaps/danar/services/DanaRExecutionService.java +++ b/danar/src/main/java/info/nightscout/androidaps/danar/services/DanaRExecutionService.java @@ -211,6 +211,8 @@ public class DanaRExecutionService extends AbstractDanaRExecutionService { lastApproachingDailyLimit = System.currentTimeMillis(); } } + + doSanityCheck(); } catch (Exception e) { aapsLogger.error("Unhandled exception", e); } diff --git a/danar/src/main/res/values/strings.xml b/danar/src/main/res/values/strings.xml index 0383441326..0a916d48c9 100644 --- a/danar/src/main/res/values/strings.xml +++ b/danar/src/main/res/values/strings.xml @@ -1,4 +1,5 @@ danar_pump_settings + Unsupported action in pump. Use AndroidAPS UI only! \ No newline at end of file diff --git a/danar/src/main/res/xml/pref_danar.xml b/danar/src/main/res/xml/pref_danar.xml index 475c49531d..c7d45b8f12 100644 --- a/danar/src/main/res/xml/pref_danar.xml +++ b/danar/src/main/res/xml/pref_danar.xml @@ -33,12 +33,6 @@ android:key="@string/key_danar_useextended" android:title="@string/danar_useextended_title" /> - - \ No newline at end of file diff --git a/danar/src/main/res/xml/pref_danarkorean.xml b/danar/src/main/res/xml/pref_danarkorean.xml index 3e2944a2a3..96479baf58 100644 --- a/danar/src/main/res/xml/pref_danarkorean.xml +++ b/danar/src/main/res/xml/pref_danarkorean.xml @@ -26,12 +26,6 @@ android:key="@string/key_danar_useextended" android:title="@string/danar_useextended_title" /> - - \ No newline at end of file diff --git a/danar/src/test/java/info/nightscout/androidaps/TestPumpPlugin.kt b/danar/src/test/java/info/nightscout/androidaps/TestPumpPlugin.kt index d104302084..bfc9e86370 100644 --- a/danar/src/test/java/info/nightscout/androidaps/TestPumpPlugin.kt +++ b/danar/src/test/java/info/nightscout/androidaps/TestPumpPlugin.kt @@ -6,6 +6,7 @@ import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.interfaces.PumpDescription import info.nightscout.androidaps.interfaces.PumpInterface +import info.nightscout.androidaps.interfaces.PumpSync import info.nightscout.androidaps.plugins.common.ManufacturerType import info.nightscout.androidaps.plugins.pump.common.defs.PumpType import info.nightscout.androidaps.utils.TimeChangeType @@ -50,8 +51,8 @@ class TestPumpPlugin(val injector: HasAndroidInjector) : PumpInterface { override val batteryLevel: Int = 0 override fun deliverTreatment(detailedBolusInfo: DetailedBolusInfo): PumpEnactResult = PumpEnactResult(injector).success(true) override fun stopBolusDelivering() {} - override fun setTempBasalAbsolute(absoluteRate: Double, durationInMinutes: Int, profile: Profile, enforceNew: Boolean): PumpEnactResult = PumpEnactResult(injector).success(true) - override fun setTempBasalPercent(percent: Int, durationInMinutes: Int, profile: Profile, enforceNew: Boolean): PumpEnactResult = PumpEnactResult(injector).success(true) + override fun setTempBasalAbsolute(absoluteRate: Double, durationInMinutes: Int, profile: Profile, enforceNew: Boolean, tbrType: PumpSync.TemporaryBasalType): PumpEnactResult = PumpEnactResult(injector).success(true) + override fun setTempBasalPercent(percent: Int, durationInMinutes: Int, profile: Profile, enforceNew: Boolean, tbrType: PumpSync.TemporaryBasalType): PumpEnactResult = PumpEnactResult(injector).success(true) override fun setExtendedBolus(insulin: Double, durationInMinutes: Int): PumpEnactResult = PumpEnactResult(injector).success(true) override fun cancelTempBasal(enforceNew: Boolean): PumpEnactResult = PumpEnactResult(injector).success(true) override fun cancelExtendedBolus(): PumpEnactResult = PumpEnactResult(injector).success(true) diff --git a/danar/src/test/java/info/nightscout/androidaps/plugins/pump/danaR/DanaRPluginTest.kt b/danar/src/test/java/info/nightscout/androidaps/plugins/pump/danaR/DanaRPluginTest.kt index 8c5daf0fa3..6bbadd14e9 100644 --- a/danar/src/test/java/info/nightscout/androidaps/plugins/pump/danaR/DanaRPluginTest.kt +++ b/danar/src/test/java/info/nightscout/androidaps/plugins/pump/danaR/DanaRPluginTest.kt @@ -47,7 +47,7 @@ class DanaRPluginTest : TestBaseWithProfile() { `when`(resourceHelper.gs(R.string.pumplimit)).thenReturn("pump limit") `when`(resourceHelper.gs(R.string.limitingbasalratio)).thenReturn("Limiting max basal rate to %1\$.2f U/h because of %2\$s") `when`(resourceHelper.gs(R.string.limitingpercentrate)).thenReturn("Limiting max percent rate to %1\$d%% because of %2\$s") - danaPump = DanaPump(aapsLogger, sp, injector) + danaPump = DanaPump(aapsLogger, sp, dateUtil, injector) danaRPlugin = DanaRPlugin(injector, aapsLogger, aapsSchedulers, rxBus, context, resourceHelper, constraintChecker, activePluginProvider, sp, commandQueue, danaPump, dateUtil, fabricPrivacy, pumpSync) } diff --git a/danar/src/test/java/info/nightscout/androidaps/plugins/pump/danaR/comm/DanaRTestBase.kt b/danar/src/test/java/info/nightscout/androidaps/plugins/pump/danaR/comm/DanaRTestBase.kt index da8485d343..3e5c5f3659 100644 --- a/danar/src/test/java/info/nightscout/androidaps/plugins/pump/danaR/comm/DanaRTestBase.kt +++ b/danar/src/test/java/info/nightscout/androidaps/plugins/pump/danaR/comm/DanaRTestBase.kt @@ -9,11 +9,9 @@ import info.nightscout.androidaps.danaRKorean.DanaRKoreanPlugin import info.nightscout.androidaps.danaRv2.DanaRv2Plugin import info.nightscout.androidaps.danar.DanaRPlugin import info.nightscout.androidaps.danar.comm.MessageBase -import info.nightscout.androidaps.db.TemporaryBasal import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker -import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInfoStorage import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.resources.ResourceHelper @@ -45,11 +43,11 @@ open class DanaRTestBase : TestBase() { @Mock lateinit var constraintChecker: ConstraintChecker @Mock lateinit var pumpSync: PumpSync - lateinit var testPumpPlugin: TestPumpPlugin + private lateinit var testPumpPlugin: TestPumpPlugin @Before fun setup() { - danaPump = DanaPump(aapsLogger, sp, injector) + danaPump = DanaPump(aapsLogger, sp, dateUtil, injector) testPumpPlugin = TestPumpPlugin(injector) `when`(activePluginProvider.activeTreatments).thenReturn(treatmentsInterface) `when`(activePluginProvider.activePump).thenReturn(testPumpPlugin) @@ -77,12 +75,6 @@ open class DanaRTestBase : TestBase() { it.commandQueue = commandQueue it.pumpSync = pumpSync } - if (it is TemporaryBasal) { - it.aapsLogger = aapsLogger - it.activePlugin = activePluginProvider - it.profileFunction = profileFunction - it.sp = sp - } } } diff --git a/danar/src/test/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgStatusBolusExtendedTest.kt b/danar/src/test/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgStatusBolusExtendedTest.kt index 4621f34029..e96a579585 100644 --- a/danar/src/test/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgStatusBolusExtendedTest.kt +++ b/danar/src/test/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgStatusBolusExtendedTest.kt @@ -1,6 +1,7 @@ package info.nightscout.androidaps.plugins.pump.danaR.comm import info.nightscout.androidaps.danar.comm.MsgStatusBolusExtended +import info.nightscout.androidaps.utils.T import org.junit.Assert import org.junit.Test import org.junit.runner.RunWith @@ -16,8 +17,8 @@ class MsgStatusBolusExtendedTest : DanaRTestBase() { val packet = MsgStatusBolusExtended(injector) // test message decoding val array = ByteArray(100) - putByteToArray(array, 0, 1) + putByteToArray(array, 1, 1) packet.handleMessage(array) - Assert.assertEquals(true, danaPump.isExtendedInProgress) + Assert.assertEquals(T.mins(30).msecs() , danaPump.extendedBolusDuration) } } \ No newline at end of file diff --git a/danar/src/test/java/info/nightscout/androidaps/plugins/pump/danaRKorean/DanaRKoreanPluginTest.kt b/danar/src/test/java/info/nightscout/androidaps/plugins/pump/danaRKorean/DanaRKoreanPluginTest.kt index 894a33be7c..b92aa6e6c6 100644 --- a/danar/src/test/java/info/nightscout/androidaps/plugins/pump/danaRKorean/DanaRKoreanPluginTest.kt +++ b/danar/src/test/java/info/nightscout/androidaps/plugins/pump/danaRKorean/DanaRKoreanPluginTest.kt @@ -47,7 +47,7 @@ class DanaRKoreanPluginTest : TestBaseWithProfile() { `when`(resourceHelper.gs(R.string.pumplimit)).thenReturn("pump limit") `when`(resourceHelper.gs(R.string.limitingbasalratio)).thenReturn("Limiting max basal rate to %1\$.2f U/h because of %2\$s") `when`(resourceHelper.gs(R.string.limitingpercentrate)).thenReturn("Limiting max percent rate to %1\$d%% because of %2\$s") - danaPump = DanaPump(aapsLogger, sp, injector) + danaPump = DanaPump(aapsLogger, sp, dateUtil, injector) danaRPlugin = DanaRKoreanPlugin(injector, aapsLogger, aapsSchedulers, rxBus, danaPump, context, resourceHelper, constraintChecker, activePluginProvider, sp, commandQueue, dateUtil, pumpSync, fabricPrivacy) } diff --git a/danar/src/test/java/info/nightscout/androidaps/plugins/pump/danaRv2/DanaRv2PluginTest.kt b/danar/src/test/java/info/nightscout/androidaps/plugins/pump/danaRv2/DanaRv2PluginTest.kt index 471071290b..a6794d7a83 100644 --- a/danar/src/test/java/info/nightscout/androidaps/plugins/pump/danaRv2/DanaRv2PluginTest.kt +++ b/danar/src/test/java/info/nightscout/androidaps/plugins/pump/danaRv2/DanaRv2PluginTest.kt @@ -14,6 +14,8 @@ import info.nightscout.androidaps.interfaces.PluginType import info.nightscout.androidaps.interfaces.PumpSync import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInfoStorage +import info.nightscout.androidaps.plugins.pump.common.bolusInfo.TemporaryBasalStorage +import info.nightscout.androidaps.utils.sharedPreferences.SP import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -28,9 +30,10 @@ class DanaRv2PluginTest : TestBaseWithProfile() { @Mock lateinit var context: Context @Mock lateinit var constraintChecker: ConstraintChecker - @Mock lateinit var sp: info.nightscout.androidaps.utils.sharedPreferences.SP + @Mock lateinit var sp: SP @Mock lateinit var commandQueue: CommandQueueProvider @Mock lateinit var detailedBolusInfoStorage: DetailedBolusInfoStorage + @Mock lateinit var temporaryBasalStorage: TemporaryBasalStorage @Mock lateinit var pumpSync: PumpSync lateinit var danaPump: DanaPump @@ -47,8 +50,8 @@ class DanaRv2PluginTest : TestBaseWithProfile() { `when`(resourceHelper.gs(R.string.pumplimit)).thenReturn("pump limit") `when`(resourceHelper.gs(R.string.limitingbasalratio)).thenReturn("Limiting max basal rate to %1\$.2f U/h because of %2\$s") `when`(resourceHelper.gs(R.string.limitingpercentrate)).thenReturn("Limiting max percent rate to %1\$d%% because of %2\$s") - danaPump = DanaPump(aapsLogger, sp, injector) - danaRv2Plugin = DanaRv2Plugin(injector, aapsLogger, aapsSchedulers, rxBus, context, danaPump, resourceHelper, constraintChecker, activePluginProvider, sp, commandQueue, detailedBolusInfoStorage, dateUtil, fabricPrivacy, pumpSync) + danaPump = DanaPump(aapsLogger, sp, dateUtil, injector) + danaRv2Plugin = DanaRv2Plugin(injector, aapsLogger, aapsSchedulers, rxBus, context, danaPump, resourceHelper, constraintChecker, activePluginProvider, sp, commandQueue, detailedBolusInfoStorage, temporaryBasalStorage, dateUtil, fabricPrivacy, pumpSync) } @Test diff --git a/danar/src/test/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgHistoryEventsRv2Test.kt b/danar/src/test/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgHistoryEventsRv2Test.kt index 89a1e4f0a1..2ee8a5e551 100644 --- a/danar/src/test/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgHistoryEventsRv2Test.kt +++ b/danar/src/test/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgHistoryEventsRv2Test.kt @@ -21,10 +21,10 @@ class MsgHistoryEventsRv2Test : DanaRTestBase() { putByteToArray(array, 0, 0xFF.toByte()) packet.handleMessage(array) - Assert.assertEquals(true, danaRv2Plugin.eventsLoadingDone) + Assert.assertEquals(true, danaPump.historyDoneReceived) // passing an bigger number putByteToArray(array, 0, 0x01.toByte()) packet.handleMessage(array) - Assert.assertEquals(false, danaRv2Plugin.eventsLoadingDone) + Assert.assertEquals(false, danaPump.historyDoneReceived) } } \ No newline at end of file diff --git a/danar/src/test/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgStatusBolusExtendedRv2Test.kt b/danar/src/test/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgStatusBolusExtendedRv2Test.kt deleted file mode 100644 index 98b42c07cb..0000000000 --- a/danar/src/test/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgStatusBolusExtendedRv2Test.kt +++ /dev/null @@ -1,20 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.danaRv2.comm - -import info.nightscout.androidaps.danaRv2.comm.MsgStatusBolusExtended_v2 -import info.nightscout.androidaps.plugins.pump.danaR.comm.DanaRTestBase -import org.junit.Assert -import org.junit.Test -import org.junit.runner.RunWith -import org.powermock.modules.junit4.PowerMockRunner - -@RunWith(PowerMockRunner::class) -class MsgStatusBolusExtendedRv2Test : DanaRTestBase() { - - @Test - fun runTest() { - val packet = MsgStatusBolusExtended_v2(injector) - // test message decoding - packet.handleMessage(createArray(34, 7.toByte())) - Assert.assertEquals(packet.intFromBuff(createArray(10, 7.toByte()), 2, 2).toDouble() / 100.0, danaPump.extendedBolusAmount, 0.0) - } -} \ No newline at end of file diff --git a/danar/src/test/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgStatusTempBasalRv2Test.kt b/danar/src/test/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgStatusTempBasalRv2Test.kt deleted file mode 100644 index 31050bf109..0000000000 --- a/danar/src/test/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgStatusTempBasalRv2Test.kt +++ /dev/null @@ -1,22 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.danaRv2.comm - -import info.nightscout.androidaps.danaRv2.comm.MsgStatusTempBasal_v2 -import info.nightscout.androidaps.plugins.pump.danaR.comm.DanaRTestBase -import org.junit.Assert -import org.junit.Test -import org.junit.runner.RunWith -import org.powermock.modules.junit4.PowerMockRunner - -@RunWith(PowerMockRunner::class) -class MsgStatusTempBasalRv2Test : DanaRTestBase() { - - @Test fun runTest() { - val packet = MsgStatusTempBasal_v2(injector) - // test message decoding - packet.handleMessage(createArray(34, 1.toByte())) - Assert.assertEquals(true, danaPump.isTempBasalInProgress) - // passing an bigger number - packet.handleMessage(createArray(34, 2.toByte())) - Assert.assertEquals(false, danaPump.isTempBasalInProgress) - } -} \ No newline at end of file diff --git a/danars/src/main/java/info/nightscout/androidaps/danars/DanaRSPlugin.kt b/danars/src/main/java/info/nightscout/androidaps/danars/DanaRSPlugin.kt index 70b21f9c84..f70e3df2f0 100644 --- a/danars/src/main/java/info/nightscout/androidaps/danars/DanaRSPlugin.kt +++ b/danars/src/main/java/info/nightscout/androidaps/danars/DanaRSPlugin.kt @@ -28,8 +28,12 @@ import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotifi import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress import info.nightscout.androidaps.plugins.general.overview.notifications.Notification import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInfoStorage +import info.nightscout.androidaps.plugins.pump.common.bolusInfo.TemporaryBasalStorage import info.nightscout.androidaps.plugins.pump.common.defs.PumpType import info.nightscout.androidaps.utils.* +import info.nightscout.androidaps.utils.T.Companion.mins +import info.nightscout.androidaps.extensions.convertedToAbsolute +import info.nightscout.androidaps.extensions.plannedRemainingMinutes import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.sharedPreferences.SP @@ -51,11 +55,12 @@ class DanaRSPlugin @Inject constructor( resourceHelper: ResourceHelper, private val constraintChecker: ConstraintChecker, private val profileFunction: ProfileFunction, - private val activePluginProvider: ActivePluginProvider, private val sp: SP, commandQueue: CommandQueueProvider, private val danaPump: DanaPump, + private val pumpSync: PumpSync, private val detailedBolusInfoStorage: DetailedBolusInfoStorage, + private val temporaryBasalStorage: TemporaryBasalStorage, private val fabricPrivacy: FabricPrivacy, private val dateUtil: DateUtil ) : PumpPluginBase(PluginDescription() @@ -323,7 +328,7 @@ class DanaRSPlugin @Inject constructor( val doHighTemp = absoluteAfterConstrain > baseBasalRate if (doTempOff) { // If temp in progress - if (activePluginProvider.activeTreatments.isTempBasalInProgress) { + if (danaPump.isTempBasalInProgress) { aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Stopping temp basal (doTempOff)") return cancelTempBasal(false) } @@ -347,16 +352,15 @@ class DanaRSPlugin @Inject constructor( if (percentRate > 500) // Special high temp 500/15min percentRate = 500 // Check if some temp is already in progress - val activeTemp = activePluginProvider.activeTreatments.getTempBasalFromHistory(System.currentTimeMillis()) - if (activeTemp != null) { - aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: currently running: $activeTemp") + if (danaPump.isTempBasalInProgress) { + aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: currently running") // Correct basal already set ? - if (activeTemp.percentRate == percentRate && activeTemp.plannedRemainingMinutes > 4) { + if (danaPump.tempBasalPercent == percentRate && danaPump.tempBasalRemainingMin > 4) { if (!enforceNew) { result.success = true result.percent = percentRate result.enacted = false - result.duration = activeTemp.plannedRemainingMinutes + result.duration = danaPump.tempBasalRemainingMin result.isPercent = true result.isTempCancel = false aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Correct temp basal already set (doLowTemp || doHighTemp)") @@ -364,6 +368,7 @@ class DanaRSPlugin @Inject constructor( } } } + temporaryBasalStorage.add(PumpSync.PumpState.TemporaryBasal(dateUtil._now(), mins(durationInMinutes.toLong()).msecs(), percentRate.toDouble(), false, tbrType, 0L, 0L)) // Convert duration from minutes to hours aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Setting temp basal $percentRate% for $durationInMinutes minutes (doLowTemp || doHighTemp)") result = if (percentRate == 0 && durationInMinutes > 30) { @@ -399,9 +404,7 @@ class DanaRSPlugin @Inject constructor( return result } if (percentAfterConstraint > pumpDescription.maxTempPercent) percentAfterConstraint = pumpDescription.maxTempPercent - val now = System.currentTimeMillis() - val activeTemp = activePluginProvider.activeTreatments.getTempBasalFromHistory(now) - if (activeTemp != null && activeTemp.percentRate == percentAfterConstraint && activeTemp.plannedRemainingMinutes > 4 && !enforceNew) { + if (danaPump.isTempBasalInProgress && danaPump.tempBasalPercent == percentAfterConstraint && danaPump.tempBasalRemainingMin > 4 && !enforceNew) { result.enacted = false result.success = true result.isTempCancel = false @@ -412,6 +415,7 @@ class DanaRSPlugin @Inject constructor( aapsLogger.debug(LTag.PUMP, "setTempBasalPercent: Correct value already set") return result } + temporaryBasalStorage.add(PumpSync.PumpState.TemporaryBasal(dateUtil._now(), mins(durationInMinutes.toLong()).msecs(), percent.toDouble(), false, tbrType, 0L, 0L)) val connectionOK: Boolean = if (durationInMinutes == 15 || durationInMinutes == 30) { danaRSService?.tempBasalShortDuration(percentAfterConstraint, durationInMinutes) ?: false @@ -465,8 +469,7 @@ class DanaRSPlugin @Inject constructor( val durationInHalfHours = max(durationInMinutes / 30, 1) insulinAfterConstraint = Round.roundTo(insulinAfterConstraint, pumpDescription.extendedBolusStep) val result = PumpEnactResult(injector) - val runningEB = activePluginProvider.activeTreatments.getExtendedBolusFromHistory(System.currentTimeMillis()) - if (runningEB != null && abs(runningEB.insulin - insulinAfterConstraint) < pumpDescription.extendedBolusStep) { + if (danaPump.isExtendedInProgress && abs(danaPump.extendedBolusAmount - insulinAfterConstraint) < pumpDescription.extendedBolusStep) { result.enacted = false result.success = true result.comment = resourceHelper.gs(R.string.ok) @@ -479,7 +482,7 @@ class DanaRSPlugin @Inject constructor( } val connectionOK = danaRSService?.extendedBolus(insulinAfterConstraint, durationInHalfHours) ?: false - if (connectionOK && danaPump.isExtendedInProgress && abs(danaPump.extendedBolusAbsoluteRate - insulinAfterConstraint) < pumpDescription.extendedBolusStep) { + if (connectionOK && danaPump.isExtendedInProgress && abs(danaPump.extendedBolusAmount - insulinAfterConstraint) < pumpDescription.extendedBolusStep) { result.enacted = true result.success = true result.comment = resourceHelper.gs(R.string.ok) @@ -501,46 +504,34 @@ class DanaRSPlugin @Inject constructor( @Synchronized override fun cancelTempBasal(enforceNew: Boolean): PumpEnactResult { val result = PumpEnactResult(injector) - val runningTB = activePluginProvider.activeTreatments.getTempBasalFromHistory(System.currentTimeMillis()) - if (runningTB != null) { + if (danaPump.isTempBasalInProgress) { danaRSService?.tempBasalStop() + result.success = !danaPump.isTempBasalInProgress result.enacted = true result.isTempCancel = true - } - return if (!danaPump.isTempBasalInProgress) { + } else { result.success = true + result.enacted = false result.isTempCancel = true result.comment = resourceHelper.gs(R.string.ok) aapsLogger.debug(LTag.PUMP, "cancelRealTempBasal: OK") - result - } else { - result.success = false - result.comment = resourceHelper.gs(R.string.danar_valuenotsetproperly) - result.isTempCancel = true - aapsLogger.error("cancelRealTempBasal: Failed to cancel temp basal") - result } + return result } @Synchronized override fun cancelExtendedBolus(): PumpEnactResult { val result = PumpEnactResult(injector) - val runningEB = activePluginProvider.activeTreatments.getExtendedBolusFromHistory(System.currentTimeMillis()) - if (runningEB != null) { + if (danaPump.isExtendedInProgress) { danaRSService?.extendedBolusStop() + result.success = !danaPump.isExtendedInProgress result.enacted = true - result.isTempCancel = true - } - return if (!danaPump.isExtendedInProgress) { + } else { result.success = true + result.enacted = false result.comment = resourceHelper.gs(R.string.ok) aapsLogger.debug(LTag.PUMP, "cancelExtendedBolus: OK") - result - } else { - result.success = false - result.comment = resourceHelper.gs(R.string.danar_valuenotsetproperly) - aapsLogger.error("cancelExtendedBolus: Failed to cancel extended bolus") - result } + return result } override fun getJSONStatus(profile: Profile, profileName: String, version: String): JSONObject { @@ -561,16 +552,16 @@ class DanaRSPlugin @Inject constructor( extended.put("LastBolus", dateUtil.dateAndTimeString(danaPump.lastBolusTime)) extended.put("LastBolusAmount", danaPump.lastBolusAmount) } - val tb = activePluginProvider.activeTreatments.getTempBasalFromHistory(now) + val tb = pumpSync.expectedPumpState().temporaryBasal if (tb != null) { - extended.put("TempBasalAbsoluteRate", tb.tempBasalConvertedToAbsolute(now, profile)) - extended.put("TempBasalStart", dateUtil.dateAndTimeString(tb.date)) + extended.put("TempBasalAbsoluteRate", tb.convertedToAbsolute(now, profile)) + extended.put("TempBasalStart", dateUtil.dateAndTimeString(tb.timestamp)) extended.put("TempBasalRemaining", tb.plannedRemainingMinutes) } - val eb = activePluginProvider.activeTreatments.getExtendedBolusFromHistory(now) + val eb = pumpSync.expectedPumpState().extendedBolus if (eb != null) { - extended.put("ExtendedBolusAbsoluteRate", eb.absoluteRate()) - extended.put("ExtendedBolusStart", dateUtil.dateAndTimeString(eb.date)) + extended.put("ExtendedBolusAbsoluteRate", eb.rate) + extended.put("ExtendedBolusStart", dateUtil.dateAndTimeString(eb.timestamp)) extended.put("ExtendedBolusRemaining", eb.plannedRemainingMinutes) } extended.put("BaseBasalRate", baseBasalRate) @@ -613,13 +604,11 @@ class DanaRSPlugin @Inject constructor( if (danaPump.lastBolusTime != 0L) ret += "LastBolus: ${DecimalFormatter.to2Decimal(danaPump.lastBolusAmount)}U @${DateFormat.format("HH:mm", danaPump.lastBolusTime)}" - val activeTemp = activePluginProvider.activeTreatments.getRealTempBasalFromHistory(System.currentTimeMillis()) - if (activeTemp != null) - ret += "Temp: ${activeTemp.toStringFull()}" + if (danaPump.isTempBasalInProgress) + ret += "Temp: ${danaPump.temporaryBasalToString()}" - val activeExtendedBolus = activePluginProvider.activeTreatments.getExtendedBolusFromHistory(System.currentTimeMillis()) - if (activeExtendedBolus != null) - ret += "Extended: $activeExtendedBolus\n" + if (danaPump.isExtendedInProgress) + ret += "Extended: ${danaPump.extendedBolusToString()}\n" if (!veryShort) { ret += "TDD: ${DecimalFormatter.to0Decimal(danaPump.dailyTotalUnits)} / ${danaPump.maxDailyTotalUnits} U" diff --git a/danars/src/main/java/info/nightscout/androidaps/danars/activities/EnterPinActivity.kt b/danars/src/main/java/info/nightscout/androidaps/danars/activities/EnterPinActivity.kt index 41c952e6c5..7161850604 100644 --- a/danars/src/main/java/info/nightscout/androidaps/danars/activities/EnterPinActivity.kt +++ b/danars/src/main/java/info/nightscout/androidaps/danars/activities/EnterPinActivity.kt @@ -11,7 +11,7 @@ import info.nightscout.androidaps.events.EventPumpStatusChanged import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.alertDialogs.OKDialog -import info.nightscout.androidaps.utils.extensions.hexStringToByteArray +import info.nightscout.androidaps.extensions.hexStringToByteArray import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.textValidator.DefaultEditTextValidator diff --git a/danars/src/main/java/info/nightscout/androidaps/danars/comm/DanaRS_Packet_APS_History_Events.kt b/danars/src/main/java/info/nightscout/androidaps/danars/comm/DanaRS_Packet_APS_History_Events.kt index fb33f44e35..8d5efb853e 100644 --- a/danars/src/main/java/info/nightscout/androidaps/danars/comm/DanaRS_Packet_APS_History_Events.kt +++ b/danars/src/main/java/info/nightscout/androidaps/danars/comm/DanaRS_Packet_APS_History_Events.kt @@ -5,17 +5,15 @@ import info.nightscout.androidaps.dana.DanaPump import info.nightscout.androidaps.danars.R import info.nightscout.androidaps.danars.encryption.BleEncryption import info.nightscout.androidaps.data.DetailedBolusInfo -import info.nightscout.androidaps.db.ExtendedBolus -import info.nightscout.androidaps.db.Source -import info.nightscout.androidaps.db.TemporaryBasal import info.nightscout.androidaps.events.EventPumpStatusChanged -import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.PumpSync import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInfoStorage +import info.nightscout.androidaps.plugins.pump.common.bolusInfo.TemporaryBasalStorage import info.nightscout.androidaps.plugins.pump.common.defs.PumpType import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.sharedPreferences.SP import org.joda.time.DateTime @@ -29,12 +27,17 @@ open class DanaRS_Packet_APS_History_Events( @Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var resourceHelper: ResourceHelper - @Inject lateinit var activePlugin: ActivePluginProvider @Inject lateinit var danaPump: DanaPump @Inject lateinit var detailedBolusInfoStorage: DetailedBolusInfoStorage + @Inject lateinit var temporaryBasalStorage: TemporaryBasalStorage @Inject lateinit var sp: SP @Inject lateinit var pumpSync: PumpSync + companion object { + + var messageBuffer = arrayListOf() // for reversing order of incoming messages + } + init { opCode = BleEncryption.DANAR_PACKET__OPCODE__APS_HISTORY_EVENTS if (from > DateUtil.now()) { @@ -43,6 +46,7 @@ open class DanaRS_Packet_APS_History_Events( } aapsLogger.debug(LTag.PUMPCOMM, "Loading event history from: " + dateUtil.dateAndTimeString(from)) danaPump.historyDoneReceived = false + messageBuffer = arrayListOf() } override fun getRequestParams(): ByteArray { @@ -69,11 +73,43 @@ open class DanaRS_Packet_APS_History_Events( } override fun handleMessage(data: ByteArray) { + val recordCode = intFromBuff(data, 0, 1).toByte() + // Last record + if (recordCode == 0xFF.toByte()) { + aapsLogger.debug(LTag.PUMPCOMM, "Last record received") + + val array: Array = messageBuffer.toTypedArray() + val sorted = array.sortedArrayWith { s1: ByteArray, s2: ByteArray -> (dateTime(s1) - dateTime(s2)).toInt() } + for (index in sorted.indices) { + val message = sorted[index] + // workaround for RS history bug + // sometimes TB is marked as canceled immediately + // but on pump is running + // at least on Model: 05 Protocol: 10 Code: 10 + if (index > 0 && recordCode(message) == DanaPump.TEMPSTOP) { + val previous = sorted[index-1] + if (recordCode(previous) == DanaPump.TEMPSTART && dateTime(message) == dateTime(previous)) { + aapsLogger.debug(LTag.PUMPCOMM, "SKIPPING EVENT TEMPSTOP (" + recordCode(message) + ") " + dateUtil.dateAndTimeString(dateTime(message)) + " (" + dateTime(message) + ")") + continue + } + } + processMessage(message) + } + danaPump.historyDoneReceived = true + } else messageBuffer.add(data) + } + + fun dateTime(data: ByteArray): Long = + if (!danaPump.usingUTC) dateTimeSecFromBuff(data, 1) // 6 bytes + else intFromBuffMsbLsb(data, 3, 4) * 1000L + + fun recordCode(data: ByteArray): Int = + intFromBuff(data, 0, 1).toInt() + + fun processMessage(data: ByteArray) { var recordCode = intFromBuff(data, 0, 1).toByte() // Last record if (recordCode == 0xFF.toByte()) { - danaPump.historyDoneReceived = true - aapsLogger.debug(LTag.PUMPCOMM, "Last record received") return } val datetime: Long @@ -90,35 +126,53 @@ open class DanaRS_Packet_APS_History_Events( id = intFromBuffMsbLsb(data, 0, 2) // range only 1-2000 pumpId = datetime shl 16 + id } - val temporaryBasal = TemporaryBasal(injector).date(datetime).source(Source.PUMP).pumpId(pumpId) - val extendedBolus = ExtendedBolus(injector).date(datetime).source(Source.PUMP).pumpId(pumpId) val status: String when (recordCode.toInt()) { DanaPump.TEMPSTART -> { - aapsLogger.debug(LTag.PUMPCOMM, "[" + id + "] " + "EVENT TEMPSTART (" + recordCode + ") " + dateUtil.dateAndTimeString(datetime) + " (" + datetime + ")" + " Ratio: " + param1 + "% Duration: " + param2 + "min") - temporaryBasal.percentRate = param1 - temporaryBasal.durationInMinutes = param2 - activePlugin.activeTreatments.addToHistoryTempBasal(temporaryBasal) + val temporaryBasalInfo = temporaryBasalStorage.findTemporaryBasal(datetime, param1.toDouble()) + val newRecord = pumpSync.syncTemporaryBasalWithPumpId( + timestamp = datetime, + rate = param1.toDouble(), + duration = T.mins(param2.toLong()).msecs(), + isAbsolute = false, + type = temporaryBasalInfo?.type, + pumpId = pumpId, + pumpType = PumpType.DANA_RS, + pumpSerial = danaPump.serialNumber) + aapsLogger.debug(LTag.PUMPCOMM, "[" + id + "] " + (if (newRecord) "**NEW** " else "") + "EVENT TEMPSTART (" + recordCode + ") " + dateUtil.dateAndTimeString(datetime) + " (" + datetime + ")" + " Ratio: " + param1 + "% Duration: " + param2 + "min") status = "TEMPSTART " + dateUtil.timeString(datetime) } DanaPump.TEMPSTOP -> { - aapsLogger.debug(LTag.PUMPCOMM, "[" + id + "] " + "EVENT TEMPSTOP (" + recordCode + ") " + dateUtil.dateAndTimeString(datetime)) - activePlugin.activeTreatments.addToHistoryTempBasal(temporaryBasal) + val newRecord = pumpSync.syncStopTemporaryBasalWithPumpId( + timestamp = datetime, + endPumpId = pumpId, + pumpType = PumpType.DANA_RS, + pumpSerial = danaPump.serialNumber) + aapsLogger.debug(LTag.PUMPCOMM, "[" + id + "] " + (if (newRecord) "**NEW** " else "") + "EVENT TEMPSTOP (" + recordCode + ") " + dateUtil.dateAndTimeString(datetime) + " (" + datetime + ")") status = "TEMPSTOP " + dateUtil.timeString(datetime) } DanaPump.EXTENDEDSTART -> { - aapsLogger.debug(LTag.PUMPCOMM, "[" + id + "] " + "EVENT EXTENDEDSTART (" + recordCode + ") " + dateUtil.dateAndTimeString(datetime) + " (" + datetime + ")" + " Amount: " + param1 / 100.0 + "U Duration: " + param2 + "min") - extendedBolus.insulin = param1 / 100.0 - extendedBolus.durationInMinutes = param2 - activePlugin.activeTreatments.addToHistoryExtendedBolus(extendedBolus) + val newRecord = pumpSync.syncExtendedBolusWithPumpId( + timestamp = datetime, + amount = param1 / 100.0, + duration = T.mins(param2.toLong()).msecs(), + isEmulatingTB = false, + pumpId = pumpId, + pumpType = PumpType.DANA_RS, + pumpSerial = danaPump.serialNumber) + aapsLogger.debug(LTag.PUMPCOMM, "[" + id + "] " + (if (newRecord) "**NEW** " else "") + "EVENT EXTENDEDSTART (" + recordCode + ") " + dateUtil.dateAndTimeString(datetime) + " (" + datetime + ")" + " Amount: " + param1 / 100.0 + "U Duration: " + param2 + "min") status = "EXTENDEDSTART " + dateUtil.timeString(datetime) } DanaPump.EXTENDEDSTOP -> { - aapsLogger.debug(LTag.PUMPCOMM, "[" + id + "] " + "EVENT EXTENDEDSTOP (" + recordCode + ") " + dateUtil.dateAndTimeString(datetime) + " (" + datetime + ")" + " Delivered: " + param1 / 100.0 + "U RealDuration: " + param2 + "min") - activePlugin.activeTreatments.addToHistoryExtendedBolus(extendedBolus) + val newRecord = pumpSync.syncStopExtendedBolusWithPumpId( + timestamp = datetime, + endPumpId = pumpId, + pumpType = PumpType.DANA_RS, + pumpSerial = danaPump.serialNumber) + aapsLogger.debug(LTag.PUMPCOMM, "[" + id + "] " + (if (newRecord) "**NEW** " else "") + "EVENT EXTENDEDSTOP (" + recordCode + ") " + dateUtil.dateAndTimeString(datetime) + " (" + datetime + ")" + " Delivered: " + param1 / 100.0 + "U RealDuration: " + param2 + "min") status = "EXTENDEDSTOP " + dateUtil.timeString(datetime) } @@ -131,7 +185,7 @@ open class DanaRS_Packet_APS_History_Events( pumpId = pumpId, pumpType = PumpType.DANA_RS, pumpSerial = danaPump.serialNumber) - aapsLogger.debug(LTag.PUMPCOMM, "[" + id + "] " + (if (newRecord) "**NEW** " else "") + "EVENT BOLUS (" + recordCode + ") " + dateUtil.dateAndTimeString(datetime) + " (" + datetime + ")" + " Bolus: " + param1 / 100.0 + "U Duration: " + param2 + "min") + aapsLogger.debug(LTag.PUMPCOMM, "[" + id + "] " + (if (newRecord) "**NEW** " else "") + "EVENT BOLUS (" + recordCode + ") " + dateUtil.dateAndTimeString(datetime) + " (" + datetime + ")" + " Bolus: " + param1 / 100.0 + "U ") status = "BOLUS " + dateUtil.timeString(datetime) } @@ -149,16 +203,25 @@ open class DanaRS_Packet_APS_History_Events( } DanaPump.DUALEXTENDEDSTART -> { - aapsLogger.debug(LTag.PUMPCOMM, "[" + id + "] " + "EVENT DUALEXTENDEDSTART (" + recordCode + ") " + dateUtil.dateAndTimeString(datetime) + " (" + datetime + ")" + " Amount: " + param1 / 100.0 + "U Duration: " + param2 + "min") - extendedBolus.insulin = param1 / 100.0 - extendedBolus.durationInMinutes = param2 - activePlugin.activeTreatments.addToHistoryExtendedBolus(extendedBolus) + val newRecord = pumpSync.syncExtendedBolusWithPumpId( + timestamp = datetime, + amount = param1 / 100.0, + duration = T.mins(param2.toLong()).msecs(), + isEmulatingTB = false, + pumpId = pumpId, + pumpType = PumpType.DANA_RS, + pumpSerial = danaPump.serialNumber) + aapsLogger.debug(LTag.PUMPCOMM, "[" + id + "] " + (if (newRecord) "**NEW** " else "") + "EVENT DUALEXTENDEDSTART (" + recordCode + ") " + dateUtil.dateAndTimeString(datetime) + " (" + datetime + ")" + " Amount: " + param1 / 100.0 + "U Duration: " + param2 + "min") status = "DUALEXTENDEDSTART " + dateUtil.timeString(datetime) } DanaPump.DUALEXTENDEDSTOP -> { - aapsLogger.debug(LTag.PUMPCOMM, "[" + id + "] " + "EVENT DUALEXTENDEDSTOP (" + recordCode + ") " + dateUtil.dateAndTimeString(datetime) + " (" + datetime + ")" + " Delivered: " + param1 / 100.0 + "U RealDuration: " + param2 + "min") - activePlugin.activeTreatments.addToHistoryExtendedBolus(extendedBolus) + val newRecord = pumpSync.syncStopExtendedBolusWithPumpId( + timestamp = datetime, + endPumpId = pumpId, + pumpType = PumpType.DANA_RS, + pumpSerial = danaPump.serialNumber) + aapsLogger.debug(LTag.PUMPCOMM, "[" + id + "] " + (if (newRecord) "**NEW** " else "") + "EVENT DUALEXTENDEDSTOP (" + recordCode + ") " + dateUtil.dateAndTimeString(datetime) + " (" + datetime + ")" + " Delivered: " + param1 / 100.0 + "U RealDuration: " + param2 + "min") status = "DUALEXTENDEDSTOP " + dateUtil.timeString(datetime) } @@ -173,15 +236,16 @@ open class DanaRS_Packet_APS_History_Events( } DanaPump.REFILL -> { - aapsLogger.debug(LTag.PUMPCOMM, "[" + id + "] " + "EVENT REFILL (" + recordCode + ") " + dateUtil.dateAndTimeString(datetime) + " (" + datetime + ")" + " Amount: " + param1 / 100.0 + "U") - if (sp.getBoolean(R.string.key_rs_loginsulinchange, true)) - pumpSync.insertTherapyEventIfNewWithTimestamp( + if (sp.getBoolean(R.string.key_rs_loginsulinchange, true)) { + val newRecord = pumpSync.insertTherapyEventIfNewWithTimestamp( timestamp = datetime, type = DetailedBolusInfo.EventType.INSULIN_CHANGE, pumpId = pumpId, pumpType = danaPump.pumpType(), pumpSerial = danaPump.serialNumber ) + aapsLogger.debug(LTag.PUMPCOMM, "[" + id + "] " + (if (newRecord) "**NEW** " else "") + "EVENT REFILL (" + recordCode + ") " + dateUtil.dateAndTimeString(datetime) + " (" + datetime + ")" + " Amount: " + param1 / 100.0 + "U") + } status = "REFILL " + dateUtil.timeString(datetime) } @@ -207,15 +271,16 @@ open class DanaRS_Packet_APS_History_Events( } DanaPump.PRIMECANNULA -> { - aapsLogger.debug(LTag.PUMPCOMM, "[" + id + "] " + "EVENT PRIMECANNULA(" + recordCode + ") " + dateUtil.dateAndTimeString(datetime) + " (" + datetime + ")" + " Amount: " + param1 / 100.0 + "U") - if (sp.getBoolean(R.string.key_rs_logcanulachange, true)) - pumpSync.insertTherapyEventIfNewWithTimestamp( + if (sp.getBoolean(R.string.key_rs_logcanulachange, true)) { + val newRecord = pumpSync.insertTherapyEventIfNewWithTimestamp( timestamp = datetime, type = DetailedBolusInfo.EventType.CANNULA_CHANGE, pumpId = pumpId, pumpType = danaPump.pumpType(), pumpSerial = danaPump.serialNumber ) + aapsLogger.debug(LTag.PUMPCOMM, "[" + id + "] " + (if (newRecord) "**NEW** " else "") + "EVENT PRIMECANNULA(" + recordCode + ") " + dateUtil.dateAndTimeString(datetime) + " (" + datetime + ")" + " Amount: " + param1 / 100.0 + "U") + } status = "PRIMECANNULA " + dateUtil.timeString(datetime) } diff --git a/danars/src/main/java/info/nightscout/androidaps/danars/comm/DanaRS_Packet_Basal_Get_Temporary_Basal_State.kt b/danars/src/main/java/info/nightscout/androidaps/danars/comm/DanaRS_Packet_Basal_Get_Temporary_Basal_State.kt index 1471af5478..874e13ab25 100644 --- a/danars/src/main/java/info/nightscout/androidaps/danars/comm/DanaRS_Packet_Basal_Get_Temporary_Basal_State.kt +++ b/danars/src/main/java/info/nightscout/androidaps/danars/comm/DanaRS_Packet_Basal_Get_Temporary_Basal_State.kt @@ -5,6 +5,7 @@ import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.dana.DanaPump import info.nightscout.androidaps.danars.encryption.BleEncryption import javax.inject.Inject +import kotlin.math.abs import kotlin.math.ceil class DanaRS_Packet_Basal_Get_Temporary_Basal_State( @@ -20,22 +21,23 @@ class DanaRS_Packet_Basal_Get_Temporary_Basal_State( override fun handleMessage(data: ByteArray) { val error = byteArrayToInt(getBytes(data, DATA_START, 1)) - danaPump.isTempBasalInProgress = byteArrayToInt(getBytes(data, DATA_START + 1, 1)) == 0x01 + val isTempBasalInProgress = byteArrayToInt(getBytes(data, DATA_START + 1, 1)) == 0x01 val isAPSTempBasalInProgress = byteArrayToInt(getBytes(data, DATA_START + 1, 1)) == 0x02 - danaPump.tempBasalPercent = byteArrayToInt(getBytes(data, DATA_START + 2, 1)) - if (danaPump.tempBasalPercent > 200) danaPump.tempBasalPercent = (danaPump.tempBasalPercent - 200) * 10 + var tempBasalPercent = byteArrayToInt(getBytes(data, DATA_START + 2, 1)) + if (tempBasalPercent > 200) tempBasalPercent = (tempBasalPercent - 200) * 10 val durationHour = byteArrayToInt(getBytes(data, DATA_START + 3, 1)) - if (durationHour == 150) danaPump.tempBasalTotalSec = 15 * 60 else if (durationHour == 160) danaPump.tempBasalTotalSec = 30 * 60 else danaPump.tempBasalTotalSec = durationHour * 60 * 60 + val tempBasalTotalSec: Int = if (durationHour == 150) 15 * 60 else if (durationHour == 160) 30 * 60 else durationHour * 60 * 60 val runningMin = byteArrayToInt(getBytes(data, DATA_START + 4, 2)) if (error != 0) failed = true val tempBasalRemainingMin = (danaPump.tempBasalTotalSec - runningMin * 60) / 60 - val tempBasalStart = if (danaPump.isTempBasalInProgress) getDateFromTempBasalSecAgo(runningMin * 60) else 0 + val tempBasalStart = if (isTempBasalInProgress) getDateFromTempBasalSecAgo(runningMin * 60) else 0 + if (!isTempBasalInProgress) danaPump.isTempBasalInProgress = false aapsLogger.debug(LTag.PUMPCOMM, "Error code: $error") - aapsLogger.debug(LTag.PUMPCOMM, "Is temp basal running: " + danaPump.isTempBasalInProgress) + aapsLogger.debug(LTag.PUMPCOMM, "Is temp basal running: $isTempBasalInProgress") aapsLogger.debug(LTag.PUMPCOMM, "Is APS temp basal running: $isAPSTempBasalInProgress") - aapsLogger.debug(LTag.PUMPCOMM, "Current temp basal percent: " + danaPump.tempBasalPercent) + aapsLogger.debug(LTag.PUMPCOMM, "Current temp basal percent: $tempBasalPercent") aapsLogger.debug(LTag.PUMPCOMM, "Current temp basal remaining min: $tempBasalRemainingMin") - aapsLogger.debug(LTag.PUMPCOMM, "Current temp basal total sec: " + danaPump.tempBasalTotalSec) + aapsLogger.debug(LTag.PUMPCOMM, "Current temp basal total sec: $tempBasalTotalSec") aapsLogger.debug(LTag.PUMPCOMM, "Current temp basal start: " + dateUtil.dateAndTimeString(tempBasalStart)) } diff --git a/danars/src/main/java/info/nightscout/androidaps/danars/comm/DanaRS_Packet_Bolus_Get_Dual_Bolus.kt b/danars/src/main/java/info/nightscout/androidaps/danars/comm/DanaRS_Packet_Bolus_Get_Dual_Bolus.kt index babe627091..309f3ed561 100644 --- a/danars/src/main/java/info/nightscout/androidaps/danars/comm/DanaRS_Packet_Bolus_Get_Dual_Bolus.kt +++ b/danars/src/main/java/info/nightscout/androidaps/danars/comm/DanaRS_Packet_Bolus_Get_Dual_Bolus.kt @@ -20,13 +20,13 @@ class DanaRS_Packet_Bolus_Get_Dual_Bolus( override fun handleMessage(data: ByteArray) { val error = byteArrayToInt(getBytes(data, DATA_START, 1)) danaPump.bolusStep = byteArrayToInt(getBytes(data, DATA_START + 1, 2)) / 100.0 - danaPump.extendedBolusAbsoluteRate = byteArrayToInt(getBytes(data, DATA_START + 3, 2)) / 100.0 + val extendedBolusAbsoluteRate = byteArrayToInt(getBytes(data, DATA_START + 3, 2)) / 100.0 danaPump.maxBolus = byteArrayToInt(getBytes(data, DATA_START + 5, 2)) / 100.0 val bolusIncrement = byteArrayToInt(getBytes(data, DATA_START + 7, 1)) / 100.0 failed = error != 0 aapsLogger.debug(LTag.PUMPCOMM, "Result: $error") aapsLogger.debug(LTag.PUMPCOMM, "Bolus step: ${danaPump.bolusStep} U") - aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus running: ${danaPump.extendedBolusAbsoluteRate} U/h") + aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus running: $extendedBolusAbsoluteRate U/h") aapsLogger.debug(LTag.PUMPCOMM, "Max bolus: " + danaPump.maxBolus + " U") aapsLogger.debug(LTag.PUMPCOMM, "bolusIncrement: $bolusIncrement U") } diff --git a/danars/src/main/java/info/nightscout/androidaps/danars/comm/DanaRS_Packet_Bolus_Get_Extended_Bolus.kt b/danars/src/main/java/info/nightscout/androidaps/danars/comm/DanaRS_Packet_Bolus_Get_Extended_Bolus.kt index 8aae55b413..623e1f8361 100644 --- a/danars/src/main/java/info/nightscout/androidaps/danars/comm/DanaRS_Packet_Bolus_Get_Extended_Bolus.kt +++ b/danars/src/main/java/info/nightscout/androidaps/danars/comm/DanaRS_Packet_Bolus_Get_Extended_Bolus.kt @@ -23,7 +23,7 @@ class DanaRS_Packet_Bolus_Get_Extended_Bolus( val error = byteArrayToInt(getBytes(data, dataIndex, dataSize)) dataIndex += dataSize dataSize = 2 - danaPump.extendedBolusAbsoluteRate = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100.0 + val extendedBolusAbsoluteRate = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100.0 dataIndex += dataSize dataSize = 2 danaPump.maxBolus = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100.0 @@ -32,7 +32,7 @@ class DanaRS_Packet_Bolus_Get_Extended_Bolus( danaPump.bolusStep = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100.0 failed = error != 0 aapsLogger.debug(LTag.PUMPCOMM, "Result: $error") - aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus running: " + danaPump.extendedBolusAbsoluteRate + " U/h") + aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus running: $extendedBolusAbsoluteRate U/h") aapsLogger.debug(LTag.PUMPCOMM, "Max bolus: " + danaPump.maxBolus + " U") aapsLogger.debug(LTag.PUMPCOMM, "Bolus step: " + danaPump.bolusStep + " U") } diff --git a/danars/src/main/java/info/nightscout/androidaps/danars/comm/DanaRS_Packet_Bolus_Get_Extended_Bolus_State.kt b/danars/src/main/java/info/nightscout/androidaps/danars/comm/DanaRS_Packet_Bolus_Get_Extended_Bolus_State.kt index 7c859ed743..a94216a90a 100644 --- a/danars/src/main/java/info/nightscout/androidaps/danars/comm/DanaRS_Packet_Bolus_Get_Extended_Bolus_State.kt +++ b/danars/src/main/java/info/nightscout/androidaps/danars/comm/DanaRS_Packet_Bolus_Get_Extended_Bolus_State.kt @@ -4,6 +4,7 @@ import dagger.android.HasAndroidInjector import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.dana.DanaPump import info.nightscout.androidaps.danars.encryption.BleEncryption +import info.nightscout.androidaps.utils.T import javax.inject.Inject class DanaRS_Packet_Bolus_Get_Extended_Bolus_State( @@ -23,26 +24,26 @@ class DanaRS_Packet_Bolus_Get_Extended_Bolus_State( val error = byteArrayToInt(getBytes(data, dataIndex, dataSize)) dataIndex += dataSize dataSize = 1 - danaPump.isExtendedInProgress = byteArrayToInt(getBytes(data, dataIndex, dataSize)) == 0x01 + val isExtendedInProgress = byteArrayToInt(getBytes(data, dataIndex, dataSize)) == 0x01 dataIndex += dataSize dataSize = 1 - danaPump.extendedBolusMinutes = byteArrayToInt(getBytes(data, dataIndex, dataSize)) * 30 + val extendedBolusDuration = T.mins(byteArrayToInt(getBytes(data, dataIndex, dataSize)) * 30L).msecs() dataIndex += dataSize dataSize = 2 - danaPump.extendedBolusAbsoluteRate = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100.0 + val extendedBolusAbsoluteRate = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100.0 // duration must be set first for recalculation to amount dataIndex += dataSize dataSize = 2 - danaPump.extendedBolusSoFarInMinutes = byteArrayToInt(getBytes(data, dataIndex, dataSize)) + val extendedBolusSoFarInMinutes = byteArrayToInt(getBytes(data, dataIndex, dataSize)) dataIndex += dataSize dataSize = 2 - danaPump.extendedBolusDeliveredSoFar = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100.0 + val extendedBolusDeliveredSoFar = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100.0 failed = error != 0 aapsLogger.debug(LTag.PUMPCOMM, "Result: $error") - aapsLogger.debug(LTag.PUMPCOMM, "Is extended bolus running: " + danaPump.isExtendedInProgress) - aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus running: " + danaPump.extendedBolusAbsoluteRate + " U/h") - aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus duration: " + danaPump.extendedBolusMinutes + " min") - aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus so far: " + danaPump.extendedBolusSoFarInMinutes + " min") - aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus delivered so far: " + danaPump.extendedBolusDeliveredSoFar + " U") + aapsLogger.debug(LTag.PUMPCOMM, "Is extended bolus running: $isExtendedInProgress") + aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus running: $extendedBolusAbsoluteRate U/h") + aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus duration: " + T.msecs(extendedBolusDuration).mins() + " min") + aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus so far: $extendedBolusSoFarInMinutes min") + aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus delivered so far: $extendedBolusDeliveredSoFar U") } override fun getFriendlyName(): String { diff --git a/danars/src/main/java/info/nightscout/androidaps/danars/comm/DanaRS_Packet_General_Get_More_Information.kt b/danars/src/main/java/info/nightscout/androidaps/danars/comm/DanaRS_Packet_General_Get_More_Information.kt index 0d110deb71..4659e91dae 100644 --- a/danars/src/main/java/info/nightscout/androidaps/danars/comm/DanaRS_Packet_General_Get_More_Information.kt +++ b/danars/src/main/java/info/nightscout/androidaps/danars/comm/DanaRS_Packet_General_Get_More_Information.kt @@ -26,8 +26,8 @@ class DanaRS_Packet_General_Get_More_Information( } danaPump.iob = intFromBuff(data, 0, 2) / 100.0 danaPump.dailyTotalUnits = intFromBuff(data, 2, 2) / 100.0 - danaPump.isExtendedInProgress = intFromBuff(data, 4, 1) == 0x01 - danaPump.extendedBolusRemainingMinutes = intFromBuff(data, 5, 2) + val isExtendedInProgress = intFromBuff(data, 4, 1) == 0x01 + val extendedBolusRemainingMinutes = intFromBuff(data, 5, 2) // val remainRate = intFromBuff(data, 7, 2) / 100.0 val hours = intFromBuff(data, 9, 1) val minutes = intFromBuff(data, 10, 1) @@ -37,8 +37,8 @@ class DanaRS_Packet_General_Get_More_Information( // On DanaRS DailyUnits can't be more than 160 if (danaPump.dailyTotalUnits > 160) failed = true aapsLogger.debug(LTag.PUMPCOMM, "Daily total units: " + danaPump.dailyTotalUnits.toString() + " U") - aapsLogger.debug(LTag.PUMPCOMM, "Is extended in progress: " + danaPump.isExtendedInProgress) - aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus remaining minutes: " + danaPump.extendedBolusRemainingMinutes) + aapsLogger.debug(LTag.PUMPCOMM, "Is extended in progress: $isExtendedInProgress") + aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus remaining minutes: $extendedBolusRemainingMinutes") aapsLogger.debug(LTag.PUMPCOMM, "Last bolus time: " + dateUtil.dateAndTimeAndSecondsString(danaPump.lastBolusTime)) aapsLogger.debug(LTag.PUMPCOMM, "Last bolus amount: " + danaPump.lastBolusAmount) } diff --git a/danars/src/main/java/info/nightscout/androidaps/danars/comm/DanaRS_Packet_General_Initial_Screen_Information.kt b/danars/src/main/java/info/nightscout/androidaps/danars/comm/DanaRS_Packet_General_Initial_Screen_Information.kt index 8eeb017ebb..35a0e35487 100644 --- a/danars/src/main/java/info/nightscout/androidaps/danars/comm/DanaRS_Packet_General_Initial_Screen_Information.kt +++ b/danars/src/main/java/info/nightscout/androidaps/danars/comm/DanaRS_Packet_General_Initial_Screen_Information.kt @@ -26,9 +26,9 @@ class DanaRS_Packet_General_Initial_Screen_Information( var dataSize = 1 val status = byteArrayToInt(getBytes(data, dataIndex, dataSize)) danaPump.pumpSuspended = status and 0x01 == 0x01 - danaPump.isTempBasalInProgress = status and 0x10 == 0x10 - danaPump.isExtendedInProgress = status and 0x04 == 0x04 - danaPump.isDualBolusInProgress = status and 0x08 == 0x08 + val isTempBasalInProgress = status and 0x10 == 0x10 + val isExtendedInProgress = status and 0x04 == 0x04 + val isDualBolusInProgress = status and 0x08 == 0x08 dataIndex += dataSize dataSize = 2 danaPump.dailyTotalUnits = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100.0 @@ -43,13 +43,13 @@ class DanaRS_Packet_General_Initial_Screen_Information( danaPump.currentBasal = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100.0 dataIndex += dataSize dataSize = 1 - danaPump.tempBasalPercent = byteArrayToInt(getBytes(data, dataIndex, dataSize)) + val tempBasalPercent = byteArrayToInt(getBytes(data, dataIndex, dataSize)) dataIndex += dataSize dataSize = 1 danaPump.batteryRemaining = byteArrayToInt(getBytes(data, dataIndex, dataSize)) dataIndex += dataSize dataSize = 2 - danaPump.extendedBolusAbsoluteRate = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100.0 + val extendedBolusAbsoluteRate = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100.0 dataIndex += dataSize dataSize = 2 danaPump.iob = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100.0 @@ -62,16 +62,16 @@ class DanaRS_Packet_General_Initial_Screen_Information( aapsLogger.debug(LTag.PUMPCOMM, "ErrorState: " + danaPump.errorState.name) } aapsLogger.debug(LTag.PUMPCOMM, "Pump suspended: " + danaPump.pumpSuspended) - aapsLogger.debug(LTag.PUMPCOMM, "Temp basal in progress: " + danaPump.isTempBasalInProgress) - aapsLogger.debug(LTag.PUMPCOMM, "Extended in progress: " + danaPump.isExtendedInProgress) - aapsLogger.debug(LTag.PUMPCOMM, "Dual in progress: " + danaPump.isDualBolusInProgress) + aapsLogger.debug(LTag.PUMPCOMM, "Temp basal in progress: $isTempBasalInProgress") + aapsLogger.debug(LTag.PUMPCOMM, "Extended in progress: $isExtendedInProgress") + aapsLogger.debug(LTag.PUMPCOMM, "Dual in progress: $isDualBolusInProgress") aapsLogger.debug(LTag.PUMPCOMM, "Daily units: " + danaPump.dailyTotalUnits) aapsLogger.debug(LTag.PUMPCOMM, "Max daily units: " + danaPump.maxDailyTotalUnits) aapsLogger.debug(LTag.PUMPCOMM, "Reservoir remaining units: " + danaPump.reservoirRemainingUnits) aapsLogger.debug(LTag.PUMPCOMM, "Battery: " + danaPump.batteryRemaining) aapsLogger.debug(LTag.PUMPCOMM, "Current basal: " + danaPump.currentBasal) - aapsLogger.debug(LTag.PUMPCOMM, "Temp basal percent: " + danaPump.tempBasalPercent) - aapsLogger.debug(LTag.PUMPCOMM, "Extended absolute rate: " + danaPump.extendedBolusAbsoluteRate) + aapsLogger.debug(LTag.PUMPCOMM, "Temp basal percent: " + tempBasalPercent) + aapsLogger.debug(LTag.PUMPCOMM, "Extended absolute rate: $extendedBolusAbsoluteRate") } override fun getFriendlyName(): String { diff --git a/danars/src/main/java/info/nightscout/androidaps/danars/services/BLEComm.kt b/danars/src/main/java/info/nightscout/androidaps/danars/services/BLEComm.kt index 3661590e90..d2abeed7a6 100644 --- a/danars/src/main/java/info/nightscout/androidaps/danars/services/BLEComm.kt +++ b/danars/src/main/java/info/nightscout/androidaps/danars/services/BLEComm.kt @@ -27,8 +27,8 @@ import info.nightscout.androidaps.plugins.general.overview.notifications.Notific import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.ToastUtils -import info.nightscout.androidaps.utils.extensions.notify -import info.nightscout.androidaps.utils.extensions.waitMillis +import info.nightscout.androidaps.extensions.notify +import info.nightscout.androidaps.extensions.waitMillis import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.sharedPreferences.SP import java.util.* diff --git a/danars/src/main/java/info/nightscout/androidaps/danars/services/DanaRSService.kt b/danars/src/main/java/info/nightscout/androidaps/danars/services/DanaRSService.kt index c729c0e3cd..6df71516d6 100644 --- a/danars/src/main/java/info/nightscout/androidaps/danars/services/DanaRSService.kt +++ b/danars/src/main/java/info/nightscout/androidaps/danars/services/DanaRSService.kt @@ -75,7 +75,6 @@ class DanaRSService : DaggerService() { private val disposable = CompositeDisposable() private val mBinder: IBinder = LocalBinder() - private var lastHistoryFetched: Long = 0 private var lastApproachingDailyLimit: Long = 0 override fun onCreate() { @@ -130,17 +129,12 @@ class DanaRSService : DaggerService() { sendMessage(DanaRS_Packet_Option_Get_User_Option(injector)) // Getting user options rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.gettingpumpstatus))) sendMessage(DanaRS_Packet_General_Initial_Screen_Information(injector)) - rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.gettingextendedbolusstatus))) - sendMessage(DanaRS_Packet_Bolus_Get_Extended_Bolus_State(injector)) rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.gettingbolusstatus))) sendMessage(DanaRS_Packet_Bolus_Get_Step_Bolus_Information(injector)) // last bolus, bolusStep, maxBolus - rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.gettingtempbasalstatus))) - sendMessage(DanaRS_Packet_Basal_Get_Temporary_Basal_State(injector)) danaPump.lastConnection = System.currentTimeMillis() val profile = profileFunction.getProfile() if (profile != null && abs(danaPump.currentBasal - profile.basal) >= pump.pumpDescription.basalStep) { rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.gettingpumpsettings))) - sendMessage(DanaRS_Packet_Basal_Get_Basal_Rate(injector)) // basal profile, basalStep, maxBasal if (!pump.isThisProfileSet(profile) && !commandQueue.isRunning(Command.CommandType.BASAL_PROFILE)) { rxBus.send(EventProfileNeedsUpdate()) } @@ -197,6 +191,11 @@ class DanaRSService : DaggerService() { } } loadEvents() + // RS doesn't provide exact timestamp = rely on history + val eb = pumpSync.expectedPumpState().extendedBolus + danaPump.fromExtendedBolus(eb) + val tbr = pumpSync.expectedPumpState().temporaryBasal + danaPump.fromTemporaryBasal(tbr) rxBus.send(EventDanaRNewStatus()) rxBus.send(EventInitializationChanged()) //NSUpload.uploadDeviceStatus(); @@ -223,18 +222,18 @@ class DanaRSService : DaggerService() { } SystemClock.sleep(1000) val msg: DanaRS_Packet_APS_History_Events - if (lastHistoryFetched == 0L) { + if (danaPump.lastHistoryFetched == 0L) { msg = DanaRS_Packet_APS_History_Events(injector, 0) aapsLogger.debug(LTag.PUMPCOMM, "Loading complete event history") } else { - msg = DanaRS_Packet_APS_History_Events(injector, lastHistoryFetched) - aapsLogger.debug(LTag.PUMPCOMM, "Loading event history from: " + dateUtil.dateAndTimeString(lastHistoryFetched)) + msg = DanaRS_Packet_APS_History_Events(injector, danaPump.lastHistoryFetched) + aapsLogger.debug(LTag.PUMPCOMM, "Loading event history from: " + dateUtil.dateAndTimeString(danaPump.lastHistoryFetched)) } sendMessage(msg) while (!danaPump.historyDoneReceived && bleComm.isConnected) { SystemClock.sleep(100) } - lastHistoryFetched = if (danaPump.lastEventTimeLoaded != 0L) danaPump.lastEventTimeLoaded - T.mins(1).msecs() else 0 + danaPump.lastHistoryFetched = if (danaPump.lastEventTimeLoaded != 0L) danaPump.lastEventTimeLoaded - T.mins(1).msecs() else 0 aapsLogger.debug(LTag.PUMPCOMM, "Events loaded") danaPump.lastConnection = System.currentTimeMillis() return PumpEnactResult(injector).success(msg.success()) @@ -263,7 +262,7 @@ class DanaRSService : DaggerService() { // sendMessage(msg); val msgSetHistoryEntryV2 = DanaRS_Packet_APS_Set_Event_History(injector, DanaPump.CARBS, carbTime, carbs, 0) sendMessage(msgSetHistoryEntryV2) - lastHistoryFetched = min(lastHistoryFetched, carbTime - T.mins(1).msecs()) + danaPump.lastHistoryFetched = min(danaPump.lastHistoryFetched, carbTime - T.mins(1).msecs()) } val bolusStart = System.currentTimeMillis() if (insulin > 0) { @@ -340,8 +339,9 @@ class DanaRSService : DaggerService() { val msgTBR = DanaRS_Packet_Basal_Set_Temporary_Basal(injector, percent, durationInHours) sendMessage(msgTBR) SystemClock.sleep(200) - sendMessage(DanaRS_Packet_Basal_Get_Temporary_Basal_State(injector)) loadEvents() + val tbr = pumpSync.expectedPumpState().temporaryBasal + danaPump.fromTemporaryBasal(tbr) rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)) return msgTBR.success() } @@ -355,8 +355,9 @@ class DanaRSService : DaggerService() { rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.settingtempbasal))) val msgTBR = DanaRS_Packet_APS_Basal_Set_Temporary_Basal(injector, percent) sendMessage(msgTBR) - sendMessage(DanaRS_Packet_Basal_Get_Temporary_Basal_State(injector)) loadEvents() + val tbr = pumpSync.expectedPumpState().temporaryBasal + danaPump.fromTemporaryBasal(tbr) rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)) return msgTBR.success() } @@ -374,8 +375,9 @@ class DanaRSService : DaggerService() { rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.settingtempbasal))) val msgTBR = DanaRS_Packet_APS_Basal_Set_Temporary_Basal(injector, percent) sendMessage(msgTBR) - sendMessage(DanaRS_Packet_Basal_Get_Temporary_Basal_State(injector)) loadEvents() + val tbr = pumpSync.expectedPumpState().temporaryBasal + danaPump.fromTemporaryBasal(tbr) rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)) return msgTBR.success() } @@ -385,8 +387,9 @@ class DanaRSService : DaggerService() { rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.stoppingtempbasal))) val msgCancel = DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal(injector) sendMessage(msgCancel) - sendMessage(DanaRS_Packet_Basal_Get_Temporary_Basal_State(injector)) loadEvents() + val tbr = pumpSync.expectedPumpState().temporaryBasal + danaPump.fromTemporaryBasal(tbr) rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)) return msgCancel.success() } @@ -397,8 +400,9 @@ class DanaRSService : DaggerService() { val msgExtended = DanaRS_Packet_Bolus_Set_Extended_Bolus(injector, insulin, durationInHalfHours) sendMessage(msgExtended) SystemClock.sleep(200) - sendMessage(DanaRS_Packet_Bolus_Get_Extended_Bolus_State(injector)) loadEvents() + val eb = pumpSync.expectedPumpState().extendedBolus + danaPump.fromExtendedBolus(eb) rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)) return msgExtended.success() } @@ -408,8 +412,9 @@ class DanaRSService : DaggerService() { rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.stoppingextendedbolus))) val msgStop = DanaRS_Packet_Bolus_Set_Extended_Bolus_Cancel(injector) sendMessage(msgStop) - sendMessage(DanaRS_Packet_Bolus_Get_Extended_Bolus_State(injector)) loadEvents() + val eb = pumpSync.expectedPumpState().extendedBolus + danaPump.fromExtendedBolus(eb) rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)) return msgStop.success() } diff --git a/danars/src/test/java/info/nightscout/androidaps/danars/DanaRSPluginTest.kt b/danars/src/test/java/info/nightscout/androidaps/danars/DanaRSPluginTest.kt index 70863cdf8d..9276960e96 100644 --- a/danars/src/test/java/info/nightscout/androidaps/danars/DanaRSPluginTest.kt +++ b/danars/src/test/java/info/nightscout/androidaps/danars/DanaRSPluginTest.kt @@ -1,17 +1,16 @@ -package info.nightscout.androidaps.plugins.pump.danars +package info.nightscout.androidaps.danars import android.content.Context import dagger.android.AndroidInjector import info.nightscout.androidaps.Constants -import info.nightscout.androidaps.danars.DanaRSPlugin -import info.nightscout.androidaps.danars.DanaRSTestBase -import info.nightscout.androidaps.danars.R import info.nightscout.androidaps.interfaces.CommandQueueProvider import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.interfaces.PluginType +import info.nightscout.androidaps.interfaces.PumpSync import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInfoStorage +import info.nightscout.androidaps.plugins.pump.common.bolusInfo.TemporaryBasalStorage import org.junit.Assert import org.junit.Before import org.junit.Test @@ -31,6 +30,8 @@ class DanaRSPluginTest : DanaRSTestBase() { @Mock lateinit var constraintChecker: ConstraintChecker @Mock lateinit var commandQueue: CommandQueueProvider @Mock lateinit var detailedBolusInfoStorage: DetailedBolusInfoStorage + @Mock lateinit var temporaryBasalStorage: TemporaryBasalStorage + @Mock lateinit var pumpSync: PumpSync private lateinit var danaRSPlugin: DanaRSPlugin @@ -64,6 +65,6 @@ class DanaRSPluginTest : DanaRSTestBase() { Mockito.`when`(resourceHelper.gs(eq(R.string.limitingbasalratio), anyObject(), anyObject())).thenReturn("limitingbasalratio") Mockito.`when`(resourceHelper.gs(eq(R.string.limitingpercentrate), anyObject(), anyObject())).thenReturn("limitingpercentrate") - danaRSPlugin = DanaRSPlugin({ AndroidInjector { } }, aapsLogger, aapsSchedulers, rxBus, context, resourceHelper, constraintChecker, profileFunction, activePluginProvider, sp, commandQueue, danaPump, detailedBolusInfoStorage, fabricPrivacy, dateUtil) + danaRSPlugin = DanaRSPlugin({ AndroidInjector { } }, aapsLogger, aapsSchedulers, rxBus, context, resourceHelper, constraintChecker, profileFunction, sp, commandQueue, danaPump, pumpSync, detailedBolusInfoStorage, temporaryBasalStorage, fabricPrivacy, dateUtil) } } \ No newline at end of file diff --git a/danars/src/test/java/info/nightscout/androidaps/danars/DanaRSTestBase.kt b/danars/src/test/java/info/nightscout/androidaps/danars/DanaRSTestBase.kt index 5168ab69df..e641f0139c 100644 --- a/danars/src/test/java/info/nightscout/androidaps/danars/DanaRSTestBase.kt +++ b/danars/src/test/java/info/nightscout/androidaps/danars/DanaRSTestBase.kt @@ -64,6 +64,6 @@ open class DanaRSTestBase : TestBaseWithProfile() { @Before fun setup() { - danaPump = DanaPump(aapsLogger, sp, injector) + danaPump = DanaPump(aapsLogger, sp, dateUtil, injector) } } \ No newline at end of file diff --git a/danars/src/test/java/info/nightscout/androidaps/danars/comm/DanaRsPacketApsHistoryEventsTest.kt b/danars/src/test/java/info/nightscout/androidaps/danars/comm/DanaRsPacketApsHistoryEventsTest.kt index cea0e79c1c..c87f4b64dc 100644 --- a/danars/src/test/java/info/nightscout/androidaps/danars/comm/DanaRsPacketApsHistoryEventsTest.kt +++ b/danars/src/test/java/info/nightscout/androidaps/danars/comm/DanaRsPacketApsHistoryEventsTest.kt @@ -4,10 +4,12 @@ import android.content.Context import dagger.android.AndroidInjector import dagger.android.HasAndroidInjector import info.nightscout.androidaps.danars.DanaRSPlugin +import info.nightscout.androidaps.danars.DanaRSTestBase import info.nightscout.androidaps.interfaces.ActivePluginProvider +import info.nightscout.androidaps.interfaces.PumpSync import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInfoStorage -import info.nightscout.androidaps.danars.DanaRSTestBase +import info.nightscout.androidaps.plugins.pump.common.bolusInfo.TemporaryBasalStorage import info.nightscout.androidaps.utils.DateUtil import org.junit.Assert import org.junit.Test @@ -23,7 +25,9 @@ class DanaRsPacketApsHistoryEventsTest : DanaRSTestBase() { @Mock lateinit var context: Context @Mock lateinit var activePlugin: ActivePluginProvider + @Mock lateinit var pumpSync: PumpSync @Mock lateinit var detailedBolusInfoStorage: DetailedBolusInfoStorage + @Mock lateinit var temporaryBasalStorage: TemporaryBasalStorage private val packetInjector = HasAndroidInjector { AndroidInjector { @@ -34,9 +38,10 @@ class DanaRsPacketApsHistoryEventsTest : DanaRSTestBase() { if (it is DanaRS_Packet_APS_History_Events) { it.rxBus = rxBus it.resourceHelper = resourceHelper - it.activePlugin = activePlugin + it.pumpSync = pumpSync it.danaPump = danaPump it.detailedBolusInfoStorage = detailedBolusInfoStorage + it.temporaryBasalStorage = temporaryBasalStorage it.sp = sp } } diff --git a/danars/src/test/java/info/nightscout/androidaps/danars/comm/DanaRsPacketBolusSetStepBolusStartTest.kt b/danars/src/test/java/info/nightscout/androidaps/danars/comm/DanaRsPacketBolusSetStepBolusStartTest.kt index 95b95df7a7..9bc907d7c2 100644 --- a/danars/src/test/java/info/nightscout/androidaps/danars/comm/DanaRsPacketBolusSetStepBolusStartTest.kt +++ b/danars/src/test/java/info/nightscout/androidaps/danars/comm/DanaRsPacketBolusSetStepBolusStartTest.kt @@ -7,8 +7,10 @@ import info.nightscout.androidaps.danars.DanaRSPlugin import info.nightscout.androidaps.danars.DanaRSTestBase import info.nightscout.androidaps.interfaces.CommandQueueProvider import info.nightscout.androidaps.interfaces.Constraint +import info.nightscout.androidaps.interfaces.PumpSync import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInfoStorage +import info.nightscout.androidaps.plugins.pump.common.bolusInfo.TemporaryBasalStorage import org.junit.Assert import org.junit.Before import org.junit.Test @@ -26,6 +28,8 @@ class DanaRsPacketBolusSetStepBolusStartTest : DanaRSTestBase() { @Mock lateinit var commandQueue: CommandQueueProvider @Mock lateinit var context: Context @Mock lateinit var detailedBolusInfoStorage: DetailedBolusInfoStorage + @Mock lateinit var temporaryBasalStorage: TemporaryBasalStorage + @Mock lateinit var pumpSync: PumpSync private lateinit var danaRSPlugin: DanaRSPlugin @@ -55,7 +59,7 @@ class DanaRsPacketBolusSetStepBolusStartTest : DanaRSTestBase() { @Before fun mock() { - danaRSPlugin = DanaRSPlugin({ AndroidInjector { } }, aapsLogger, aapsSchedulers, rxBus, context, resourceHelper, constraintChecker, profileFunction, activePluginProvider, sp, commandQueue, danaPump, detailedBolusInfoStorage, fabricPrivacy, dateUtil) + danaRSPlugin = DanaRSPlugin({ AndroidInjector { } }, aapsLogger, aapsSchedulers, rxBus, context, resourceHelper, constraintChecker, profileFunction, sp, commandQueue, danaPump, pumpSync, detailedBolusInfoStorage, temporaryBasalStorage, fabricPrivacy, dateUtil) Mockito.`when`(constraintChecker.applyBolusConstraints(anyObject())).thenReturn(Constraint(0.0)) } } \ No newline at end of file diff --git a/danars/src/test/java/info/nightscout/androidaps/danars/comm/DanaRsPacketNotifyDeliveryRateDisplayTest.kt b/danars/src/test/java/info/nightscout/androidaps/danars/comm/DanaRsPacketNotifyDeliveryRateDisplayTest.kt index 1c24195165..1e039e0fda 100644 --- a/danars/src/test/java/info/nightscout/androidaps/danars/comm/DanaRsPacketNotifyDeliveryRateDisplayTest.kt +++ b/danars/src/test/java/info/nightscout/androidaps/danars/comm/DanaRsPacketNotifyDeliveryRateDisplayTest.kt @@ -7,10 +7,12 @@ import info.nightscout.androidaps.danars.DanaRSPlugin import info.nightscout.androidaps.danars.DanaRSTestBase import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.CommandQueueProvider +import info.nightscout.androidaps.interfaces.PumpSync import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInfoStorage +import info.nightscout.androidaps.plugins.pump.common.bolusInfo.TemporaryBasalStorage import org.junit.Assert import org.junit.Before import org.junit.Test @@ -30,6 +32,8 @@ class DanaRsPacketNotifyDeliveryRateDisplayTest : DanaRSTestBase() { @Mock lateinit var commandQueue: CommandQueueProvider @Mock lateinit var context: Context @Mock lateinit var detailedBolusInfoStorage: DetailedBolusInfoStorage + @Mock lateinit var temporaryBasalStorage: TemporaryBasalStorage + @Mock lateinit var pumpSync: PumpSync private lateinit var danaRSPlugin: DanaRSPlugin @@ -62,7 +66,7 @@ class DanaRsPacketNotifyDeliveryRateDisplayTest : DanaRSTestBase() { @Before fun mock() { - danaRSPlugin = DanaRSPlugin(packetInjector, aapsLogger, aapsSchedulers, rxBus, context, resourceHelper, constraintChecker, profileFunction, activePluginProvider, sp, commandQueue, danaPump, detailedBolusInfoStorage, fabricPrivacy, dateUtil) + danaRSPlugin = DanaRSPlugin(packetInjector, aapsLogger, aapsSchedulers, rxBus, context, resourceHelper, constraintChecker, profileFunction, sp, commandQueue, danaPump, pumpSync, detailedBolusInfoStorage, temporaryBasalStorage, fabricPrivacy, dateUtil) danaPump.bolusingTreatment = EventOverviewBolusProgress.Treatment(0.0, 0, true) } } \ No newline at end of file diff --git a/database/schemas/info.nightscout.androidaps.database.AppDatabase/11.json b/database/schemas/info.nightscout.androidaps.database.AppDatabase/11.json new file mode 100644 index 0000000000..15956090cc --- /dev/null +++ b/database/schemas/info.nightscout.androidaps.database.AppDatabase/11.json @@ -0,0 +1,2943 @@ +{ + "formatVersion": 1, + "database": { + "version": 11, + "identityHash": "5590bbcf7038e4422cf50dc16863b7c2", + "entities": [ + { + "tableName": "apsResults", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `algorithm` TEXT NOT NULL, `glucoseStatusJson` TEXT NOT NULL, `currentTempJson` TEXT NOT NULL, `iobDataJson` TEXT NOT NULL, `profileJson` TEXT NOT NULL, `autosensDataJson` TEXT, `mealDataJson` TEXT NOT NULL, `isMicroBolusAllowed` INTEGER, `resultJson` TEXT NOT NULL, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `temporaryId` INTEGER, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`referenceId`) REFERENCES `apsResults`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isValid", + "columnName": "isValid", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "referenceId", + "columnName": "referenceId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "utcOffset", + "columnName": "utcOffset", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "algorithm", + "columnName": "algorithm", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "glucoseStatusJson", + "columnName": "glucoseStatusJson", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "currentTempJson", + "columnName": "currentTempJson", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "iobDataJson", + "columnName": "iobDataJson", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "profileJson", + "columnName": "profileJson", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "autosensDataJson", + "columnName": "autosensDataJson", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "mealDataJson", + "columnName": "mealDataJson", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "isMicroBolusAllowed", + "columnName": "isMicroBolusAllowed", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "resultJson", + "columnName": "resultJson", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutSystemId", + "columnName": "nightscoutSystemId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutId", + "columnName": "nightscoutId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpType", + "columnName": "pumpType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpSerial", + "columnName": "pumpSerial", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.temporaryId", + "columnName": "temporaryId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpId", + "columnName": "pumpId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.startId", + "columnName": "startId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.endId", + "columnName": "endId", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_apsResults_referenceId", + "unique": false, + "columnNames": [ + "referenceId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_apsResults_referenceId` ON `${TABLE_NAME}` (`referenceId`)" + }, + { + "name": "index_apsResults_timestamp", + "unique": false, + "columnNames": [ + "timestamp" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_apsResults_timestamp` ON `${TABLE_NAME}` (`timestamp`)" + } + ], + "foreignKeys": [ + { + "table": "apsResults", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "referenceId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "boluses", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `amount` REAL NOT NULL, `type` TEXT NOT NULL, `isBasalInsulin` INTEGER NOT NULL, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `temporaryId` INTEGER, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, `insulinLabel` TEXT, `insulinEndTime` INTEGER, `peak` INTEGER, FOREIGN KEY(`referenceId`) REFERENCES `boluses`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isValid", + "columnName": "isValid", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "referenceId", + "columnName": "referenceId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "utcOffset", + "columnName": "utcOffset", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "amount", + "columnName": "amount", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "isBasalInsulin", + "columnName": "isBasalInsulin", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutSystemId", + "columnName": "nightscoutSystemId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutId", + "columnName": "nightscoutId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpType", + "columnName": "pumpType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpSerial", + "columnName": "pumpSerial", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.temporaryId", + "columnName": "temporaryId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpId", + "columnName": "pumpId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.startId", + "columnName": "startId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.endId", + "columnName": "endId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "insulinConfiguration.insulinLabel", + "columnName": "insulinLabel", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "insulinConfiguration.insulinEndTime", + "columnName": "insulinEndTime", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "insulinConfiguration.peak", + "columnName": "peak", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_boluses_referenceId", + "unique": false, + "columnNames": [ + "referenceId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_boluses_referenceId` ON `${TABLE_NAME}` (`referenceId`)" + }, + { + "name": "index_boluses_timestamp", + "unique": false, + "columnNames": [ + "timestamp" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_boluses_timestamp` ON `${TABLE_NAME}` (`timestamp`)" + } + ], + "foreignKeys": [ + { + "table": "boluses", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "referenceId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "bolusCalculatorResults", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `targetBGLow` REAL NOT NULL, `targetBGHigh` REAL NOT NULL, `isf` REAL NOT NULL, `ic` REAL NOT NULL, `bolusIOB` REAL NOT NULL, `wasBolusIOBUsed` INTEGER NOT NULL, `basalIOB` REAL NOT NULL, `wasBasalIOBUsed` INTEGER NOT NULL, `glucoseValue` REAL NOT NULL, `wasGlucoseUsed` INTEGER NOT NULL, `glucoseDifference` REAL NOT NULL, `glucoseInsulin` REAL NOT NULL, `glucoseTrend` REAL NOT NULL, `wasTrendUsed` INTEGER NOT NULL, `trendInsulin` REAL NOT NULL, `cob` REAL NOT NULL, `wasCOBUsed` INTEGER NOT NULL, `cobInsulin` REAL NOT NULL, `carbs` REAL NOT NULL, `wereCarbsUsed` INTEGER NOT NULL, `carbsInsulin` REAL NOT NULL, `otherCorrection` REAL NOT NULL, `wasSuperbolusUsed` INTEGER NOT NULL, `superbolusInsulin` REAL NOT NULL, `wasTempTargetUsed` INTEGER NOT NULL, `totalInsulin` REAL NOT NULL, `percentageCorrection` INTEGER NOT NULL, `profileName` TEXT NOT NULL, `note` TEXT NOT NULL, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `temporaryId` INTEGER, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`referenceId`) REFERENCES `bolusCalculatorResults`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isValid", + "columnName": "isValid", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "referenceId", + "columnName": "referenceId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "utcOffset", + "columnName": "utcOffset", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "targetBGLow", + "columnName": "targetBGLow", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "targetBGHigh", + "columnName": "targetBGHigh", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "isf", + "columnName": "isf", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "ic", + "columnName": "ic", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "bolusIOB", + "columnName": "bolusIOB", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "wasBolusIOBUsed", + "columnName": "wasBolusIOBUsed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "basalIOB", + "columnName": "basalIOB", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "wasBasalIOBUsed", + "columnName": "wasBasalIOBUsed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "glucoseValue", + "columnName": "glucoseValue", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "wasGlucoseUsed", + "columnName": "wasGlucoseUsed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "glucoseDifference", + "columnName": "glucoseDifference", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "glucoseInsulin", + "columnName": "glucoseInsulin", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "glucoseTrend", + "columnName": "glucoseTrend", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "wasTrendUsed", + "columnName": "wasTrendUsed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "trendInsulin", + "columnName": "trendInsulin", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "cob", + "columnName": "cob", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "wasCOBUsed", + "columnName": "wasCOBUsed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "cobInsulin", + "columnName": "cobInsulin", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "carbs", + "columnName": "carbs", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "wereCarbsUsed", + "columnName": "wereCarbsUsed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "carbsInsulin", + "columnName": "carbsInsulin", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "otherCorrection", + "columnName": "otherCorrection", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "wasSuperbolusUsed", + "columnName": "wasSuperbolusUsed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "superbolusInsulin", + "columnName": "superbolusInsulin", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "wasTempTargetUsed", + "columnName": "wasTempTargetUsed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "totalInsulin", + "columnName": "totalInsulin", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "percentageCorrection", + "columnName": "percentageCorrection", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "profileName", + "columnName": "profileName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "note", + "columnName": "note", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutSystemId", + "columnName": "nightscoutSystemId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutId", + "columnName": "nightscoutId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpType", + "columnName": "pumpType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpSerial", + "columnName": "pumpSerial", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.temporaryId", + "columnName": "temporaryId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpId", + "columnName": "pumpId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.startId", + "columnName": "startId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.endId", + "columnName": "endId", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_bolusCalculatorResults_referenceId", + "unique": false, + "columnNames": [ + "referenceId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_bolusCalculatorResults_referenceId` ON `${TABLE_NAME}` (`referenceId`)" + }, + { + "name": "index_bolusCalculatorResults_timestamp", + "unique": false, + "columnNames": [ + "timestamp" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_bolusCalculatorResults_timestamp` ON `${TABLE_NAME}` (`timestamp`)" + } + ], + "foreignKeys": [ + { + "table": "bolusCalculatorResults", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "referenceId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "carbs", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `duration` INTEGER NOT NULL, `amount` REAL NOT NULL, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `temporaryId` INTEGER, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`referenceId`) REFERENCES `carbs`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isValid", + "columnName": "isValid", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "referenceId", + "columnName": "referenceId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "utcOffset", + "columnName": "utcOffset", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "duration", + "columnName": "duration", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "amount", + "columnName": "amount", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutSystemId", + "columnName": "nightscoutSystemId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutId", + "columnName": "nightscoutId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpType", + "columnName": "pumpType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpSerial", + "columnName": "pumpSerial", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.temporaryId", + "columnName": "temporaryId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpId", + "columnName": "pumpId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.startId", + "columnName": "startId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.endId", + "columnName": "endId", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_carbs_referenceId", + "unique": false, + "columnNames": [ + "referenceId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_carbs_referenceId` ON `${TABLE_NAME}` (`referenceId`)" + }, + { + "name": "index_carbs_timestamp", + "unique": false, + "columnNames": [ + "timestamp" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_carbs_timestamp` ON `${TABLE_NAME}` (`timestamp`)" + } + ], + "foreignKeys": [ + { + "table": "carbs", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "referenceId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "effectiveProfileSwitches", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `duration` INTEGER NOT NULL, `basalBlocks` TEXT NOT NULL, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `temporaryId` INTEGER, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`referenceId`) REFERENCES `effectiveProfileSwitches`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isValid", + "columnName": "isValid", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "referenceId", + "columnName": "referenceId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "utcOffset", + "columnName": "utcOffset", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "duration", + "columnName": "duration", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "basalBlocks", + "columnName": "basalBlocks", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutSystemId", + "columnName": "nightscoutSystemId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutId", + "columnName": "nightscoutId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpType", + "columnName": "pumpType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpSerial", + "columnName": "pumpSerial", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.temporaryId", + "columnName": "temporaryId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpId", + "columnName": "pumpId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.startId", + "columnName": "startId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.endId", + "columnName": "endId", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_effectiveProfileSwitches_referenceId", + "unique": false, + "columnNames": [ + "referenceId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_effectiveProfileSwitches_referenceId` ON `${TABLE_NAME}` (`referenceId`)" + }, + { + "name": "index_effectiveProfileSwitches_timestamp", + "unique": false, + "columnNames": [ + "timestamp" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_effectiveProfileSwitches_timestamp` ON `${TABLE_NAME}` (`timestamp`)" + } + ], + "foreignKeys": [ + { + "table": "effectiveProfileSwitches", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "referenceId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "extendedBoluses", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `duration` INTEGER NOT NULL, `amount` REAL NOT NULL, `isEmulatingTempBasal` INTEGER NOT NULL, `endPumpId` INTEGER, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `temporaryId` INTEGER, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`referenceId`) REFERENCES `extendedBoluses`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isValid", + "columnName": "isValid", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "referenceId", + "columnName": "referenceId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "utcOffset", + "columnName": "utcOffset", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "duration", + "columnName": "duration", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "amount", + "columnName": "amount", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "isEmulatingTempBasal", + "columnName": "isEmulatingTempBasal", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "endPumpId", + "columnName": "endPumpId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutSystemId", + "columnName": "nightscoutSystemId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutId", + "columnName": "nightscoutId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpType", + "columnName": "pumpType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpSerial", + "columnName": "pumpSerial", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.temporaryId", + "columnName": "temporaryId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpId", + "columnName": "pumpId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.startId", + "columnName": "startId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.endId", + "columnName": "endId", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_extendedBoluses_referenceId", + "unique": false, + "columnNames": [ + "referenceId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_extendedBoluses_referenceId` ON `${TABLE_NAME}` (`referenceId`)" + }, + { + "name": "index_extendedBoluses_timestamp", + "unique": false, + "columnNames": [ + "timestamp" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_extendedBoluses_timestamp` ON `${TABLE_NAME}` (`timestamp`)" + } + ], + "foreignKeys": [ + { + "table": "extendedBoluses", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "referenceId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "glucoseValues", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `raw` REAL, `value` REAL NOT NULL, `trendArrow` TEXT NOT NULL, `noise` REAL, `sourceSensor` TEXT NOT NULL, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `temporaryId` INTEGER, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`referenceId`) REFERENCES `glucoseValues`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isValid", + "columnName": "isValid", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "referenceId", + "columnName": "referenceId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "utcOffset", + "columnName": "utcOffset", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "raw", + "columnName": "raw", + "affinity": "REAL", + "notNull": false + }, + { + "fieldPath": "value", + "columnName": "value", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "trendArrow", + "columnName": "trendArrow", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "noise", + "columnName": "noise", + "affinity": "REAL", + "notNull": false + }, + { + "fieldPath": "sourceSensor", + "columnName": "sourceSensor", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutSystemId", + "columnName": "nightscoutSystemId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutId", + "columnName": "nightscoutId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpType", + "columnName": "pumpType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpSerial", + "columnName": "pumpSerial", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.temporaryId", + "columnName": "temporaryId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpId", + "columnName": "pumpId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.startId", + "columnName": "startId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.endId", + "columnName": "endId", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_glucoseValues_referenceId", + "unique": false, + "columnNames": [ + "referenceId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_glucoseValues_referenceId` ON `${TABLE_NAME}` (`referenceId`)" + }, + { + "name": "index_glucoseValues_timestamp", + "unique": false, + "columnNames": [ + "timestamp" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_glucoseValues_timestamp` ON `${TABLE_NAME}` (`timestamp`)" + } + ], + "foreignKeys": [ + { + "table": "glucoseValues", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "referenceId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "profileSwitches", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `profileName` TEXT NOT NULL, `glucoseUnit` TEXT NOT NULL, `basalBlocks` TEXT NOT NULL, `isfBlocks` TEXT NOT NULL, `icBlocks` TEXT NOT NULL, `targetBlocks` TEXT NOT NULL, `timeshift` INTEGER NOT NULL, `percentage` INTEGER NOT NULL, `duration` INTEGER NOT NULL, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `temporaryId` INTEGER, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, `insulinLabel` TEXT NOT NULL, `insulinEndTime` INTEGER NOT NULL, `peak` INTEGER NOT NULL, FOREIGN KEY(`referenceId`) REFERENCES `profileSwitches`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isValid", + "columnName": "isValid", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "referenceId", + "columnName": "referenceId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "utcOffset", + "columnName": "utcOffset", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "profileName", + "columnName": "profileName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "glucoseUnit", + "columnName": "glucoseUnit", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "basalBlocks", + "columnName": "basalBlocks", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "isfBlocks", + "columnName": "isfBlocks", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "icBlocks", + "columnName": "icBlocks", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "targetBlocks", + "columnName": "targetBlocks", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "timeshift", + "columnName": "timeshift", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "percentage", + "columnName": "percentage", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "duration", + "columnName": "duration", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutSystemId", + "columnName": "nightscoutSystemId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutId", + "columnName": "nightscoutId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpType", + "columnName": "pumpType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpSerial", + "columnName": "pumpSerial", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.temporaryId", + "columnName": "temporaryId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpId", + "columnName": "pumpId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.startId", + "columnName": "startId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.endId", + "columnName": "endId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "insulinConfiguration.insulinLabel", + "columnName": "insulinLabel", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "insulinConfiguration.insulinEndTime", + "columnName": "insulinEndTime", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "insulinConfiguration.peak", + "columnName": "peak", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_profileSwitches_referenceId", + "unique": false, + "columnNames": [ + "referenceId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_profileSwitches_referenceId` ON `${TABLE_NAME}` (`referenceId`)" + }, + { + "name": "index_profileSwitches_timestamp", + "unique": false, + "columnNames": [ + "timestamp" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_profileSwitches_timestamp` ON `${TABLE_NAME}` (`timestamp`)" + } + ], + "foreignKeys": [ + { + "table": "profileSwitches", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "referenceId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "temporaryBasals", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `endPumpId` INTEGER, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `type` TEXT NOT NULL, `isAbsolute` INTEGER NOT NULL, `rate` REAL NOT NULL, `duration` INTEGER NOT NULL, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `temporaryId` INTEGER, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`referenceId`) REFERENCES `temporaryBasals`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isValid", + "columnName": "isValid", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "referenceId", + "columnName": "referenceId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "endPumpId", + "columnName": "endPumpId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "utcOffset", + "columnName": "utcOffset", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "isAbsolute", + "columnName": "isAbsolute", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "rate", + "columnName": "rate", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "duration", + "columnName": "duration", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutSystemId", + "columnName": "nightscoutSystemId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutId", + "columnName": "nightscoutId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpType", + "columnName": "pumpType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpSerial", + "columnName": "pumpSerial", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.temporaryId", + "columnName": "temporaryId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpId", + "columnName": "pumpId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.startId", + "columnName": "startId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.endId", + "columnName": "endId", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_temporaryBasals_referenceId", + "unique": false, + "columnNames": [ + "referenceId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_temporaryBasals_referenceId` ON `${TABLE_NAME}` (`referenceId`)" + }, + { + "name": "index_temporaryBasals_timestamp", + "unique": false, + "columnNames": [ + "timestamp" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_temporaryBasals_timestamp` ON `${TABLE_NAME}` (`timestamp`)" + } + ], + "foreignKeys": [ + { + "table": "temporaryBasals", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "referenceId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "temporaryTargets", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `reason` TEXT NOT NULL, `highTarget` REAL NOT NULL, `lowTarget` REAL NOT NULL, `duration` INTEGER NOT NULL, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `temporaryId` INTEGER, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`referenceId`) REFERENCES `temporaryTargets`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isValid", + "columnName": "isValid", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "referenceId", + "columnName": "referenceId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "utcOffset", + "columnName": "utcOffset", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "reason", + "columnName": "reason", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "highTarget", + "columnName": "highTarget", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "lowTarget", + "columnName": "lowTarget", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "duration", + "columnName": "duration", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutSystemId", + "columnName": "nightscoutSystemId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutId", + "columnName": "nightscoutId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpType", + "columnName": "pumpType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpSerial", + "columnName": "pumpSerial", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.temporaryId", + "columnName": "temporaryId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpId", + "columnName": "pumpId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.startId", + "columnName": "startId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.endId", + "columnName": "endId", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_temporaryTargets_referenceId", + "unique": false, + "columnNames": [ + "referenceId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_temporaryTargets_referenceId` ON `${TABLE_NAME}` (`referenceId`)" + }, + { + "name": "index_temporaryTargets_timestamp", + "unique": false, + "columnNames": [ + "timestamp" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_temporaryTargets_timestamp` ON `${TABLE_NAME}` (`timestamp`)" + } + ], + "foreignKeys": [ + { + "table": "temporaryTargets", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "referenceId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "therapyEvents", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `duration` INTEGER NOT NULL, `type` TEXT NOT NULL, `note` TEXT, `enteredBy` TEXT, `glucose` REAL, `glucoseType` TEXT, `glucoseUnit` TEXT NOT NULL, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `temporaryId` INTEGER, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`referenceId`) REFERENCES `therapyEvents`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isValid", + "columnName": "isValid", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "referenceId", + "columnName": "referenceId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "utcOffset", + "columnName": "utcOffset", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "duration", + "columnName": "duration", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "note", + "columnName": "note", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "enteredBy", + "columnName": "enteredBy", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "glucose", + "columnName": "glucose", + "affinity": "REAL", + "notNull": false + }, + { + "fieldPath": "glucoseType", + "columnName": "glucoseType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "glucoseUnit", + "columnName": "glucoseUnit", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutSystemId", + "columnName": "nightscoutSystemId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutId", + "columnName": "nightscoutId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpType", + "columnName": "pumpType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpSerial", + "columnName": "pumpSerial", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.temporaryId", + "columnName": "temporaryId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpId", + "columnName": "pumpId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.startId", + "columnName": "startId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.endId", + "columnName": "endId", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_therapyEvents_referenceId", + "unique": false, + "columnNames": [ + "referenceId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_therapyEvents_referenceId` ON `${TABLE_NAME}` (`referenceId`)" + }, + { + "name": "index_therapyEvents_timestamp", + "unique": false, + "columnNames": [ + "timestamp" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_therapyEvents_timestamp` ON `${TABLE_NAME}` (`timestamp`)" + } + ], + "foreignKeys": [ + { + "table": "therapyEvents", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "referenceId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "totalDailyDoses", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `basalAmount` REAL, `bolusAmount` REAL, `totalAmount` REAL, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `temporaryId` INTEGER, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`referenceId`) REFERENCES `totalDailyDoses`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isValid", + "columnName": "isValid", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "referenceId", + "columnName": "referenceId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "utcOffset", + "columnName": "utcOffset", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "basalAmount", + "columnName": "basalAmount", + "affinity": "REAL", + "notNull": false + }, + { + "fieldPath": "bolusAmount", + "columnName": "bolusAmount", + "affinity": "REAL", + "notNull": false + }, + { + "fieldPath": "totalAmount", + "columnName": "totalAmount", + "affinity": "REAL", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutSystemId", + "columnName": "nightscoutSystemId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutId", + "columnName": "nightscoutId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpType", + "columnName": "pumpType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpSerial", + "columnName": "pumpSerial", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.temporaryId", + "columnName": "temporaryId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpId", + "columnName": "pumpId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.startId", + "columnName": "startId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.endId", + "columnName": "endId", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_totalDailyDoses_referenceId", + "unique": false, + "columnNames": [ + "referenceId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_totalDailyDoses_referenceId` ON `${TABLE_NAME}` (`referenceId`)" + }, + { + "name": "index_totalDailyDoses_timestamp", + "unique": false, + "columnNames": [ + "timestamp" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_totalDailyDoses_timestamp` ON `${TABLE_NAME}` (`timestamp`)" + } + ], + "foreignKeys": [ + { + "table": "totalDailyDoses", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "referenceId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "apsResultLinks", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `apsResultId` INTEGER NOT NULL, `smbId` INTEGER, `tbrId` INTEGER, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `temporaryId` INTEGER, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`apsResultId`) REFERENCES `apsResults`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`smbId`) REFERENCES `boluses`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`tbrId`) REFERENCES `temporaryBasals`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`referenceId`) REFERENCES `apsResultLinks`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isValid", + "columnName": "isValid", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "referenceId", + "columnName": "referenceId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "apsResultId", + "columnName": "apsResultId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "smbId", + "columnName": "smbId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "tbrId", + "columnName": "tbrId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutSystemId", + "columnName": "nightscoutSystemId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutId", + "columnName": "nightscoutId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpType", + "columnName": "pumpType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpSerial", + "columnName": "pumpSerial", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.temporaryId", + "columnName": "temporaryId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpId", + "columnName": "pumpId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.startId", + "columnName": "startId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.endId", + "columnName": "endId", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_apsResultLinks_referenceId", + "unique": false, + "columnNames": [ + "referenceId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_apsResultLinks_referenceId` ON `${TABLE_NAME}` (`referenceId`)" + }, + { + "name": "index_apsResultLinks_apsResultId", + "unique": false, + "columnNames": [ + "apsResultId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_apsResultLinks_apsResultId` ON `${TABLE_NAME}` (`apsResultId`)" + }, + { + "name": "index_apsResultLinks_smbId", + "unique": false, + "columnNames": [ + "smbId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_apsResultLinks_smbId` ON `${TABLE_NAME}` (`smbId`)" + }, + { + "name": "index_apsResultLinks_tbrId", + "unique": false, + "columnNames": [ + "tbrId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_apsResultLinks_tbrId` ON `${TABLE_NAME}` (`tbrId`)" + } + ], + "foreignKeys": [ + { + "table": "apsResults", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "apsResultId" + ], + "referencedColumns": [ + "id" + ] + }, + { + "table": "boluses", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "smbId" + ], + "referencedColumns": [ + "id" + ] + }, + { + "table": "temporaryBasals", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "tbrId" + ], + "referencedColumns": [ + "id" + ] + }, + { + "table": "apsResultLinks", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "referenceId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "multiwaveBolusLinks", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `bolusId` INTEGER NOT NULL, `extendedBolusId` INTEGER NOT NULL, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `temporaryId` INTEGER, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`bolusId`) REFERENCES `boluses`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`extendedBolusId`) REFERENCES `extendedBoluses`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`referenceId`) REFERENCES `multiwaveBolusLinks`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isValid", + "columnName": "isValid", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "referenceId", + "columnName": "referenceId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "bolusId", + "columnName": "bolusId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "extendedBolusId", + "columnName": "extendedBolusId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutSystemId", + "columnName": "nightscoutSystemId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutId", + "columnName": "nightscoutId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpType", + "columnName": "pumpType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpSerial", + "columnName": "pumpSerial", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.temporaryId", + "columnName": "temporaryId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpId", + "columnName": "pumpId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.startId", + "columnName": "startId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.endId", + "columnName": "endId", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_multiwaveBolusLinks_referenceId", + "unique": false, + "columnNames": [ + "referenceId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_multiwaveBolusLinks_referenceId` ON `${TABLE_NAME}` (`referenceId`)" + }, + { + "name": "index_multiwaveBolusLinks_bolusId", + "unique": false, + "columnNames": [ + "bolusId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_multiwaveBolusLinks_bolusId` ON `${TABLE_NAME}` (`bolusId`)" + }, + { + "name": "index_multiwaveBolusLinks_extendedBolusId", + "unique": false, + "columnNames": [ + "extendedBolusId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_multiwaveBolusLinks_extendedBolusId` ON `${TABLE_NAME}` (`extendedBolusId`)" + } + ], + "foreignKeys": [ + { + "table": "boluses", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "bolusId" + ], + "referencedColumns": [ + "id" + ] + }, + { + "table": "extendedBoluses", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "extendedBolusId" + ], + "referencedColumns": [ + "id" + ] + }, + { + "table": "multiwaveBolusLinks", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "referenceId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "preferenceChanges", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `key` TEXT NOT NULL, `value` TEXT)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "utcOffset", + "columnName": "utcOffset", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "key", + "columnName": "key", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "value", + "columnName": "value", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "versionChanges", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `versionCode` INTEGER NOT NULL, `versionName` TEXT NOT NULL, `gitRemote` TEXT, `commitHash` TEXT)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "utcOffset", + "columnName": "utcOffset", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "versionCode", + "columnName": "versionCode", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "versionName", + "columnName": "versionName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "gitRemote", + "columnName": "gitRemote", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "commitHash", + "columnName": "commitHash", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "userEntry", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `action` TEXT NOT NULL, `s` TEXT NOT NULL, `values` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "utcOffset", + "columnName": "utcOffset", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "action", + "columnName": "action", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "s", + "columnName": "s", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "values", + "columnName": "values", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "foods", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `name` TEXT NOT NULL, `category` TEXT, `subCategory` TEXT, `portion` REAL NOT NULL, `carbs` INTEGER NOT NULL, `fat` INTEGER, `protein` INTEGER, `energy` INTEGER, `unit` TEXT NOT NULL, `gi` INTEGER, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `temporaryId` INTEGER, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`referenceId`) REFERENCES `foods`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isValid", + "columnName": "isValid", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "referenceId", + "columnName": "referenceId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "category", + "columnName": "category", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "subCategory", + "columnName": "subCategory", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "portion", + "columnName": "portion", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "carbs", + "columnName": "carbs", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "fat", + "columnName": "fat", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "protein", + "columnName": "protein", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "energy", + "columnName": "energy", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "unit", + "columnName": "unit", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "gi", + "columnName": "gi", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutSystemId", + "columnName": "nightscoutSystemId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutId", + "columnName": "nightscoutId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpType", + "columnName": "pumpType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpSerial", + "columnName": "pumpSerial", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.temporaryId", + "columnName": "temporaryId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpId", + "columnName": "pumpId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.startId", + "columnName": "startId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.endId", + "columnName": "endId", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_foods_referenceId", + "unique": false, + "columnNames": [ + "referenceId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_foods_referenceId` ON `${TABLE_NAME}` (`referenceId`)" + } + ], + "foreignKeys": [ + { + "table": "foods", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "referenceId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "deviceStatus", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `device` TEXT, `pump` TEXT, `enacted` TEXT, `suggested` TEXT, `iob` TEXT, `uploaderBattery` INTEGER NOT NULL, `configuration` TEXT, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `temporaryId` INTEGER, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "utcOffset", + "columnName": "utcOffset", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "device", + "columnName": "device", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "pump", + "columnName": "pump", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "enacted", + "columnName": "enacted", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "suggested", + "columnName": "suggested", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "iob", + "columnName": "iob", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "uploaderBattery", + "columnName": "uploaderBattery", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "configuration", + "columnName": "configuration", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutSystemId", + "columnName": "nightscoutSystemId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutId", + "columnName": "nightscoutId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpType", + "columnName": "pumpType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpSerial", + "columnName": "pumpSerial", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.temporaryId", + "columnName": "temporaryId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpId", + "columnName": "pumpId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.startId", + "columnName": "startId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.endId", + "columnName": "endId", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_deviceStatus_timestamp", + "unique": false, + "columnNames": [ + "timestamp" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_deviceStatus_timestamp` ON `${TABLE_NAME}` (`timestamp`)" + } + ], + "foreignKeys": [] + } + ], + "views": [], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '5590bbcf7038e4422cf50dc16863b7c2')" + ] + } +} \ No newline at end of file diff --git a/database/schemas/info.nightscout.androidaps.database.AppDatabase/12.json b/database/schemas/info.nightscout.androidaps.database.AppDatabase/12.json new file mode 100644 index 0000000000..f0d6ba022f --- /dev/null +++ b/database/schemas/info.nightscout.androidaps.database.AppDatabase/12.json @@ -0,0 +1,2931 @@ +{ + "formatVersion": 1, + "database": { + "version": 12, + "identityHash": "e41836fe7fbd4aa439ec970af929ad7c", + "entities": [ + { + "tableName": "apsResults", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `algorithm` TEXT NOT NULL, `glucoseStatusJson` TEXT NOT NULL, `currentTempJson` TEXT NOT NULL, `iobDataJson` TEXT NOT NULL, `profileJson` TEXT NOT NULL, `autosensDataJson` TEXT, `mealDataJson` TEXT NOT NULL, `isMicroBolusAllowed` INTEGER, `resultJson` TEXT NOT NULL, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `temporaryId` INTEGER, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`referenceId`) REFERENCES `apsResults`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isValid", + "columnName": "isValid", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "referenceId", + "columnName": "referenceId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "utcOffset", + "columnName": "utcOffset", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "algorithm", + "columnName": "algorithm", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "glucoseStatusJson", + "columnName": "glucoseStatusJson", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "currentTempJson", + "columnName": "currentTempJson", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "iobDataJson", + "columnName": "iobDataJson", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "profileJson", + "columnName": "profileJson", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "autosensDataJson", + "columnName": "autosensDataJson", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "mealDataJson", + "columnName": "mealDataJson", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "isMicroBolusAllowed", + "columnName": "isMicroBolusAllowed", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "resultJson", + "columnName": "resultJson", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutSystemId", + "columnName": "nightscoutSystemId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutId", + "columnName": "nightscoutId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpType", + "columnName": "pumpType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpSerial", + "columnName": "pumpSerial", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.temporaryId", + "columnName": "temporaryId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpId", + "columnName": "pumpId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.startId", + "columnName": "startId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.endId", + "columnName": "endId", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_apsResults_referenceId", + "unique": false, + "columnNames": [ + "referenceId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_apsResults_referenceId` ON `${TABLE_NAME}` (`referenceId`)" + }, + { + "name": "index_apsResults_timestamp", + "unique": false, + "columnNames": [ + "timestamp" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_apsResults_timestamp` ON `${TABLE_NAME}` (`timestamp`)" + } + ], + "foreignKeys": [ + { + "table": "apsResults", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "referenceId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "boluses", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `amount` REAL NOT NULL, `type` TEXT NOT NULL, `isBasalInsulin` INTEGER NOT NULL, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `temporaryId` INTEGER, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, `insulinLabel` TEXT, `insulinEndTime` INTEGER, `peak` INTEGER, FOREIGN KEY(`referenceId`) REFERENCES `boluses`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isValid", + "columnName": "isValid", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "referenceId", + "columnName": "referenceId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "utcOffset", + "columnName": "utcOffset", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "amount", + "columnName": "amount", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "isBasalInsulin", + "columnName": "isBasalInsulin", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutSystemId", + "columnName": "nightscoutSystemId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutId", + "columnName": "nightscoutId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpType", + "columnName": "pumpType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpSerial", + "columnName": "pumpSerial", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.temporaryId", + "columnName": "temporaryId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpId", + "columnName": "pumpId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.startId", + "columnName": "startId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.endId", + "columnName": "endId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "insulinConfiguration.insulinLabel", + "columnName": "insulinLabel", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "insulinConfiguration.insulinEndTime", + "columnName": "insulinEndTime", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "insulinConfiguration.peak", + "columnName": "peak", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_boluses_referenceId", + "unique": false, + "columnNames": [ + "referenceId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_boluses_referenceId` ON `${TABLE_NAME}` (`referenceId`)" + }, + { + "name": "index_boluses_timestamp", + "unique": false, + "columnNames": [ + "timestamp" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_boluses_timestamp` ON `${TABLE_NAME}` (`timestamp`)" + } + ], + "foreignKeys": [ + { + "table": "boluses", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "referenceId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "bolusCalculatorResults", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `targetBGLow` REAL NOT NULL, `targetBGHigh` REAL NOT NULL, `isf` REAL NOT NULL, `ic` REAL NOT NULL, `bolusIOB` REAL NOT NULL, `wasBolusIOBUsed` INTEGER NOT NULL, `basalIOB` REAL NOT NULL, `wasBasalIOBUsed` INTEGER NOT NULL, `glucoseValue` REAL NOT NULL, `wasGlucoseUsed` INTEGER NOT NULL, `glucoseDifference` REAL NOT NULL, `glucoseInsulin` REAL NOT NULL, `glucoseTrend` REAL NOT NULL, `wasTrendUsed` INTEGER NOT NULL, `trendInsulin` REAL NOT NULL, `cob` REAL NOT NULL, `wasCOBUsed` INTEGER NOT NULL, `cobInsulin` REAL NOT NULL, `carbs` REAL NOT NULL, `wereCarbsUsed` INTEGER NOT NULL, `carbsInsulin` REAL NOT NULL, `otherCorrection` REAL NOT NULL, `wasSuperbolusUsed` INTEGER NOT NULL, `superbolusInsulin` REAL NOT NULL, `wasTempTargetUsed` INTEGER NOT NULL, `totalInsulin` REAL NOT NULL, `percentageCorrection` INTEGER NOT NULL, `profileName` TEXT NOT NULL, `note` TEXT NOT NULL, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `temporaryId` INTEGER, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`referenceId`) REFERENCES `bolusCalculatorResults`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isValid", + "columnName": "isValid", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "referenceId", + "columnName": "referenceId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "utcOffset", + "columnName": "utcOffset", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "targetBGLow", + "columnName": "targetBGLow", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "targetBGHigh", + "columnName": "targetBGHigh", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "isf", + "columnName": "isf", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "ic", + "columnName": "ic", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "bolusIOB", + "columnName": "bolusIOB", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "wasBolusIOBUsed", + "columnName": "wasBolusIOBUsed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "basalIOB", + "columnName": "basalIOB", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "wasBasalIOBUsed", + "columnName": "wasBasalIOBUsed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "glucoseValue", + "columnName": "glucoseValue", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "wasGlucoseUsed", + "columnName": "wasGlucoseUsed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "glucoseDifference", + "columnName": "glucoseDifference", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "glucoseInsulin", + "columnName": "glucoseInsulin", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "glucoseTrend", + "columnName": "glucoseTrend", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "wasTrendUsed", + "columnName": "wasTrendUsed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "trendInsulin", + "columnName": "trendInsulin", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "cob", + "columnName": "cob", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "wasCOBUsed", + "columnName": "wasCOBUsed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "cobInsulin", + "columnName": "cobInsulin", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "carbs", + "columnName": "carbs", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "wereCarbsUsed", + "columnName": "wereCarbsUsed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "carbsInsulin", + "columnName": "carbsInsulin", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "otherCorrection", + "columnName": "otherCorrection", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "wasSuperbolusUsed", + "columnName": "wasSuperbolusUsed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "superbolusInsulin", + "columnName": "superbolusInsulin", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "wasTempTargetUsed", + "columnName": "wasTempTargetUsed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "totalInsulin", + "columnName": "totalInsulin", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "percentageCorrection", + "columnName": "percentageCorrection", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "profileName", + "columnName": "profileName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "note", + "columnName": "note", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutSystemId", + "columnName": "nightscoutSystemId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutId", + "columnName": "nightscoutId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpType", + "columnName": "pumpType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpSerial", + "columnName": "pumpSerial", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.temporaryId", + "columnName": "temporaryId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpId", + "columnName": "pumpId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.startId", + "columnName": "startId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.endId", + "columnName": "endId", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_bolusCalculatorResults_referenceId", + "unique": false, + "columnNames": [ + "referenceId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_bolusCalculatorResults_referenceId` ON `${TABLE_NAME}` (`referenceId`)" + }, + { + "name": "index_bolusCalculatorResults_timestamp", + "unique": false, + "columnNames": [ + "timestamp" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_bolusCalculatorResults_timestamp` ON `${TABLE_NAME}` (`timestamp`)" + } + ], + "foreignKeys": [ + { + "table": "bolusCalculatorResults", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "referenceId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "carbs", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `duration` INTEGER NOT NULL, `amount` REAL NOT NULL, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `temporaryId` INTEGER, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`referenceId`) REFERENCES `carbs`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isValid", + "columnName": "isValid", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "referenceId", + "columnName": "referenceId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "utcOffset", + "columnName": "utcOffset", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "duration", + "columnName": "duration", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "amount", + "columnName": "amount", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutSystemId", + "columnName": "nightscoutSystemId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutId", + "columnName": "nightscoutId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpType", + "columnName": "pumpType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpSerial", + "columnName": "pumpSerial", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.temporaryId", + "columnName": "temporaryId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpId", + "columnName": "pumpId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.startId", + "columnName": "startId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.endId", + "columnName": "endId", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_carbs_referenceId", + "unique": false, + "columnNames": [ + "referenceId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_carbs_referenceId` ON `${TABLE_NAME}` (`referenceId`)" + }, + { + "name": "index_carbs_timestamp", + "unique": false, + "columnNames": [ + "timestamp" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_carbs_timestamp` ON `${TABLE_NAME}` (`timestamp`)" + } + ], + "foreignKeys": [ + { + "table": "carbs", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "referenceId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "effectiveProfileSwitches", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `duration` INTEGER NOT NULL, `basalBlocks` TEXT NOT NULL, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `temporaryId` INTEGER, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`referenceId`) REFERENCES `effectiveProfileSwitches`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isValid", + "columnName": "isValid", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "referenceId", + "columnName": "referenceId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "utcOffset", + "columnName": "utcOffset", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "duration", + "columnName": "duration", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "basalBlocks", + "columnName": "basalBlocks", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutSystemId", + "columnName": "nightscoutSystemId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutId", + "columnName": "nightscoutId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpType", + "columnName": "pumpType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpSerial", + "columnName": "pumpSerial", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.temporaryId", + "columnName": "temporaryId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpId", + "columnName": "pumpId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.startId", + "columnName": "startId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.endId", + "columnName": "endId", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_effectiveProfileSwitches_referenceId", + "unique": false, + "columnNames": [ + "referenceId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_effectiveProfileSwitches_referenceId` ON `${TABLE_NAME}` (`referenceId`)" + }, + { + "name": "index_effectiveProfileSwitches_timestamp", + "unique": false, + "columnNames": [ + "timestamp" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_effectiveProfileSwitches_timestamp` ON `${TABLE_NAME}` (`timestamp`)" + } + ], + "foreignKeys": [ + { + "table": "effectiveProfileSwitches", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "referenceId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "extendedBoluses", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `duration` INTEGER NOT NULL, `amount` REAL NOT NULL, `isEmulatingTempBasal` INTEGER NOT NULL, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `temporaryId` INTEGER, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`referenceId`) REFERENCES `extendedBoluses`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isValid", + "columnName": "isValid", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "referenceId", + "columnName": "referenceId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "utcOffset", + "columnName": "utcOffset", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "duration", + "columnName": "duration", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "amount", + "columnName": "amount", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "isEmulatingTempBasal", + "columnName": "isEmulatingTempBasal", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutSystemId", + "columnName": "nightscoutSystemId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutId", + "columnName": "nightscoutId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpType", + "columnName": "pumpType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpSerial", + "columnName": "pumpSerial", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.temporaryId", + "columnName": "temporaryId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpId", + "columnName": "pumpId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.startId", + "columnName": "startId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.endId", + "columnName": "endId", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_extendedBoluses_referenceId", + "unique": false, + "columnNames": [ + "referenceId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_extendedBoluses_referenceId` ON `${TABLE_NAME}` (`referenceId`)" + }, + { + "name": "index_extendedBoluses_timestamp", + "unique": false, + "columnNames": [ + "timestamp" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_extendedBoluses_timestamp` ON `${TABLE_NAME}` (`timestamp`)" + } + ], + "foreignKeys": [ + { + "table": "extendedBoluses", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "referenceId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "glucoseValues", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `raw` REAL, `value` REAL NOT NULL, `trendArrow` TEXT NOT NULL, `noise` REAL, `sourceSensor` TEXT NOT NULL, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `temporaryId` INTEGER, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`referenceId`) REFERENCES `glucoseValues`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isValid", + "columnName": "isValid", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "referenceId", + "columnName": "referenceId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "utcOffset", + "columnName": "utcOffset", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "raw", + "columnName": "raw", + "affinity": "REAL", + "notNull": false + }, + { + "fieldPath": "value", + "columnName": "value", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "trendArrow", + "columnName": "trendArrow", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "noise", + "columnName": "noise", + "affinity": "REAL", + "notNull": false + }, + { + "fieldPath": "sourceSensor", + "columnName": "sourceSensor", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutSystemId", + "columnName": "nightscoutSystemId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutId", + "columnName": "nightscoutId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpType", + "columnName": "pumpType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpSerial", + "columnName": "pumpSerial", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.temporaryId", + "columnName": "temporaryId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpId", + "columnName": "pumpId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.startId", + "columnName": "startId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.endId", + "columnName": "endId", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_glucoseValues_referenceId", + "unique": false, + "columnNames": [ + "referenceId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_glucoseValues_referenceId` ON `${TABLE_NAME}` (`referenceId`)" + }, + { + "name": "index_glucoseValues_timestamp", + "unique": false, + "columnNames": [ + "timestamp" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_glucoseValues_timestamp` ON `${TABLE_NAME}` (`timestamp`)" + } + ], + "foreignKeys": [ + { + "table": "glucoseValues", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "referenceId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "profileSwitches", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `profileName` TEXT NOT NULL, `glucoseUnit` TEXT NOT NULL, `basalBlocks` TEXT NOT NULL, `isfBlocks` TEXT NOT NULL, `icBlocks` TEXT NOT NULL, `targetBlocks` TEXT NOT NULL, `timeshift` INTEGER NOT NULL, `percentage` INTEGER NOT NULL, `duration` INTEGER NOT NULL, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `temporaryId` INTEGER, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, `insulinLabel` TEXT NOT NULL, `insulinEndTime` INTEGER NOT NULL, `peak` INTEGER NOT NULL, FOREIGN KEY(`referenceId`) REFERENCES `profileSwitches`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isValid", + "columnName": "isValid", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "referenceId", + "columnName": "referenceId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "utcOffset", + "columnName": "utcOffset", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "profileName", + "columnName": "profileName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "glucoseUnit", + "columnName": "glucoseUnit", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "basalBlocks", + "columnName": "basalBlocks", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "isfBlocks", + "columnName": "isfBlocks", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "icBlocks", + "columnName": "icBlocks", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "targetBlocks", + "columnName": "targetBlocks", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "timeshift", + "columnName": "timeshift", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "percentage", + "columnName": "percentage", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "duration", + "columnName": "duration", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutSystemId", + "columnName": "nightscoutSystemId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutId", + "columnName": "nightscoutId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpType", + "columnName": "pumpType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpSerial", + "columnName": "pumpSerial", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.temporaryId", + "columnName": "temporaryId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpId", + "columnName": "pumpId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.startId", + "columnName": "startId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.endId", + "columnName": "endId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "insulinConfiguration.insulinLabel", + "columnName": "insulinLabel", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "insulinConfiguration.insulinEndTime", + "columnName": "insulinEndTime", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "insulinConfiguration.peak", + "columnName": "peak", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_profileSwitches_referenceId", + "unique": false, + "columnNames": [ + "referenceId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_profileSwitches_referenceId` ON `${TABLE_NAME}` (`referenceId`)" + }, + { + "name": "index_profileSwitches_timestamp", + "unique": false, + "columnNames": [ + "timestamp" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_profileSwitches_timestamp` ON `${TABLE_NAME}` (`timestamp`)" + } + ], + "foreignKeys": [ + { + "table": "profileSwitches", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "referenceId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "temporaryBasals", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `type` TEXT NOT NULL, `isAbsolute` INTEGER NOT NULL, `rate` REAL NOT NULL, `duration` INTEGER NOT NULL, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `temporaryId` INTEGER, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`referenceId`) REFERENCES `temporaryBasals`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isValid", + "columnName": "isValid", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "referenceId", + "columnName": "referenceId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "utcOffset", + "columnName": "utcOffset", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "isAbsolute", + "columnName": "isAbsolute", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "rate", + "columnName": "rate", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "duration", + "columnName": "duration", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutSystemId", + "columnName": "nightscoutSystemId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutId", + "columnName": "nightscoutId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpType", + "columnName": "pumpType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpSerial", + "columnName": "pumpSerial", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.temporaryId", + "columnName": "temporaryId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpId", + "columnName": "pumpId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.startId", + "columnName": "startId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.endId", + "columnName": "endId", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_temporaryBasals_referenceId", + "unique": false, + "columnNames": [ + "referenceId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_temporaryBasals_referenceId` ON `${TABLE_NAME}` (`referenceId`)" + }, + { + "name": "index_temporaryBasals_timestamp", + "unique": false, + "columnNames": [ + "timestamp" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_temporaryBasals_timestamp` ON `${TABLE_NAME}` (`timestamp`)" + } + ], + "foreignKeys": [ + { + "table": "temporaryBasals", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "referenceId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "temporaryTargets", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `reason` TEXT NOT NULL, `highTarget` REAL NOT NULL, `lowTarget` REAL NOT NULL, `duration` INTEGER NOT NULL, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `temporaryId` INTEGER, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`referenceId`) REFERENCES `temporaryTargets`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isValid", + "columnName": "isValid", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "referenceId", + "columnName": "referenceId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "utcOffset", + "columnName": "utcOffset", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "reason", + "columnName": "reason", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "highTarget", + "columnName": "highTarget", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "lowTarget", + "columnName": "lowTarget", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "duration", + "columnName": "duration", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutSystemId", + "columnName": "nightscoutSystemId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutId", + "columnName": "nightscoutId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpType", + "columnName": "pumpType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpSerial", + "columnName": "pumpSerial", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.temporaryId", + "columnName": "temporaryId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpId", + "columnName": "pumpId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.startId", + "columnName": "startId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.endId", + "columnName": "endId", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_temporaryTargets_referenceId", + "unique": false, + "columnNames": [ + "referenceId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_temporaryTargets_referenceId` ON `${TABLE_NAME}` (`referenceId`)" + }, + { + "name": "index_temporaryTargets_timestamp", + "unique": false, + "columnNames": [ + "timestamp" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_temporaryTargets_timestamp` ON `${TABLE_NAME}` (`timestamp`)" + } + ], + "foreignKeys": [ + { + "table": "temporaryTargets", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "referenceId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "therapyEvents", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `duration` INTEGER NOT NULL, `type` TEXT NOT NULL, `note` TEXT, `enteredBy` TEXT, `glucose` REAL, `glucoseType` TEXT, `glucoseUnit` TEXT NOT NULL, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `temporaryId` INTEGER, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`referenceId`) REFERENCES `therapyEvents`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isValid", + "columnName": "isValid", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "referenceId", + "columnName": "referenceId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "utcOffset", + "columnName": "utcOffset", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "duration", + "columnName": "duration", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "note", + "columnName": "note", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "enteredBy", + "columnName": "enteredBy", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "glucose", + "columnName": "glucose", + "affinity": "REAL", + "notNull": false + }, + { + "fieldPath": "glucoseType", + "columnName": "glucoseType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "glucoseUnit", + "columnName": "glucoseUnit", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutSystemId", + "columnName": "nightscoutSystemId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutId", + "columnName": "nightscoutId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpType", + "columnName": "pumpType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpSerial", + "columnName": "pumpSerial", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.temporaryId", + "columnName": "temporaryId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpId", + "columnName": "pumpId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.startId", + "columnName": "startId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.endId", + "columnName": "endId", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_therapyEvents_referenceId", + "unique": false, + "columnNames": [ + "referenceId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_therapyEvents_referenceId` ON `${TABLE_NAME}` (`referenceId`)" + }, + { + "name": "index_therapyEvents_timestamp", + "unique": false, + "columnNames": [ + "timestamp" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_therapyEvents_timestamp` ON `${TABLE_NAME}` (`timestamp`)" + } + ], + "foreignKeys": [ + { + "table": "therapyEvents", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "referenceId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "totalDailyDoses", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `basalAmount` REAL, `bolusAmount` REAL, `totalAmount` REAL, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `temporaryId` INTEGER, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`referenceId`) REFERENCES `totalDailyDoses`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isValid", + "columnName": "isValid", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "referenceId", + "columnName": "referenceId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "utcOffset", + "columnName": "utcOffset", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "basalAmount", + "columnName": "basalAmount", + "affinity": "REAL", + "notNull": false + }, + { + "fieldPath": "bolusAmount", + "columnName": "bolusAmount", + "affinity": "REAL", + "notNull": false + }, + { + "fieldPath": "totalAmount", + "columnName": "totalAmount", + "affinity": "REAL", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutSystemId", + "columnName": "nightscoutSystemId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutId", + "columnName": "nightscoutId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpType", + "columnName": "pumpType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpSerial", + "columnName": "pumpSerial", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.temporaryId", + "columnName": "temporaryId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpId", + "columnName": "pumpId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.startId", + "columnName": "startId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.endId", + "columnName": "endId", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_totalDailyDoses_referenceId", + "unique": false, + "columnNames": [ + "referenceId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_totalDailyDoses_referenceId` ON `${TABLE_NAME}` (`referenceId`)" + }, + { + "name": "index_totalDailyDoses_timestamp", + "unique": false, + "columnNames": [ + "timestamp" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_totalDailyDoses_timestamp` ON `${TABLE_NAME}` (`timestamp`)" + } + ], + "foreignKeys": [ + { + "table": "totalDailyDoses", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "referenceId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "apsResultLinks", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `apsResultId` INTEGER NOT NULL, `smbId` INTEGER, `tbrId` INTEGER, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `temporaryId` INTEGER, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`apsResultId`) REFERENCES `apsResults`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`smbId`) REFERENCES `boluses`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`tbrId`) REFERENCES `temporaryBasals`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`referenceId`) REFERENCES `apsResultLinks`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isValid", + "columnName": "isValid", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "referenceId", + "columnName": "referenceId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "apsResultId", + "columnName": "apsResultId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "smbId", + "columnName": "smbId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "tbrId", + "columnName": "tbrId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutSystemId", + "columnName": "nightscoutSystemId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutId", + "columnName": "nightscoutId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpType", + "columnName": "pumpType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpSerial", + "columnName": "pumpSerial", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.temporaryId", + "columnName": "temporaryId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpId", + "columnName": "pumpId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.startId", + "columnName": "startId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.endId", + "columnName": "endId", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_apsResultLinks_referenceId", + "unique": false, + "columnNames": [ + "referenceId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_apsResultLinks_referenceId` ON `${TABLE_NAME}` (`referenceId`)" + }, + { + "name": "index_apsResultLinks_apsResultId", + "unique": false, + "columnNames": [ + "apsResultId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_apsResultLinks_apsResultId` ON `${TABLE_NAME}` (`apsResultId`)" + }, + { + "name": "index_apsResultLinks_smbId", + "unique": false, + "columnNames": [ + "smbId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_apsResultLinks_smbId` ON `${TABLE_NAME}` (`smbId`)" + }, + { + "name": "index_apsResultLinks_tbrId", + "unique": false, + "columnNames": [ + "tbrId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_apsResultLinks_tbrId` ON `${TABLE_NAME}` (`tbrId`)" + } + ], + "foreignKeys": [ + { + "table": "apsResults", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "apsResultId" + ], + "referencedColumns": [ + "id" + ] + }, + { + "table": "boluses", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "smbId" + ], + "referencedColumns": [ + "id" + ] + }, + { + "table": "temporaryBasals", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "tbrId" + ], + "referencedColumns": [ + "id" + ] + }, + { + "table": "apsResultLinks", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "referenceId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "multiwaveBolusLinks", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `bolusId` INTEGER NOT NULL, `extendedBolusId` INTEGER NOT NULL, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `temporaryId` INTEGER, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`bolusId`) REFERENCES `boluses`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`extendedBolusId`) REFERENCES `extendedBoluses`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`referenceId`) REFERENCES `multiwaveBolusLinks`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isValid", + "columnName": "isValid", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "referenceId", + "columnName": "referenceId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "bolusId", + "columnName": "bolusId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "extendedBolusId", + "columnName": "extendedBolusId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutSystemId", + "columnName": "nightscoutSystemId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutId", + "columnName": "nightscoutId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpType", + "columnName": "pumpType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpSerial", + "columnName": "pumpSerial", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.temporaryId", + "columnName": "temporaryId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpId", + "columnName": "pumpId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.startId", + "columnName": "startId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.endId", + "columnName": "endId", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_multiwaveBolusLinks_referenceId", + "unique": false, + "columnNames": [ + "referenceId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_multiwaveBolusLinks_referenceId` ON `${TABLE_NAME}` (`referenceId`)" + }, + { + "name": "index_multiwaveBolusLinks_bolusId", + "unique": false, + "columnNames": [ + "bolusId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_multiwaveBolusLinks_bolusId` ON `${TABLE_NAME}` (`bolusId`)" + }, + { + "name": "index_multiwaveBolusLinks_extendedBolusId", + "unique": false, + "columnNames": [ + "extendedBolusId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_multiwaveBolusLinks_extendedBolusId` ON `${TABLE_NAME}` (`extendedBolusId`)" + } + ], + "foreignKeys": [ + { + "table": "boluses", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "bolusId" + ], + "referencedColumns": [ + "id" + ] + }, + { + "table": "extendedBoluses", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "extendedBolusId" + ], + "referencedColumns": [ + "id" + ] + }, + { + "table": "multiwaveBolusLinks", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "referenceId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "preferenceChanges", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `key` TEXT NOT NULL, `value` TEXT)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "utcOffset", + "columnName": "utcOffset", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "key", + "columnName": "key", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "value", + "columnName": "value", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "versionChanges", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `versionCode` INTEGER NOT NULL, `versionName` TEXT NOT NULL, `gitRemote` TEXT, `commitHash` TEXT)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "utcOffset", + "columnName": "utcOffset", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "versionCode", + "columnName": "versionCode", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "versionName", + "columnName": "versionName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "gitRemote", + "columnName": "gitRemote", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "commitHash", + "columnName": "commitHash", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "userEntry", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `action` TEXT NOT NULL, `s` TEXT NOT NULL, `values` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "utcOffset", + "columnName": "utcOffset", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "action", + "columnName": "action", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "s", + "columnName": "s", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "values", + "columnName": "values", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "foods", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `name` TEXT NOT NULL, `category` TEXT, `subCategory` TEXT, `portion` REAL NOT NULL, `carbs` INTEGER NOT NULL, `fat` INTEGER, `protein` INTEGER, `energy` INTEGER, `unit` TEXT NOT NULL, `gi` INTEGER, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `temporaryId` INTEGER, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`referenceId`) REFERENCES `foods`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isValid", + "columnName": "isValid", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "referenceId", + "columnName": "referenceId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "category", + "columnName": "category", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "subCategory", + "columnName": "subCategory", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "portion", + "columnName": "portion", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "carbs", + "columnName": "carbs", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "fat", + "columnName": "fat", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "protein", + "columnName": "protein", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "energy", + "columnName": "energy", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "unit", + "columnName": "unit", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "gi", + "columnName": "gi", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutSystemId", + "columnName": "nightscoutSystemId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutId", + "columnName": "nightscoutId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpType", + "columnName": "pumpType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpSerial", + "columnName": "pumpSerial", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.temporaryId", + "columnName": "temporaryId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpId", + "columnName": "pumpId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.startId", + "columnName": "startId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.endId", + "columnName": "endId", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_foods_referenceId", + "unique": false, + "columnNames": [ + "referenceId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_foods_referenceId` ON `${TABLE_NAME}` (`referenceId`)" + } + ], + "foreignKeys": [ + { + "table": "foods", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "referenceId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "deviceStatus", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `device` TEXT, `pump` TEXT, `enacted` TEXT, `suggested` TEXT, `iob` TEXT, `uploaderBattery` INTEGER NOT NULL, `configuration` TEXT, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `temporaryId` INTEGER, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "utcOffset", + "columnName": "utcOffset", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "device", + "columnName": "device", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "pump", + "columnName": "pump", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "enacted", + "columnName": "enacted", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "suggested", + "columnName": "suggested", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "iob", + "columnName": "iob", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "uploaderBattery", + "columnName": "uploaderBattery", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "configuration", + "columnName": "configuration", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutSystemId", + "columnName": "nightscoutSystemId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.nightscoutId", + "columnName": "nightscoutId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpType", + "columnName": "pumpType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpSerial", + "columnName": "pumpSerial", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.temporaryId", + "columnName": "temporaryId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.pumpId", + "columnName": "pumpId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.startId", + "columnName": "startId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "interfaceIDs_backing.endId", + "columnName": "endId", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_deviceStatus_timestamp", + "unique": false, + "columnNames": [ + "timestamp" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_deviceStatus_timestamp` ON `${TABLE_NAME}` (`timestamp`)" + } + ], + "foreignKeys": [] + } + ], + "views": [], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'e41836fe7fbd4aa439ec970af929ad7c')" + ] + } +} \ No newline at end of file diff --git a/database/src/main/java/info/nightscout/androidaps/database/AppDatabase.kt b/database/src/main/java/info/nightscout/androidaps/database/AppDatabase.kt index 97993088c0..11b38c3b56 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/AppDatabase.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/AppDatabase.kt @@ -6,7 +6,7 @@ import androidx.room.TypeConverters import info.nightscout.androidaps.database.daos.* import info.nightscout.androidaps.database.entities.* -const val DATABASE_VERSION = 11 +const val DATABASE_VERSION = 13 @Database(version = DATABASE_VERSION, entities = [APSResult::class, Bolus::class, BolusCalculatorResult::class, Carbs::class, 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 1e866dee24..ac01633682 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/AppRepository.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/AppRepository.kt @@ -456,7 +456,7 @@ open class AppRepository @Inject internal constructor( database.bolusCalculatorResultDao.deleteAllEntries() // DEVICE STATUS - fun insert(deviceStatus: DeviceStatus) : Long = + fun insert(deviceStatus: DeviceStatus): Long = database.deviceStatusDao.insert(deviceStatus) /* @@ -475,6 +475,116 @@ open class AppRepository @Inject internal constructor( database.deviceStatusDao.getModifiedFrom(lastId) .subscribeOn(Schedulers.io()) + // TEMPORARY BASAL + /* + * returns a Pair of the next entity to sync and the ID of the "update". + * The update id might either be the entry id itself if it is a new entry - or the id + * of the update ("historic") entry. The sync counter should be incremented to that id if it was synced successfully. + * + * It is a Maybe as there might be no next element. + * */ + + fun getNextSyncElementTemporaryBasal(id: Long): Maybe> = + database.temporaryBasalDao.getNextModifiedOrNewAfter(id) + .flatMap { nextIdElement -> + val nextIdElemReferenceId = nextIdElement.referenceId + if (nextIdElemReferenceId == null) { + Maybe.just(nextIdElement to nextIdElement.id) + } else { + database.temporaryBasalDao.getCurrentFromHistoric(nextIdElemReferenceId) + .map { it to nextIdElement.id } + } + } + + fun getModifiedTemporaryBasalDataFromId(lastId: Long): Single> = + database.temporaryBasalDao.getModifiedFrom(lastId) + .subscribeOn(Schedulers.io()) + + fun getTemporaryBasalsData(): Single> = + database.temporaryBasalDao.getTemporaryBasalData() + .subscribeOn(Schedulers.io()) + + fun getTemporaryBasalActiveAt(timestamp: Long): Single> = + database.temporaryBasalDao.getTemporaryBasalActiveAt(timestamp) + .subscribeOn(Schedulers.io()) + .toWrappedSingle() + + fun getTemporaryBasalsDataFromTime(timestamp: Long, ascending: Boolean): Single> = + database.temporaryBasalDao.getTemporaryBasalDataFromTime(timestamp) + .map { if (!ascending) it.reversed() else it } + .subscribeOn(Schedulers.io()) + + fun getTemporaryBasalsDataFromTimeToTime(from: Long, to: Long, ascending: Boolean): Single> = + database.temporaryBasalDao.getTemporaryBasalDataFromTimeToTime(from, to) + .map { if (!ascending) it.reversed() else it } + .subscribeOn(Schedulers.io()) + + fun getTemporaryBasalsDataIncludingInvalidFromTime(timestamp: Long, ascending: Boolean): Single> = + database.temporaryBasalDao.getTemporaryBasalDataIncludingInvalidFromTime(timestamp) + .map { if (!ascending) it.reversed() else it } + .subscribeOn(Schedulers.io()) + + fun getTemporaryBasalsDataIncludingInvalidFromTimeToTime(from: Long, to: Long, ascending: Boolean): Single> = + database.temporaryBasalDao.getTemporaryBasalDataIncludingInvalidFromTimeToTime(from, to) + .map { if (!ascending) it.reversed() else it } + .subscribeOn(Schedulers.io()) + + fun getOldestTemporaryBasalRecord(): TemporaryBasal? = + database.temporaryBasalDao.getOldestRecord() + + // EXTENDED BOLUS + /* + * returns a Pair of the next entity to sync and the ID of the "update". + * The update id might either be the entry id itself if it is a new entry - or the id + * of the update ("historic") entry. The sync counter should be incremented to that id if it was synced successfully. + * + * It is a Maybe as there might be no next element. + * */ + + fun getNextSyncElementExtendedBolus(id: Long): Maybe> = + database.extendedBolusDao.getNextModifiedOrNewAfter(id) + .flatMap { nextIdElement -> + val nextIdElemReferenceId = nextIdElement.referenceId + if (nextIdElemReferenceId == null) { + Maybe.just(nextIdElement to nextIdElement.id) + } else { + database.extendedBolusDao.getCurrentFromHistoric(nextIdElemReferenceId) + .map { it to nextIdElement.id } + } + } + + fun getModifiedExtendedBolusDataFromId(lastId: Long): Single> = + database.extendedBolusDao.getModifiedFrom(lastId) + .subscribeOn(Schedulers.io()) + + fun getExtendedBolusActiveAt(timestamp: Long): Single> = + database.extendedBolusDao.getExtendedBolusActiveAt(timestamp) + .subscribeOn(Schedulers.io()) + .toWrappedSingle() + + fun getExtendedBolusDataFromTime(timestamp: Long, ascending: Boolean): Single> = + database.extendedBolusDao.getExtendedBolusDataFromTime(timestamp) + .map { if (!ascending) it.reversed() else it } + .subscribeOn(Schedulers.io()) + + fun getExtendedBolusDataFromTimeToTime(start: Long, end: Long, ascending: Boolean): Single> = + database.extendedBolusDao.getExtendedBolusDataFromTimeToTime(start, end) + .map { if (!ascending) it.reversed() else it } + .subscribeOn(Schedulers.io()) + + fun getExtendedBolusDataIncludingInvalidFromTime(timestamp: Long, ascending: Boolean): Single> = + database.extendedBolusDao.getExtendedBolusDataIncludingInvalidFromTime(timestamp) + .map { if (!ascending) it.reversed() else it } + .subscribeOn(Schedulers.io()) + + fun getExtendedBolusDataIncludingInvalidFromTimeToTime(start: Long, end: Long, ascending: Boolean): Single> = + database.extendedBolusDao.getExtendedBolusDataIncludingInvalidFromTimeToTime(start, end) + .map { if (!ascending) it.reversed() else it } + .subscribeOn(Schedulers.io()) + + fun getOldestExtendedBolusRecord(): ExtendedBolus? = + database.extendedBolusDao.getOldestRecord() + } @Suppress("USELESS_CAST") diff --git a/database/src/main/java/info/nightscout/androidaps/database/daos/ExtendedBolusDao.kt b/database/src/main/java/info/nightscout/androidaps/database/daos/ExtendedBolusDao.kt index c5e0b979bd..8f318577f8 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/daos/ExtendedBolusDao.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/daos/ExtendedBolusDao.kt @@ -5,7 +5,7 @@ import androidx.room.Query import info.nightscout.androidaps.database.TABLE_EXTENDED_BOLUSES import info.nightscout.androidaps.database.embedments.InterfaceIDs import info.nightscout.androidaps.database.entities.ExtendedBolus -import io.reactivex.Flowable +import io.reactivex.Maybe import io.reactivex.Single @Suppress("FunctionName") @@ -17,4 +17,49 @@ internal interface ExtendedBolusDao : TraceableDao { @Query("DELETE FROM $TABLE_EXTENDED_BOLUSES") override fun deleteAllEntries() + + @Query("SELECT * FROM $TABLE_EXTENDED_BOLUSES WHERE timestamp = :timestamp AND referenceId IS NULL") + fun findByTimestamp(timestamp: Long): ExtendedBolus? + + @Query("SELECT * FROM $TABLE_EXTENDED_BOLUSES WHERE nightscoutId = :nsId AND referenceId IS NULL") + fun findByNSId(nsId: String): ExtendedBolus? + + @Query("SELECT * FROM $TABLE_EXTENDED_BOLUSES WHERE pumpId = :pumpId AND pumpType = :pumpType AND pumpSerial = :pumpSerial AND referenceId IS NULL") + fun findByPumpIds(pumpId: Long, pumpType: InterfaceIDs.PumpType, pumpSerial: String): ExtendedBolus? + + @Query("SELECT * FROM $TABLE_EXTENDED_BOLUSES WHERE endId = :endPumpId AND pumpType = :pumpType AND pumpSerial = :pumpSerial AND referenceId IS NULL") + fun findByPumpEndIds(endPumpId: Long, pumpType: InterfaceIDs.PumpType, pumpSerial: String): ExtendedBolus? + + @Query("SELECT * FROM $TABLE_EXTENDED_BOLUSES WHERE timestamp <= :timestamp AND (timestamp + duration) > :timestamp AND pumpType = :pumpType AND pumpSerial = :pumpSerial AND referenceId IS NULL AND isValid = 1 ORDER BY timestamp DESC LIMIT 1") + fun getExtendedBolusActiveAt(timestamp: Long, pumpType: InterfaceIDs.PumpType, pumpSerial: String): Maybe + + @Query("SELECT * FROM $TABLE_EXTENDED_BOLUSES WHERE timestamp <= :timestamp AND (timestamp + duration) > :timestamp AND referenceId IS NULL AND isValid = 1 ORDER BY timestamp DESC LIMIT 1") + fun getExtendedBolusActiveAt(timestamp: Long): Maybe + + @Query("SELECT * FROM $TABLE_EXTENDED_BOLUSES WHERE timestamp >= :timestamp AND isValid = 1 AND referenceId IS NULL ORDER BY timestamp ASC") + fun getExtendedBolusDataFromTime(timestamp: Long): Single> + + @Query("SELECT * FROM $TABLE_EXTENDED_BOLUSES WHERE timestamp >= :from AND timestamp <= :to AND isValid = 1 AND referenceId IS NULL ORDER BY timestamp ASC") + fun getExtendedBolusDataFromTimeToTime(from: Long, to: Long): Single> + + @Query("SELECT * FROM $TABLE_EXTENDED_BOLUSES WHERE timestamp >= :timestamp AND referenceId IS NULL ORDER BY timestamp ASC") + fun getExtendedBolusDataIncludingInvalidFromTime(timestamp: Long): Single> + + @Query("SELECT * FROM $TABLE_EXTENDED_BOLUSES WHERE timestamp >= :from AND timestamp <= :to AND referenceId IS NULL ORDER BY timestamp ASC") + fun getExtendedBolusDataIncludingInvalidFromTimeToTime(from: Long, to: Long): Single> + + // This query will be used with v3 to get all changed records + @Query("SELECT * FROM $TABLE_EXTENDED_BOLUSES WHERE id > :id AND referenceId IS NULL OR id IN (SELECT DISTINCT referenceId FROM $TABLE_EXTENDED_BOLUSES WHERE id > :id) ORDER BY id ASC") + fun getModifiedFrom(id: Long): Single> + + // for WS we need 1 record only + @Query("SELECT * FROM $TABLE_EXTENDED_BOLUSES WHERE id > :id ORDER BY id ASC limit 1") + fun getNextModifiedOrNewAfter(id: Long): Maybe + + @Query("SELECT * FROM $TABLE_EXTENDED_BOLUSES WHERE id = :referenceId") + fun getCurrentFromHistoric(referenceId: Long): Maybe + + @Query("SELECT * FROM $TABLE_EXTENDED_BOLUSES WHERE isValid = 1 AND referenceId IS NULL ORDER BY id ASC LIMIT 1") + fun getOldestRecord(): ExtendedBolus? + } \ No newline at end of file diff --git a/database/src/main/java/info/nightscout/androidaps/database/daos/TemporaryBasalDao.kt b/database/src/main/java/info/nightscout/androidaps/database/daos/TemporaryBasalDao.kt index bc01def71b..49f0c8342c 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/daos/TemporaryBasalDao.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/daos/TemporaryBasalDao.kt @@ -18,10 +18,13 @@ internal interface TemporaryBasalDao : TraceableDao { @Query("DELETE FROM $TABLE_TEMPORARY_BASALS") override fun deleteAllEntries() + @Query("SELECT * FROM $TABLE_TEMPORARY_BASALS WHERE timestamp = :timestamp AND referenceId IS NULL") + fun findByTimestamp(timestamp: Long): TemporaryBasal? + @Query("SELECT * FROM $TABLE_TEMPORARY_BASALS WHERE pumpId = :pumpId AND pumpType = :pumpType AND pumpSerial = :pumpSerial AND referenceId IS NULL") fun findByPumpIds(pumpId: Long, pumpType: InterfaceIDs.PumpType, pumpSerial: String): TemporaryBasal? - @Query("SELECT * FROM $TABLE_TEMPORARY_BASALS WHERE endPumpId = :endPumpId AND pumpType = :pumpType AND pumpSerial = :pumpSerial AND referenceId IS NULL") + @Query("SELECT * FROM $TABLE_TEMPORARY_BASALS WHERE endId = :endPumpId AND pumpType = :pumpType AND pumpSerial = :pumpSerial AND referenceId IS NULL") fun findByPumpEndIds(endPumpId: Long, pumpType: InterfaceIDs.PumpType, pumpSerial: String): TemporaryBasal? @Query("SELECT * FROM $TABLE_TEMPORARY_BASALS WHERE nightscoutId = :nsId AND referenceId IS NULL") @@ -36,9 +39,15 @@ internal interface TemporaryBasalDao : TraceableDao { @Query("SELECT * FROM $TABLE_TEMPORARY_BASALS WHERE timestamp >= :timestamp AND isValid = 1 AND referenceId IS NULL ORDER BY timestamp ASC") fun getTemporaryBasalDataFromTime(timestamp: Long): Single> + @Query("SELECT * FROM $TABLE_TEMPORARY_BASALS WHERE timestamp >= :from AND timestamp <= :to AND isValid = 1 AND referenceId IS NULL ORDER BY timestamp ASC") + fun getTemporaryBasalDataFromTimeToTime(from: Long, to: Long): Single> + @Query("SELECT * FROM $TABLE_TEMPORARY_BASALS WHERE timestamp >= :timestamp AND referenceId IS NULL ORDER BY timestamp ASC") fun getTemporaryBasalDataIncludingInvalidFromTime(timestamp: Long): Single> + @Query("SELECT * FROM $TABLE_TEMPORARY_BASALS WHERE timestamp >= :from AND timestamp <= :to AND referenceId IS NULL ORDER BY timestamp ASC") + fun getTemporaryBasalDataIncludingInvalidFromTimeToTime(from: Long, to: Long): Single> + @Query("SELECT * FROM $TABLE_TEMPORARY_BASALS WHERE isValid = 1 AND referenceId IS NULL ORDER BY timestamp ASC") fun getTemporaryBasalData(): Single> @@ -56,4 +65,6 @@ internal interface TemporaryBasalDao : TraceableDao { @Query("SELECT * FROM $TABLE_TEMPORARY_BASALS WHERE id = :referenceId") fun getCurrentFromHistoric(referenceId: Long): Maybe + @Query("SELECT * FROM $TABLE_TEMPORARY_BASALS WHERE isValid = 1 AND referenceId IS NULL ORDER BY id ASC LIMIT 1") + fun getOldestRecord(): TemporaryBasal? } \ No newline at end of file diff --git a/database/src/main/java/info/nightscout/androidaps/database/entities/ExtendedBolus.kt b/database/src/main/java/info/nightscout/androidaps/database/entities/ExtendedBolus.kt index 40792c11c7..c64dfa8535 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/entities/ExtendedBolus.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/entities/ExtendedBolus.kt @@ -1,30 +1,38 @@ 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_EXTENDED_BOLUSES import info.nightscout.androidaps.database.embedments.InterfaceIDs import info.nightscout.androidaps.database.interfaces.DBEntryWithTimeAndDuration import info.nightscout.androidaps.database.interfaces.TraceableDBEntry -import java.util.TimeZone +import java.util.* @Entity(tableName = TABLE_EXTENDED_BOLUSES, - foreignKeys = [ForeignKey( - entity = ExtendedBolus::class, - parentColumns = ["id"], - childColumns = ["referenceId"])], - indices = [Index("referenceId"), Index("timestamp")]) + foreignKeys = [ForeignKey( + entity = ExtendedBolus::class, + parentColumns = ["id"], + childColumns = ["referenceId"])], + indices = [Index("referenceId"), Index("timestamp")]) data class ExtendedBolus( @PrimaryKey(autoGenerate = true) - override var id: Long = 0, + override var id: Long = 0, override var version: Int = 0, override var dateCreated: Long = -1, override var isValid: Boolean = true, override var referenceId: Long? = null, @Embedded - override var interfaceIDs_backing: InterfaceIDs? = InterfaceIDs(), + override var interfaceIDs_backing: InterfaceIDs? = InterfaceIDs(), override var timestamp: Long, override var utcOffset: Long = TimeZone.getDefault().getOffset(timestamp).toLong(), override var duration: Long, var amount: Double, - var isEmulatingTempBasal: Boolean -) : TraceableDBEntry, DBEntryWithTimeAndDuration \ No newline at end of file + var isEmulatingTempBasal: Boolean = false +) : TraceableDBEntry, DBEntryWithTimeAndDuration { + + val rate: Double // in U/h + get() = amount * (60 * 60 * 1000.0) / duration +} \ No newline at end of file diff --git a/database/src/main/java/info/nightscout/androidaps/database/entities/TemporaryBasal.kt b/database/src/main/java/info/nightscout/androidaps/database/entities/TemporaryBasal.kt index 53be33f22f..b72cac99f0 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/entities/TemporaryBasal.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/entities/TemporaryBasal.kt @@ -1,28 +1,31 @@ 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_TEMPORARY_BASALS import info.nightscout.androidaps.database.embedments.InterfaceIDs import info.nightscout.androidaps.database.interfaces.DBEntryWithTimeAndDuration import info.nightscout.androidaps.database.interfaces.TraceableDBEntry -import java.util.TimeZone +import java.util.* @Entity(tableName = TABLE_TEMPORARY_BASALS, - foreignKeys = [ForeignKey( - entity = TemporaryBasal::class, - parentColumns = ["id"], - childColumns = ["referenceId"])], - indices = [Index("referenceId"), Index("timestamp")]) + foreignKeys = [ForeignKey( + entity = TemporaryBasal::class, + parentColumns = ["id"], + childColumns = ["referenceId"])], + indices = [Index("referenceId"), Index("timestamp")]) data class TemporaryBasal( @PrimaryKey(autoGenerate = true) - override var id: Long = 0, + override var id: Long = 0, override var version: Int = 0, override var dateCreated: Long = -1, override var isValid: Boolean = true, override var referenceId: Long? = null, @Embedded - override var interfaceIDs_backing: InterfaceIDs? = InterfaceIDs(), - var endPumpId: Long? = null, // Some pumps provide separate start and end events in history. Even event pump id can be stored here + override var interfaceIDs_backing: InterfaceIDs? = InterfaceIDs(), override var timestamp: Long, override var utcOffset: Long = TimeZone.getDefault().getOffset(timestamp).toLong(), var type: Type, @@ -30,10 +33,21 @@ data class TemporaryBasal( var rate: Double, override var duration: Long ) : TraceableDBEntry, DBEntryWithTimeAndDuration { + enum class Type { NORMAL, EMULATED_PUMP_SUSPEND, PUMP_SUSPEND, - SUPERBOLUS + SUPERBOLUS, + FAKE_EXTENDED // in memory only + ; + + companion object { + + fun fromString(name: String?) = values().firstOrNull { it.name == name } ?: NORMAL + } } + + val isInProgress: Boolean + get() = System.currentTimeMillis() in timestamp..timestamp + duration } \ No newline at end of file diff --git a/database/src/main/java/info/nightscout/androidaps/database/entities/UserEntry.kt b/database/src/main/java/info/nightscout/androidaps/database/entities/UserEntry.kt index 889d560c3c..400dcfdd0c 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/entities/UserEntry.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/entities/UserEntry.kt @@ -66,6 +66,7 @@ data class UserEntry( @SerializedName("RESTART_EVENTS_REMOVED") RESTART_EVENTS_REMOVED (ColorGroup.Aaps), @SerializedName("TREATMENT_REMOVED") TREATMENT_REMOVED (ColorGroup.InsulinTreatment), @SerializedName("TT_REMOVED") TT_REMOVED (ColorGroup.TT), + @SerializedName("TB_REMOVED") TB_REMOVED (ColorGroup.TT), @SerializedName("NS_PAUSED") NS_PAUSED (ColorGroup.Aaps), @SerializedName("NS_RESUME") NS_RESUME (ColorGroup.Aaps), @SerializedName("NS_QUEUE_CLEARED") NS_QUEUE_CLEARED (ColorGroup.Aaps), diff --git a/database/src/main/java/info/nightscout/androidaps/database/transactions/InvalidateExtendedBolusTransaction.kt b/database/src/main/java/info/nightscout/androidaps/database/transactions/InvalidateExtendedBolusTransaction.kt new file mode 100644 index 0000000000..7f28f09acf --- /dev/null +++ b/database/src/main/java/info/nightscout/androidaps/database/transactions/InvalidateExtendedBolusTransaction.kt @@ -0,0 +1,21 @@ +package info.nightscout.androidaps.database.transactions + +import info.nightscout.androidaps.database.entities.ExtendedBolus + +class InvalidateExtendedBolusTransaction(val id: Long) : Transaction() { + + override fun run(): TransactionResult { + val result = TransactionResult() + val extendedBolus = database.extendedBolusDao.findById(id) + ?: throw IllegalArgumentException("There is no such Extended Bolus with the specified ID.") + extendedBolus.isValid = false + database.extendedBolusDao.updateExistingEntry(extendedBolus) + result.invalidated.add(extendedBolus) + 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/InvalidateTemporaryBasalTransaction.kt b/database/src/main/java/info/nightscout/androidaps/database/transactions/InvalidateTemporaryBasalTransaction.kt new file mode 100644 index 0000000000..5fcc6d90be --- /dev/null +++ b/database/src/main/java/info/nightscout/androidaps/database/transactions/InvalidateTemporaryBasalTransaction.kt @@ -0,0 +1,21 @@ +package info.nightscout.androidaps.database.transactions + +import info.nightscout.androidaps.database.entities.TemporaryBasal + +class InvalidateTemporaryBasalTransaction(val id: Long) : Transaction() { + + override fun run(): TransactionResult { + val result = TransactionResult() + val temporaryBasal = database.temporaryBasalDao.findById(id) + ?: throw IllegalArgumentException("There is no such Temporary Basal with the specified ID.") + temporaryBasal.isValid = false + database.temporaryBasalDao.updateExistingEntry(temporaryBasal) + result.invalidated.add(temporaryBasal) + 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/SyncNsExtendedBolusTransaction.kt b/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncNsExtendedBolusTransaction.kt new file mode 100644 index 0000000000..51ed168f16 --- /dev/null +++ b/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncNsExtendedBolusTransaction.kt @@ -0,0 +1,71 @@ +package info.nightscout.androidaps.database.transactions + +import info.nightscout.androidaps.database.entities.ExtendedBolus +import info.nightscout.androidaps.database.interfaces.end +import kotlin.math.abs + +/** + * Sync the Extended bolus from NS + */ +class SyncNsExtendedBolusTransaction(private val extendedBolus: ExtendedBolus) : Transaction() { + + override fun run(): TransactionResult { + val result = TransactionResult() + + if (extendedBolus.duration != 0L) { + // not ending event + val current: ExtendedBolus? = + extendedBolus.interfaceIDs.nightscoutId?.let { + database.extendedBolusDao.findByNSId(it) + } + + if (current != null) { + // nsId exists, allow only invalidation + if (current.isValid && !extendedBolus.isValid) { + current.isValid = false + database.extendedBolusDao.updateExistingEntry(current) + result.invalidated.add(current) + } + return result + } + + // not known nsId + val running = database.extendedBolusDao.getExtendedBolusActiveAt(extendedBolus.timestamp).blockingGet() + if (running != null && abs(running.timestamp - extendedBolus.timestamp) < 1000 && running.interfaceIDs.nightscoutId == null) { // allow missing milliseconds + // the same record, update nsId only + running.interfaceIDs.nightscoutId = extendedBolus.interfaceIDs.nightscoutId + database.extendedBolusDao.updateExistingEntry(running) + result.updatedNsId.add(running) + } else if (running != null) { + // another running record. end current and insert new + running.end = extendedBolus.timestamp + database.extendedBolusDao.updateExistingEntry(running) + database.extendedBolusDao.insertNewEntry(extendedBolus) + result.ended.add(running) + result.inserted.add(extendedBolus) + } else { + database.extendedBolusDao.insertNewEntry(extendedBolus) + result.inserted.add(extendedBolus) + } + return result + + } else { + // ending event + val running = database.extendedBolusDao.getExtendedBolusActiveAt(extendedBolus.timestamp).blockingGet() + if (running != null) { + running.end = extendedBolus.timestamp + database.extendedBolusDao.updateExistingEntry(running) + result.ended.add(running) + } + } + return result + } + + class TransactionResult { + + val updatedNsId = mutableListOf() + val inserted = mutableListOf() + val invalidated = mutableListOf() + val ended = mutableListOf() + } +} \ No newline at end of file diff --git a/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncNsTemporaryBasalTransaction.kt b/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncNsTemporaryBasalTransaction.kt new file mode 100644 index 0000000000..ca3d9581e4 --- /dev/null +++ b/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncNsTemporaryBasalTransaction.kt @@ -0,0 +1,62 @@ +package info.nightscout.androidaps.database.transactions + +import info.nightscout.androidaps.database.entities.TemporaryBasal +import info.nightscout.androidaps.database.interfaces.end +import kotlin.math.abs + +/** + * Sync the Temporary Basal from NS + */ +class SyncNsTemporaryBasalTransaction(private val temporaryBasal: TemporaryBasal) : Transaction() { + + override fun run(): TransactionResult { + val result = TransactionResult() + + if (temporaryBasal.duration != 0L) { + // not ending event + val current: TemporaryBasal? = + temporaryBasal.interfaceIDs.nightscoutId?.let { + database.temporaryBasalDao.findByNSId(it) + } + + if (current != null) { + // nsId exists, allow only invalidation + if (current.isValid && !temporaryBasal.isValid) { + current.isValid = false + database.temporaryBasalDao.updateExistingEntry(current) + result.invalidated.add(current) + } + return result + } + + // not known nsId + val running = database.temporaryBasalDao.getTemporaryBasalActiveAt(temporaryBasal.timestamp).blockingGet() + if (running != null && abs(running.timestamp - temporaryBasal.timestamp) < 1000 && running.interfaceIDs.nightscoutId == null) { // allow missing milliseconds + // the same record, update nsId only + running.interfaceIDs.nightscoutId = temporaryBasal.interfaceIDs.nightscoutId + database.temporaryBasalDao.updateExistingEntry(running) + result.updatedNsId.add(running) + } else if (running != null) { + // another running record. end current and insert new + running.end = temporaryBasal.timestamp + database.temporaryBasalDao.updateExistingEntry(running) + database.temporaryBasalDao.insertNewEntry(temporaryBasal) + result.ended.add(running) + result.inserted.add(temporaryBasal) + } else { + database.temporaryBasalDao.insertNewEntry(temporaryBasal) + result.inserted.add(temporaryBasal) + } + return result + } + return result + } + + class TransactionResult { + + val updatedNsId = mutableListOf() + val inserted = mutableListOf() + val invalidated = mutableListOf() + val ended = mutableListOf() + } +} \ No newline at end of file diff --git a/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncPumpBolusTransaction.kt b/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncPumpBolusTransaction.kt index 5c531a5bb2..c7ff85ba21 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncPumpBolusTransaction.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncPumpBolusTransaction.kt @@ -19,11 +19,17 @@ class SyncPumpBolusTransaction( database.bolusDao.insertNewEntry(bolus) result.inserted.add(bolus) } else { - current.timestamp = bolus.timestamp - current.amount = bolus.amount - current.type = bolusType ?: current.type - database.bolusDao.updateExistingEntry(current) - result.updated.add(current) + if ( + current.timestamp != bolus.timestamp || + current.amount != bolus.amount || + current.type != bolusType ?: current.type + ) { + current.timestamp = bolus.timestamp + current.amount = bolus.amount + current.type = bolusType ?: current.type + database.bolusDao.updateExistingEntry(current) + result.updated.add(current) + } } return result } diff --git a/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncPumpCancelExtendedBolusIfAnyTransaction.kt b/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncPumpCancelExtendedBolusIfAnyTransaction.kt new file mode 100644 index 0000000000..c73b7bb201 --- /dev/null +++ b/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncPumpCancelExtendedBolusIfAnyTransaction.kt @@ -0,0 +1,32 @@ +package info.nightscout.androidaps.database.transactions + +import info.nightscout.androidaps.database.embedments.InterfaceIDs +import info.nightscout.androidaps.database.entities.ExtendedBolus +import info.nightscout.androidaps.database.interfaces.end + +class SyncPumpCancelExtendedBolusIfAnyTransaction( + private val timestamp: Long, private val endPumpId: Long, private val pumpType: InterfaceIDs.PumpType, private val pumpSerial: String +) : Transaction() { + + override fun run(): TransactionResult { + val result = TransactionResult() + val existing = database.extendedBolusDao.findByPumpEndIds(endPumpId, pumpType, pumpSerial) + if (existing != null) // assume EB has been cut already + return result + val running = database.extendedBolusDao.getExtendedBolusActiveAt(timestamp, pumpType, pumpSerial).blockingGet() + if (running != null && running.interfaceIDs.endId == null) { // do not allow overwrite if cut by end event + val pctRun = (timestamp - running.timestamp) / running.duration.toDouble() + running.amount *= pctRun + running.end = timestamp + running.interfaceIDs.endId = endPumpId + database.extendedBolusDao.updateExistingEntry(running) + result.updated.add(running) + } + return result + } + + class TransactionResult { + + val updated = mutableListOf() + } +} \ No newline at end of file diff --git a/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncPumpCancelTemporaryBasalIfAnyTransaction.kt b/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncPumpCancelTemporaryBasalIfAnyTransaction.kt index 82cb7fb304..fb7eaaadb9 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncPumpCancelTemporaryBasalIfAnyTransaction.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncPumpCancelTemporaryBasalIfAnyTransaction.kt @@ -14,9 +14,9 @@ class SyncPumpCancelTemporaryBasalIfAnyTransaction( if (existing != null) // assume TBR has been cut already return result val current = database.temporaryBasalDao.getTemporaryBasalActiveAt(timestamp, pumpType, pumpSerial).blockingGet() - if (current != null) { + if (current != null && current.interfaceIDs.endId == null) { // do not allow overwrite if cut by end event current.end = timestamp - current.endPumpId = endPumpId + current.interfaceIDs.endId = endPumpId database.temporaryBasalDao.updateExistingEntry(current) result.updated.add(current) } diff --git a/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncPumpExtendedBolusTransaction.kt b/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncPumpExtendedBolusTransaction.kt new file mode 100644 index 0000000000..f3cd17eaa6 --- /dev/null +++ b/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncPumpExtendedBolusTransaction.kt @@ -0,0 +1,49 @@ +package info.nightscout.androidaps.database.transactions + +import info.nightscout.androidaps.database.entities.ExtendedBolus +import info.nightscout.androidaps.database.interfaces.end + +/** + * Creates or updates the extended bolus from pump synchronization + */ +class SyncPumpExtendedBolusTransaction(private val extendedBolus: ExtendedBolus) : Transaction() { + + override fun run(): TransactionResult { + extendedBolus.interfaceIDs.pumpId ?: extendedBolus.interfaceIDs.pumpType + ?: extendedBolus.interfaceIDs.pumpSerial + ?: throw IllegalStateException("Some pump ID is null") + val result = TransactionResult() + val current = database.extendedBolusDao.findByPumpIds(extendedBolus.interfaceIDs.pumpId!!, extendedBolus.interfaceIDs.pumpType!!, extendedBolus.interfaceIDs.pumpSerial!!) + if (current != null) { + if (current.interfaceIDs.endId == null && + (current.timestamp != extendedBolus.timestamp || + current.amount != extendedBolus.amount || + current.duration != extendedBolus.duration) + ) { + current.timestamp = extendedBolus.timestamp + current.amount = extendedBolus.amount + current.duration = extendedBolus.duration + database.extendedBolusDao.updateExistingEntry(current) + result.updated.add(current) + } + } else { + val running = database.extendedBolusDao.getExtendedBolusActiveAt(extendedBolus.timestamp, extendedBolus.interfaceIDs.pumpType!!, extendedBolus.interfaceIDs.pumpSerial!!).blockingGet() + if (running != null) { + val pctRun = (extendedBolus.timestamp - running.timestamp) / running.duration.toDouble() + running.amount /= pctRun + running.end = extendedBolus.timestamp + database.extendedBolusDao.updateExistingEntry(running) + result.updated.add(running) + } + database.extendedBolusDao.insertNewEntry(extendedBolus) + result.inserted.add(extendedBolus) + } + return result + } + + class TransactionResult { + + val inserted = mutableListOf() + val updated = mutableListOf() + } +} \ No newline at end of file diff --git a/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncPumpTemporaryBasalTransaction.kt b/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncPumpTemporaryBasalTransaction.kt index 5949a79653..bd4c64cf2d 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncPumpTemporaryBasalTransaction.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncPumpTemporaryBasalTransaction.kt @@ -12,17 +12,25 @@ class SyncPumpTemporaryBasalTransaction( ) : Transaction() { override fun run(): TransactionResult { - temporaryBasal.interfaceIDs.pumpId ?: temporaryBasal.interfaceIDs.pumpType ?: temporaryBasal.interfaceIDs.pumpSerial ?: - throw IllegalStateException("Some pump ID is null") + temporaryBasal.interfaceIDs.pumpId ?: temporaryBasal.interfaceIDs.pumpType + ?: temporaryBasal.interfaceIDs.pumpSerial + ?: throw IllegalStateException("Some pump ID is null") val result = TransactionResult() val current = database.temporaryBasalDao.findByPumpIds(temporaryBasal.interfaceIDs.pumpId!!, temporaryBasal.interfaceIDs.pumpType!!, temporaryBasal.interfaceIDs.pumpSerial!!) if (current != null) { - current.timestamp = temporaryBasal.timestamp - current.rate = temporaryBasal.rate - current.duration = temporaryBasal.duration - current.type = type ?: current.type - database.temporaryBasalDao.updateExistingEntry(current) - result.updated.add(current) + if ( + current.timestamp != temporaryBasal.timestamp || + current.rate != temporaryBasal.rate || + current.duration != temporaryBasal.duration && current.interfaceIDs.endId == null || + current.type != type ?: current.type + ) { + current.timestamp = temporaryBasal.timestamp + current.rate = temporaryBasal.rate + current.duration = temporaryBasal.duration + current.type = type ?: current.type + database.temporaryBasalDao.updateExistingEntry(current) + result.updated.add(current) + } } else { val running = database.temporaryBasalDao.getTemporaryBasalActiveAt(temporaryBasal.timestamp, temporaryBasal.interfaceIDs.pumpType!!, temporaryBasal.interfaceIDs.pumpSerial!!).blockingGet() if (running != null) { diff --git a/database/src/main/java/info/nightscout/androidaps/database/transactions/UpdateNsIdExtendedBolusTransaction.kt b/database/src/main/java/info/nightscout/androidaps/database/transactions/UpdateNsIdExtendedBolusTransaction.kt new file mode 100644 index 0000000000..cfa12027b1 --- /dev/null +++ b/database/src/main/java/info/nightscout/androidaps/database/transactions/UpdateNsIdExtendedBolusTransaction.kt @@ -0,0 +1,12 @@ +package info.nightscout.androidaps.database.transactions + +import info.nightscout.androidaps.database.entities.ExtendedBolus + +class UpdateNsIdExtendedBolusTransaction(val bolus: ExtendedBolus) : Transaction() { + + override fun run() { + val current = database.extendedBolusDao.findById(bolus.id) + if (current != null && current.interfaceIDs.nightscoutId != bolus.interfaceIDs.nightscoutId) + database.extendedBolusDao.updateExistingEntry(bolus) + } +} \ No newline at end of file diff --git a/database/src/main/java/info/nightscout/androidaps/database/transactions/UpdateNsIdTemporaryBasalTransaction.kt b/database/src/main/java/info/nightscout/androidaps/database/transactions/UpdateNsIdTemporaryBasalTransaction.kt new file mode 100644 index 0000000000..be9a3c3efa --- /dev/null +++ b/database/src/main/java/info/nightscout/androidaps/database/transactions/UpdateNsIdTemporaryBasalTransaction.kt @@ -0,0 +1,12 @@ +package info.nightscout.androidaps.database.transactions + +import info.nightscout.androidaps.database.entities.TemporaryBasal + +class UpdateNsIdTemporaryBasalTransaction(val bolus: TemporaryBasal) : Transaction() { + + override fun run() { + val current = database.temporaryBasalDao.findById(bolus.id) + if (current != null && current.interfaceIDs.nightscoutId != bolus.interfaceIDs.nightscoutId) + database.temporaryBasalDao.updateExistingEntry(bolus) + } +} \ No newline at end of file diff --git a/insight/src/main/java/info/nightscout/androidaps/plugins/pump/insight/LocalInsightPlugin.java b/insight/src/main/java/info/nightscout/androidaps/plugins/pump/insight/LocalInsightPlugin.java index 923bc8bcd5..7d4a3a0193 100644 --- a/insight/src/main/java/info/nightscout/androidaps/plugins/pump/insight/LocalInsightPlugin.java +++ b/insight/src/main/java/info/nightscout/androidaps/plugins/pump/insight/LocalInsightPlugin.java @@ -1,5 +1,8 @@ package info.nightscout.androidaps.plugins.pump.insight; +import static info.nightscout.androidaps.extensions.PumpStateExtensionKt.convertedToAbsolute; +import static info.nightscout.androidaps.extensions.PumpStateExtensionKt.getPlannedRemainingMinutes; + import android.app.NotificationChannel; import android.app.NotificationManager; import android.content.ComponentName; @@ -987,17 +990,17 @@ public class LocalInsightPlugin extends PumpPluginBase implements PumpInterface, } catch (Exception e) { e.printStackTrace(); } - TemporaryBasal tb = treatmentsPlugin.getTempBasalFromHistory(now); + PumpSync.PumpState.TemporaryBasal tb = pumpSync.expectedPumpState().getTemporaryBasal(); if (tb != null) { - extended.put("TempBasalAbsoluteRate", tb.tempBasalConvertedToAbsolute(now, profile)); - extended.put("TempBasalStart", dateUtil.dateAndTimeString(tb.date)); - extended.put("TempBasalRemaining", tb.getPlannedRemainingMinutes()); + extended.put("TempBasalAbsoluteRate", convertedToAbsolute(tb, now, profile)); + extended.put("TempBasalStart", dateUtil.dateAndTimeString(tb.getTimestamp())); + extended.put("TempBasalRemaining", getPlannedRemainingMinutes(tb)); } - ExtendedBolus eb = treatmentsPlugin.getExtendedBolusFromHistory(now); + PumpSync.PumpState.ExtendedBolus eb = pumpSync.expectedPumpState().getExtendedBolus(); if (eb != null) { - extended.put("ExtendedBolusAbsoluteRate", eb.absoluteRate()); - extended.put("ExtendedBolusStart", dateUtil.dateAndTimeString(eb.date)); - extended.put("ExtendedBolusRemaining", eb.getPlannedRemainingMinutes()); + extended.put("ExtendedBolusAbsoluteRate", eb.getRate()); + extended.put("ExtendedBolusStart", dateUtil.dateAndTimeString(eb.getTimestamp())); + extended.put("ExtendedBolusRemaining", getPlannedRemainingMinutes(eb)); } extended.put("BaseBasalRate", getBaseBasalRate()); status.put("timestamp", DateUtil.toISOString(now)); diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.java index 5195da9e36..ad18d2543b 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.java +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.java @@ -1,5 +1,8 @@ package info.nightscout.androidaps.plugins.pump.common; +import static info.nightscout.androidaps.extensions.PumpStateExtensionKt.convertedToAbsolute; +import static info.nightscout.androidaps.extensions.PumpStateExtensionKt.getPlannedRemainingMinutes; + import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; @@ -16,10 +19,9 @@ import info.nightscout.androidaps.core.R; import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.PumpEnactResult; -import info.nightscout.androidaps.db.ExtendedBolus; -import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.events.EventCustomActionsChanged; +import info.nightscout.androidaps.extensions.PumpStateExtensionKt; import info.nightscout.androidaps.interfaces.ActivePluginProvider; import info.nightscout.androidaps.interfaces.CommandQueueProvider; import info.nightscout.androidaps.interfaces.ConstraintsInterface; @@ -70,7 +72,7 @@ public abstract class PumpPluginAbstract extends PumpPluginBase implements PumpI protected boolean displayConnectionMessages = false; protected PumpType pumpType; protected AapsSchedulers aapsSchedulers; - + protected PumpSync pumpSync; protected PumpPluginAbstract( PluginDescription pluginDescription, @@ -85,7 +87,8 @@ public abstract class PumpPluginAbstract extends PumpPluginBase implements PumpI Context context, FabricPrivacy fabricPrivacy, DateUtil dateUtil, - AapsSchedulers aapsSchedulers + AapsSchedulers aapsSchedulers, + PumpSync pumpSync ) { super(pluginDescription, injector, aapsLogger, resourceHelper, commandQueue); @@ -102,6 +105,7 @@ public abstract class PumpPluginAbstract extends PumpPluginBase implements PumpI this.pumpType = pumpType; this.dateUtil = dateUtil; this.aapsSchedulers = aapsSchedulers; + this.pumpSync = pumpSync; } @@ -323,6 +327,7 @@ public abstract class PumpPluginAbstract extends PumpPluginBase implements PumpI return new JSONObject(); } + long now = System.currentTimeMillis(); JSONObject pump = new JSONObject(); JSONObject battery = new JSONObject(); JSONObject status = new JSONObject(); @@ -336,19 +341,18 @@ public abstract class PumpPluginAbstract extends PumpPluginBase implements PumpI } catch (Exception ignored) { } - TemporaryBasal tb = activePlugin.getActiveTreatments().getTempBasalFromHistory(System.currentTimeMillis()); + PumpSync.PumpState.TemporaryBasal tb = pumpSync.expectedPumpState().getTemporaryBasal(); if (tb != null) { - extended.put("TempBasalAbsoluteRate", - tb.tempBasalConvertedToAbsolute(System.currentTimeMillis(), profile)); - extended.put("TempBasalStart", dateUtil.dateAndTimeString(tb.date)); - extended.put("TempBasalRemaining", tb.getPlannedRemainingMinutes()); + extended.put("TempBasalAbsoluteRate", convertedToAbsolute(tb, now, profile)); + extended.put("TempBasalStart", dateUtil.dateAndTimeString(tb.getTimestamp())); + extended.put("TempBasalRemaining", getPlannedRemainingMinutes(tb)); } - ExtendedBolus eb = activePlugin.getActiveTreatments().getExtendedBolusFromHistory(System.currentTimeMillis()); + PumpSync.PumpState.ExtendedBolus eb = pumpSync.expectedPumpState().getExtendedBolus(); if (eb != null) { - extended.put("ExtendedBolusAbsoluteRate", eb.absoluteRate()); - extended.put("ExtendedBolusStart", dateUtil.dateAndTimeString(eb.date)); - extended.put("ExtendedBolusRemaining", eb.getPlannedRemainingMinutes()); + extended.put("ExtendedBolusAbsoluteRate", eb.getRate()); + extended.put("ExtendedBolusStart", dateUtil.dateAndTimeString(eb.getTimestamp())); + extended.put("ExtendedBolusRemaining", getPlannedRemainingMinutes(eb)); } status.put("timestamp", DateUtil.toISOString(new Date())); @@ -378,14 +382,13 @@ public abstract class PumpPluginAbstract extends PumpPluginBase implements PumpI ret += "LastBolus: " + DecimalFormatter.INSTANCE.to2Decimal(getPumpStatusData().lastBolusAmount) + "U @" + // android.text.format.DateFormat.format("HH:mm", getPumpStatusData().lastBolusTime) + "\n"; } - TemporaryBasal activeTemp = activePlugin.getActiveTreatments().getRealTempBasalFromHistory(System.currentTimeMillis()); + PumpSync.PumpState.TemporaryBasal activeTemp = pumpSync.expectedPumpState().getTemporaryBasal(); if (activeTemp != null) { - ret += "Temp: " + activeTemp.toStringFull() + "\n"; + ret += "Temp: " + PumpStateExtensionKt.toStringFull(activeTemp, dateUtil) + "\n"; } - ExtendedBolus activeExtendedBolus = activePlugin.getActiveTreatments().getExtendedBolusFromHistory( - System.currentTimeMillis()); + PumpSync.PumpState.ExtendedBolus activeExtendedBolus = pumpSync.expectedPumpState().getExtendedBolus(); if (activeExtendedBolus != null) { - ret += "Extended: " + activeExtendedBolus.toString() + "\n"; + ret += "Extended: " + PumpStateExtensionKt.toStringFull(activeTemp, dateUtil) + "\n"; } // if (!veryShort) { // ret += "TDD: " + DecimalFormatter.to0Decimal(pumpStatus.dailyTotalUnits) + " / " diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicFragment.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicFragment.kt index b18d539464..dab3c800f1 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicFragment.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicFragment.kt @@ -9,11 +9,13 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import dagger.android.support.DaggerFragment +import info.nightscout.androidaps.extensions.toStringFull import info.nightscout.androidaps.events.EventExtendedBolusChange import info.nightscout.androidaps.events.EventPumpStatusChanged import info.nightscout.androidaps.events.EventTempBasalChange import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.CommandQueueProvider +import info.nightscout.androidaps.interfaces.PumpSync import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.bus.RxBusWrapper @@ -45,12 +47,15 @@ import info.nightscout.androidaps.utils.rx.AapsSchedulers import io.reactivex.disposables.CompositeDisposable import io.reactivex.rxkotlin.plusAssign import javax.inject.Inject +import kotlin.math.min +import kotlin.math.roundToInt class MedtronicFragment : DaggerFragment() { @Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var resourceHelper: ResourceHelper + @Inject lateinit var dateUtil: DateUtil @Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var commandQueue: CommandQueueProvider @Inject lateinit var activePlugin: ActivePluginProvider @@ -61,6 +66,7 @@ class MedtronicFragment : DaggerFragment() { @Inject lateinit var medtronicPumpStatus: MedtronicPumpStatus @Inject lateinit var rileyLinkServiceData: RileyLinkServiceData @Inject lateinit var aapsSchedulers: AapsSchedulers + @Inject lateinit var pumpSync: PumpSync private var disposable: CompositeDisposable = CompositeDisposable() @@ -307,11 +313,12 @@ class MedtronicFragment : DaggerFragment() { binding.lastBolus.text = "" } + val pumpState = pumpSync.expectedPumpState() // base basal rate binding.baseBasalRate.text = ("(" + medtronicPumpStatus.activeProfileName + ") " + resourceHelper.gs(R.string.pump_basebasalrate, medtronicPumpPlugin.baseBasalRate)) - binding.tempBasal.text = activePlugin.activeTreatments.getTempBasalFromHistory(System.currentTimeMillis())?.toStringFull() + binding.tempBasal.text = pumpState.temporaryBasal?.toStringFull(dateUtil) ?: "" // battery @@ -329,7 +336,7 @@ class MedtronicFragment : DaggerFragment() { medtronicPumpPlugin.rileyLinkService?.verifyConfiguration() binding.errors.text = medtronicPumpStatus.errorInfo - var showRileyLinkBatteryLevel: Boolean = rileyLinkServiceData.showBatteryLevel + val showRileyLinkBatteryLevel: Boolean = rileyLinkServiceData.showBatteryLevel if (showRileyLinkBatteryLevel) { binding.rlBatteryView.visibility = View.VISIBLE diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.java index 8fb40886f5..0c66db266c 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.java +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.java @@ -137,7 +137,8 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter RileyLinkServiceData rileyLinkServiceData, ServiceTaskExecutor serviceTaskExecutor, DateUtil dateUtil, - AapsSchedulers aapsSchedulers + AapsSchedulers aapsSchedulers, + PumpSync pumpSync ) { super(new PluginDescription() // @@ -149,7 +150,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter .preferencesId(R.xml.pref_medtronic) .description(R.string.description_pump_medtronic), // PumpType.MEDTRONIC_522_722, // we default to most basic model, correct model from config is loaded later - injector, resourceHelper, aapsLogger, commandQueue, rxBus, activePlugin, sp, context, fabricPrivacy, dateUtil, aapsSchedulers + injector, resourceHelper, aapsLogger, commandQueue, rxBus, activePlugin, sp, context, fabricPrivacy, dateUtil, aapsSchedulers, pumpSync ); this.medtronicUtil = medtronicUtil; diff --git a/omnipod-common/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/common/ui/wizard/common/fragment/ActionFragmentBase.kt b/omnipod-common/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/common/ui/wizard/common/fragment/ActionFragmentBase.kt index 945ebfae50..681f837150 100644 --- a/omnipod-common/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/common/ui/wizard/common/fragment/ActionFragmentBase.kt +++ b/omnipod-common/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/common/ui/wizard/common/fragment/ActionFragmentBase.kt @@ -10,7 +10,7 @@ import android.widget.TextView import androidx.annotation.LayoutRes import info.nightscout.androidaps.plugins.pump.omnipod.common.R import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.common.viewmodel.ActionViewModelBase -import info.nightscout.androidaps.utils.extensions.toVisibility +import info.nightscout.androidaps.extensions.toVisibility abstract class ActionFragmentBase : WizardFragmentBase() { diff --git a/omnipod-eros/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/OmnipodErosPumpPlugin.java b/omnipod-eros/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/OmnipodErosPumpPlugin.java index 91959c5a7b..2286b61052 100644 --- a/omnipod-eros/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/OmnipodErosPumpPlugin.java +++ b/omnipod-eros/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/OmnipodErosPumpPlugin.java @@ -1,6 +1,9 @@ package info.nightscout.androidaps.plugins.pump.omnipod.eros; import static info.nightscout.androidaps.plugins.pump.omnipod.eros.driver.definition.OmnipodConstants.BASAL_STEP_DURATION; +import static info.nightscout.androidaps.extensions.PumpStateExtensionKt.convertedToAbsolute; +import static info.nightscout.androidaps.extensions.PumpStateExtensionKt.getPlannedRemainingMinutes; +import static info.nightscout.androidaps.extensions.PumpStateExtensionKt.toStringFull; import android.content.ComponentName; import android.content.Context; @@ -13,6 +16,7 @@ import android.os.SystemClock; import android.text.TextUtils; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import org.joda.time.DateTime; import org.joda.time.Duration; @@ -33,9 +37,6 @@ import info.nightscout.androidaps.activities.ErrorHelperActivity; import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.PumpEnactResult; -import info.nightscout.androidaps.db.ExtendedBolus; -import info.nightscout.androidaps.db.Source; -import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.events.EventAppInitialized; import info.nightscout.androidaps.events.EventPreferenceChange; @@ -57,8 +58,8 @@ import info.nightscout.androidaps.plugins.general.actions.defs.CustomActionType; import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; -import info.nightscout.androidaps.plugins.pump.common.defs.TempBasalPair; import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; +import info.nightscout.androidaps.plugins.pump.common.defs.TempBasalPair; import info.nightscout.androidaps.plugins.pump.common.events.EventRileyLinkDeviceStatusChange; import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst; import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil; @@ -103,6 +104,7 @@ import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.DecimalFormatter; import info.nightscout.androidaps.utils.FabricPrivacy; import info.nightscout.androidaps.utils.Round; +import info.nightscout.androidaps.utils.T; import info.nightscout.androidaps.utils.TimeChangeType; import info.nightscout.androidaps.utils.resources.ResourceHelper; import info.nightscout.androidaps.utils.rx.AapsSchedulers; @@ -364,13 +366,14 @@ public class OmnipodErosPumpPlugin extends PumpPluginBase implements PumpInterfa } private void handleCancelledTbr() { - if (!podStateManager.isTempBasalRunning() && activePlugin.getActiveTreatments().isTempBasalInProgress() && !aapsOmnipodErosManager.hasSuspendedFakeTbr()) { + PumpSync.PumpState.TemporaryBasal tbr = pumpSync.expectedPumpState().getTemporaryBasal(); + if (!podStateManager.isTempBasalRunning() && tbr != null && !aapsOmnipodErosManager.hasSuspendedFakeTbr()) { aapsOmnipodErosManager.reportCancelledTbr(); } } private void handleUncertainTbrRecovery() { - TemporaryBasal tempBasal = activePlugin.getActiveTreatments().getTempBasalFromHistory(System.currentTimeMillis()); + PumpSync.PumpState.TemporaryBasal tempBasal = pumpSync.expectedPumpState().getTemporaryBasal(); if (podStateManager.isTempBasalRunning() && tempBasal == null) { if (podStateManager.hasTempBasal()) { @@ -378,14 +381,16 @@ public class OmnipodErosPumpPlugin extends PumpPluginBase implements PumpInterfa long pumpId = aapsOmnipodErosManager.addTbrSuccessToHistory(podStateManager.getTempBasalStartTime().getMillis(), new TempBasalPair(podStateManager.getTempBasalAmount(), false, (int) podStateManager.getTempBasalDuration().getStandardMinutes())); - TemporaryBasal temporaryBasal = new TemporaryBasal(getInjector()) // - .absolute(podStateManager.getTempBasalAmount()) // - .duration((int) podStateManager.getTempBasalDuration().getStandardMinutes()) - .date(podStateManager.getTempBasalStartTime().getMillis()) // - .source(Source.PUMP) // - .pumpId(pumpId); - - activePlugin.getActiveTreatments().addToHistoryTempBasal(temporaryBasal); + pumpSync.syncTemporaryBasalWithPumpId( + podStateManager.getTempBasalStartTime().getMillis(), + podStateManager.getTempBasalAmount(), + podStateManager.getTempBasalDuration().getMillis(), + true, + PumpSync.TemporaryBasalType.NORMAL, + pumpId, + PumpType.OMNIPOD_EROS, + serialNumber() + ); } else { // Not sure what's going on. Notify the user aapsLogger.error(LTag.PUMP, "Unknown TBR in both Pod state and AAPS"); @@ -393,7 +398,7 @@ public class OmnipodErosPumpPlugin extends PumpPluginBase implements PumpInterfa } } else if (!podStateManager.isTempBasalRunning() && tempBasal != null) { aapsLogger.warn(LTag.PUMP, "Removing AAPS TBR that actually hadn't succeeded"); - activePlugin.getActiveTreatments().removeTempBasal(tempBasal); + pumpSync.invalidateTemporaryBasal(tempBasal.getId()); } rxBus.send(new EventDismissNotification(Notification.OMNIPOD_TBR_ALERTS)); @@ -668,15 +673,15 @@ public class OmnipodErosPumpPlugin extends PumpPluginBase implements PumpInterfa } // read current TBR - TemporaryBasal tbrCurrent = readTBR(); + PumpSync.PumpState.TemporaryBasal tbrCurrent = readTBR(); if (tbrCurrent != null) { aapsLogger.info(LTag.PUMP, "setTempBasalAbsolute: Current Basal: duration: {} min, rate={}", - tbrCurrent.durationInMinutes, tbrCurrent.absoluteRate); + T.msecs(tbrCurrent.getDuration()).mins(), tbrCurrent.getRate()); } if (tbrCurrent != null && !enforceNew) { - if (Round.isSame(tbrCurrent.absoluteRate, absoluteRate)) { + if (Round.isSame(tbrCurrent.getRate(), absoluteRate)) { aapsLogger.info(LTag.PUMP, "setTempBasalAbsolute - No enforceNew and same rate. Exiting."); return new PumpEnactResult(getInjector()).success(true).enacted(false); } @@ -696,7 +701,7 @@ public class OmnipodErosPumpPlugin extends PumpPluginBase implements PumpInterfa @Override @NonNull public PumpEnactResult cancelTempBasal(boolean enforceNew) { - TemporaryBasal tbrCurrent = readTBR(); + PumpSync.PumpState.TemporaryBasal tbrCurrent = readTBR(); if (tbrCurrent == null) { aapsLogger.info(LTag.PUMP, "cancelTempBasal - TBR already cancelled."); @@ -714,6 +719,7 @@ public class OmnipodErosPumpPlugin extends PumpPluginBase implements PumpInterfa return new JSONObject(); } + long now = System.currentTimeMillis(); JSONObject pump = new JSONObject(); JSONObject battery = new JSONObject(); JSONObject status = new JSONObject(); @@ -730,19 +736,17 @@ public class OmnipodErosPumpPlugin extends PumpPluginBase implements PumpInterfa } catch (Exception ignored) { } - TemporaryBasal tb = activePlugin.getActiveTreatments().getRealTempBasalFromHistory(System.currentTimeMillis()); + PumpSync.PumpState.TemporaryBasal tb = pumpSync.expectedPumpState().getTemporaryBasal(); if (tb != null) { - extended.put("TempBasalAbsoluteRate", - tb.tempBasalConvertedToAbsolute(System.currentTimeMillis(), profile)); - extended.put("TempBasalStart", dateUtil.dateAndTimeString(tb.date)); - extended.put("TempBasalRemaining", tb.getPlannedRemainingMinutes()); + extended.put("TempBasalAbsoluteRate", convertedToAbsolute(tb, now, profile)); + extended.put("TempBasalStart", dateUtil.dateAndTimeString(tb.getTimestamp())); + extended.put("TempBasalRemaining", getPlannedRemainingMinutes(tb)); } - - ExtendedBolus eb = activePlugin.getActiveTreatments().getExtendedBolusFromHistory(System.currentTimeMillis()); + PumpSync.PumpState.ExtendedBolus eb = pumpSync.expectedPumpState().getExtendedBolus(); if (eb != null) { - extended.put("ExtendedBolusAbsoluteRate", eb.absoluteRate()); - extended.put("ExtendedBolusStart", dateUtil.dateAndTimeString(eb.date)); - extended.put("ExtendedBolusRemaining", eb.getPlannedRemainingMinutes()); + extended.put("ExtendedBolusAbsoluteRate", eb.getRate()); + extended.put("ExtendedBolusStart", dateUtil.dateAndTimeString(eb.getTimestamp())); + extended.put("ExtendedBolusRemaining", getPlannedRemainingMinutes(eb)); } status.put("timestamp", DateUtil.toISOString(new Date())); @@ -803,14 +807,12 @@ public class OmnipodErosPumpPlugin extends PumpPluginBase implements PumpInterfa ret += resourceHelper.gs(R.string.omnipod_common_short_status_last_bolus, DecimalFormatter.INSTANCE.to2Decimal(podStateManager.getLastBolusAmount()), android.text.format.DateFormat.format("HH:mm", podStateManager.getLastBolusStartTime().toDate())) + "\n"; } - TemporaryBasal activeTemp = activePlugin.getActiveTreatments().getRealTempBasalFromHistory(System.currentTimeMillis()); - if (activeTemp != null) { - ret += resourceHelper.gs(R.string.omnipod_common_short_status_temp_basal, activeTemp.toStringFull()) + "\n"; + PumpSync.PumpState pumpState = pumpSync.expectedPumpState(); + if (pumpState.getTemporaryBasal() != null && pumpState.getProfile() != null) { + ret += resourceHelper.gs(R.string.omnipod_common_short_status_temp_basal, toStringFull(pumpState.getTemporaryBasal(), dateUtil) + "\n"); } - ExtendedBolus activeExtendedBolus = activePlugin.getActiveTreatments().getExtendedBolusFromHistory( - System.currentTimeMillis()); - if (activeExtendedBolus != null) { - ret += resourceHelper.gs(R.string.omnipod_common_short_status_extended_bolus, activeExtendedBolus.toString()) + "\n"; + if (pumpState.getExtendedBolus() != null) { + ret += resourceHelper.gs(R.string.omnipod_common_short_status_extended_bolus, toStringFull(pumpState.getExtendedBolus(), dateUtil) + "\n"); } ret += resourceHelper.gs(R.string.omnipod_common_short_status_reservoir, (getReservoirLevel() > OmnipodConstants.MAX_RESERVOIR_READING ? "50+" : DecimalFormatter.INSTANCE.to0Decimal(getReservoirLevel()))) + "\n"; if (isUseRileyLinkBatteryLevel()) { @@ -1130,8 +1132,8 @@ public class OmnipodErosPumpPlugin extends PumpPluginBase implements PumpInterfa sp.putLong(statsKey, currentCount); } - private TemporaryBasal readTBR() { - return activePlugin.getActiveTreatments().getTempBasalFromHistory(System.currentTimeMillis()); + @Nullable private PumpSync.PumpState.TemporaryBasal readTBR() { + return pumpSync.expectedPumpState().getTemporaryBasal(); } private PumpEnactResult getOperationNotSupportedWithCustomText(int resourceId) { diff --git a/omnipod-eros/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/manager/AapsOmnipodErosManager.java b/omnipod-eros/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/manager/AapsOmnipodErosManager.java index da38299c6c..206b182ad6 100644 --- a/omnipod-eros/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/manager/AapsOmnipodErosManager.java +++ b/omnipod-eros/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/manager/AapsOmnipodErosManager.java @@ -19,10 +19,9 @@ import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.db.OmnipodHistoryRecord; -import info.nightscout.androidaps.db.Source; -import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.events.Event; import info.nightscout.androidaps.events.EventRefreshOverview; +import info.nightscout.androidaps.extensions.PumpStateExtensionKt; import info.nightscout.androidaps.interfaces.ActivePluginProvider; import info.nightscout.androidaps.interfaces.DatabaseHelperInterface; import info.nightscout.androidaps.interfaces.PumpSync; @@ -33,8 +32,8 @@ import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNo import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress; import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; -import info.nightscout.androidaps.plugins.pump.common.defs.TempBasalPair; import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; +import info.nightscout.androidaps.plugins.pump.common.defs.TempBasalPair; import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; import info.nightscout.androidaps.plugins.pump.omnipod.common.definition.OmnipodCommandType; import info.nightscout.androidaps.plugins.pump.omnipod.eros.R; @@ -80,6 +79,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.eros.event.EventOmnipodEr import info.nightscout.androidaps.plugins.pump.omnipod.eros.rileylink.manager.OmnipodRileyLinkCommunicationManager; import info.nightscout.androidaps.plugins.pump.omnipod.eros.util.AapsOmnipodUtil; import info.nightscout.androidaps.plugins.pump.omnipod.eros.util.OmnipodAlertUtil; +import info.nightscout.androidaps.utils.T; import info.nightscout.androidaps.utils.resources.ResourceHelper; import info.nightscout.androidaps.utils.rx.AapsSchedulers; import info.nightscout.androidaps.utils.sharedPreferences.SP; @@ -476,7 +476,7 @@ public class AapsOmnipodErosManager { return new PumpEnactResult(injector).success(false).enacted(false).comment(comment); } - public PumpEnactResult setTemporaryBasal(TempBasalPair tempBasalPair) { + public PumpEnactResult setTemporaryBasal(TempBasalPair tempBasalPair) { boolean beepsEnabled = isTbrBeepsEnabled(); try { executeCommand(() -> delegate.setTemporaryBasal(PumpType.OMNIPOD_EROS.determineCorrectBasalSize(tempBasalPair.getInsulinRate()), Duration.standardMinutes(tempBasalPair.getDurationMinutes()), beepsEnabled, beepsEnabled)); @@ -541,13 +541,12 @@ public class AapsOmnipodErosManager { long pumpId = addSuccessToHistory(PodHistoryEntryType.CANCEL_TEMPORARY_BASAL, null); - TemporaryBasal tempBasal = new TemporaryBasal(injector) // - .date(System.currentTimeMillis()) // - .duration(0) // - .pumpId(pumpId) // - .source(Source.PUMP); - - activePlugin.getActiveTreatments().addToHistoryTempBasal(tempBasal); + pumpSync.syncStopTemporaryBasalWithPumpId( + System.currentTimeMillis(), + pumpId, + PumpType.OMNIPOD_EROS, + serialNumber() + ); sendEvent(new EventDismissNotification(Notification.OMNIPOD_TBR_ALERTS)); @@ -721,14 +720,16 @@ public class AapsOmnipodErosManager { long pumpId = addSuccessToHistory(System.currentTimeMillis(), PodHistoryEntryType.SET_FAKE_SUSPENDED_TEMPORARY_BASAL, null); - TemporaryBasal temporaryBasal = new TemporaryBasal(injector) // - .date(System.currentTimeMillis()) // - .absolute(0.0) // - .duration((int) OmnipodConstants.SERVICE_DURATION.getStandardMinutes()) // - .source(Source.PUMP) // - .pumpId(pumpId); - - activePlugin.getActiveTreatments().addToHistoryTempBasal(temporaryBasal); + pumpSync.syncTemporaryBasalWithPumpId( + System.currentTimeMillis(), + 0.0, + OmnipodConstants.SERVICE_DURATION.getMillis(), + true, + PumpSync.TemporaryBasalType.EMULATED_PUMP_SUSPEND, + pumpId, + PumpType.OMNIPOD_EROS, + serialNumber() + ); } } @@ -737,20 +738,19 @@ public class AapsOmnipodErosManager { aapsLogger.debug(LTag.PUMP, "Cancelling fake suspended TBR"); long pumpId = addSuccessToHistory(System.currentTimeMillis(), PodHistoryEntryType.CANCEL_FAKE_SUSPENDED_TEMPORARY_BASAL, null); - TemporaryBasal temporaryBasal = new TemporaryBasal(injector) // - .date(System.currentTimeMillis()) // - .duration(0) // - .source(Source.PUMP) // - .pumpId(pumpId); - - activePlugin.getActiveTreatments().addToHistoryTempBasal(temporaryBasal); + pumpSync.syncStopTemporaryBasalWithPumpId( + System.currentTimeMillis(), + pumpId, + PumpType.OMNIPOD_EROS, + serialNumber() + ); } } public boolean hasSuspendedFakeTbr() { - if (activePlugin.getActiveTreatments().isTempBasalInProgress()) { - TemporaryBasal tempBasal = activePlugin.getActiveTreatments().getTempBasalFromHistory(System.currentTimeMillis()); - OmnipodHistoryRecord historyRecord = databaseHelper.findOmnipodHistoryRecordByPumpId(tempBasal.pumpId); + PumpSync.PumpState pumpState = pumpSync.expectedPumpState(); + if (pumpState.getTemporaryBasal() != null && pumpState.getTemporaryBasal().getPumpId() != null) { + OmnipodHistoryRecord historyRecord = databaseHelper.findOmnipodHistoryRecordByPumpId(pumpState.getTemporaryBasal().getPumpId()); return historyRecord != null && PodHistoryEntryType.getByCode(historyRecord.getPodEntryTypeCode()).equals(PodHistoryEntryType.SET_FAKE_SUSPENDED_TEMPORARY_BASAL); } return false; @@ -765,13 +765,12 @@ public class AapsOmnipodErosManager { long pumpId = addSuccessToHistory(PodHistoryEntryType.CANCEL_TEMPORARY_BASAL_BY_DRIVER, null); - TemporaryBasal temporaryBasal = new TemporaryBasal(injector) // - .date(time) // - .duration(0) // - .source(Source.PUMP) // - .pumpId(pumpId); - - activePlugin.getActiveTreatments().addToHistoryTempBasal(temporaryBasal); + pumpSync.syncStopTemporaryBasalWithPumpId( + time, + pumpId, + PumpType.OMNIPOD_EROS, + serialNumber() + ); sendEvent(new EventRefreshOverview("AapsOmnipodManager.reportCancelledTbr()", false)); } @@ -782,39 +781,44 @@ public class AapsOmnipodErosManager { // Cancels current TBR and adds a new TBR for the remaining duration private void splitActiveTbr() { - TemporaryBasal previouslyRunningTempBasal = activePlugin.getActiveTreatments().getTempBasalFromHistory(System.currentTimeMillis()); + PumpSync.PumpState pumpState = pumpSync.expectedPumpState(); + PumpSync.PumpState.TemporaryBasal previouslyRunningTempBasal = pumpSync.expectedPumpState().getTemporaryBasal(); if (previouslyRunningTempBasal != null) { // Cancel the previously running TBR and start a NEW TBR here for the remaining duration, // so that we only cancel the remaining part when recovering from an uncertain failure in the cancellation - int minutesRemaining = previouslyRunningTempBasal.getPlannedRemainingMinutesRoundedUp(); + int minutesRemaining = PumpStateExtensionKt.getPlannedRemainingMinutesRoundedUp(previouslyRunningTempBasal); if (minutesRemaining > 0) { reportCancelledTbr(System.currentTimeMillis() - 1000); - TempBasalPair newTempBasalPair = new TempBasalPair(previouslyRunningTempBasal.absoluteRate, false, minutesRemaining); + TempBasalPair newTempBasalPair = new TempBasalPair(previouslyRunningTempBasal.getRate(), false, minutesRemaining); long pumpId = addSuccessToHistory(PodHistoryEntryType.SPLIT_TEMPORARY_BASAL, newTempBasalPair); - TemporaryBasal tempBasal = new TemporaryBasal(injector) // - .date(System.currentTimeMillis()) // - .absolute(previouslyRunningTempBasal.absoluteRate) - .duration(minutesRemaining) // - .pumpId(pumpId) // - .source(Source.PUMP); - - activePlugin.getActiveTreatments().addToHistoryTempBasal(tempBasal); + pumpSync.syncTemporaryBasalWithPumpId( + System.currentTimeMillis(), + previouslyRunningTempBasal.getRate(), + minutesRemaining, + true, + PumpSync.TemporaryBasalType.NORMAL, + pumpId, + PumpType.OMNIPOD_EROS, + serialNumber() + ); } } } private void addTempBasalTreatment(long time, long pumpId, TempBasalPair tempBasalPair) { - TemporaryBasal tempStart = new TemporaryBasal(injector) // - .date(time) // - .duration(tempBasalPair.getDurationMinutes()) // - .absolute(tempBasalPair.getInsulinRate()) // - .pumpId(pumpId) // - .source(Source.PUMP); - - activePlugin.getActiveTreatments().addToHistoryTempBasal(tempStart); + pumpSync.syncTemporaryBasalWithPumpId( + time, + tempBasalPair.getInsulinRate(), + T.mins(tempBasalPair.getDurationMinutes()).msecs(), + true, + PumpSync.TemporaryBasalType.NORMAL, + pumpId, + PumpType.OMNIPOD_EROS, + serialNumber() + ); } private long addSuccessToHistory(PodHistoryEntryType entryType, Object data) { diff --git a/omnipod-eros/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/ui/ErosPodManagementActivity.kt b/omnipod-eros/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/ui/ErosPodManagementActivity.kt index 95c3e7e586..3d16b252e6 100644 --- a/omnipod-eros/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/ui/ErosPodManagementActivity.kt +++ b/omnipod-eros/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/ui/ErosPodManagementActivity.kt @@ -29,7 +29,7 @@ import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.queue.events.EventQueueChanged import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.alertDialogs.OKDialog -import info.nightscout.androidaps.utils.extensions.toVisibility +import info.nightscout.androidaps.extensions.toVisibility import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.ui.UIRunnable import io.reactivex.disposables.CompositeDisposable diff --git a/omnipod-eros/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/OmnipodErosPumpPluginTest.java b/omnipod-eros/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/OmnipodErosPumpPluginTest.java index 4ee2afab5e..0bb6fe6d8e 100644 --- a/omnipod-eros/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/OmnipodErosPumpPluginTest.java +++ b/omnipod-eros/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/OmnipodErosPumpPluginTest.java @@ -1,5 +1,12 @@ package info.nightscout.androidaps.plugins.pump.omnipod.eros; +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import android.os.Looper; import org.joda.time.DateTimeZone; @@ -20,23 +27,17 @@ import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.interfaces.ActivePluginProvider; import info.nightscout.androidaps.interfaces.CommandQueueProvider; +import info.nightscout.androidaps.interfaces.PumpSync; import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.logging.AAPSLoggerTest; import info.nightscout.androidaps.plugins.bus.RxBusWrapper; -import info.nightscout.androidaps.plugins.pump.common.defs.TempBasalPair; import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; +import info.nightscout.androidaps.plugins.pump.common.defs.TempBasalPair; import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil; import info.nightscout.androidaps.plugins.pump.omnipod.eros.manager.AapsOmnipodErosManager; import info.nightscout.androidaps.utils.resources.ResourceHelper; import info.nightscout.androidaps.utils.rx.TestAapsSchedulers; -import static org.junit.Assert.assertEquals; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - @RunWith(PowerMockRunner.class) public class OmnipodErosPumpPluginTest { @@ -49,6 +50,7 @@ public class OmnipodErosPumpPluginTest { @Mock AapsOmnipodErosManager aapsOmnipodErosManager; @Mock CommandQueueProvider commandQueueProvider; @Mock RileyLinkUtil rileyLinkUtil; + @Mock PumpSync pumpSync; @Before public void prepare() { @@ -68,7 +70,7 @@ public class OmnipodErosPumpPluginTest { null, null, null, null, rileyLinkUtil, null, null, null ); - when(activePluginProvider.getActiveTreatments().getTempBasalFromHistory(anyLong())).thenReturn(null); + when(pumpSync.expectedPumpState().getTemporaryBasal()).thenReturn(null); when(rileyLinkUtil.getRileyLinkHistory()).thenReturn(new ArrayList<>()); when(injector.androidInjector()).thenReturn(instance -> { }); @@ -89,11 +91,11 @@ public class OmnipodErosPumpPluginTest { // Given standard basal when(profile.getBasal()).thenReturn(0.5d); // When - PumpEnactResult result1 = plugin.setTempBasalPercent(80, 30, profile, false); - PumpEnactResult result2 = plugin.setTempBasalPercent(5000, 30000, profile, false); - PumpEnactResult result3 = plugin.setTempBasalPercent(0, 30, profile, false); - PumpEnactResult result4 = plugin.setTempBasalPercent(0, 0, profile, false); - PumpEnactResult result5 = plugin.setTempBasalPercent(-50, 60, profile, false); + PumpEnactResult result1 = plugin.setTempBasalPercent(80, 30, profile, false, PumpSync.TemporaryBasalType.NORMAL); + PumpEnactResult result2 = plugin.setTempBasalPercent(5000, 30000, profile, false, PumpSync.TemporaryBasalType.NORMAL); + PumpEnactResult result3 = plugin.setTempBasalPercent(0, 30, profile, false, PumpSync.TemporaryBasalType.NORMAL); + PumpEnactResult result4 = plugin.setTempBasalPercent(0, 0, profile, false, PumpSync.TemporaryBasalType.NORMAL); + PumpEnactResult result5 = plugin.setTempBasalPercent(-50, 60, profile, false, PumpSync.TemporaryBasalType.NORMAL); // Then return correct values assertEquals(result1.getAbsolute(), 0.4d, 0.01d); assertEquals(result1.getDuration(), 30); @@ -110,8 +112,8 @@ public class OmnipodErosPumpPluginTest { // Given zero basal when(profile.getBasal()).thenReturn(0d); // When - result1 = plugin.setTempBasalPercent(8000, 90, profile, false); - result2 = plugin.setTempBasalPercent(0, 0, profile, false); + result1 = plugin.setTempBasalPercent(8000, 90, profile, false, PumpSync.TemporaryBasalType.NORMAL); + result2 = plugin.setTempBasalPercent(0, 0, profile, false, PumpSync.TemporaryBasalType.NORMAL); // Then return zero values assertEquals(result1.getAbsolute(), 0d, 0.01d); assertEquals(result1.getDuration(), 90); @@ -121,7 +123,7 @@ public class OmnipodErosPumpPluginTest { // Given unhealthy basal when(profile.getBasal()).thenReturn(500d); // When treatment - result1 = plugin.setTempBasalPercent(80, 30, profile, false); + result1 = plugin.setTempBasalPercent(80, 30, profile, false, PumpSync.TemporaryBasalType.NORMAL); // Then return sane values assertEquals(result1.getAbsolute(), PumpType.OMNIPOD_EROS.determineCorrectBasalSize(500d * 0.8), 0.01d); assertEquals(result1.getDuration(), 30); @@ -129,7 +131,7 @@ public class OmnipodErosPumpPluginTest { // Given weird basal when(profile.getBasal()).thenReturn(1.234567d); // When treatment - result1 = plugin.setTempBasalPercent(280, 600, profile, false); + result1 = plugin.setTempBasalPercent(280, 600, profile, false, PumpSync.TemporaryBasalType.NORMAL); // Then return sane values assertEquals(result1.getAbsolute(), 3.4567876, 0.01d); assertEquals(result1.getDuration(), 600); @@ -137,7 +139,7 @@ public class OmnipodErosPumpPluginTest { // Given negative basal when(profile.getBasal()).thenReturn(-1.234567d); // When treatment - result1 = plugin.setTempBasalPercent(280, 510, profile, false); + result1 = plugin.setTempBasalPercent(280, 510, profile, false, PumpSync.TemporaryBasalType.NORMAL); // Then return negative value (this is validated further downstream, see TempBasalExtraCommand) assertEquals(result1.getAbsolute(), -3.4567876, 0.01d); assertEquals(result1.getDuration(), 510);