Merge branch 'dev' into smoothing

This commit is contained in:
Milos Kozak 2022-12-09 15:08:36 +01:00 committed by GitHub
commit 0c176102cf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
110 changed files with 578 additions and 504 deletions

View file

@ -198,6 +198,7 @@ dependencies {
implementation project(':plugins:automation')
implementation project(':plugins:configuration')
implementation project(':plugins:constraints')
implementation project(':plugins:insulin')
implementation project(':plugins:main')
implementation project(':plugins:openhumans')
implementation project(':plugins:sensitivity')

View file

@ -132,7 +132,7 @@
</provider>
<service
android:name="info.nightscout.core.services.AlarmSoundService"
android:name="info.nightscout.ui.services.AlarmSoundService"
android:enabled="true"
android:exported="true" />
<uses-library

View file

@ -28,6 +28,7 @@ import info.nightscout.automation.AutomationPlugin
import info.nightscout.configuration.maintenance.MaintenancePlugin
import info.nightscout.core.ui.dialogs.OKDialog
import info.nightscout.implementation.plugin.PluginStore
import info.nightscout.insulin.InsulinOrefFreePeakPlugin
import info.nightscout.interfaces.Config
import info.nightscout.interfaces.nsclient.NSSettingsStatus
import info.nightscout.interfaces.plugin.PluginBase
@ -47,7 +48,6 @@ import info.nightscout.plugins.general.autotune.AutotunePlugin
import info.nightscout.plugins.general.smsCommunicator.SmsCommunicatorPlugin
import info.nightscout.plugins.general.wear.WearPlugin
import info.nightscout.plugins.general.xdripStatusline.StatusLinePlugin
import info.nightscout.plugins.insulin.InsulinOrefFreePeakPlugin
import info.nightscout.plugins.pump.virtual.VirtualPumpPlugin
import info.nightscout.plugins.source.AidexPlugin
import info.nightscout.plugins.source.DexcomPlugin

View file

@ -20,6 +20,7 @@ import info.nightscout.core.di.CoreModule
import info.nightscout.core.validators.di.ValidatorsModule
import info.nightscout.database.impl.DatabaseModule
import info.nightscout.implementation.di.ImplementationModule
import info.nightscout.insulin.di.InsulinModule
import info.nightscout.plugins.aps.di.ApsModule
import info.nightscout.plugins.constraints.di.PluginsConstraintsModule
import info.nightscout.plugins.di.PluginsModule
@ -55,6 +56,7 @@ import javax.inject.Singleton
CoreModule::class,
DatabaseModule::class,
ImplementationModule::class,
InsulinModule::class,
OpenHumansModule::class,
PluginsModule::class,
RxModule::class,

View file

@ -16,6 +16,10 @@ import info.nightscout.androidaps.plugins.pump.omnipod.eros.OmnipodErosPumpPlugi
import info.nightscout.automation.AutomationPlugin
import info.nightscout.configuration.configBuilder.ConfigBuilderPlugin
import info.nightscout.configuration.maintenance.MaintenancePlugin
import info.nightscout.insulin.InsulinLyumjevPlugin
import info.nightscout.insulin.InsulinOrefFreePeakPlugin
import info.nightscout.insulin.InsulinOrefRapidActingPlugin
import info.nightscout.insulin.InsulinOrefUltraRapidActingPlugin
import info.nightscout.interfaces.plugin.PluginBase
import info.nightscout.plugins.aps.loop.LoopPlugin
import info.nightscout.plugins.aps.openAPSAMA.OpenAPSAMAPlugin
@ -35,10 +39,6 @@ import info.nightscout.plugins.general.smsCommunicator.SmsCommunicatorPlugin
import info.nightscout.plugins.general.themes.ThemeSwitcherPlugin
import info.nightscout.plugins.general.wear.WearPlugin
import info.nightscout.plugins.general.xdripStatusline.StatusLinePlugin
import info.nightscout.plugins.insulin.InsulinLyumjevPlugin
import info.nightscout.plugins.insulin.InsulinOrefFreePeakPlugin
import info.nightscout.plugins.insulin.InsulinOrefRapidActingPlugin
import info.nightscout.plugins.insulin.InsulinOrefUltraRapidActingPlugin
import info.nightscout.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
import info.nightscout.plugins.profile.ProfilePlugin
import info.nightscout.plugins.pump.virtual.VirtualPumpPlugin

View file

@ -14,8 +14,8 @@ import info.nightscout.androidaps.activities.MyPreferenceFragment
import info.nightscout.androidaps.activities.PreferencesActivity
import info.nightscout.configuration.activities.SingleFragmentActivity
import info.nightscout.core.events.EventNewNotification
import info.nightscout.core.services.AlarmSoundService
import info.nightscout.core.services.AlarmSoundServiceHelper
import info.nightscout.ui.services.AlarmSoundService
import info.nightscout.ui.services.AlarmSoundServiceHelper
import info.nightscout.core.ui.toast.ToastUtils
import info.nightscout.interfaces.notifications.Notification
import info.nightscout.interfaces.nsclient.NSAlarm
@ -39,6 +39,7 @@ import info.nightscout.ui.dialogs.TempBasalDialog
import info.nightscout.ui.dialogs.TempTargetDialog
import info.nightscout.ui.dialogs.TreatmentDialog
import info.nightscout.ui.dialogs.WizardDialog
import info.nightscout.ui.widget.Widget
import javax.inject.Inject
class UiInteractionImpl @Inject constructor(
@ -67,6 +68,10 @@ class UiInteractionImpl @Inject constructor(
context.startActivity(i)
}
override fun updateWidget(context: Context) {
Widget.updateWidget(context)
}
override fun runWizardDialog(fragmentManager: FragmentManager, carbs: Int?, name: String?) {
WizardDialog().also { dialog ->
dialog.arguments = Bundle().also { bundle ->

View file

@ -79,7 +79,6 @@
<string name="authorizationfailed">Authorization failed</string>
<string name="copytolocalprofile_invalid">Unable to create profile. Profile is invalid.</string>
<string name="cta_dont_kill_my_app_info">Don\'t kill my app?</string>
<string name="time_to_eat">Time to eat!\nRun Bolus wizard and do calculation again.</string>
<string name="fabric_upload_disabled">Crash logs upload disabled!</string>
<string name="clear_filter">Clear filter</string>
<string name="cannula">Cannula</string>

View file

@ -1,4 +1,4 @@
package info.nightscout.plugins.insulin
package info.nightscout.core.graph
import android.content.Context
import android.graphics.Color

View file

@ -1,14 +0,0 @@
package info.nightscout.interfaces
interface BolusTimer {
/**
* Create new Automation event to alarm when is time to bolus
*/
fun scheduleAutomationEventBolusReminder()
/**
* Remove Automation event
*/
fun removeAutomationEventBolusReminder()
}

View file

@ -1,21 +0,0 @@
package info.nightscout.interfaces
interface CarbTimer {
/**
* Generate reminder via [info.nightscout.androidaps.utils.TimerUtil]
*
* @param seconds seconds to the future
*/
fun scheduleTimeToEatReminder(seconds: Int)
/**
* Create new Automation event to alarm when is time to eat
*/
fun scheduleAutomationEventEatReminder()
/**
* Remove Automation event
*/
fun removeAutomationEventEatReminder()
}

View file

@ -8,6 +8,7 @@ import info.nightscout.interfaces.iob.IobTotal
import org.json.JSONObject
interface APSResult {
var date: Long
var json: JSONObject?
var reason: String
var rate: Double

View file

@ -18,8 +18,13 @@ interface AutosensData {
var pastSensitivity: String
var deviation: Double
var validDeviation: Boolean
var activeCarbsList: MutableList<CarbsInPast>
var absorbed: Double
var carbsFromBolus: Double
var cob: Double
var bgi: Double
var delta: Double
var avgDelta: Double
var slopeFromMaxDeviation: Double
var slopeFromMinDeviation: Double
var usedMinCarbsImpact: Double
@ -37,4 +42,6 @@ interface AutosensData {
var autosensResult: AutosensResult
fun cloneCarbsList(): MutableList<CarbsInPast>
fun deductAbsorbedCarbs()
fun removeOldCarbs(toTime: Long, isAAPSOrWeighted: Boolean)
}

View file

@ -57,4 +57,6 @@ interface Loop {
runningConfiguration: RunningConfiguration,
version: String
): DeviceStatus?
fun provideEmptyAPSResultObject(): APSResult
}

View file

@ -1,6 +1,36 @@
package info.nightscout.interfaces.automation
interface Automation {
fun userEvents(): List<AutomationEvent>
fun processEvent(someEvent: AutomationEvent)
/**
* Generate reminder via [info.nightscout.interfaces.utils.TimerUtil]
*
*/
fun scheduleAutomationEventBolusReminder()
/**
* Remove scheduled reminder from automations
*
*/
fun removeAutomationEventBolusReminder()
/**
* Generate reminder via [info.nightscout.interfaces.utils.TimerUtil]
*
* @param seconds seconds to the future
*/
fun scheduleTimeToEatReminder(seconds: Int)
/**
* Remove Automation event
*/
fun removeAutomationEventEatReminder()
/**
* Create new Automation event to alarm when is time to eat
*/
fun scheduleAutomationEventEatReminder()
}

View file

@ -104,4 +104,6 @@ interface IobCobCalculator {
* @return IobTotal
*/
fun calculateIobFromTempBasalsIncludingConvertedExtended(): IobTotal
fun provideEmptyAutosensDataObject(): AutosensData
}

View file

@ -31,6 +31,9 @@ interface UiInteraction {
* @param soundId sound resource. if == 0 alarm is not started
*/
fun runAlarm(status: String, title: String, @RawRes soundId: Int = 0)
fun updateWidget(context: Context)
fun runWizardDialog(fragmentManager: FragmentManager, carbs: Int? = null, name: String? = null)
fun runLoopDialog(fragmentManager: FragmentManager, showOkCancel: Int)
fun runProfileSwitchDialog(fragmentManager: FragmentManager, profileName: String? = null)

View file

@ -2,8 +2,6 @@ package info.nightscout.core.di
import dagger.Module
import dagger.android.ContributesAndroidInjector
import info.nightscout.core.aps.APSResultObject
import info.nightscout.core.iob.iobCobCalculator.data.AutosensDataObject
import info.nightscout.core.wizard.BolusWizard
import info.nightscout.core.wizard.QuickWizardEntry
import info.nightscout.interfaces.pump.PumpEnactResult
@ -13,8 +11,6 @@ import info.nightscout.interfaces.pump.PumpEnactResult
abstract class CoreDataClassesModule {
@ContributesAndroidInjector abstract fun pumpEnactResultInjector(): PumpEnactResult
@ContributesAndroidInjector abstract fun apsResultInjector(): APSResultObject
@ContributesAndroidInjector abstract fun autosensDataInjector(): AutosensDataObject
@ContributesAndroidInjector abstract fun bolusWizardInjector(): BolusWizard
@ContributesAndroidInjector abstract fun quickWizardEntryInjector(): QuickWizardEntry
}

View file

@ -5,14 +5,11 @@ import android.os.Build
import android.telephony.SmsManager
import dagger.Module
import dagger.Provides
import dagger.android.ContributesAndroidInjector
import info.nightscout.core.services.AlarmSoundService
@Module(
includes = [
CoreDataClassesModule::class,
PreferencesModule::class,
ServicesModule::class
PreferencesModule::class
]
)
open class CoreModule {

View file

@ -1,12 +0,0 @@
package info.nightscout.core.di
import dagger.Module
import dagger.android.ContributesAndroidInjector
import info.nightscout.core.services.AlarmSoundService
@Module
@Suppress("unused")
abstract class ServicesModule {
@ContributesAndroidInjector abstract fun contributesAlarmSoundService(): AlarmSoundService
}

View file

@ -1,2 +0,0 @@
package info.nightscout.core.profile

View file

@ -15,10 +15,9 @@ import info.nightscout.database.entities.TemporaryTarget
import info.nightscout.database.entities.UserEntry.Action
import info.nightscout.database.entities.UserEntry.Sources
import info.nightscout.database.entities.ValueWithUnit
import info.nightscout.interfaces.BolusTimer
import info.nightscout.interfaces.CarbTimer
import info.nightscout.interfaces.Config
import info.nightscout.interfaces.aps.Loop
import info.nightscout.interfaces.automation.Automation
import info.nightscout.interfaces.constraints.Constraint
import info.nightscout.interfaces.constraints.Constraints
import info.nightscout.interfaces.db.PersistenceLayer
@ -69,8 +68,7 @@ class BolusWizard @Inject constructor(
@Inject lateinit var dateUtil: DateUtil
@Inject lateinit var config: Config
@Inject lateinit var uel: UserEntryLogger
@Inject lateinit var carbTimer: CarbTimer
@Inject lateinit var bolusTimer: BolusTimer
@Inject lateinit var automation: Automation
@Inject lateinit var glucoseStatusProvider: GlucoseStatusProvider
@Inject lateinit var uiInteraction: UiInteraction
@Inject lateinit var persistenceLayer: PersistenceLayer
@ -361,9 +359,9 @@ class BolusWizard @Inject constructor(
}
accepted = true
if (calculatedTotalInsulin > 0.0)
bolusTimer.removeAutomationEventBolusReminder()
automation.removeAutomationEventBolusReminder()
if (carbs > 0.0)
carbTimer.removeAutomationEventEatReminder()
automation.removeAutomationEventEatReminder()
if (sp.getBoolean(info.nightscout.core.ui.R.string.key_usebolusadvisor, false) && Profile.toMgdl(bg, profile.units) > 180 && carbs > 0 && carbTime >= 0)
OKDialog.showYesNoCancel(ctx, rh.gs(info.nightscout.core.ui.R.string.bolus_advisor), rh.gs(info.nightscout.core.ui.R.string.bolus_advisor_message),
{ bolusAdvisorProcessing(ctx) },
@ -402,7 +400,7 @@ class BolusWizard @Inject constructor(
if (!result.success) {
uiInteraction.runAlarm(result.comment, rh.gs(info.nightscout.core.ui.R.string.treatmentdeliveryerror), info.nightscout.core.ui.R.raw.boluserror)
} else
carbTimer.scheduleAutomationEventEatReminder()
automation.scheduleAutomationEventEatReminder()
}
})
}
@ -494,7 +492,7 @@ class BolusWizard @Inject constructor(
bolusCalculatorResult?.let { persistenceLayer.insertOrUpdate(it) }
}
if (useAlarm && carbs > 0 && carbTime > 0) {
carbTimer.scheduleTimeToEatReminder(T.mins(carbTime.toLong()).secs().toInt())
automation.scheduleTimeToEatReminder(T.mins(carbTime.toLong()).secs().toInt())
}
}
})

View file

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

View file

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

View file

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

View file

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

View file

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View file

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View file

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

View file

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View file

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

View file

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

View file

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View file

Before

Width:  |  Height:  |  Size: 7 KiB

After

Width:  |  Height:  |  Size: 7 KiB

View file

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View file

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View file

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View file

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View file

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View file

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View file

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View file

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View file

@ -11,16 +11,18 @@ files:
translation: /plugins/aps/src/main/res/values-%android_code%/strings.xml
- source: /plugins/main/src/main/res/values/strings.xml
translation: /plugins/main/src/main/res/values-%android_code%/strings.xml
- source: /plugins/main/src/main/res/values/exam.xml
translation: /plugins/main/src/main/res/values-%android_code%/%original_file_name%
- source: /plugins/main/src/main/res/values/objectives.xml
translation: /plugins/main/src/main/res/values-%android_code%/%original_file_name%
- source: /plugins/constraints/src/main/res/values/exam.xml
translation: /plugins/constraints/src/main/res/values-%android_code%/%original_file_name%
- source: /plugins/constraints/src/main/res/values/objectives.xml
translation: /plugins/constraints/src/main/res/values-%android_code%/%original_file_name%
- source: /plugins/automation/src/main/res/values/strings.xml
translation: /plugins/automation/src/main/res/values-%android_code%/strings.xml
- source: /plugins/openhumans/src/main/res/values/strings.xml
translation: /plugins/openhumans/src/main/res/values-%android_code%/strings.xml
- source: /plugins/sensitivity/src/main/res/values/strings.xml
translation: /plugins/sensitivity/src/main/res/values-%android_code%/strings.xml
- source: /plugins/insulin/src/main/res/values/strings.xml
translation: /plugins/insulin/src/main/res/values-%android_code%/strings.xml
- source: /plugins/configuration/src/main/res/values/strings.xml
translation: /plugins/configuration/src/main/res/values-%android_code%/strings.xml
- source: /plugins/sync/src/main/res/values/strings.xml

View file

@ -19,14 +19,12 @@ dependencies {
implementation project(':app-wear-shared:shared')
implementation project(':database:entities')
implementation project(':database:impl')
implementation project(':plugins:automation')
implementation project(':core:main')
implementation project(':core:graph')
implementation project(':core:graphview')
implementation project(':core:interfaces')
implementation project(':core:ui')
implementation project(':core:utils')
implementation project(':ui')
// Protection
api 'androidx.biometric:biometric:1.1.0'

View file

@ -1,55 +0,0 @@
package info.nightscout.implementation
import dagger.android.HasAndroidInjector
import info.nightscout.automation.AutomationEventObject
import info.nightscout.automation.AutomationPlugin
import info.nightscout.automation.actions.ActionAlarm
import info.nightscout.automation.elements.Comparator
import info.nightscout.automation.elements.InputDelta
import info.nightscout.automation.triggers.TriggerBg
import info.nightscout.automation.triggers.TriggerConnector
import info.nightscout.automation.triggers.TriggerDelta
import info.nightscout.interfaces.BolusTimer
import info.nightscout.interfaces.GlucoseUnit
import info.nightscout.shared.interfaces.ResourceHelper
import java.text.DecimalFormat
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class BolusTimerImpl @Inject constructor(
private val injector: HasAndroidInjector,
private val rh: ResourceHelper,
private val automationPlugin: AutomationPlugin,
) : BolusTimer {
override fun scheduleAutomationEventBolusReminder() {
val event = AutomationEventObject(injector).apply {
title = rh.gs(info.nightscout.core.ui.R.string.bolus_reminder)
readOnly = true
systemAction = true
autoRemove = true
trigger = TriggerConnector(injector, TriggerConnector.Type.AND).apply {
// Bg above 70 mgdl and delta positive mgdl
list.add(TriggerBg(injector, 70.0, GlucoseUnit.MGDL, Comparator.Compare.IS_EQUAL_OR_GREATER))
list.add(
TriggerDelta(
injector, InputDelta(rh, 0.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.DELTA), GlucoseUnit.MGDL, Comparator.Compare
.IS_GREATER
)
)
}
actions.add(ActionAlarm(injector, rh.gs(R.string.time_to_bolus)))
}
automationPlugin.addIfNotExists(event)
}
override fun removeAutomationEventBolusReminder() {
val event = AutomationEventObject(injector).apply {
title = rh.gs(info.nightscout.core.ui.R.string.bolus_reminder)
}
automationPlugin.removeIfExists(event)
}
}

View file

@ -1,102 +0,0 @@
package info.nightscout.implementation
import dagger.android.HasAndroidInjector
import info.nightscout.automation.AutomationEventObject
import info.nightscout.automation.AutomationPlugin
import info.nightscout.automation.actions.ActionAlarm
import info.nightscout.automation.elements.Comparator
import info.nightscout.automation.elements.InputDelta
import info.nightscout.automation.triggers.TriggerBg
import info.nightscout.automation.triggers.TriggerConnector
import info.nightscout.automation.triggers.TriggerDelta
import info.nightscout.interfaces.CarbTimer
import info.nightscout.interfaces.GlucoseUnit
import info.nightscout.interfaces.utils.TimerUtil
import info.nightscout.shared.interfaces.ResourceHelper
import java.text.DecimalFormat
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class CarbTimerImpl @Inject constructor(
private val injector: HasAndroidInjector,
private val rh: ResourceHelper,
private val automationPlugin: AutomationPlugin,
private val timerUtil: TimerUtil
) : CarbTimer {
/**
* Generate reminder via [info.nightscout.androidaps.utils.TimerUtil]
*
* @param seconds seconds to the future
*/
override fun scheduleTimeToEatReminder(seconds: Int) =
timerUtil.scheduleReminder(seconds, rh.gs(R.string.time_to_eat))
/**
* Create new Automation event to alarm when is time to eat
*/
override fun scheduleAutomationEventEatReminder() {
val event = AutomationEventObject(injector).apply {
title = rh.gs(info.nightscout.core.ui.R.string.bolus_advisor)
readOnly = true
systemAction = true
autoRemove = true
trigger = TriggerConnector(injector, TriggerConnector.Type.OR).apply {
// Bg under 180 mgdl and dropping by 15 mgdl
list.add(TriggerConnector(injector, TriggerConnector.Type.AND).apply {
list.add(TriggerBg(injector, 180.0, GlucoseUnit.MGDL, Comparator.Compare.IS_LESSER))
list.add(TriggerDelta(injector, InputDelta(rh, -15.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.DELTA), GlucoseUnit.MGDL, Comparator.Compare.IS_EQUAL_OR_LESSER))
list.add(
TriggerDelta(
injector,
InputDelta(rh, -8.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.SHORT_AVERAGE),
GlucoseUnit.MGDL,
Comparator.Compare.IS_EQUAL_OR_LESSER
)
)
})
// Bg under 160 mgdl and dropping by 9 mgdl
list.add(TriggerConnector(injector, TriggerConnector.Type.AND).apply {
list.add(TriggerBg(injector, 160.0, GlucoseUnit.MGDL, Comparator.Compare.IS_LESSER))
list.add(TriggerDelta(injector, InputDelta(rh, -9.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.DELTA), GlucoseUnit.MGDL, Comparator.Compare.IS_EQUAL_OR_LESSER))
list.add(
TriggerDelta(
injector,
InputDelta(rh, -5.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.SHORT_AVERAGE),
GlucoseUnit.MGDL,
Comparator.Compare.IS_EQUAL_OR_LESSER
)
)
})
// Bg under 145 mgdl and dropping
list.add(TriggerConnector(injector, TriggerConnector.Type.AND).apply {
list.add(TriggerBg(injector, 145.0, GlucoseUnit.MGDL, Comparator.Compare.IS_LESSER))
list.add(TriggerDelta(injector, InputDelta(rh, 0.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.DELTA), GlucoseUnit.MGDL, Comparator.Compare.IS_EQUAL_OR_LESSER))
list.add(
TriggerDelta(
injector,
InputDelta(rh, 0.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.SHORT_AVERAGE),
GlucoseUnit.MGDL,
Comparator.Compare.IS_EQUAL_OR_LESSER
)
)
})
}
actions.add(ActionAlarm(injector, rh.gs(R.string.time_to_eat)))
}
automationPlugin.addIfNotExists(event)
}
/**
* Remove Automation event
*/
override fun removeAutomationEventEatReminder() {
val event = AutomationEventObject(injector).apply {
title = rh.gs(info.nightscout.core.ui.R.string.bolus_advisor)
}
automationPlugin.removeIfExists(event)
}
}

View file

@ -13,6 +13,7 @@ import info.nightscout.database.entities.TemporaryBasal
import info.nightscout.database.entities.TemporaryTarget
import info.nightscout.database.entities.TherapyEvent
import info.nightscout.database.impl.AppRepository
import info.nightscout.interfaces.ui.UiInteraction
import info.nightscout.rx.bus.RxBus
import info.nightscout.rx.events.EventEffectiveProfileSwitchChanged
import info.nightscout.rx.events.EventExtendedBolusChange
@ -27,24 +28,24 @@ import info.nightscout.rx.events.EventTherapyEventChange
import info.nightscout.rx.events.EventTreatmentChange
import info.nightscout.rx.logging.AAPSLogger
import info.nightscout.rx.logging.LTag
import info.nightscout.ui.widget.Widget
import io.reactivex.rxjava3.disposables.Disposable
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class CompatDBHelper @Inject constructor(
val aapsLogger: AAPSLogger,
val repository: AppRepository,
val rxBus: RxBus,
val context: Context
private val aapsLogger: AAPSLogger,
private val repository: AppRepository,
private val rxBus: RxBus,
private val context: Context,
private val uiInteraction: UiInteraction
) {
fun dbChangeDisposable(): Disposable = repository
.changeObservable()
.doOnSubscribe {
rxBus.send(EventNewBG(null))
Widget.updateWidget(context)
uiInteraction.updateWidget(context)
}
.subscribe {
/**
@ -57,7 +58,7 @@ class CompatDBHelper @Inject constructor(
it.filterIsInstance<GlucoseValue>().maxByOrNull { gv -> gv.timestamp }?.let { gv ->
aapsLogger.debug(LTag.DATABASE, "Firing EventNewBg $gv")
rxBus.send(EventNewBG(gv.timestamp))
Widget.updateWidget(context)
uiInteraction.updateWidget(context)
newestGlucoseValue = gv
}
it.filterIsInstance<GlucoseValue>().minOfOrNull { gv -> gv.timestamp }?.let { timestamp ->

View file

@ -4,8 +4,6 @@ import dagger.Binds
import dagger.Module
import dagger.android.ContributesAndroidInjector
import info.nightscout.core.graph.OverviewData
import info.nightscout.implementation.BolusTimerImpl
import info.nightscout.implementation.CarbTimerImpl
import info.nightscout.implementation.DefaultValueHelperImpl
import info.nightscout.implementation.HardLimitsImpl
import info.nightscout.implementation.LocalAlertUtilsImpl
@ -40,8 +38,6 @@ import info.nightscout.implementation.stats.TddCalculatorImpl
import info.nightscout.implementation.stats.TirCalculatorImpl
import info.nightscout.implementation.storage.FileStorage
import info.nightscout.implementation.userEntry.UserEntryPresentationHelperImpl
import info.nightscout.interfaces.BolusTimer
import info.nightscout.interfaces.CarbTimer
import info.nightscout.interfaces.LocalAlertUtils
import info.nightscout.interfaces.NotificationHolder
import info.nightscout.interfaces.Translator
@ -113,8 +109,6 @@ abstract class ImplementationModule {
@Binds fun bindDexcomTirCalculatorInterface(dexcomTirCalculator: DexcomTirCalculatorImpl): DexcomTirCalculator
@Binds fun bindPumpSyncInterface(pumpSyncImplementation: PumpSyncImplementation): PumpSync
@Binds fun bindXDripBroadcastInterface(xDripBroadcastImpl: XDripBroadcastImpl): XDripBroadcast
@Binds fun bindCarbTimerInterface(carbTimer: CarbTimerImpl): CarbTimer
@Binds fun bindBolusTimerInterface(bolusTimer: BolusTimerImpl): BolusTimer
@Binds fun bindLocalAlertUtilsInterface(localAlertUtils: LocalAlertUtilsImpl): LocalAlertUtils
@Binds fun bindIconsProviderInterface(iconsProvider: IconsProviderImplementation): IconsProvider
@Binds fun bindNotificationHolderInterface(notificationHolder: NotificationHolderImpl): NotificationHolder

View file

@ -11,9 +11,9 @@ class IconsProviderImplementation @Inject constructor(private val config: Config
override fun getIcon(): Int =
when {
config.NSCLIENT -> info.nightscout.ui.R.mipmap.ic_yellowowl
config.PUMPCONTROL -> info.nightscout.ui.R.mipmap.ic_pumpcontrol
else -> info.nightscout.ui.R.mipmap.ic_launcher
config.NSCLIENT -> info.nightscout.core.ui.R.mipmap.ic_yellowowl
config.PUMPCONTROL -> info.nightscout.core.ui.R.mipmap.ic_pumpcontrol
else -> info.nightscout.core.ui.R.mipmap.ic_launcher
}
override fun getNotificationIcon(): Int =

View file

@ -5,8 +5,6 @@
<string name="bg_label">BG</string>
<string name="time_to_eat">Time to eat</string>
<string name="time_to_bolus">Time to bolus!\nRun Bolus wizard and do calculation again.</string>
<string name="executing_right_now">Command is executed right now</string>
<string name="basal_value_below_minimum">Basal value below minimum. Profile not set!</string>
<string name="permission">Permission</string>

View file

@ -1,9 +1,10 @@
package info.nightscout.core.aps
package info.nightscout.plugins.aps
import android.text.Spanned
import dagger.android.HasAndroidInjector
import info.nightscout.core.extensions.convertedToAbsolute
import info.nightscout.core.extensions.convertedToPercent
import info.nightscout.core.ui.R
import info.nightscout.database.entities.GlucoseValue
import info.nightscout.interfaces.aps.APSResult
import info.nightscout.interfaces.constraints.Constraint
@ -14,7 +15,7 @@ import info.nightscout.interfaces.plugin.ActivePlugin
import info.nightscout.interfaces.profile.ProfileFunction
import info.nightscout.interfaces.pump.defs.PumpDescription
import info.nightscout.interfaces.utils.DecimalFormatter
import info.nightscout.interfaces.utils.HtmlHelper.fromHtml
import info.nightscout.interfaces.utils.HtmlHelper
import info.nightscout.rx.logging.AAPSLogger
import info.nightscout.rx.logging.LTag
import info.nightscout.shared.interfaces.ResourceHelper
@ -41,7 +42,7 @@ open class APSResultObject @Inject constructor(val injector: HasAndroidInjector)
@Inject lateinit var rh: ResourceHelper
@Inject lateinit var dateUtil: DateUtil
var date: Long = 0
override var date: Long = 0
override var reason: String = ""
override var rate = 0.0
override var percent = 0
@ -116,11 +117,11 @@ open class APSResultObject @Inject constructor(val injector: HasAndroidInjector)
// reason
ret += "<b>" + rh.gs(info.nightscout.core.ui.R.string.reason) + "</b>: " + reason.replace("<", "&lt;").replace(">", "&gt;")
return fromHtml(ret)
return HtmlHelper.fromHtml(ret)
}
return if (isCarbsRequired) {
fromHtml(carbsRequiredText)
} else fromHtml(rh.gs(info.nightscout.core.ui.R.string.nochangerequested))
HtmlHelper.fromHtml(carbsRequiredText)
} else HtmlHelper.fromHtml(rh.gs(R.string.nochangerequested))
}
override fun newAndClone(injector: HasAndroidInjector): APSResult {

View file

@ -3,8 +3,10 @@ package info.nightscout.plugins.aps.di
import dagger.Binds
import dagger.Module
import dagger.android.ContributesAndroidInjector
import info.nightscout.interfaces.aps.APSResult
import info.nightscout.interfaces.aps.Loop
import info.nightscout.interfaces.autotune.Autotune
import info.nightscout.plugins.aps.APSResultObject
import info.nightscout.plugins.aps.OpenAPSFragment
import info.nightscout.plugins.aps.loop.LoopPlugin
import info.nightscout.plugins.general.autotune.AutotunePlugin
@ -22,6 +24,7 @@ import info.nightscout.plugins.general.autotune.AutotunePlugin
abstract class ApsModule {
@ContributesAndroidInjector abstract fun contributesOpenAPSFragment(): OpenAPSFragment
@ContributesAndroidInjector abstract fun apsResultInjector(): APSResultObject
@Module
interface Bindings {

View file

@ -2,10 +2,12 @@ package info.nightscout.plugins.aps.di
import dagger.Module
import dagger.android.ContributesAndroidInjector
import info.nightscout.plugins.aps.loop.CarbSuggestionReceiver
import info.nightscout.plugins.aps.loop.LoopFragment
@Module
@Suppress("unused")
abstract class LoopModule {
@ContributesAndroidInjector abstract fun contributesLoopFragment(): info.nightscout.plugins.aps.loop.LoopFragment
@ContributesAndroidInjector abstract fun contributesCarbSuggestionReceiver(): info.nightscout.plugins.aps.loop.CarbSuggestionReceiver
@ContributesAndroidInjector abstract fun contributesLoopFragment(): LoopFragment
@ContributesAndroidInjector abstract fun contributesCarbSuggestionReceiver(): CarbSuggestionReceiver
}

View file

@ -57,6 +57,7 @@ import info.nightscout.interfaces.queue.CommandQueue
import info.nightscout.interfaces.receivers.ReceiverStatusStore
import info.nightscout.interfaces.ui.UiInteraction
import info.nightscout.interfaces.utils.HardLimits
import info.nightscout.plugins.aps.APSResultObject
import info.nightscout.plugins.aps.R
import info.nightscout.plugins.aps.loop.events.EventLoopSetLastRunGui
import info.nightscout.plugins.aps.loop.extensions.json
@ -782,6 +783,9 @@ class LoopPlugin @Inject constructor(
configuration = runningConfiguration.configuration().toString()
)
}
override fun provideEmptyAPSResultObject(): APSResult = APSResultObject(injector)
companion object {
private const val CHANNEL_ID = "AAPS-OpenLoop"

View file

@ -1,7 +1,7 @@
package info.nightscout.plugins.aps.openAPSAMA
import dagger.android.HasAndroidInjector
import info.nightscout.core.aps.APSResultObject
import info.nightscout.plugins.aps.APSResultObject
import info.nightscout.core.extensions.convertedToAbsolute
import info.nightscout.core.extensions.getPassedDurationToTimeInMinutes
import info.nightscout.core.extensions.plannedRemainingMinutes

View file

@ -1,7 +1,7 @@
package info.nightscout.plugins.aps.openAPSAMA
import dagger.android.HasAndroidInjector
import info.nightscout.core.aps.APSResultObject
import info.nightscout.plugins.aps.APSResultObject
import info.nightscout.rx.logging.LTag
import org.json.JSONException
import org.json.JSONObject

View file

@ -1,7 +1,7 @@
package info.nightscout.plugins.aps.openAPSSMB
import dagger.android.HasAndroidInjector
import info.nightscout.core.aps.APSResultObject
import info.nightscout.plugins.aps.APSResultObject
import info.nightscout.core.extensions.convertedToAbsolute
import info.nightscout.core.extensions.getPassedDurationToTimeInMinutes
import info.nightscout.core.extensions.plannedRemainingMinutes

View file

@ -1,7 +1,7 @@
package info.nightscout.plugins.aps.openAPSSMB
import dagger.android.HasAndroidInjector
import info.nightscout.core.aps.APSResultObject
import info.nightscout.plugins.aps.APSResultObject
import info.nightscout.interfaces.aps.VariableSensitivityResult
import info.nightscout.rx.logging.LTag
import org.json.JSONException

View file

@ -38,6 +38,7 @@ open class TestBaseWithProfile : TestBase() {
@Mock lateinit var context: Context
lateinit var dateUtil: DateUtil
lateinit var testPumpPlugin: TestPumpPlugin
val rxBus = RxBus(aapsSchedulers, aapsLogger)
val profileInjector = HasAndroidInjector { AndroidInjector { } }
@ -56,6 +57,8 @@ open class TestBaseWithProfile : TestBase() {
dateUtil = Mockito.spy(DateUtil(context))
`when`(dateUtil.now()).thenReturn(1656358822000)
validProfile = ProfileSealed.Pure(pureProfileFromJson(JSONObject(validProfileJSON), dateUtil)!!)
testPumpPlugin = TestPumpPlugin(profileInjector)
`when`(activePluginProvider.activePump).thenReturn(testPumpPlugin)
effectiveProfileSwitch = EffectiveProfileSwitch(
timestamp = dateUtil.now(),
basalBlocks = validProfile.basalBlocks,

View file

@ -1,17 +1,16 @@
package info.nightscout.androidaps.plugins.aps.loop
package info.nightscout.plugins.aps.loop
import dagger.android.AndroidInjector
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.TestBaseWithProfile
import info.nightscout.core.aps.APSResultObject
import info.nightscout.database.entities.TemporaryBasal
import info.nightscout.interfaces.aps.APSResult
import info.nightscout.interfaces.constraints.Constraint
import info.nightscout.interfaces.constraints.Constraints
import info.nightscout.interfaces.iob.IobCobCalculator
import info.nightscout.interfaces.pump.defs.PumpType
import info.nightscout.interfaces.utils.JsonHelper.safeGetDouble
import org.junit.Assert
import info.nightscout.shared.sharedPreferences.SP
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.mockito.ArgumentMatchers
@ -21,7 +20,7 @@ import org.mockito.Mockito.`when`
class APSResultTest : TestBaseWithProfile() {
@Mock lateinit var constraints: Constraints
@Mock lateinit var iobCobCalculator: IobCobCalculator
@Mock lateinit var sp: SP
private val injector = HasAndroidInjector { AndroidInjector { } }
@ -55,7 +54,7 @@ class APSResultTest : TestBaseWithProfile() {
@Test
fun changeRequestedTest() {
val apsResult = APSResultObject { AndroidInjector { } }
val apsResult = info.nightscout.plugins.aps.APSResultObject { AndroidInjector { } }
.also {
it.aapsLogger = aapsLogger
it.constraintChecker = constraints
@ -76,21 +75,21 @@ class APSResultTest : TestBaseWithProfile() {
closedLoopEnabled.set(aapsLogger, true)
`when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(ArgumentMatchers.anyLong())).thenReturn(null)
apsResult.tempBasalRequested(false)
Assert.assertEquals(false, apsResult.isChangeRequested)
Assertions.assertEquals(false, apsResult.isChangeRequested)
apsResult.tempBasalRequested(true).percent(200).duration(30)
Assert.assertEquals(true, apsResult.isChangeRequested)
Assertions.assertEquals(true, apsResult.isChangeRequested)
// open loop
closedLoopEnabled.set(aapsLogger, false)
// no change requested
`when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(ArgumentMatchers.anyLong())).thenReturn(null)
apsResult.tempBasalRequested(false)
Assert.assertEquals(false, apsResult.isChangeRequested)
Assertions.assertEquals(false, apsResult.isChangeRequested)
// request 100% when no temp is running
`when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(ArgumentMatchers.anyLong())).thenReturn(null)
apsResult.tempBasalRequested(true).percent(100).duration(30)
Assert.assertEquals(false, apsResult.isChangeRequested)
Assertions.assertEquals(false, apsResult.isChangeRequested)
// request equal temp
`when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(ArgumentMatchers.anyLong())).thenReturn(
@ -103,7 +102,7 @@ class APSResultTest : TestBaseWithProfile() {
)
)
apsResult.tempBasalRequested(true).percent(70).duration(30)
Assert.assertEquals(false, apsResult.isChangeRequested)
Assertions.assertEquals(false, apsResult.isChangeRequested)
// request zero temp
`when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(ArgumentMatchers.anyLong())).thenReturn(
@ -116,7 +115,7 @@ class APSResultTest : TestBaseWithProfile() {
)
)
apsResult.tempBasalRequested(true).percent(0).duration(30)
Assert.assertEquals(true, apsResult.isChangeRequested)
Assertions.assertEquals(true, apsResult.isChangeRequested)
// request high temp
`when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(ArgumentMatchers.anyLong())).thenReturn(
@ -129,7 +128,7 @@ class APSResultTest : TestBaseWithProfile() {
)
)
apsResult.tempBasalRequested(true).percent(200).duration(30)
Assert.assertEquals(true, apsResult.isChangeRequested)
Assertions.assertEquals(true, apsResult.isChangeRequested)
// request slightly different temp
`when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(ArgumentMatchers.anyLong())).thenReturn(
@ -142,7 +141,7 @@ class APSResultTest : TestBaseWithProfile() {
)
)
apsResult.tempBasalRequested(true).percent(80).duration(30)
Assert.assertEquals(false, apsResult.isChangeRequested)
Assertions.assertEquals(false, apsResult.isChangeRequested)
// request different temp
`when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(ArgumentMatchers.anyLong())).thenReturn(
@ -155,7 +154,7 @@ class APSResultTest : TestBaseWithProfile() {
)
)
apsResult.tempBasalRequested(true).percent(120).duration(30)
Assert.assertEquals(true, apsResult.isChangeRequested)
Assertions.assertEquals(true, apsResult.isChangeRequested)
// it should work with absolute temps too
// request different temp
@ -169,7 +168,7 @@ class APSResultTest : TestBaseWithProfile() {
)
)
apsResult.tempBasalRequested(true).percent(100).duration(30)
Assert.assertEquals(false, apsResult.isChangeRequested)
Assertions.assertEquals(false, apsResult.isChangeRequested)
`when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(ArgumentMatchers.anyLong())).thenReturn(
TemporaryBasal(
timestamp = 0,
@ -180,7 +179,7 @@ class APSResultTest : TestBaseWithProfile() {
)
)
apsResult.tempBasalRequested(true).percent(50).duration(30)
Assert.assertEquals(true, apsResult.isChangeRequested)
Assertions.assertEquals(true, apsResult.isChangeRequested)
// **** ABSOLUTE pump ****
testPumpPlugin.pumpDescription.fillFor(PumpType.MEDTRONIC_515_715) // U/h based
@ -191,7 +190,7 @@ class APSResultTest : TestBaseWithProfile() {
// request 100% when no temp is running
`when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(ArgumentMatchers.anyLong())).thenReturn(null)
apsResult.tempBasalRequested(true).rate(1.0).duration(30)
Assert.assertEquals(false, apsResult.isChangeRequested)
Assertions.assertEquals(false, apsResult.isChangeRequested)
// request equal temp
`when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(ArgumentMatchers.anyLong())).thenReturn(
@ -204,7 +203,7 @@ class APSResultTest : TestBaseWithProfile() {
)
)
apsResult.tempBasalRequested(true).rate(2.0).duration(30)
Assert.assertEquals(false, apsResult.isChangeRequested)
Assertions.assertEquals(false, apsResult.isChangeRequested)
`when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(ArgumentMatchers.anyLong())).thenReturn(
TemporaryBasal(
timestamp = 0,
@ -215,7 +214,7 @@ class APSResultTest : TestBaseWithProfile() {
)
)
apsResult.tempBasalRequested(true).rate(2.0).duration(30)
Assert.assertEquals(false, apsResult.isChangeRequested)
Assertions.assertEquals(false, apsResult.isChangeRequested)
// request zero temp
`when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(ArgumentMatchers.anyLong())).thenReturn(
@ -228,7 +227,7 @@ class APSResultTest : TestBaseWithProfile() {
)
)
apsResult.tempBasalRequested(true).rate(0.0).duration(30)
Assert.assertEquals(true, apsResult.isChangeRequested)
Assertions.assertEquals(true, apsResult.isChangeRequested)
// request high temp
`when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(ArgumentMatchers.anyLong())).thenReturn(
@ -241,7 +240,7 @@ class APSResultTest : TestBaseWithProfile() {
)
)
apsResult.tempBasalRequested(true).rate(35.0).duration(30)
Assert.assertEquals(true, apsResult.isChangeRequested)
Assertions.assertEquals(true, apsResult.isChangeRequested)
// request slightly different temp
`when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(ArgumentMatchers.anyLong())).thenReturn(
@ -254,7 +253,7 @@ class APSResultTest : TestBaseWithProfile() {
)
)
apsResult.tempBasalRequested(true).rate(1.2).duration(30)
Assert.assertEquals(false, apsResult.isChangeRequested)
Assertions.assertEquals(false, apsResult.isChangeRequested)
// request different temp
`when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(ArgumentMatchers.anyLong())).thenReturn(
@ -267,7 +266,7 @@ class APSResultTest : TestBaseWithProfile() {
)
)
apsResult.tempBasalRequested(true).rate(1.5).duration(30)
Assert.assertEquals(true, apsResult.isChangeRequested)
Assertions.assertEquals(true, apsResult.isChangeRequested)
// it should work with percent temps too
// request different temp
@ -281,7 +280,7 @@ class APSResultTest : TestBaseWithProfile() {
)
)
apsResult.tempBasalRequested(true).rate(1.1).duration(30)
Assert.assertEquals(false, apsResult.isChangeRequested)
Assertions.assertEquals(false, apsResult.isChangeRequested)
`when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(ArgumentMatchers.anyLong())).thenReturn(
TemporaryBasal(
timestamp = 0,
@ -292,11 +291,11 @@ class APSResultTest : TestBaseWithProfile() {
)
)
apsResult.tempBasalRequested(true).rate(0.5).duration(30)
Assert.assertEquals(true, apsResult.isChangeRequested)
Assertions.assertEquals(true, apsResult.isChangeRequested)
}
@Test fun cloneTest() {
val apsResult = APSResultObject { AndroidInjector { } }
val apsResult = info.nightscout.plugins.aps.APSResultObject { AndroidInjector { } }
.also {
it.aapsLogger = aapsLogger
it.constraintChecker = constraints
@ -308,12 +307,12 @@ class APSResultTest : TestBaseWithProfile() {
}
apsResult.rate(10.0)
val apsResult2 = apsResult.newAndClone(injector)
Assert.assertEquals(apsResult.rate, apsResult2.rate, 0.0)
Assertions.assertEquals(apsResult.rate, apsResult2.rate, 0.0)
}
@Test fun jsonTest() {
closedLoopEnabled.set(aapsLogger, true)
val apsResult = APSResultObject { AndroidInjector { } }
val apsResult = info.nightscout.plugins.aps.APSResultObject { AndroidInjector { } }
.also {
it.aapsLogger = aapsLogger
it.constraintChecker = constraints
@ -324,9 +323,9 @@ class APSResultTest : TestBaseWithProfile() {
it.rh = rh
}
apsResult.rate(20.0).tempBasalRequested(true)
Assert.assertEquals(20.0, safeGetDouble(apsResult.json(), "rate"), 0.0)
Assertions.assertEquals(20.0, safeGetDouble(apsResult.json(), "rate"), 0.0)
apsResult.rate(20.0).tempBasalRequested(false)
Assert.assertEquals(false, apsResult.json()?.has("rate"))
Assertions.assertEquals(false, apsResult.json()?.has("rate"))
}
@BeforeEach

View file

@ -28,6 +28,7 @@ dependencies {
implementation project(':core:interfaces')
testImplementation project(':implementation')
testImplementation project(':plugins:main')
api "androidx.constraintlayout:constraintlayout:$constraintlayout_version"
api "com.google.android.gms:play-services-location:$play_services_location_version"

View file

@ -17,6 +17,8 @@ import info.nightscout.automation.actions.ActionSendSMS
import info.nightscout.automation.actions.ActionStartTempTarget
import info.nightscout.automation.actions.ActionStopProcessing
import info.nightscout.automation.actions.ActionStopTempTarget
import info.nightscout.automation.elements.Comparator
import info.nightscout.automation.elements.InputDelta
import info.nightscout.automation.events.EventAutomationDataChanged
import info.nightscout.automation.events.EventAutomationUpdateGui
import info.nightscout.automation.events.EventLocationChange
@ -41,6 +43,7 @@ import info.nightscout.automation.triggers.TriggerTimeRange
import info.nightscout.automation.triggers.TriggerWifiSsid
import info.nightscout.core.utils.fabric.FabricPrivacy
import info.nightscout.interfaces.Config
import info.nightscout.interfaces.GlucoseUnit
import info.nightscout.interfaces.aps.Loop
import info.nightscout.interfaces.automation.Automation
import info.nightscout.interfaces.automation.AutomationEvent
@ -50,6 +53,7 @@ import info.nightscout.interfaces.plugin.PluginBase
import info.nightscout.interfaces.plugin.PluginDescription
import info.nightscout.interfaces.plugin.PluginType
import info.nightscout.interfaces.queue.Callback
import info.nightscout.interfaces.utils.TimerUtil
import info.nightscout.rx.AapsSchedulers
import info.nightscout.rx.bus.RxBus
import info.nightscout.rx.events.EventBTChange
@ -67,6 +71,7 @@ import io.reactivex.rxjava3.kotlin.plusAssign
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
import java.text.DecimalFormat
import java.util.Collections
import javax.inject.Inject
import javax.inject.Singleton
@ -87,7 +92,8 @@ class AutomationPlugin @Inject constructor(
private val config: Config,
private val locationServiceHelper: LocationServiceHelper,
private val dateUtil: DateUtil,
private val activePlugin: ActivePlugin
private val activePlugin: ActivePlugin,
private val timerUtil: TimerUtil
) : PluginBase(
PluginDescription()
.mainType(PluginType.GENERAL)
@ -402,4 +408,109 @@ class AutomationPlugin @Inject constructor(
TriggerBTDevice(injector),
)
}
/**
* Generate reminder via [info.nightscout.interfaces.utils.TimerUtil]
*
* @param seconds seconds to the future
*/
override fun scheduleTimeToEatReminder(seconds: Int) =
timerUtil.scheduleReminder(seconds, rh.gs(R.string.time_to_eat))
/**
* Create new Automation event to alarm when is time to eat
*/
override fun scheduleAutomationEventEatReminder() {
val event = AutomationEventObject(injector).apply {
title = rh.gs(info.nightscout.core.ui.R.string.bolus_advisor)
readOnly = true
systemAction = true
autoRemove = true
trigger = TriggerConnector(injector, TriggerConnector.Type.OR).apply {
// Bg under 180 mgdl and dropping by 15 mgdl
list.add(TriggerConnector(injector, TriggerConnector.Type.AND).apply {
list.add(TriggerBg(injector, 180.0, GlucoseUnit.MGDL, Comparator.Compare.IS_LESSER))
list.add(TriggerDelta(injector, InputDelta(rh, -15.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.DELTA), GlucoseUnit.MGDL, Comparator.Compare.IS_EQUAL_OR_LESSER))
list.add(
TriggerDelta(
injector,
InputDelta(rh, -8.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.SHORT_AVERAGE),
GlucoseUnit.MGDL,
Comparator.Compare.IS_EQUAL_OR_LESSER
)
)
})
// Bg under 160 mgdl and dropping by 9 mgdl
list.add(TriggerConnector(injector, TriggerConnector.Type.AND).apply {
list.add(TriggerBg(injector, 160.0, GlucoseUnit.MGDL, Comparator.Compare.IS_LESSER))
list.add(TriggerDelta(injector, InputDelta(rh, -9.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.DELTA), GlucoseUnit.MGDL, Comparator.Compare.IS_EQUAL_OR_LESSER))
list.add(
TriggerDelta(
injector,
InputDelta(rh, -5.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.SHORT_AVERAGE),
GlucoseUnit.MGDL,
Comparator.Compare.IS_EQUAL_OR_LESSER
)
)
})
// Bg under 145 mgdl and dropping
list.add(TriggerConnector(injector, TriggerConnector.Type.AND).apply {
list.add(TriggerBg(injector, 145.0, GlucoseUnit.MGDL, Comparator.Compare.IS_LESSER))
list.add(TriggerDelta(injector, InputDelta(rh, 0.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.DELTA), GlucoseUnit.MGDL, Comparator.Compare.IS_EQUAL_OR_LESSER))
list.add(
TriggerDelta(
injector,
InputDelta(rh, 0.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.SHORT_AVERAGE),
GlucoseUnit.MGDL,
Comparator.Compare.IS_EQUAL_OR_LESSER
)
)
})
}
actions.add(ActionAlarm(injector, rh.gs(R.string.time_to_eat)))
}
addIfNotExists(event)
}
/**
* Remove Automation event
*/
override fun removeAutomationEventEatReminder() {
val event = AutomationEventObject(injector).apply {
title = rh.gs(info.nightscout.core.ui.R.string.bolus_advisor)
}
removeIfExists(event)
}
override fun scheduleAutomationEventBolusReminder() {
val event = AutomationEventObject(injector).apply {
title = rh.gs(info.nightscout.core.ui.R.string.bolus_reminder)
readOnly = true
systemAction = true
autoRemove = true
trigger = TriggerConnector(injector, TriggerConnector.Type.AND).apply {
// Bg above 70 mgdl and delta positive mgdl
list.add(TriggerBg(injector, 70.0, GlucoseUnit.MGDL, Comparator.Compare.IS_EQUAL_OR_GREATER))
list.add(
TriggerDelta(
injector, InputDelta(rh, 0.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.DELTA), GlucoseUnit.MGDL, Comparator.Compare
.IS_GREATER
)
)
}
actions.add(ActionAlarm(injector, rh.gs(R.string.time_to_bolus)))
}
addIfNotExists(event)
}
override fun removeAutomationEventBolusReminder() {
val event = AutomationEventObject(injector).apply {
title = rh.gs(info.nightscout.core.ui.R.string.bolus_reminder)
}
removeIfExists(event)
}
}

View file

@ -131,4 +131,8 @@
<string name="saturday_short">S</string>
<string name="sunday_short">S</string>
<!-- Reminders-->
<string name="time_to_eat">Time to eat!\nRun Bolus wizard and do calculation again.</string>
<string name="time_to_bolus">Time to bolus!\nRun Bolus wizard and do calculation again.</string>
</resources>

View file

@ -1,10 +1,9 @@
package info.nightscout.implementation
package info.nightscout.automation
import android.content.Context
import dagger.android.AndroidInjector
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.TestBase
import info.nightscout.automation.AutomationPlugin
import info.nightscout.automation.services.LocationServiceHelper
import info.nightscout.automation.triggers.Trigger
import info.nightscout.core.utils.fabric.FabricPrivacy
@ -14,16 +13,17 @@ import info.nightscout.interfaces.aps.Loop
import info.nightscout.interfaces.constraints.Constraints
import info.nightscout.interfaces.plugin.ActivePlugin
import info.nightscout.interfaces.profile.ProfileFunction
import info.nightscout.interfaces.utils.TimerUtil
import info.nightscout.rx.bus.RxBus
import info.nightscout.shared.interfaces.ResourceHelper
import info.nightscout.shared.sharedPreferences.SP
import info.nightscout.shared.utils.DateUtil
import org.junit.Assert
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
import org.mockito.Mockito.anyInt
import org.mockito.Mockito.`when`
import org.mockito.Mockito
class BolusTimerImplTest : TestBase() {
@ -38,6 +38,7 @@ class BolusTimerImplTest : TestBase() {
@Mock lateinit var locationServiceHelper: LocationServiceHelper
@Mock lateinit var activePlugin: ActivePlugin
@Mock lateinit var profileFunction: ProfileFunction
@Mock lateinit var timerUtil: TimerUtil
private val injector = HasAndroidInjector {
AndroidInjector {
@ -50,23 +51,22 @@ class BolusTimerImplTest : TestBase() {
private lateinit var dateUtil: DateUtil
private lateinit var automationPlugin: AutomationPlugin
private lateinit var sut: BolusTimerImpl
@BeforeEach
fun init() {
`when`(rh.gs(anyInt())).thenReturn("")
`when`(profileFunction.getUnits()).thenReturn(GlucoseUnit.MGDL)
Mockito.`when`(rh.gs(anyInt())).thenReturn("")
Mockito.`when`(profileFunction.getUnits()).thenReturn(GlucoseUnit.MGDL)
dateUtil = DateUtil(context)
automationPlugin = AutomationPlugin(injector, rh, context, sp, fabricPrivacy, loop, rxBus, constraintChecker, aapsLogger, aapsSchedulers, config, locationServiceHelper, dateUtil, activePlugin)
sut = BolusTimerImpl(injector, rh, automationPlugin)
automationPlugin = AutomationPlugin(injector, rh, context, sp, fabricPrivacy, loop, rxBus, constraintChecker, aapsLogger, aapsSchedulers, config, locationServiceHelper, dateUtil,
activePlugin, timerUtil)
}
@Test
fun doTest() {
Assert.assertEquals(0, automationPlugin.size())
sut.scheduleAutomationEventBolusReminder()
Assert.assertEquals(1, automationPlugin.size())
sut.removeAutomationEventBolusReminder()
Assert.assertEquals(0, automationPlugin.size())
Assertions.assertEquals(0, automationPlugin.size())
automationPlugin.scheduleAutomationEventBolusReminder()
Assertions.assertEquals(1, automationPlugin.size())
automationPlugin.removeAutomationEventBolusReminder()
Assertions.assertEquals(0, automationPlugin.size())
}
}

View file

@ -1,10 +1,9 @@
package info.nightscout.implementation
package info.nightscout.automation
import android.content.Context
import dagger.android.AndroidInjector
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.TestBase
import info.nightscout.automation.AutomationPlugin
import info.nightscout.automation.services.LocationServiceHelper
import info.nightscout.automation.triggers.Trigger
import info.nightscout.core.utils.fabric.FabricPrivacy
@ -19,14 +18,13 @@ import info.nightscout.rx.bus.RxBus
import info.nightscout.shared.interfaces.ResourceHelper
import info.nightscout.shared.sharedPreferences.SP
import info.nightscout.shared.utils.DateUtil
import org.junit.Assert
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.mockito.ArgumentMatchers.any
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.any
import org.mockito.Mockito.anyInt
import org.mockito.Mockito.`when`
class CarbTimerImplTest : TestBase() {
@ -54,27 +52,26 @@ class CarbTimerImplTest : TestBase() {
private lateinit var timerUtil: TimerUtil
private lateinit var automationPlugin: AutomationPlugin
private lateinit var sut: CarbTimerImpl
@BeforeEach
fun init() {
`when`(rh.gs(anyInt())).thenReturn("")
`when`(profileFunction.getUnits()).thenReturn(GlucoseUnit.MGDL)
Mockito.`when`(rh.gs(anyInt())).thenReturn("")
Mockito.`when`(profileFunction.getUnits()).thenReturn(GlucoseUnit.MGDL)
dateUtil = DateUtil(context)
timerUtil = TimerUtil(context)
automationPlugin = AutomationPlugin(injector, rh, context, sp, fabricPrivacy, loop, rxBus, constraintChecker, aapsLogger, aapsSchedulers, config, locationServiceHelper, dateUtil, activePlugin)
sut = CarbTimerImpl(injector, rh, automationPlugin, timerUtil)
automationPlugin = AutomationPlugin(injector, rh, context, sp, fabricPrivacy, loop, rxBus, constraintChecker, aapsLogger, aapsSchedulers, config, locationServiceHelper, dateUtil,
activePlugin, timerUtil)
}
@Test
fun doTest() {
Assert.assertEquals(0, automationPlugin.size())
sut.scheduleAutomationEventEatReminder()
Assert.assertEquals(1, automationPlugin.size())
sut.removeAutomationEventEatReminder()
Assert.assertEquals(0, automationPlugin.size())
Assertions.assertEquals(0, automationPlugin.size())
automationPlugin.scheduleAutomationEventEatReminder()
Assertions.assertEquals(1, automationPlugin.size())
automationPlugin.removeAutomationEventEatReminder()
Assertions.assertEquals(0, automationPlugin.size())
sut.scheduleTimeToEatReminder(1)
automationPlugin.scheduleTimeToEatReminder(1)
Mockito.verify(context, Mockito.times(1)).startActivity(any())
}
}

View file

@ -10,6 +10,7 @@ import info.nightscout.database.entities.DeviceStatus
import info.nightscout.database.entities.OfflineEvent
import info.nightscout.interfaces.ConfigBuilder
import info.nightscout.interfaces.GlucoseUnit
import info.nightscout.interfaces.aps.APSResult
import info.nightscout.interfaces.aps.Loop
import info.nightscout.interfaces.configBuilder.RunningConfiguration
import info.nightscout.interfaces.constraints.Constraint
@ -42,7 +43,8 @@ ActionsTestBase : TestBaseWithProfile() {
aapsLogger: AAPSLogger,
rh: ResourceHelper,
injector: HasAndroidInjector,
pluginDescription: PluginDescription
pluginDescription: PluginDescription,
private val apsResult: APSResult
) : PluginBase(
pluginDescription, aapsLogger, rh, injector
), Loop {
@ -75,6 +77,9 @@ ActionsTestBase : TestBaseWithProfile() {
runningConfiguration: RunningConfiguration,
version: String
): DeviceStatus? = null
override fun provideEmptyAPSResultObject(): APSResult = apsResult
override fun setPluginEnabled(type: PluginType, newState: Boolean) {}
}
@ -87,6 +92,7 @@ ActionsTestBase : TestBaseWithProfile() {
@Mock lateinit var loopPlugin: TestLoopPlugin
@Mock lateinit var uel: UserEntryLogger
@Mock lateinit var context: Context
@Mock lateinit var apsResult: APSResult
private val pluginDescription = PluginDescription()
lateinit var testPumpPlugin: TestPumpPlugin

View file

@ -3,9 +3,9 @@ package info.nightscout.automation.triggers
import com.google.common.base.Optional
import info.nightscout.automation.R
import info.nightscout.automation.elements.Comparator
import info.nightscout.core.iob.iobCobCalculator.data.AutosensDataObject
import info.nightscout.plugins.iob.iobCobCalculator.data.AutosensDataObject
import org.json.JSONObject
import org.junit.Assert
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.mockito.ArgumentMatchers
@ -22,53 +22,53 @@ class TriggerAutosensValueTest : TriggerTestBase() {
var t = TriggerAutosensValue(injector)
t.autosens.value = 110.0
t.comparator.value = Comparator.Compare.IS_EQUAL
Assert.assertEquals(110.0, t.autosens.value, 0.01)
Assert.assertEquals(Comparator.Compare.IS_EQUAL, t.comparator.value)
Assert.assertFalse(t.shouldRun())
Assertions.assertEquals(110.0, t.autosens.value, 0.01)
Assertions.assertEquals(Comparator.Compare.IS_EQUAL, t.comparator.value)
Assertions.assertFalse(t.shouldRun())
t = TriggerAutosensValue(injector)
t.autosens.value = 100.0
t.comparator.value = Comparator.Compare.IS_EQUAL
Assert.assertEquals(100.0, t.autosens.value, 0.01)
Assert.assertTrue(t.shouldRun())
Assertions.assertEquals(100.0, t.autosens.value, 0.01)
Assertions.assertTrue(t.shouldRun())
t = TriggerAutosensValue(injector)
t.autosens.value = 50.0
t.comparator.value = Comparator.Compare.IS_EQUAL_OR_GREATER
Assert.assertTrue(t.shouldRun())
Assertions.assertTrue(t.shouldRun())
t = TriggerAutosensValue(injector)
t.autosens.value = 310.0
t.comparator.value = Comparator.Compare.IS_EQUAL_OR_LESSER
Assert.assertTrue(t.shouldRun())
Assertions.assertTrue(t.shouldRun())
t = TriggerAutosensValue(injector)
t.autosens.value = 420.0
t.comparator.value = Comparator.Compare.IS_EQUAL
Assert.assertFalse(t.shouldRun())
Assertions.assertFalse(t.shouldRun())
t = TriggerAutosensValue(injector)
t.autosens.value = 390.0
t.comparator.value = Comparator.Compare.IS_EQUAL_OR_LESSER
Assert.assertTrue(t.shouldRun())
Assertions.assertTrue(t.shouldRun())
t = TriggerAutosensValue(injector)
t.autosens.value = 390.0
t.comparator.value = Comparator.Compare.IS_EQUAL_OR_GREATER
Assert.assertFalse(t.shouldRun())
Assertions.assertFalse(t.shouldRun())
t = TriggerAutosensValue(injector)
t.autosens.value = 20.0
t.comparator.value = Comparator.Compare.IS_EQUAL_OR_GREATER
Assert.assertTrue(t.shouldRun())
Assertions.assertTrue(t.shouldRun())
t = TriggerAutosensValue(injector)
t.autosens.value = 390.0
t.comparator.value = Comparator.Compare.IS_EQUAL_OR_LESSER
Assert.assertTrue(t.shouldRun())
Assertions.assertTrue(t.shouldRun())
`when`(autosensDataStore.getLastAutosensData(anyObject(), anyObject(), anyObject())).thenReturn(AutosensDataObject(injector))
t = TriggerAutosensValue(injector)
t.autosens.value = 80.0
t.comparator.value = Comparator.Compare.IS_EQUAL_OR_LESSER
Assert.assertFalse(t.shouldRun())
Assertions.assertFalse(t.shouldRun())
// Test autosensData == null and Comparator == IS_NOT_AVAILABLE
`when`(autosensDataStore.getLastAutosensData(anyObject(), anyObject(), anyObject())).thenReturn(null)
t = TriggerAutosensValue(injector)
t.comparator.value = Comparator.Compare.IS_NOT_AVAILABLE
Assert.assertTrue(t.shouldRun())
Assertions.assertTrue(t.shouldRun())
}
@Test
@ -77,8 +77,8 @@ class TriggerAutosensValueTest : TriggerTestBase() {
t.autosens.value = 213.0
t.comparator.value = Comparator.Compare.IS_EQUAL_OR_LESSER
val t1 = t.duplicate() as TriggerAutosensValue
Assert.assertEquals(213.0, t1.autosens.value, 0.01)
Assert.assertEquals(Comparator.Compare.IS_EQUAL_OR_LESSER, t.comparator.value)
Assertions.assertEquals(213.0, t1.autosens.value, 0.01)
Assertions.assertEquals(Comparator.Compare.IS_EQUAL_OR_LESSER, t.comparator.value)
}
private var asJson = "{\"data\":{\"comparator\":\"IS_EQUAL\",\"value\":410},\"type\":\"TriggerAutosensValue\"}"
@ -88,7 +88,7 @@ class TriggerAutosensValueTest : TriggerTestBase() {
val t = TriggerAutosensValue(injector)
t.autosens.value = 410.0
t.comparator.value = Comparator.Compare.IS_EQUAL
Assert.assertEquals(asJson, t.toJSON())
Assertions.assertEquals(asJson, t.toJSON())
}
@Test
@ -97,12 +97,12 @@ class TriggerAutosensValueTest : TriggerTestBase() {
t.autosens.value = 410.0
t.comparator.value = Comparator.Compare.IS_EQUAL
val t2 = TriggerDummy(injector).instantiate(JSONObject(t.toJSON())) as TriggerAutosensValue
Assert.assertEquals(Comparator.Compare.IS_EQUAL, t2.comparator.value)
Assert.assertEquals(410.0, t2.autosens.value, 0.01)
Assertions.assertEquals(Comparator.Compare.IS_EQUAL, t2.comparator.value)
Assertions.assertEquals(410.0, t2.autosens.value, 0.01)
}
@Test fun iconTest() {
Assert.assertEquals(Optional.of(R.drawable.ic_as), TriggerAutosensValue(injector).icon())
Assertions.assertEquals(Optional.of(R.drawable.ic_as), TriggerAutosensValue(injector).icon())
}
@BeforeEach

1
plugins/insulin/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/build

View file

@ -0,0 +1,28 @@
plugins {
id 'com.android.library'
id 'kotlin-android'
id 'kotlin-kapt'
id 'kotlin-allopen'
id 'com.hiya.jacoco-android'
}
apply from: "${project.rootDir}/core/main/android_dependencies.gradle"
apply from: "${project.rootDir}/core/main/android_module_dependencies.gradle"
apply from: "${project.rootDir}/core/main/allopen_dependencies.gradle"
apply from: "${project.rootDir}/core/main/test_dependencies.gradle"
apply from: "${project.rootDir}/core/main/jacoco_global.gradle"
android {
namespace 'info.nightscout.insulin'
}
dependencies {
implementation project(':app-wear-shared:shared')
implementation project(':core:graph')
implementation project(':core:graphview')
implementation project(':core:interfaces')
implementation project(':core:ui')
implementation project(':core:utils')
implementation project(':core:validators')
implementation project(':database:entities')
}

View file

21
plugins/insulin/proguard-rules.pro vendored Normal file
View file

@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest>
</manifest>

View file

@ -1,12 +1,12 @@
package info.nightscout.plugins.insulin
package info.nightscout.insulin
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import dagger.android.support.DaggerFragment
import info.nightscout.insulin.databinding.InsulinFragmentBinding
import info.nightscout.interfaces.plugin.ActivePlugin
import info.nightscout.plugins.databinding.InsulinFragmentBinding
import info.nightscout.shared.interfaces.ResourceHelper
import javax.inject.Inject

View file

@ -1,11 +1,11 @@
package info.nightscout.plugins.insulin
package info.nightscout.insulin
import dagger.android.HasAndroidInjector
import info.nightscout.interfaces.Config
import info.nightscout.interfaces.insulin.Insulin
import info.nightscout.interfaces.profile.ProfileFunction
import info.nightscout.interfaces.ui.UiInteraction
import info.nightscout.interfaces.utils.HardLimits
import info.nightscout.plugins.R
import info.nightscout.rx.bus.RxBus
import info.nightscout.rx.logging.AAPSLogger
import info.nightscout.shared.interfaces.ResourceHelper
@ -21,8 +21,9 @@ class InsulinLyumjevPlugin @Inject constructor(
rxBus: RxBus,
aapsLogger: AAPSLogger,
config: Config,
hardLimits: HardLimits
) : InsulinOrefBasePlugin(injector, rh, profileFunction, rxBus, aapsLogger, config, hardLimits) {
hardLimits: HardLimits,
uiInteraction: UiInteraction
) : InsulinOrefBasePlugin(injector, rh, profileFunction, rxBus, aapsLogger, config, hardLimits, uiInteraction) {
override val id get(): Insulin.InsulinType = Insulin.InsulinType.OREF_LYUMJEV
override val friendlyName get(): String = rh.gs(R.string.lyumjev)

View file

@ -1,7 +1,6 @@
package info.nightscout.plugins.insulin
package info.nightscout.insulin
import dagger.android.HasAndroidInjector
import info.nightscout.core.events.EventNewNotification
import info.nightscout.database.entities.Bolus
import info.nightscout.database.entities.embedments.InsulinConfiguration
import info.nightscout.interfaces.Config
@ -12,8 +11,8 @@ import info.nightscout.interfaces.plugin.PluginBase
import info.nightscout.interfaces.plugin.PluginDescription
import info.nightscout.interfaces.plugin.PluginType
import info.nightscout.interfaces.profile.ProfileFunction
import info.nightscout.interfaces.ui.UiInteraction
import info.nightscout.interfaces.utils.HardLimits
import info.nightscout.plugins.R
import info.nightscout.rx.bus.RxBus
import info.nightscout.rx.logging.AAPSLogger
import info.nightscout.shared.interfaces.ResourceHelper
@ -34,7 +33,8 @@ abstract class InsulinOrefBasePlugin(
val rxBus: RxBus,
aapsLogger: AAPSLogger,
config: Config,
val hardLimits: HardLimits
val hardLimits: HardLimits,
val uiInteraction: UiInteraction
) : PluginBase(
PluginDescription()
.mainType(PluginType.INSULIN)
@ -61,8 +61,7 @@ abstract class InsulinOrefBasePlugin(
open fun sendShortDiaNotification(dia: Double) {
if (System.currentTimeMillis() - lastWarned > 60 * 1000) {
lastWarned = System.currentTimeMillis()
val notification = Notification(Notification.SHORT_DIA, String.format(notificationPattern, dia, hardLimits.minDia()), Notification.URGENT)
rxBus.send(EventNewNotification(notification))
uiInteraction.addNotification(Notification.SHORT_DIA, String.format(notificationPattern, dia, hardLimits.minDia()), Notification.URGENT)
}
}

View file

@ -1,4 +1,4 @@
package info.nightscout.plugins.insulin
package info.nightscout.insulin
import dagger.android.HasAndroidInjector
import info.nightscout.core.extensions.putInt
@ -6,8 +6,8 @@ import info.nightscout.core.extensions.storeInt
import info.nightscout.interfaces.Config
import info.nightscout.interfaces.insulin.Insulin
import info.nightscout.interfaces.profile.ProfileFunction
import info.nightscout.interfaces.ui.UiInteraction
import info.nightscout.interfaces.utils.HardLimits
import info.nightscout.plugins.R
import info.nightscout.rx.bus.RxBus
import info.nightscout.rx.logging.AAPSLogger
import info.nightscout.shared.interfaces.ResourceHelper
@ -28,16 +28,17 @@ class InsulinOrefFreePeakPlugin @Inject constructor(
rxBus: RxBus,
aapsLogger: AAPSLogger,
config: Config,
hardLimits: HardLimits
) : InsulinOrefBasePlugin(injector, rh, profileFunction, rxBus, aapsLogger, config, hardLimits) {
hardLimits: HardLimits,
uiInteraction: UiInteraction
) : InsulinOrefBasePlugin(injector, rh, profileFunction, rxBus, aapsLogger, config, hardLimits, uiInteraction) {
override val id get(): Insulin.InsulinType = Insulin.InsulinType.OREF_FREE_PEAK
override val friendlyName get(): String = rh.gs(R.string.free_peak_oref)
override fun configuration(): JSONObject = JSONObject().putInt(R.string.key_insulin_oref_peak, sp, rh)
override fun configuration(): JSONObject = JSONObject().putInt(info.nightscout.core.utils.R.string.key_insulin_oref_peak, sp, rh)
override fun applyConfiguration(configuration: JSONObject) {
configuration.storeInt(R.string.key_insulin_oref_peak, sp, rh)
configuration.storeInt(info.nightscout.core.utils.R.string.key_insulin_oref_peak, sp, rh)
}
override fun commentStandardText(): String {
@ -45,7 +46,7 @@ class InsulinOrefFreePeakPlugin @Inject constructor(
}
override val peak: Int
get() = sp.getInt(R.string.key_insulin_oref_peak, DEFAULT_PEAK)
get() = sp.getInt(info.nightscout.core.utils.R.string.key_insulin_oref_peak, DEFAULT_PEAK)
companion object {

View file

@ -1,11 +1,11 @@
package info.nightscout.plugins.insulin
package info.nightscout.insulin
import dagger.android.HasAndroidInjector
import info.nightscout.interfaces.Config
import info.nightscout.interfaces.insulin.Insulin
import info.nightscout.interfaces.profile.ProfileFunction
import info.nightscout.interfaces.ui.UiInteraction
import info.nightscout.interfaces.utils.HardLimits
import info.nightscout.plugins.R
import info.nightscout.rx.bus.RxBus
import info.nightscout.rx.logging.AAPSLogger
import info.nightscout.shared.interfaces.ResourceHelper
@ -24,8 +24,9 @@ class InsulinOrefRapidActingPlugin @Inject constructor(
rxBus: RxBus,
aapsLogger: AAPSLogger,
config: Config,
hardLimits: HardLimits
) : InsulinOrefBasePlugin(injector, rh, profileFunction, rxBus, aapsLogger, config, hardLimits) {
hardLimits: HardLimits,
uiInteraction: UiInteraction
) : InsulinOrefBasePlugin(injector, rh, profileFunction, rxBus, aapsLogger, config, hardLimits, uiInteraction) {
override val id get(): Insulin.InsulinType = Insulin.InsulinType.OREF_RAPID_ACTING
override val friendlyName get(): String = rh.gs(R.string.rapid_acting_oref)

View file

@ -1,11 +1,11 @@
package info.nightscout.plugins.insulin
package info.nightscout.insulin
import dagger.android.HasAndroidInjector
import info.nightscout.interfaces.Config
import info.nightscout.interfaces.insulin.Insulin
import info.nightscout.interfaces.profile.ProfileFunction
import info.nightscout.interfaces.ui.UiInteraction
import info.nightscout.interfaces.utils.HardLimits
import info.nightscout.plugins.R
import info.nightscout.rx.bus.RxBus
import info.nightscout.rx.logging.AAPSLogger
import info.nightscout.shared.interfaces.ResourceHelper
@ -24,8 +24,9 @@ class InsulinOrefUltraRapidActingPlugin @Inject constructor(
rxBus: RxBus,
aapsLogger: AAPSLogger,
config: Config,
hardLimits: HardLimits
) : InsulinOrefBasePlugin(injector, rh, profileFunction, rxBus, aapsLogger, config, hardLimits) {
hardLimits: HardLimits,
uiInteraction: UiInteraction
) : InsulinOrefBasePlugin(injector, rh, profileFunction, rxBus, aapsLogger, config, hardLimits, uiInteraction) {
override val id get(): Insulin.InsulinType = Insulin.InsulinType.OREF_ULTRA_RAPID_ACTING
override val friendlyName get(): String = rh.gs(R.string.ultra_rapid_oref)

View file

@ -1,8 +1,8 @@
package info.nightscout.plugins.di
package info.nightscout.insulin.di
import dagger.Module
import dagger.android.ContributesAndroidInjector
import info.nightscout.plugins.insulin.InsulinFragment
import info.nightscout.insulin.InsulinFragment
@Module
@Suppress("unused")

View file

@ -2,7 +2,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".insulin.InsulinFragment">
tools:context="info.nightscout.insulin.InsulinFragment">
<LinearLayout
android:layout_width="match_parent"
@ -30,7 +30,7 @@
android:layout_margin="10dp"
android:textAppearance="?android:attr/textAppearanceMedium" />
<info.nightscout.plugins.insulin.ActivityGraph
<info.nightscout.core.graph.ActivityGraph
android:id="@+id/graph"
android:layout_width="match_parent"
android:layout_height="200dip"

View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Insulin -->
<string name="key_insulin_oref_peak_settings" translatable="false">insulin_oref_peak_settings</string>
<string name="lyumjev">Lyumjev</string>
<string name="description_insulin_rapid">Insulin preset for Humalog and NovoRapid / NovoLog</string>
<string name="description_insulin_ultra_rapid">Insulin preset for Fiasp</string>
<string name="description_insulin_lyumjev">Insulin preset for Lyumjev</string>
<string name="description_insulin_free_peak">Allows you to define the peak of the insulin activity and should only be used by advanced users</string>
<string name="insulin_shortname">INS</string>
<string name="insulin_oref_peak">IOB Curve Peak Time</string>
<string name="insulin_peak_time">Peak Time [min]</string>
<string name="free_peak_oref">Free-Peak Oref</string>
<string name="rapid_acting_oref">Rapid-Acting Oref</string>
<string name="ultra_rapid_oref">Ultra-Rapid Oref</string>
<string name="dia_too_short">DIA of %1$f too short - using %2$f instead!</string>
<string name="fast_acting_insulin_comment">Novorapid, Novolog, Humalog</string>
<string name="ultra_fast_acting_insulin_comment">Fiasp</string>
</resources>

View file

@ -0,0 +1,37 @@
package info.nightscout.androidaps
import info.nightscout.rx.AapsSchedulers
import info.nightscout.rx.TestAapsSchedulers
import info.nightscout.rx.logging.AAPSLoggerTest
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.extension.ExtendWith
import org.mockito.Mockito
import org.mockito.junit.jupiter.MockitoExtension
import org.mockito.junit.jupiter.MockitoSettings
import org.mockito.quality.Strictness
import java.util.Locale
@ExtendWith(MockitoExtension::class)
@MockitoSettings(strictness = Strictness.LENIENT)
open class TestBase {
val aapsLogger = AAPSLoggerTest()
val aapsSchedulers: AapsSchedulers = TestAapsSchedulers()
@BeforeEach
fun setupLocale() {
Locale.setDefault(Locale.ENGLISH)
System.setProperty("disableFirebase", "true")
}
// Workaround for Kotlin nullability.
// https://medium.com/@elye.project/befriending-kotlin-and-mockito-1c2e7b0ef791
// https://stackoverflow.com/questions/30305217/is-it-possible-to-use-mockito-in-kotlin
fun <T> anyObject(): T {
Mockito.any<T>()
return uninitialized()
}
@Suppress("Unchecked_Cast")
fun <T> uninitialized(): T = null as T
}

View file

@ -1,16 +1,16 @@
package info.nightscout.plugins.insulin
package info.nightscout.insulin
import dagger.android.AndroidInjector
import dagger.android.HasAndroidInjector
import info.nightscout.interfaces.Config
import info.nightscout.interfaces.insulin.Insulin
import info.nightscout.interfaces.profile.ProfileFunction
import info.nightscout.interfaces.ui.UiInteraction
import info.nightscout.interfaces.utils.HardLimits
import info.nightscout.plugins.R
import info.nightscout.rx.bus.RxBus
import info.nightscout.rx.logging.AAPSLogger
import info.nightscout.shared.interfaces.ResourceHelper
import org.junit.Assert.assertEquals
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
@ -33,6 +33,7 @@ class InsulinLyumjevPluginTest {
@Mock lateinit var aapsLogger: AAPSLogger
@Mock lateinit var config: Config
@Mock lateinit var hardLimits: HardLimits
@Mock lateinit var uiInteraction: UiInteraction
private var injector: HasAndroidInjector = HasAndroidInjector {
AndroidInjector {
@ -41,29 +42,29 @@ class InsulinLyumjevPluginTest {
@BeforeEach
fun setup() {
sut = InsulinLyumjevPlugin(injector, rh, profileFunction, rxBus, aapsLogger, config, hardLimits)
sut = InsulinLyumjevPlugin(injector, rh, profileFunction, rxBus, aapsLogger, config, hardLimits, uiInteraction)
}
@Test
fun `simple peak test`() {
assertEquals(45, sut.peak)
Assertions.assertEquals(45, sut.peak)
}
@Test
fun getIdTest() {
assertEquals(Insulin.InsulinType.OREF_LYUMJEV, sut.id)
Assertions.assertEquals(Insulin.InsulinType.OREF_LYUMJEV, sut.id)
}
@Test
fun commentStandardTextTest() {
`when`(rh.gs(eq(R.string.lyumjev))).thenReturn("Lyumjev")
assertEquals("Lyumjev", sut.commentStandardText())
Assertions.assertEquals("Lyumjev", sut.commentStandardText())
}
@Test
fun getFriendlyNameTest() {
`when`(rh.gs(eq(R.string.lyumjev))).thenReturn("Lyumjev")
assertEquals("Lyumjev", sut.friendlyName)
Assertions.assertEquals("Lyumjev", sut.friendlyName)
}
}

View file

@ -1,4 +1,4 @@
package info.nightscout.plugins.insulin
package info.nightscout.insulin
import dagger.android.AndroidInjector
import dagger.android.HasAndroidInjector
@ -7,12 +7,13 @@ import info.nightscout.interfaces.Config
import info.nightscout.interfaces.Constants
import info.nightscout.interfaces.insulin.Insulin
import info.nightscout.interfaces.profile.ProfileFunction
import info.nightscout.interfaces.ui.UiInteraction
import info.nightscout.interfaces.utils.HardLimits
import info.nightscout.rx.bus.RxBus
import info.nightscout.rx.logging.AAPSLogger
import info.nightscout.shared.interfaces.ResourceHelper
import org.json.JSONObject
import org.junit.Assert
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
@ -38,7 +39,7 @@ class InsulinOrefBasePluginTest {
aapsLogger: AAPSLogger,
config: Config,
hardLimits: HardLimits
) : InsulinOrefBasePlugin(injector, rh, profileFunction, rxBus, aapsLogger, config, hardLimits) {
) : InsulinOrefBasePlugin(injector, rh, profileFunction, rxBus, aapsLogger, config, hardLimits, uiInteraction) {
override fun sendShortDiaNotification(dia: Double) {
shortDiaNotificationSend = true
@ -65,6 +66,7 @@ class InsulinOrefBasePluginTest {
@Mock lateinit var aapsLogger: AAPSLogger
@Mock lateinit var config: Config
@Mock lateinit var hardLimits: HardLimits
@Mock lateinit var uiInteraction: UiInteraction
private var injector: HasAndroidInjector = HasAndroidInjector {
AndroidInjector {
@ -79,12 +81,12 @@ class InsulinOrefBasePluginTest {
@Test
fun testGetDia() {
Assert.assertEquals(5.0, sut.dia, 0.0)
Assertions.assertEquals(5.0, sut.dia, 0.0)
testUserDefinedDia = 5.0 + 1
Assert.assertEquals(5.0 + 1, sut.dia, 0.0)
Assertions.assertEquals(5.0 + 1, sut.dia, 0.0)
testUserDefinedDia = 5.0 - 1
Assert.assertEquals(5.0, sut.dia, 0.0)
Assert.assertTrue(shortDiaNotificationSend)
Assertions.assertEquals(5.0, sut.dia, 0.0)
Assertions.assertTrue(shortDiaNotificationSend)
}
@Test
@ -96,22 +98,22 @@ class InsulinOrefBasePluginTest {
// check directly after bolus
treatment.timestamp = time
treatment.amount = 10.0
Assert.assertEquals(10.0, sut.iobCalcForTreatment(treatment, time, Constants.defaultDIA).iobContrib, 0.1)
Assertions.assertEquals(10.0, sut.iobCalcForTreatment(treatment, time, Constants.defaultDIA).iobContrib, 0.1)
// check after 1 hour
treatment.timestamp = time - 1 * 60 * 60 * 1000 // 1 hour
treatment.amount = 10.0
Assert.assertEquals(3.92, sut.iobCalcForTreatment(treatment, time, Constants.defaultDIA).iobContrib, 0.1)
Assertions.assertEquals(3.92, sut.iobCalcForTreatment(treatment, time, Constants.defaultDIA).iobContrib, 0.1)
// check after 2 hour
treatment.timestamp = time - 2 * 60 * 60 * 1000 // 2 hours
treatment.amount = 10.0
Assert.assertEquals(0.77, sut.iobCalcForTreatment(treatment, time, Constants.defaultDIA).iobContrib, 0.1)
Assertions.assertEquals(0.77, sut.iobCalcForTreatment(treatment, time, Constants.defaultDIA).iobContrib, 0.1)
// check after 3 hour
treatment.timestamp = time - 3 * 60 * 60 * 1000 // 3 hours
treatment.amount = 10.0
Assert.assertEquals(0.10, sut.iobCalcForTreatment(treatment, time, Constants.defaultDIA).iobContrib, 0.1)
Assertions.assertEquals(0.10, sut.iobCalcForTreatment(treatment, time, Constants.defaultDIA).iobContrib, 0.1)
// check after dia
treatment.timestamp = time - 4 * 60 * 60 * 1000 // 4 hours
treatment.amount = 10.0
Assert.assertEquals(0.0, sut.iobCalcForTreatment(treatment, time, Constants.defaultDIA).iobContrib, 0.1)
Assertions.assertEquals(0.0, sut.iobCalcForTreatment(treatment, time, Constants.defaultDIA).iobContrib, 0.1)
}
}

View file

@ -1,4 +1,4 @@
package info.nightscout.plugins.insulin
package info.nightscout.insulin
import dagger.android.AndroidInjector
import dagger.android.HasAndroidInjector
@ -6,12 +6,12 @@ import info.nightscout.androidaps.TestBase
import info.nightscout.interfaces.Config
import info.nightscout.interfaces.insulin.Insulin
import info.nightscout.interfaces.profile.ProfileFunction
import info.nightscout.interfaces.ui.UiInteraction
import info.nightscout.interfaces.utils.HardLimits
import info.nightscout.plugins.R
import info.nightscout.rx.bus.RxBus
import info.nightscout.shared.interfaces.ResourceHelper
import info.nightscout.shared.sharedPreferences.SP
import org.junit.Assert.assertEquals
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.mockito.ArgumentMatchers.anyInt
@ -33,6 +33,7 @@ class InsulinOrefFreePeakPluginTest : TestBase() {
@Mock lateinit var profileFunction: ProfileFunction
@Mock lateinit var config: Config
@Mock lateinit var hardLimits: HardLimits
@Mock lateinit var uiInteraction: UiInteraction
private var injector: HasAndroidInjector = HasAndroidInjector {
AndroidInjector {
@ -41,30 +42,30 @@ class InsulinOrefFreePeakPluginTest : TestBase() {
@BeforeEach
fun setup() {
sut = InsulinOrefFreePeakPlugin(injector, sp, rh, profileFunction, rxBus, aapsLogger, config, hardLimits)
sut = InsulinOrefFreePeakPlugin(injector, sp, rh, profileFunction, rxBus, aapsLogger, config, hardLimits, uiInteraction)
}
@Test
fun `simple peak test`() {
`when`(sp.getInt(eq(R.string.key_insulin_oref_peak), anyInt())).thenReturn(90)
assertEquals(90, sut.peak)
`when`(sp.getInt(eq(info.nightscout.core.utils.R.string.key_insulin_oref_peak), anyInt())).thenReturn(90)
Assertions.assertEquals(90, sut.peak)
}
@Test
fun getIdTest() {
assertEquals(Insulin.InsulinType.OREF_FREE_PEAK, sut.id)
Assertions.assertEquals(Insulin.InsulinType.OREF_FREE_PEAK, sut.id)
}
@Test
fun commentStandardTextTest() {
`when`(sp.getInt(eq(R.string.key_insulin_oref_peak), anyInt())).thenReturn(90)
`when`(sp.getInt(eq(info.nightscout.core.utils.R.string.key_insulin_oref_peak), anyInt())).thenReturn(90)
`when`(rh.gs(eq(R.string.insulin_peak_time))).thenReturn("Peak Time [min]")
assertEquals("Peak Time [min]: 90", sut.commentStandardText())
Assertions.assertEquals("Peak Time [min]: 90", sut.commentStandardText())
}
@Test
fun getFriendlyNameTest() {
`when`(rh.gs(eq(R.string.free_peak_oref))).thenReturn("Free-Peak Oref")
assertEquals("Free-Peak Oref", sut.friendlyName)
Assertions.assertEquals("Free-Peak Oref", sut.friendlyName)
}
}

View file

@ -1,16 +1,16 @@
package info.nightscout.plugins.insulin
package info.nightscout.insulin
import dagger.android.AndroidInjector
import dagger.android.HasAndroidInjector
import info.nightscout.interfaces.Config
import info.nightscout.interfaces.insulin.Insulin
import info.nightscout.interfaces.profile.ProfileFunction
import info.nightscout.interfaces.ui.UiInteraction
import info.nightscout.interfaces.utils.HardLimits
import info.nightscout.plugins.R
import info.nightscout.rx.bus.RxBus
import info.nightscout.rx.logging.AAPSLogger
import info.nightscout.shared.interfaces.ResourceHelper
import org.junit.Assert.assertEquals
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
@ -33,6 +33,7 @@ class InsulinOrefRapidActingPluginTest {
@Mock lateinit var aapsLogger: AAPSLogger
@Mock lateinit var config: Config
@Mock lateinit var hardLimits: HardLimits
@Mock lateinit var uiInteraction: UiInteraction
private var injector: HasAndroidInjector = HasAndroidInjector {
AndroidInjector {
@ -41,29 +42,29 @@ class InsulinOrefRapidActingPluginTest {
@BeforeEach
fun setup() {
sut = InsulinOrefRapidActingPlugin(injector, rh, profileFunction, rxBus, aapsLogger, config, hardLimits)
sut = InsulinOrefRapidActingPlugin(injector, rh, profileFunction, rxBus, aapsLogger, config, hardLimits, uiInteraction)
}
@Test
fun `simple peak test`() {
assertEquals(75, sut.peak)
Assertions.assertEquals(75, sut.peak)
}
@Test
fun getIdTest() {
assertEquals(Insulin.InsulinType.OREF_RAPID_ACTING, sut.id)
Assertions.assertEquals(Insulin.InsulinType.OREF_RAPID_ACTING, sut.id)
}
@Test
fun commentStandardTextTest() {
`when`(rh.gs(eq(R.string.fast_acting_insulin_comment))).thenReturn("Novorapid, Novolog, Humalog")
assertEquals("Novorapid, Novolog, Humalog", sut.commentStandardText())
Assertions.assertEquals("Novorapid, Novolog, Humalog", sut.commentStandardText())
}
@Test
fun getFriendlyNameTest() {
`when`(rh.gs(eq(R.string.rapid_acting_oref))).thenReturn("Rapid-Acting Oref")
assertEquals("Rapid-Acting Oref", sut.friendlyName)
Assertions.assertEquals("Rapid-Acting Oref", sut.friendlyName)
}
}

View file

@ -1,16 +1,16 @@
package info.nightscout.plugins.insulin
package info.nightscout.insulin
import dagger.android.AndroidInjector
import dagger.android.HasAndroidInjector
import info.nightscout.interfaces.Config
import info.nightscout.interfaces.insulin.Insulin
import info.nightscout.interfaces.profile.ProfileFunction
import info.nightscout.interfaces.ui.UiInteraction
import info.nightscout.interfaces.utils.HardLimits
import info.nightscout.plugins.R
import info.nightscout.rx.bus.RxBus
import info.nightscout.rx.logging.AAPSLogger
import info.nightscout.shared.interfaces.ResourceHelper
import org.junit.Assert.assertEquals
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
@ -33,6 +33,7 @@ class InsulinOrefUltraRapidActingPluginTest {
@Mock lateinit var aapsLogger: AAPSLogger
@Mock lateinit var config: Config
@Mock lateinit var hardLimits: HardLimits
@Mock lateinit var uiInteraction: UiInteraction
private var injector: HasAndroidInjector = HasAndroidInjector {
AndroidInjector {
@ -41,29 +42,29 @@ class InsulinOrefUltraRapidActingPluginTest {
@BeforeEach
fun setup() {
sut = InsulinOrefUltraRapidActingPlugin(injector, rh, profileFunction, rxBus, aapsLogger, config, hardLimits)
sut = InsulinOrefUltraRapidActingPlugin(injector, rh, profileFunction, rxBus, aapsLogger, config, hardLimits, uiInteraction)
}
@Test
fun `simple peak test`() {
assertEquals(55, sut.peak)
Assertions.assertEquals(55, sut.peak)
}
@Test
fun getIdTest() {
assertEquals(Insulin.InsulinType.OREF_ULTRA_RAPID_ACTING, sut.id)
Assertions.assertEquals(Insulin.InsulinType.OREF_ULTRA_RAPID_ACTING, sut.id)
}
@Test
fun commentStandardTextTest() {
`when`(rh.gs(eq(R.string.ultra_fast_acting_insulin_comment))).thenReturn("Fiasp")
assertEquals("Fiasp", sut.commentStandardText())
Assertions.assertEquals("Fiasp", sut.commentStandardText())
}
@Test
fun getFriendlyNameTest() {
`when`(rh.gs(eq(R.string.ultra_rapid_oref))).thenReturn("Ultra-Rapid Oref")
assertEquals("Ultra-Rapid Oref", sut.friendlyName)
Assertions.assertEquals("Ultra-Rapid Oref", sut.friendlyName)
}
}

View file

@ -9,11 +9,11 @@ import info.nightscout.plugins.general.persistentNotification.DummyService
import info.nightscout.plugins.general.smsCommunicator.SmsCommunicatorPlugin
import info.nightscout.plugins.general.wear.WearFragment
import info.nightscout.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
import info.nightscout.plugins.iob.iobCobCalculator.data.AutosensDataObject
@Module(
includes = [
PluginsModule.Bindings::class,
InsulinModule::class,
FoodModule::class,
SMSCommunicatorModule::class,
ProfileModule::class,
@ -32,6 +32,8 @@ abstract class PluginsModule {
@ContributesAndroidInjector abstract fun contributesWearFragment(): WearFragment
@ContributesAndroidInjector abstract fun contributesDummyService(): DummyService
@ContributesAndroidInjector abstract fun autosensDataObjectInjector(): AutosensDataObject
@Module
interface Bindings {

View file

@ -909,7 +909,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
val useBatteryLevel = (pump.model() == PumpType.OMNIPOD_EROS)
|| (pump.model() != PumpType.ACCU_CHEK_COMBO && pump.model() != PumpType.OMNIPOD_DASH)
batteryLevel.visibility = useBatteryLevel.toVisibility()
statusLights.visibility = (sp.getBoolean(R.string.key_show_statuslights, true) || config.NSCLIENT).toVisibility()
statusLightsLayout.visibility = (sp.getBoolean(R.string.key_show_statuslights, true) || config.NSCLIENT).toVisibility()
}
statusLightHandler.updateStatusLights(
binding.statusLightsLayout.cannulaAge,

View file

@ -38,6 +38,7 @@ import info.nightscout.interfaces.profile.ProfileFunction
import info.nightscout.interfaces.utils.DecimalFormatter
import info.nightscout.interfaces.utils.MidnightTime
import info.nightscout.plugins.R
import info.nightscout.plugins.iob.iobCobCalculator.data.AutosensDataObject
import info.nightscout.plugins.iob.iobCobCalculator.data.AutosensDataStoreObject
import info.nightscout.rx.AapsSchedulers
import info.nightscout.rx.bus.RxBus
@ -128,7 +129,7 @@ class IobCobCalculatorPlugin @Inject constructor(
event.isChanged(rh.gs(info.nightscout.core.utils.R.string.key_absorption_cutoff)) ||
event.isChanged(rh.gs(info.nightscout.core.utils.R.string.key_openapsama_autosens_max)) ||
event.isChanged(rh.gs(info.nightscout.core.utils.R.string.key_openapsama_autosens_min)) ||
event.isChanged(rh.gs(R.string.key_insulin_oref_peak))
event.isChanged(rh.gs(info.nightscout.core.utils.R.string.key_insulin_oref_peak))
) {
resetDataAndRunCalculation("onEventPreferenceChange", event)
}
@ -599,6 +600,8 @@ class IobCobCalculatorPlugin @Inject constructor(
override fun calculateIobFromTempBasalsIncludingConvertedExtended(): IobTotal =
calculateIobToTimeFromTempBasalsIncludingConvertedExtended(dateUtil.now())
override fun provideEmptyAutosensDataObject(): AutosensData = AutosensDataObject(injector)
override fun calculateIobToTimeFromTempBasalsIncludingConvertedExtended(toTime: Long): IobTotal {
val total = IobTotal(toTime)
val now = dateUtil.now()

View file

@ -1,4 +1,4 @@
package info.nightscout.core.iob.iobCobCalculator.data
package info.nightscout.plugins.iob.iobCobCalculator.data
import dagger.android.HasAndroidInjector
import info.nightscout.interfaces.Constants
@ -22,18 +22,22 @@ class AutosensDataObject(injector: HasAndroidInjector) : AutosensData {
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var dateUtil: DateUtil
init {
injector.androidInjector().inject(this)
}
override var time = 0L
override var bg = 0.0 // mgdl
override var pastSensitivity = ""
override var deviation = 0.0
override var validDeviation = false
var activeCarbsList: MutableList<AutosensData.CarbsInPast> = ArrayList()
var absorbed = 0.0
override var activeCarbsList: MutableList<AutosensData.CarbsInPast> = ArrayList()
override var absorbed = 0.0
override var carbsFromBolus = 0.0
override var cob = 0.0
var bgi = 0.0
var delta = 0.0
var avgDelta = 0.0
override var bgi = 0.0
override var delta = 0.0
override var avgDelta = 0.0
override var avgDeviation = 0.0
override var autosensResult = AutosensResult()
override var slopeFromMaxDeviation = 0.0
@ -86,7 +90,7 @@ class AutosensDataObject(injector: HasAndroidInjector) : AutosensData {
}
// remove carbs older than timeframe
fun removeOldCarbs(toTime: Long, isAAPSOrWeighted: Boolean) {
override fun removeOldCarbs(toTime: Long, isAAPSOrWeighted: Boolean) {
val maxAbsorptionHours: Double =
if (isAAPSOrWeighted) sp.getDouble(info.nightscout.core.utils.R.string.key_absorption_maxtime, Constants.DEFAULT_MAX_ABSORPTION_TIME)
else sp.getDouble(info.nightscout.core.utils.R.string.key_absorption_cutoff, Constants.DEFAULT_MAX_ABSORPTION_TIME)
@ -102,7 +106,7 @@ class AutosensDataObject(injector: HasAndroidInjector) : AutosensData {
}
}
fun deductAbsorbedCarbs() {
override fun deductAbsorbedCarbs() {
var ac = absorbed
var i = 0
while (i < activeCarbsList.size && ac > 0) {
@ -115,7 +119,4 @@ class AutosensDataObject(injector: HasAndroidInjector) : AutosensData {
i++
}
}
init {
injector.androidInjector().inject(this)
}
}

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/overview_buttons"
android:id="@+id/buttons_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
@ -28,7 +28,6 @@
</LinearLayout>
<LinearLayout
android:id="@+id/buttons_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"

View file

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/graphs_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

View file

@ -2,7 +2,7 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/status_lights"
android:id="@+id/status_lights_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"

View file

@ -198,7 +198,7 @@
</LinearLayout>
<info.nightscout.plugins.insulin.ActivityGraph
<info.nightscout.core.graph.ActivityGraph
android:id="@+id/insulin_graph"
android:layout_width="match_parent"
android:layout_height="100dip"

View file

@ -109,25 +109,6 @@
<string name="sms_wrong_tbr_duration">TBR duration must be a multiple of %1$d minutes and greater than 0.</string>
<string name="a11y_otp_qr_code">QR Code for setup one time password</string>
<!-- Insulin -->
<string name="key_insulin_oref_peak" translatable="false">insulin_oref_peak</string>
<string name="key_insulin_oref_peak_settings" translatable="false">insulin_oref_peak_settings</string>
<string name="lyumjev">Lyumjev</string>
<string name="description_insulin_rapid">Insulin preset for Humalog and NovoRapid / NovoLog</string>
<string name="description_insulin_ultra_rapid">Insulin preset for Fiasp</string>
<string name="description_insulin_lyumjev">Insulin preset for Lyumjev</string>
<string name="description_insulin_free_peak">Allows you to define the peak of the insulin activity and should only be used by advanced users</string>
<string name="insulin_shortname">INS</string>
<string name="insulin_oref_peak">IOB Curve Peak Time</string>
<string name="insulin_peak_time">Peak Time [min]</string>
<string name="free_peak_oref">Free-Peak Oref</string>
<string name="rapid_acting_oref">Rapid-Acting Oref</string>
<string name="ultra_rapid_oref">Ultra-Rapid Oref</string>
<string name="dia_too_short">DIA of %1$f too short - using %2$f instead!</string>
<string name="fast_acting_insulin_comment">Novorapid, Novolog, Humalog</string>
<string name="ultra_fast_acting_insulin_comment">Fiasp</string>
<!-- xDrip status line -->
<string name="key_xdrip_status_detailed_iob" translatable="false">xdripstatus_detailediob</string>
<string name="key_xdrip_status_show_bgi" translatable="false">xdripstatus_showbgi</string>

View file

@ -1,8 +1,10 @@
package info.nightscout.plugins.sync.nsclient.data
import android.text.Spanned
import dagger.Lazy
import dagger.android.HasAndroidInjector
import info.nightscout.core.aps.APSResultObject
import info.nightscout.interfaces.aps.APSResult
import info.nightscout.interfaces.aps.Loop
import info.nightscout.interfaces.nsclient.NSSettingsStatus
import info.nightscout.interfaces.nsclient.ProcessedDeviceStatusData
import info.nightscout.interfaces.utils.HtmlHelper
@ -21,7 +23,8 @@ import javax.inject.Singleton
class ProcessedDeviceStatusDataImpl @Inject constructor(
private val rh: ResourceHelper,
private val dateUtil: DateUtil,
private val sp: SP
private val sp: SP,
private val loop: Lazy<Loop>
) : ProcessedDeviceStatusData {
override var pumpData: ProcessedDeviceStatusData.PumpData? = null
@ -112,11 +115,10 @@ class ProcessedDeviceStatusDataImpl @Inject constructor(
override val openApsTimestamp: Long
get() = if (openAPSData.clockSuggested != 0L) openAPSData.clockSuggested else -1
override fun getAPSResult(injector: HasAndroidInjector): APSResultObject {
val result = APSResultObject(injector)
result.json = openAPSData.suggested
result.date = openAPSData.clockSuggested
return result
override fun getAPSResult(injector: HasAndroidInjector): APSResult =
loop.get().provideEmptyAPSResultObject().also {
it.json = openAPSData.suggested
it.date = openAPSData.clockSuggested
}
override val uploaderStatus: String
get() {

View file

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="info.nightscout.comboctl.android">
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

View file

@ -18,6 +18,7 @@ include ':implementation'
include ':plugins:aps'
include ':plugins:automation'
include ':plugins:configuration'
include ':plugins:insulin'
include ':plugins:main'
include ':plugins:openhumans'
include ':plugins:sensitivity'

Some files were not shown because too many files have changed in this diff Show more