CommandQueueImpl -> implementation module

This commit is contained in:
Milos Kozak 2022-11-01 11:39:40 +01:00
parent 369bf25647
commit 4c5d015b40
54 changed files with 832 additions and 356 deletions

View file

@ -44,9 +44,7 @@ import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.constraints.signatureVerifier.SignatureVerifierPlugin
import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtils
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin
import info.nightscout.androidaps.setupwizard.SetupWizardActivity
import info.nightscout.androidaps.utils.AndroidPermission
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.extensions.isRunningRealPumpTest
@ -72,7 +70,7 @@ class MainActivity : NoSplashAppCompatActivity() {
@Inject lateinit var androidPermission: AndroidPermission
@Inject lateinit var sp: SP
@Inject lateinit var versionCheckerUtils: VersionCheckerUtils
@Inject lateinit var smsCommunicatorPlugin: SmsCommunicatorPlugin
@Inject lateinit var smsCommunicator: SmsCommunicator
@Inject lateinit var loop: Loop
@Inject lateinit var nsSettingsStatus: NSSettingsStatus
@Inject lateinit var buildHelper: BuildHelper
@ -152,7 +150,7 @@ class MainActivity : NoSplashAppCompatActivity() {
androidPermission.notifyForBatteryOptimizationPermission(this)
if (!config.NSCLIENT) androidPermission.notifyForLocationPermissions(this)
if (config.PUMPDRIVERS) {
androidPermission.notifyForSMSPermissions(this, smsCommunicatorPlugin)
androidPermission.notifyForSMSPermissions(this, smsCommunicator)
androidPermission.notifyForSystemWindowPermissions(this)
androidPermission.notifyForBtConnectPermission(this)
}

View file

@ -23,8 +23,10 @@ import info.nightscout.androidaps.database.transactions.VersionChangeTransaction
import info.nightscout.androidaps.db.CompatDBHelper
import info.nightscout.androidaps.di.DaggerAppComponent
import info.nightscout.androidaps.di.StaticInjector
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.interfaces.ConfigBuilder
import info.nightscout.androidaps.interfaces.LocalAlertUtils
import info.nightscout.androidaps.interfaces.PluginBase
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.logging.UserEntryLogger
@ -41,9 +43,7 @@ import info.nightscout.androidaps.receivers.TimeDateOrTZChangeReceiver
import info.nightscout.androidaps.services.AlarmSoundServiceHelper
import info.nightscout.androidaps.utils.ActivityMonitor
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.LocalAlertUtils
import info.nightscout.androidaps.utils.ProcessLifecycleListener
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.androidaps.utils.locale.LocaleHelper
import info.nightscout.androidaps.widget.updateWidget
import info.nightscout.shared.logging.AAPSLogger

View file

@ -22,6 +22,7 @@ import info.nightscout.androidaps.plugins.pump.common.di.RileyLinkModule
import info.nightscout.androidaps.plugins.pump.medtronic.di.MedtronicModule
import info.nightscout.androidaps.plugins.pump.omnipod.dash.di.OmnipodDashModule
import info.nightscout.androidaps.plugins.pump.omnipod.eros.di.OmnipodErosModule
import info.nightscout.implementation.di.CommandQueueModule
import info.nightscout.shared.di.SharedModule
import info.nightscout.ui.di.UiModule
import javax.inject.Singleton

View file

@ -8,8 +8,28 @@ import dagger.Provides
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.interfaces.*
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.AndroidPermission
import info.nightscout.androidaps.interfaces.Autotune
import info.nightscout.androidaps.interfaces.BolusTimer
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.androidaps.interfaces.CarbTimer
import info.nightscout.androidaps.interfaces.CommandQueue
import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.interfaces.ConfigBuilder
import info.nightscout.androidaps.interfaces.DataSyncSelector
import info.nightscout.androidaps.interfaces.IconsProvider
import info.nightscout.androidaps.interfaces.ImportExportPrefs
import info.nightscout.androidaps.interfaces.IobCobCalculator
import info.nightscout.androidaps.interfaces.LocalAlertUtils
import info.nightscout.androidaps.interfaces.Loop
import info.nightscout.androidaps.interfaces.NotificationHolder
import info.nightscout.androidaps.interfaces.PluginBase
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.interfaces.PumpSync
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.interfaces.SmsCommunicator
import info.nightscout.androidaps.interfaces.XDripBroadcast
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
@ -23,23 +43,24 @@ import info.nightscout.androidaps.plugins.general.nsclient.data.DeviceStatusData
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
import info.nightscout.androidaps.plugins.pump.PumpSyncImplementation
import info.nightscout.androidaps.queue.CommandQueueImplementation
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.HardLimits
import info.nightscout.androidaps.utils.androidNotification.NotificationHolderImpl
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.androidaps.utils.buildHelper.BuildHelperImpl
import info.nightscout.androidaps.utils.buildHelper.ConfigImpl
import info.nightscout.androidaps.utils.resources.IconsProviderImplementation
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.implementation.XDripBroadcastImpl
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.androidaps.utils.rx.DefaultAapsSchedulers
import info.nightscout.androidaps.utils.storage.FileStorage
import info.nightscout.androidaps.utils.storage.Storage
import info.nightscout.implementation.AndroidPermissionImpl
import info.nightscout.implementation.BolusTimerImpl
import info.nightscout.implementation.CarbTimerImpl
import info.nightscout.implementation.LocalAlertUtilsImpl
import info.nightscout.implementation.XDripBroadcastImpl
import info.nightscout.implementation.queue.CommandQueueImplementation
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.sharedPreferences.SP
import javax.inject.Singleton
@ -109,10 +130,12 @@ open class AppModule {
@Binds fun bindSmsCommunicatorInterface(smsCommunicatorPlugin: SmsCommunicatorPlugin): SmsCommunicator
@Binds fun bindDataSyncSelector(dataSyncSelectorImplementation: DataSyncSelectorImplementation): DataSyncSelector
@Binds fun bindPumpSync(pumpSyncImplementation: PumpSyncImplementation): PumpSync
@Binds fun bindXDripBroadcast(xDripBroadcastImpl: XDripBroadcastImpl): XDripBroadcast
@Binds fun bindCarbTimer(carbTimer: CarbTimerImpl): CarbTimer
@Binds fun bindBolusTimer(bolusTimer: BolusTimerImpl): BolusTimer
@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 bindAndroidPermissionInterface(androidPermission: AndroidPermissionImpl): AndroidPermission
@Binds fun bindLocalAlertUtilsInterface(localAlertUtils: LocalAlertUtilsImpl): LocalAlertUtils
}
}

View file

@ -9,6 +9,5 @@ import info.nightscout.androidaps.plugins.general.overview.notifications.Notific
@Suppress("unused")
abstract class OverviewModule {
@ContributesAndroidInjector abstract fun notificationWithActionInjector(): NotificationWithAction
@ContributesAndroidInjector abstract fun graphDataInjector(): GraphData
}

View file

@ -13,7 +13,12 @@ import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.work.*
import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequest
import androidx.work.WorkManager
import androidx.work.Worker
import androidx.work.WorkerParameters
import androidx.work.workDataOf
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.BuildConfig
import info.nightscout.androidaps.R
@ -25,13 +30,21 @@ import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.diaconn.events.EventDiaconnG8PumpLogReset
import info.nightscout.androidaps.events.EventAppExit
import info.nightscout.androidaps.interfaces.AndroidPermission
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.interfaces.ImportExportPrefs
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.general.maintenance.formats.*
import info.nightscout.androidaps.utils.AndroidPermission
import info.nightscout.androidaps.plugins.general.maintenance.formats.EncryptedPrefsFormat
import info.nightscout.androidaps.plugins.general.maintenance.formats.PrefFileNotFoundError
import info.nightscout.androidaps.plugins.general.maintenance.formats.PrefIOError
import info.nightscout.androidaps.plugins.general.maintenance.formats.PrefMetadata
import info.nightscout.androidaps.plugins.general.maintenance.formats.Prefs
import info.nightscout.androidaps.plugins.general.maintenance.formats.PrefsFormat
import info.nightscout.androidaps.plugins.general.maintenance.formats.PrefsMetadataKey
import info.nightscout.androidaps.plugins.general.maintenance.formats.PrefsStatus
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.MidnightTime
import info.nightscout.androidaps.utils.T
@ -40,7 +53,6 @@ import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.alertDialogs.PrefImportSummaryDialog
import info.nightscout.androidaps.utils.alertDialogs.TwoMessagesAlertDialog
import info.nightscout.androidaps.utils.alertDialogs.WarningDialog
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.androidaps.utils.protection.PasswordCheck
import info.nightscout.androidaps.utils.storage.Storage
import info.nightscout.androidaps.utils.userEntry.UserEntryPresentationHelper
@ -251,13 +263,13 @@ class ImportExportPrefsImpl @Inject constructor(
activity, rh.gs(R.string.preferences_export_canceled)
+ "\n\n" + rh.gs(R.string.filenotfound)
+ ": " + e.message
+ "\n\n" + rh.gs(R.string.needstoragepermission)
+ "\n\n" + rh.gs(R.string.need_storage_permission)
)
log.error(LTag.CORE, "File system exception", e)
} catch (e: PrefIOError) {
ToastUtils.Long.errorToast(
activity, rh.gs(R.string.preferences_export_canceled)
+ "\n\n" + rh.gs(R.string.needstoragepermission)
+ "\n\n" + rh.gs(R.string.need_storage_permission)
+ ": " + e.message
)
log.error(LTag.CORE, "File system exception", e)

View file

@ -1,12 +1,23 @@
package info.nightscout.androidaps.plugins.general.overview
import androidx.annotation.StringRes
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.SwitchPreference
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.events.EventPumpStatusChanged
import info.nightscout.androidaps.extensions.*
import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.extensions.putDouble
import info.nightscout.androidaps.extensions.putInt
import info.nightscout.androidaps.extensions.putString
import info.nightscout.androidaps.extensions.storeDouble
import info.nightscout.androidaps.extensions.storeInt
import info.nightscout.androidaps.extensions.storeString
import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.interfaces.Overview
import info.nightscout.androidaps.interfaces.PluginBase
import info.nightscout.androidaps.interfaces.PluginDescription
import info.nightscout.androidaps.interfaces.PluginType
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
@ -15,6 +26,7 @@ import info.nightscout.androidaps.plugins.general.overview.events.EventUpdateOve
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.Scale
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.ScaledDataPoint
import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationStore
import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationWithAction
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.rx.AapsSchedulers
@ -56,6 +68,18 @@ class OverviewPlugin @Inject constructor(
private var disposable: CompositeDisposable = CompositeDisposable()
override val overviewBus = RxBus(aapsSchedulers, aapsLogger)
override fun addNotification(id: Int, text: String, level: Int, @StringRes actionButtonId: Int, action: Runnable) {
rxBus.send(
EventNewNotification(
NotificationWithAction(injector, id, text, level).apply {
action(actionButtonId, action)
})
)
}
override fun dismissNotification(id: Int) {
rxBus.send(EventDismissNotification(id))
}
class DeviationDataPoint(x: Double, y: Double, var color: Int, scale: Scale) : ScaledDataPoint(x, y, scale)

View file

@ -4,14 +4,16 @@ import android.os.SystemClock
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Sms
import info.nightscout.androidaps.interfaces.CommandQueue
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.interfaces.SmsCommunicator
import info.nightscout.androidaps.plugins.general.smsCommunicator.otp.OneTimePassword
import info.nightscout.androidaps.plugins.general.smsCommunicator.otp.OneTimePasswordValidationResult
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import javax.inject.Inject
class AuthRequest internal constructor(
@ -22,7 +24,7 @@ class AuthRequest internal constructor(
val action: SmsAction) {
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var smsCommunicatorPlugin: SmsCommunicatorPlugin
@Inject lateinit var smsCommunicator: SmsCommunicator
@Inject lateinit var rh: ResourceHelper
@Inject lateinit var otp: OneTimePassword
@Inject lateinit var dateUtil: DateUtil
@ -34,7 +36,7 @@ class AuthRequest internal constructor(
init {
injector.androidInjector().inject(this)
date = dateUtil.now()
smsCommunicatorPlugin.sendSMS(Sms(requester.phoneNumber, requestText))
smsCommunicator.sendSMS(Sms(requester.phoneNumber, requestText))
}
private fun codeIsValid(toValidate: String): Boolean =
@ -48,7 +50,7 @@ class AuthRequest internal constructor(
if (!codeIsValid(codeReceived)) {
processed = true
aapsLogger.debug(LTag.SMS, "Wrong code")
smsCommunicatorPlugin.sendSMS(Sms(requester.phoneNumber, rh.gs(R.string.sms_wrongcode)))
smsCommunicator.sendSMS(Sms(requester.phoneNumber, rh.gs(R.string.sms_wrongcode)))
return
}
if (dateUtil.now() - date < Constants.SMS_CONFIRM_TIMEOUT) {
@ -62,7 +64,7 @@ class AuthRequest internal constructor(
}
if (commandQueue.size() != 0) {
aapsLogger.debug(LTag.SMS, "Command timed out: " + requester.text)
smsCommunicatorPlugin.sendSMS(Sms(requester.phoneNumber, rh.gs(R.string.sms_timeout_while_wating)))
smsCommunicator.sendSMS(Sms(requester.phoneNumber, rh.gs(R.string.sms_timeout_while_wating)))
return
}
}

View file

@ -5,6 +5,7 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.data.Sms
import info.nightscout.androidaps.databinding.SmscommunicatorFragmentBinding
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.general.smsCommunicator.events.EventSmsCommunicatorUpdateGui

View file

@ -15,6 +15,7 @@ import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R
import info.nightscout.androidaps.annotations.OpenForTesting
import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.data.Sms
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.OfflineEvent
import info.nightscout.androidaps.database.entities.TemporaryTarget
@ -184,7 +185,6 @@ class SmsCommunicatorPlugin @Inject constructor(
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
}
@Suppress("SpellCheckingInspection")
override fun doWork(): Result {
val bundle = dataWorkerStorage.pickupBundle(inputData.getLong(DataWorkerStorage.STORE_KEY, -1))
?: return Result.failure(workDataOf("Error" to "missing input data"))
@ -1099,7 +1099,7 @@ class SmsCommunicatorPlugin @Inject constructor(
}
}
fun sendSMS(sms: Sms): Boolean {
override fun sendSMS(sms: Sms): Boolean {
sms.text = stripAccents(sms.text)
try {
aapsLogger.debug(LTag.SMS, "Sending SMS to " + sms.phoneNumber + ": " + sms.text)

View file

@ -22,6 +22,7 @@ import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.CommandQueue
import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.interfaces.IobCobCalculator
import info.nightscout.androidaps.interfaces.LocalAlertUtils
import info.nightscout.androidaps.interfaces.Loop
import info.nightscout.androidaps.interfaces.PluginBase
import info.nightscout.androidaps.interfaces.ProfileFunction
@ -32,7 +33,6 @@ import info.nightscout.androidaps.plugins.general.maintenance.MaintenancePlugin
import info.nightscout.androidaps.queue.commands.Command
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.LocalAlertUtils
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.widget.updateWidget
import info.nightscout.shared.logging.AAPSLogger

View file

@ -12,7 +12,15 @@ import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.ProfileSealed
import info.nightscout.androidaps.dialogs.ProfileSwitchDialog
import info.nightscout.androidaps.events.EventPumpStatusChanged
import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.AndroidPermission
import info.nightscout.androidaps.interfaces.CommandQueue
import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.interfaces.ConfigBuilder
import info.nightscout.androidaps.interfaces.ImportExportPrefs
import info.nightscout.androidaps.interfaces.PluginType
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesFragment
@ -24,15 +32,25 @@ import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin
import info.nightscout.androidaps.plugins.pump.common.events.EventRileyLinkDeviceStatusChange
import info.nightscout.androidaps.plugins.pump.omnipod.dash.OmnipodDashPumpPlugin
import info.nightscout.androidaps.plugins.pump.omnipod.eros.OmnipodErosPumpPlugin
import info.nightscout.androidaps.setupwizard.elements.*
import info.nightscout.androidaps.setupwizard.elements.SWBreak
import info.nightscout.androidaps.setupwizard.elements.SWButton
import info.nightscout.androidaps.setupwizard.elements.SWEditEncryptedPassword
import info.nightscout.androidaps.setupwizard.elements.SWEditIntNumber
import info.nightscout.androidaps.setupwizard.elements.SWEditNumber
import info.nightscout.androidaps.setupwizard.elements.SWEditNumberWithUnits
import info.nightscout.androidaps.setupwizard.elements.SWEditString
import info.nightscout.androidaps.setupwizard.elements.SWEditUrl
import info.nightscout.androidaps.setupwizard.elements.SWFragment
import info.nightscout.androidaps.setupwizard.elements.SWHtmlLink
import info.nightscout.androidaps.setupwizard.elements.SWInfoText
import info.nightscout.androidaps.setupwizard.elements.SWPlugin
import info.nightscout.androidaps.setupwizard.elements.SWPreference
import info.nightscout.androidaps.setupwizard.elements.SWRadioButton
import info.nightscout.androidaps.setupwizard.events.EventSWUpdate
import info.nightscout.androidaps.utils.AndroidPermission
import info.nightscout.androidaps.utils.CryptoUtil
import info.nightscout.androidaps.utils.HardLimits
import info.nightscout.androidaps.utils.extensions.isRunningTest
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.shared.sharedPreferences.SP
import java.util.*
import javax.inject.Inject
import javax.inject.Singleton
@ -110,7 +128,7 @@ class SWDefinition @Inject constructor(
private val screenPermissionWindow = SWScreen(injector, R.string.permission)
.skippable(false)
.add(SWInfoText(injector)
.label(rh.gs(R.string.needsystemwindowpermission)))
.label(rh.gs(R.string.need_system_window_permission)))
.add(SWBreak(injector))
.add(SWButton(injector)
.text(R.string.askforpermission)
@ -121,7 +139,7 @@ class SWDefinition @Inject constructor(
private val screenPermissionBattery = SWScreen(injector, R.string.permission)
.skippable(false)
.add(SWInfoText(injector)
.label(rh.gs(R.string.needwhitelisting, rh.gs(R.string.app_name))))
.label(rh.gs(R.string.need_whitelisting, rh.gs(R.string.app_name))))
.add(SWBreak(injector))
.add(SWButton(injector)
.text(R.string.askforpermission)
@ -132,7 +150,7 @@ class SWDefinition @Inject constructor(
private val screenPermissionBt = SWScreen(injector, R.string.permission)
.skippable(false)
.add(SWInfoText(injector)
.label(rh.gs(R.string.needlocationpermission)))
.label(rh.gs(R.string.need_location_permission)))
.add(SWBreak(injector))
.add(SWButton(injector)
.text(R.string.askforpermission)
@ -143,7 +161,7 @@ class SWDefinition @Inject constructor(
private val screenPermissionStore = SWScreen(injector, R.string.permission)
.skippable(false)
.add(SWInfoText(injector)
.label(rh.gs(R.string.needstoragepermission)))
.label(rh.gs(R.string.need_storage_permission)))
.add(SWBreak(injector))
.add(SWButton(injector)
.text(R.string.askforpermission)

View file

@ -1,167 +0,0 @@
package info.nightscout.androidaps.utils
import android.Manifest
import android.annotation.SuppressLint
import android.bluetooth.BluetoothAdapter
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.os.PowerManager
import android.provider.Settings
import androidx.core.content.ContextCompat
import androidx.fragment.app.FragmentActivity
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.DaggerAppCompatActivityWithResult
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationWithAction
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.interfaces.ResourceHelper
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class AndroidPermission @Inject constructor(
val rh: ResourceHelper,
val rxBus: RxBus,
val injector: HasAndroidInjector
) {
private var permissionBatteryOptimizationFailed = false
@SuppressLint("BatteryLife")
fun askForPermission(activity: FragmentActivity, permissions: Array<String>) {
var test = false
var testBattery = false
for (s in permissions) {
test = test || ContextCompat.checkSelfPermission(activity, s) != PackageManager.PERMISSION_GRANTED
if (s == Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) {
val powerManager = activity.getSystemService(Context.POWER_SERVICE) as PowerManager
val packageName = activity.packageName
testBattery = testBattery || !powerManager.isIgnoringBatteryOptimizations(packageName)
}
}
if (test) {
if (activity is DaggerAppCompatActivityWithResult)
try {
activity.requestMultiplePermissions.launch(permissions)
} catch (ignored: IllegalStateException) {
ToastUtils.errorToast(activity, rh.gs(R.string.error_asking_for_permissions))
}
}
if (testBattery) {
try {
if (activity is DaggerAppCompatActivityWithResult)
try {
activity.callForBatteryOptimization.launch(null)
} catch (ignored: IllegalStateException) {
ToastUtils.errorToast(activity, rh.gs(R.string.error_asking_for_permissions))
}
} catch (e: ActivityNotFoundException) {
permissionBatteryOptimizationFailed = true
OKDialog.show(activity, rh.gs(R.string.permission), rh.gs(R.string.alert_dialog_permission_battery_optimization_failed)) { activity.recreate() }
}
}
}
fun askForPermission(activity: FragmentActivity, permission: String) = askForPermission(activity, arrayOf(permission))
fun permissionNotGranted(context: Context, permission: String): Boolean {
var selfCheck = ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED
if (permission == Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) {
if (!permissionBatteryOptimizationFailed) {
val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager
val packageName = context.packageName
selfCheck = selfCheck && powerManager.isIgnoringBatteryOptimizations(packageName)
}
}
return !selfCheck
}
@Synchronized
fun notifyForSMSPermissions(activity: FragmentActivity, smsCommunicatorPlugin: SmsCommunicatorPlugin) {
if (smsCommunicatorPlugin.isEnabled()) {
if (permissionNotGranted(activity, Manifest.permission.RECEIVE_SMS)) {
val notification = NotificationWithAction(injector, Notification.PERMISSION_SMS, rh.gs(R.string.smscommunicator_missingsmspermission), Notification.URGENT)
notification.action(R.string.request) { askForPermission(activity, arrayOf(Manifest.permission.RECEIVE_SMS, Manifest.permission.SEND_SMS, Manifest.permission.RECEIVE_MMS)) }
rxBus.send(EventNewNotification(notification))
} else rxBus.send(EventDismissNotification(Notification.PERMISSION_SMS))
// Following is a bug in Android 8
// if (permissionNotGranted(activity, Manifest.permission.READ_PHONE_STATE)) {
// val notification = NotificationWithAction(injector, Notification.PERMISSION_PHONE_STATE, rh.gs(R.string.smscommunicator_missingphonestatepermission), Notification.URGENT)
// notification.action(R.string.request) { askForPermission(activity, arrayOf(Manifest.permission.READ_PHONE_STATE)) }
// rxBus.send(EventNewNotification(notification))
// } else rxBus.send(EventDismissNotification(Notification.PERMISSION_PHONE_STATE))
}
}
@SuppressLint("MissingPermission")
@Synchronized
fun notifyForBtConnectPermission(activity: FragmentActivity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
// Manifest.permission.BLUETOOTH_CONNECT
if (permissionNotGranted(activity, Manifest.permission.BLUETOOTH_CONNECT) || permissionNotGranted(activity, Manifest.permission.BLUETOOTH_SCAN)) {
val notification = NotificationWithAction(injector, Notification.PERMISSION_BT, rh.gs(R.string.needconnectpermission), Notification.URGENT)
notification.action(R.string.request) { askForPermission(activity, arrayOf(Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_CONNECT)) }
rxBus.send(EventNewNotification(notification))
} else {
activity.startActivity(Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE))
rxBus.send(EventDismissNotification(Notification.PERMISSION_BT))
}
}
}
@Synchronized
fun notifyForBatteryOptimizationPermission(activity: FragmentActivity) {
if (permissionNotGranted(activity, Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) {
val notification = NotificationWithAction(injector, Notification.PERMISSION_BATTERY, rh.gs(R.string.needwhitelisting, rh.gs(R.string.app_name)), Notification.URGENT)
notification.action(R.string.request) { askForPermission(activity, arrayOf(Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) }
rxBus.send(EventNewNotification(notification))
} else rxBus.send(EventDismissNotification(Notification.PERMISSION_BATTERY))
}
@Synchronized fun notifyForStoragePermission(activity: FragmentActivity) {
if (permissionNotGranted(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
val notification = NotificationWithAction(injector, Notification.PERMISSION_STORAGE, rh.gs(R.string.needstoragepermission), Notification.URGENT)
notification.action(R.string.request) { askForPermission(activity, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)) }
rxBus.send(EventNewNotification(notification))
} else rxBus.send(EventDismissNotification(Notification.PERMISSION_STORAGE))
}
@Synchronized fun notifyForLocationPermissions(activity: FragmentActivity) {
if (permissionNotGranted(activity, Manifest.permission.ACCESS_FINE_LOCATION)) {
val notification = NotificationWithAction(injector, Notification.PERMISSION_LOCATION, rh.gs(R.string.needlocationpermission), Notification.URGENT)
notification.action(R.string.request) { askForPermission(activity, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION)) }
rxBus.send(EventNewNotification(notification))
} else rxBus.send(EventDismissNotification(Notification.PERMISSION_LOCATION))
}
@Synchronized fun notifyForSystemWindowPermissions(activity: FragmentActivity) {
// Check if Android Q or higher
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
if (!Settings.canDrawOverlays(activity)) {
val notification = NotificationWithAction(injector, Notification.PERMISSION_SYSTEM_WINDOW, rh.gs(R.string.needsystemwindowpermission), Notification.URGENT)
notification.action(R.string.request) {
// Check if Android Q or higher
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
// Show alert dialog to the user saying a separate permission is needed
// Launch the settings activity if the user prefers
val intent = Intent(
Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + activity.packageName)
)
activity.startActivity(intent)
}
}
rxBus.send(EventNewNotification(notification))
} else rxBus.send(EventDismissNotification(Notification.PERMISSION_SYSTEM_WINDOW))
}
}
}

View file

@ -67,7 +67,6 @@
<string name="nav_resetdb">Reset Databases</string>
<string name="reset_db_confirm">Do you really want to reset the databases?</string>
<string name="nav_exit">Exit</string>
<string name="alert_dialog_permission_battery_optimization_failed">This device does not appear to support battery optimization whitelisting - you may experience performance issues.</string>
<string name="description_actions">Some buttons to quickly access common features</string>
<string name="description_config_builder">Used for configuring the active plugins</string>
<string name="description_objectives">Learning program</string>
@ -225,7 +224,6 @@
<string name="smscommunicator_remotebolusmindistance_summary">Minimum number of minutes that must elapse between one remote bolus and the next</string>
<string name="smscommunicator_remotebolusmindistance">How many minutes must elapse, at least, between one bolus and the next</string>
<string name="smscommunicator_remotebolusmindistance_caveat">For your safety, to edit this preference you need to add at least 2 phone numbers.</string>
<string name="bolusrequested">Going to deliver %1$.2f U</string>
<string name="smscommunicator_bolusdelivered">Bolus %1$.2f U delivered successfully</string>
<string name="smscommunicator_mealbolusdelivered">Meal Bolus %1$.2f U delivered successfully</string>
<string name="smscommunicator_mealbolusdelivered_tt">Target %1$s for %2$d minutes</string>
@ -295,7 +293,6 @@
<string name="resend_all_data">Resend All Data</string>
<string name="open_settings_on_wear">Open Settings on Wear</string>
<string name="basal_rate">Basal rate</string>
<string name="basalvaluebelowminimum">Basal value below minimum. Profile not set!</string>
<string name="sms_actualbg">BG:</string>
<string name="sms_lastbg">Last BG:</string>
<string name="MM640g">MM640g</string>
@ -386,7 +383,6 @@
<string name="key_patient_name" translatable="false">patient_name</string>
<string name="key_i_understand" translatable="false">I_understand</string>
<string name="Glimp">Glimp</string>
<string name="needwhitelisting">%1$s needs battery optimization whitelisting for proper performance</string>
<string name="loopsuspended">Loop suspended</string>
<string name="loopsuspendedfor">Suspended (%1$d m)</string>
<string name="suspendloopfor1h">Suspend loop for 1h</string>
@ -460,7 +456,6 @@
<string name="abs_insulin_shortname">ABS</string>
<string name="devslope_shortname">DEVSLOPE</string>
<string name="nav_about">About</string>
<string name="smscommunicator_missingsmspermission">Missing SMS permission</string>
<string name="smscommunicator_missingphonestatepermission">Missing phone state permission</string>
<string name="xdripstatus_settings">xDrip+ Status (watch)</string>
<string name="xdripstatus">xDrip+ Statusline (watch)</string>
@ -551,14 +546,9 @@
<string name="shortenergy">En</string>
<string name="shortprotein">Pr</string>
<string name="shortfat">Fat</string>
<string name="executingrightnow">Command is executed right now</string>
<string name="missed_bg_readings">Missed BG readings</string>
<string name="key_raise_notifications_as_android_notifications" translatable="false">raise_urgent_alarms_as_android_notification</string>
<string name="raise_notifications_as_android_notifications">Use system notifications for alerts and notifications</string>
<string name="gradually_increase_notification_volume">Gradually increase the volume for alerts and notifications</string>
<string name="key_enable_pump_unreachable_alert" translatable="false">enable_pump_unreachable_alert</string>
<string name="key_enable_missed_bg_readings_alert" translatable="false">enable_missed_bg_readings</string>
<string name="key_enable_carbs_required_alert_local" translatable="false">enable_carbs_required_alert_local</string>
<string name="localalertsettings_title">Local alerts</string>
<string name="enable_missed_bg_readings_alert">Alert if no BG data is received</string>
<string name="enable_pump_unreachable_alert">Alert if pump is unreachable</string>
@ -765,12 +755,7 @@
<string name="setupwizard_pump_waiting_for_riley_link_connection">Please configure your RileyLink below. After selecting a RileyLink, it will be possible to continue setup once the RileyLink status is \"Connected\". This might take a minute.\n</string>
<string name="setupwizard_pump_pump_not_initialized"><b>Note:</b> You can continue setup once the pump has been set up.\n</string>
<string name="startobjective">Start your first objective</string>
<string name="permission">Permission</string>
<string name="askforpermission">Ask for permission</string>
<string name="needsystemwindowpermission">Application needs system window permission for notifications</string>
<string name="needlocationpermission">Application needs location permission for BT scan and WiFi identification</string>
<string name="needstoragepermission">Application needs storage permission to be able store log files and export settings</string>
<string name="request">Request</string>
<string name="open_navigation">Open navigation</string>
<string name="close_navigation">Close navigation</string>
<string name="nav_plugin_preferences">Plugin preferences</string>
@ -1020,7 +1005,6 @@
<string name="filter">Filter</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="key_smscommunicator_report_pump_ureachable" translatable="false">smscommunicator_report_pump_ureachable</string>
<string name="smscommunicator_report_pump_ureachable_summary">Send SMS if unreachable pump event is triggered</string>
<string name="smscommunicator_pump_ureachable">Report pump unreachable</string>
<string name="advisoralarm">Run alarm when is time to eat</string>
@ -1220,7 +1204,6 @@
<string name="blocked_by_charging">Blocked by charging options</string>
<string name="blocked_by_connectivity">Blocked by connectivity options</string>
<string name="no_watch_connected">(No Watch Connected)</string>
<string name="error_asking_for_permissions">Error asking for permissions</string>
<string name="key_adjust_sensitivity" translatable="false">dynisf_adjust_sensitivity</string>
<string name="dynisf_adjust_sensitivity">Adjust sensitivity and BG</string>
<string name="database_cleanup">Database cleanup</string>

View file

@ -44,7 +44,7 @@
<SwitchPreference
android:defaultValue="true"
android:key="@string/key_smscommunicator_report_pump_ureachable"
android:key="@string/key_smscommunicator_report_pump_unreachable"
android:summary="@string/smscommunicator_report_pump_ureachable_summary"
android:title="@string/smscommunicator_pump_ureachable" />

View file

@ -5,6 +5,7 @@ import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R
import info.nightscout.androidaps.TestBase
import info.nightscout.androidaps.data.Sms
import info.nightscout.androidaps.plugins.general.smsCommunicator.otp.OneTimePassword
import info.nightscout.androidaps.plugins.general.smsCommunicator.otp.OneTimePasswordValidationResult
import info.nightscout.androidaps.utils.DateUtil

View file

@ -8,6 +8,7 @@ import info.nightscout.androidaps.R
import info.nightscout.androidaps.TestBaseWithProfile
import info.nightscout.androidaps.data.IobTotal
import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.data.Sms
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.GlucoseValue
import info.nightscout.androidaps.database.transactions.CancelCurrentOfflineEventIfAnyTransaction

View file

@ -2,6 +2,7 @@ package info.nightscout.androidaps.plugins.general.smsCommunicator
import android.telephony.SmsMessage
import info.nightscout.androidaps.TestBase
import info.nightscout.androidaps.data.Sms
import org.junit.Assert
import org.junit.Test
import org.mockito.Mockito

View file

@ -15,6 +15,11 @@ android {
dimension "standard"
}
}
// disable for modules here
buildFeatures {
buildConfig = true
}
}
dependencies {

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps.plugins.general.smsCommunicator
package info.nightscout.androidaps.data
import android.telephony.SmsMessage
@ -12,21 +12,21 @@ class Sms {
var processed = false
var ignored = false
internal constructor(message: SmsMessage) {
constructor(message: SmsMessage) {
phoneNumber = message.originatingAddress ?: ""
text = message.messageBody
date = message.timestampMillis
received = true
}
internal constructor(phoneNumber: String, text: String) {
constructor(phoneNumber: String, text: String) {
this.phoneNumber = phoneNumber
this.text = text
date = System.currentTimeMillis()
sent = true
}
internal constructor(other: Sms, number: String? = null) {
constructor(other: Sms, number: String? = null) {
phoneNumber = number ?: other.phoneNumber
text = other.text
date = other.date

View file

@ -0,0 +1,17 @@
package info.nightscout.androidaps.interfaces
import android.content.Context
import androidx.fragment.app.FragmentActivity
interface AndroidPermission {
fun askForPermission(activity: FragmentActivity, permissions: Array<String>)
fun askForPermission(activity: FragmentActivity, permission: String) = askForPermission(activity, arrayOf(permission))
fun permissionNotGranted(context: Context, permission: String): Boolean
fun notifyForSMSPermissions(activity: FragmentActivity, smsCommunicator: SmsCommunicator)
fun notifyForBtConnectPermission(activity: FragmentActivity)
fun notifyForBatteryOptimizationPermission(activity: FragmentActivity)
fun notifyForStoragePermission(activity: FragmentActivity)
fun notifyForLocationPermissions(activity: FragmentActivity)
fun notifyForSystemWindowPermissions(activity: FragmentActivity)
}

View file

@ -0,0 +1,10 @@
package info.nightscout.androidaps.interfaces
import info.nightscout.androidaps.data.PumpEnactResult
interface Insight {
fun setTBROverNotification(enabled: Boolean): PumpEnactResult
fun startPump(): PumpEnactResult
fun stopPump(): PumpEnactResult
}

View file

@ -0,0 +1,17 @@
package info.nightscout.androidaps.interfaces
interface LocalAlertUtils {
fun checkPumpUnreachableAlarm(lastConnection: Long, isStatusOutdated: Boolean, isDisconnected: Boolean)
/* Pre-snoozes the alarms with 5 minutes if no snooze exists.
* Call only at startup!
*/
fun preSnoozeAlarms()
/* shortens alarm times in case of setting changes or future data
*/
fun shortenSnoozeInterval()
fun notifyPumpStatusRead()
fun checkStaleBGAlert()
}

View file

@ -1,8 +1,12 @@
package info.nightscout.androidaps.interfaces
import androidx.annotation.StringRes
import info.nightscout.androidaps.plugins.bus.RxBus
interface Overview : ConfigExportImport {
val overviewBus: RxBus
fun addNotification(id: Int, text: String, level: Int, @StringRes actionButtonId: Int, action: Runnable)
fun dismissNotification(id: Int)
}

View file

@ -1,6 +1,9 @@
package info.nightscout.androidaps.interfaces
import info.nightscout.androidaps.data.Sms
interface SmsCommunicator {
fun sendNotificationToAllNumbers(text: String): Boolean
fun sendSMS(sms: Sms): Boolean
}

View file

@ -80,6 +80,10 @@
<string name="key_carbs_button_increment_1" translatable="false">carbs_button_increment_1</string>
<string name="key_carbs_button_increment_2" translatable="false">carbs_button_increment_2</string>
<string name="key_carbs_button_increment_3" translatable="false">carbs_button_increment_3</string>
<string name="key_enable_pump_unreachable_alert" translatable="false">enable_pump_unreachable_alert</string>
<string name="key_enable_missed_bg_readings_alert" translatable="false">enable_missed_bg_readings</string>
<string name="key_enable_carbs_required_alert_local" translatable="false">enable_carbs_required_alert_local</string>
<string name="key_smscommunicator_report_pump_unreachable" translatable="false">smscommunicator_report_pump_unreachable</string>
<!-- General-->
<string name="refresh">Refresh</string>
@ -617,6 +621,9 @@
<string name="autotune_run_cancelled">Another run of Autotune is detected, run cancelled</string>
<string name="needconnectpermission">Application needs bluetooth permission</string>
<!-- SmsCommunicator -->
<string name="smscommunicator_missingsmspermission">Missing SMS permission</string>
<plurals name="days">
<item quantity="one">%1$d day</item>
<item quantity="other">%1$d days</item>

View file

@ -0,0 +1,185 @@
package info.nightscout.implementation
import android.Manifest
import android.annotation.SuppressLint
import android.bluetooth.BluetoothAdapter
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.os.PowerManager
import android.provider.Settings
import androidx.core.content.ContextCompat
import androidx.fragment.app.FragmentActivity
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.activities.DaggerAppCompatActivityWithResult
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.AndroidPermission
import info.nightscout.androidaps.interfaces.PluginBase
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.interfaces.SmsCommunicator
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
import info.nightscout.androidaps.utils.ToastUtils
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class AndroidPermissionImpl @Inject constructor(
val rh: ResourceHelper,
val rxBus: RxBus,
val injector: HasAndroidInjector,
val activePlugin: ActivePlugin
) : AndroidPermission {
private var permissionBatteryOptimizationFailed = false
@SuppressLint("BatteryLife")
override fun askForPermission(activity: FragmentActivity, permissions: Array<String>) {
var test = false
var testBattery = false
for (s in permissions) {
test = test || ContextCompat.checkSelfPermission(activity, s) != PackageManager.PERMISSION_GRANTED
if (s == Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) {
val powerManager = activity.getSystemService(Context.POWER_SERVICE) as PowerManager
val packageName = activity.packageName
testBattery = testBattery || !powerManager.isIgnoringBatteryOptimizations(packageName)
}
}
if (test) {
if (activity is DaggerAppCompatActivityWithResult)
try {
activity.requestMultiplePermissions.launch(permissions)
} catch (ignored: IllegalStateException) {
ToastUtils.errorToast(activity, rh.gs(R.string.error_asking_for_permissions))
}
}
if (testBattery) {
try {
if (activity is DaggerAppCompatActivityWithResult)
try {
activity.callForBatteryOptimization.launch(null)
} catch (ignored: IllegalStateException) {
ToastUtils.errorToast(activity, rh.gs(R.string.error_asking_for_permissions))
}
} catch (e: ActivityNotFoundException) {
permissionBatteryOptimizationFailed = true
OKDialog.show(activity, rh.gs(R.string.permission), rh.gs(R.string.alert_dialog_permission_battery_optimization_failed)) { activity.recreate() }
}
}
}
override fun askForPermission(activity: FragmentActivity, permission: String) = askForPermission(activity, arrayOf(permission))
override fun permissionNotGranted(context: Context, permission: String): Boolean {
var selfCheck = ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED
if (permission == Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) {
if (!permissionBatteryOptimizationFailed) {
val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager
val packageName = context.packageName
selfCheck = selfCheck && powerManager.isIgnoringBatteryOptimizations(packageName)
}
}
return !selfCheck
}
@Synchronized
override fun notifyForSMSPermissions(activity: FragmentActivity, smsCommunicator: SmsCommunicator) {
if ((smsCommunicator as PluginBase).isEnabled()) {
if (permissionNotGranted(activity, Manifest.permission.RECEIVE_SMS))
activePlugin.activeOverview.addNotification(
id = Notification.PERMISSION_SMS,
text = rh.gs(R.string.smscommunicator_missingsmspermission),
level = Notification.URGENT,
actionButtonId = R.string.request
) {
askForPermission(
activity,
arrayOf(Manifest.permission.RECEIVE_SMS, Manifest.permission.SEND_SMS, Manifest.permission.RECEIVE_MMS)
)
}
else activePlugin.activeOverview.dismissNotification(Notification.PERMISSION_SMS)
}
}
@SuppressLint("MissingPermission")
@Synchronized
override fun notifyForBtConnectPermission(activity: FragmentActivity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
// Manifest.permission.BLUETOOTH_CONNECT
if (permissionNotGranted(activity, Manifest.permission.BLUETOOTH_CONNECT) || permissionNotGranted(activity, Manifest.permission.BLUETOOTH_SCAN))
activePlugin.activeOverview.addNotification(
id = Notification.PERMISSION_BT,
text = rh.gs(R.string.needconnectpermission),
level = Notification.URGENT,
actionButtonId = R.string.request
) { askForPermission(activity, arrayOf(Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_CONNECT)) }
else {
activity.startActivity(Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE))
activePlugin.activeOverview.dismissNotification(Notification.PERMISSION_BT)
}
}
}
@Synchronized
override fun notifyForBatteryOptimizationPermission(activity: FragmentActivity) {
if (permissionNotGranted(activity, Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS))
activePlugin.activeOverview.addNotification(
id = Notification.PERMISSION_BATTERY,
text = rh.gs(R.string.need_whitelisting, rh.gs(R.string.app_name)),
level = Notification.URGENT,
actionButtonId = R.string.request
) { askForPermission(activity, arrayOf(Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) }
else activePlugin.activeOverview.dismissNotification(Notification.PERMISSION_BATTERY)
}
@Synchronized override fun notifyForStoragePermission(activity: FragmentActivity) {
if (permissionNotGranted(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE))
activePlugin.activeOverview.addNotification(
id = Notification.PERMISSION_STORAGE,
text = rh.gs(R.string.need_storage_permission),
level = Notification.URGENT,
actionButtonId = R.string.request
) { askForPermission(activity, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)) }
else activePlugin.activeOverview.dismissNotification(Notification.PERMISSION_STORAGE)
}
@Synchronized override fun notifyForLocationPermissions(activity: FragmentActivity) {
if (permissionNotGranted(activity, Manifest.permission.ACCESS_FINE_LOCATION)) {
activePlugin.activeOverview.addNotification(
id = Notification.PERMISSION_LOCATION,
text = rh.gs(R.string.need_location_permission),
level = Notification.URGENT,
actionButtonId = R.string.request
) { askForPermission(activity, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION)) }
} else activePlugin.activeOverview.dismissNotification(Notification.PERMISSION_LOCATION)
}
@Synchronized override fun notifyForSystemWindowPermissions(activity: FragmentActivity) {
// Check if Android Q or higher
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
if (!Settings.canDrawOverlays(activity))
activePlugin.activeOverview.addNotification(
id = Notification.PERMISSION_SYSTEM_WINDOW,
text = rh.gs(R.string.need_location_permission),
level = Notification.URGENT,
actionButtonId = R.string.request
) {
// Check if Android Q or higher
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
// Show alert dialog to the user saying a separate permission is needed
// Launch the settings activity if the user prefers
val intent = Intent(
Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + activity.packageName)
)
activity.startActivity(intent)
}
}
else activePlugin.activeOverview.dismissNotification(Notification.PERMISSION_SYSTEM_WINDOW)
}
}
}

View file

@ -1,7 +1,6 @@
package info.nightscout.androidaps.utils
package info.nightscout.implementation
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.database.entities.TherapyEvent
@ -11,14 +10,17 @@ import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.database.transactions.InsertTherapyEventAnnouncementTransaction
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.interfaces.LocalAlertUtils
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.interfaces.SmsCommunicator
import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.T
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.shared.sharedPreferences.SP
@ -32,19 +34,19 @@ import kotlin.math.min
* Created by adrian on 17/12/17.
*/
@Singleton
class LocalAlertUtils @Inject constructor(
class LocalAlertUtilsImpl @Inject constructor(
private val aapsLogger: AAPSLogger,
private val sp: SP,
private val rxBus: RxBus,
private val rh: ResourceHelper,
private val activePlugin: ActivePlugin,
private val profileFunction: ProfileFunction,
private val smsCommunicatorPlugin: SmsCommunicatorPlugin,
private val smsCommunicatorPlugin: SmsCommunicator,
private val config: Config,
private val repository: AppRepository,
private val dateUtil: DateUtil,
private val uel: UserEntryLogger
) {
) : LocalAlertUtils {
private val disposable = CompositeDisposable()
@ -56,7 +58,7 @@ class LocalAlertUtils @Inject constructor(
return T.mins(sp.getInt(R.string.key_pump_unreachable_threshold_minutes, Constants.DEFAULT_PUMP_UNREACHABLE_THRESHOLD_MINUTES).toLong()).msecs()
}
fun checkPumpUnreachableAlarm(lastConnection: Long, isStatusOutdated: Boolean, isDisconnected: Boolean) {
override fun checkPumpUnreachableAlarm(lastConnection: Long, isStatusOutdated: Boolean, isDisconnected: Boolean) {
val alarmTimeoutExpired = isAlarmTimeoutExpired(lastConnection, pumpUnreachableThreshold())
val nextAlarmOccurrenceReached = sp.getLong("nextPumpDisconnectedAlarm", 0L) < System.currentTimeMillis()
if (config.APS && isStatusOutdated && alarmTimeoutExpired && nextAlarmOccurrenceReached && !isDisconnected) {
@ -68,7 +70,7 @@ class LocalAlertUtils @Inject constructor(
if (sp.getBoolean(R.string.key_ns_create_announcements_from_errors, true))
disposable += repository.runTransaction(InsertTherapyEventAnnouncementTransaction(rh.gs(R.string.pump_unreachable))).subscribe()
}
if (sp.getBoolean(R.string.key_smscommunicator_report_pump_ureachable, true))
if (sp.getBoolean(R.string.key_smscommunicator_report_pump_unreachable, true))
smsCommunicatorPlugin.sendNotificationToAllNumbers(rh.gs(R.string.pump_unreachable))
}
if (!isStatusOutdated && !alarmTimeoutExpired) rxBus.send(EventDismissNotification(Notification.PUMP_UNREACHABLE))
@ -85,7 +87,7 @@ class LocalAlertUtils @Inject constructor(
/*Pre-snoozes the alarms with 5 minutes if no snooze exists.
* Call only at startup!
*/
fun preSnoozeAlarms() {
override fun preSnoozeAlarms() {
if (sp.getLong("nextMissedReadingsAlarm", 0L) < System.currentTimeMillis()) {
sp.putLong("nextMissedReadingsAlarm", System.currentTimeMillis() + 5 * 60 * 1000)
}
@ -94,7 +96,7 @@ class LocalAlertUtils @Inject constructor(
}
}
fun shortenSnoozeInterval() { //shortens alarm times in case of setting changes or future data
override fun shortenSnoozeInterval() { //shortens alarm times in case of setting changes or future data
var nextMissedReadingsAlarm = sp.getLong("nextMissedReadingsAlarm", 0L)
nextMissedReadingsAlarm = min(System.currentTimeMillis() + missedReadingsThreshold(), nextMissedReadingsAlarm)
sp.putLong("nextMissedReadingsAlarm", nextMissedReadingsAlarm)
@ -103,7 +105,7 @@ class LocalAlertUtils @Inject constructor(
sp.putLong("nextPumpDisconnectedAlarm", nextPumpDisconnectedAlarm)
}
fun notifyPumpStatusRead() { //TODO: persist the actual time the pump is read and simplify the whole logic when to alarm
override fun notifyPumpStatusRead() { //TODO: persist the actual time the pump is read and simplify the whole logic when to alarm
val pump = activePlugin.activePump
val profile = profileFunction.getProfile()
if (profile != null) {
@ -115,7 +117,7 @@ class LocalAlertUtils @Inject constructor(
}
}
fun checkStaleBGAlert() {
override fun checkStaleBGAlert() {
val bgReadingWrapped = repository.getLastGlucoseValueWrapped().blockingGet()
val bgReading = if (bgReadingWrapped is ValueWrapper.Existing) bgReadingWrapped.value else return
if (sp.getBoolean(R.string.key_enable_missed_bg_readings_alert, false)

View file

@ -1,9 +1,25 @@
package info.nightscout.androidaps.di
package info.nightscout.implementation.di
import dagger.Module
import dagger.android.ContributesAndroidInjector
import info.nightscout.androidaps.queue.CommandQueueImplementation
import info.nightscout.androidaps.queue.commands.*
import info.nightscout.implementation.queue.CommandQueueImplementation
import info.nightscout.implementation.queue.commands.CommandReadStatus
import info.nightscout.implementation.queue.commands.CommandSMBBolus
import info.nightscout.implementation.queue.commands.CommandSetProfile
import info.nightscout.implementation.queue.commands.CommandSetUserSettings
import info.nightscout.implementation.queue.commands.CommandStartPump
import info.nightscout.implementation.queue.commands.CommandStopPump
import info.nightscout.implementation.queue.commands.CommandTempBasalAbsolute
import info.nightscout.implementation.queue.commands.CommandTempBasalPercent
import info.nightscout.implementation.queue.commands.CommandBolus
import info.nightscout.implementation.queue.commands.CommandCancelExtendedBolus
import info.nightscout.implementation.queue.commands.CommandCancelTempBasal
import info.nightscout.implementation.queue.commands.CommandCustomCommand
import info.nightscout.implementation.queue.commands.CommandExtendedBolus
import info.nightscout.implementation.queue.commands.CommandInsightSetTBROverNotification
import info.nightscout.implementation.queue.commands.CommandLoadEvents
import info.nightscout.implementation.queue.commands.CommandLoadHistory
import info.nightscout.implementation.queue.commands.CommandLoadTDDs
@Module
@Suppress("unused")

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps.queue
package info.nightscout.implementation.queue
import android.content.Context
import android.content.Intent
@ -6,7 +6,6 @@ import android.os.SystemClock
import android.text.Spanned
import androidx.appcompat.app.AppCompatActivity
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.BolusProgressHelperActivity
import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.annotations.OpenForTesting
@ -22,22 +21,48 @@ import info.nightscout.androidaps.dialogs.BolusProgressDialog
import info.nightscout.androidaps.events.EventMobileToWear
import info.nightscout.androidaps.events.EventProfileSwitchChanged
import info.nightscout.androidaps.extensions.getCustomizedName
import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.AndroidPermission
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.androidaps.interfaces.CommandQueue
import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.interfaces.PumpSync
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissBolusProgressIfRunning
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
import info.nightscout.androidaps.queue.commands.*
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.queue.commands.Command
import info.nightscout.androidaps.queue.commands.Command.CommandType
import info.nightscout.androidaps.utils.AndroidPermission
import info.nightscout.androidaps.queue.commands.CustomCommand
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.implementation.R
import info.nightscout.implementation.queue.commands.CommandBolus
import info.nightscout.implementation.queue.commands.CommandCancelExtendedBolus
import info.nightscout.implementation.queue.commands.CommandCancelTempBasal
import info.nightscout.implementation.queue.commands.CommandCustomCommand
import info.nightscout.implementation.queue.commands.CommandExtendedBolus
import info.nightscout.implementation.queue.commands.CommandInsightSetTBROverNotification
import info.nightscout.implementation.queue.commands.CommandLoadEvents
import info.nightscout.implementation.queue.commands.CommandLoadHistory
import info.nightscout.implementation.queue.commands.CommandLoadTDDs
import info.nightscout.implementation.queue.commands.CommandReadStatus
import info.nightscout.implementation.queue.commands.CommandSMBBolus
import info.nightscout.implementation.queue.commands.CommandSetProfile
import info.nightscout.implementation.queue.commands.CommandSetUserSettings
import info.nightscout.implementation.queue.commands.CommandStartPump
import info.nightscout.implementation.queue.commands.CommandStopPump
import info.nightscout.implementation.queue.commands.CommandTempBasalAbsolute
import info.nightscout.implementation.queue.commands.CommandTempBasalPercent
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.shared.sharedPreferences.SP
@ -45,7 +70,7 @@ import info.nightscout.shared.weardata.EventData
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import io.reactivex.rxjava3.kotlin.subscribeBy
import java.util.*
import java.util.LinkedList
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import javax.inject.Singleton
@ -121,7 +146,7 @@ class CommandQueueImplementation @Inject constructor(
}
private fun executingNowError(): PumpEnactResult =
PumpEnactResult(injector).success(false).enacted(false).comment(R.string.executingrightnow)
PumpEnactResult(injector).success(false).enacted(false).comment(R.string.executing_right_now)
override fun isRunning(type: CommandType): Boolean = performing?.commandType == type
@ -300,7 +325,7 @@ class CommandQueueImplementation @Inject constructor(
// not when the Bolus command is starting. The command closes the dialog upon completion).
showBolusProgressDialog(detailedBolusInfo)
// Notify Wear about upcoming bolus
rxBus.send(EventMobileToWear(EventData.BolusProgress(percent = 0, status = rh.gs(R.string.bolusrequested, detailedBolusInfo.insulin))))
rxBus.send(EventMobileToWear(EventData.BolusProgress(percent = 0, status = rh.gs(R.string.goingtodeliver, detailedBolusInfo.insulin))))
}
}
notifyAboutNewCommand()
@ -421,9 +446,9 @@ class CommandQueueImplementation @Inject constructor(
val basalValues = profile.getBasalValues()
for (basalValue in basalValues) {
if (basalValue.value < activePlugin.activePump.pumpDescription.basalMinimumRate) {
val notification = Notification(Notification.BASAL_VALUE_BELOW_MINIMUM, rh.gs(R.string.basalvaluebelowminimum), Notification.URGENT)
val notification = Notification(Notification.BASAL_VALUE_BELOW_MINIMUM, rh.gs(R.string.basal_value_below_minimum), Notification.URGENT)
rxBus.send(EventNewNotification(notification))
callback?.result(PumpEnactResult(injector).success(false).enacted(false).comment(R.string.basalvaluebelowminimum))?.run()
callback?.result(PumpEnactResult(injector).success(false).enacted(false).comment(R.string.basal_value_below_minimum))?.run()
return false
}
}

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps.queue
package info.nightscout.implementation.queue
import android.bluetooth.BluetoothManager
import android.content.Context
@ -6,19 +6,19 @@ import android.os.Build
import android.os.PowerManager
import android.os.SystemClock
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R
import info.nightscout.androidaps.events.EventPumpStatusChanged
import info.nightscout.androidaps.extensions.safeDisable
import info.nightscout.androidaps.extensions.safeEnable
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.AndroidPermission
import info.nightscout.androidaps.interfaces.CommandQueue
import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissBolusProgressIfRunning
import info.nightscout.androidaps.queue.events.EventQueueChanged
import info.nightscout.androidaps.utils.AndroidPermission
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.implementation.R
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.shared.sharedPreferences.SP

View file

@ -1,14 +1,15 @@
package info.nightscout.androidaps.queue.commands
package info.nightscout.implementation.queue.commands
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.dialogs.BolusProgressDialog
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissBolusProgressIfRunning
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.queue.commands.Command
import info.nightscout.implementation.R
import info.nightscout.shared.logging.LTag
import javax.inject.Inject
class CommandBolus(

View file

@ -1,10 +1,11 @@
package info.nightscout.androidaps.queue.commands
package info.nightscout.implementation.queue.commands
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.queue.commands.Command
import info.nightscout.implementation.R
import info.nightscout.shared.logging.LTag
import javax.inject.Inject
class CommandCancelExtendedBolus constructor(

View file

@ -1,10 +1,11 @@
package info.nightscout.androidaps.queue.commands
package info.nightscout.implementation.queue.commands
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.queue.commands.Command
import info.nightscout.implementation.R
import info.nightscout.shared.logging.LTag
import javax.inject.Inject
class CommandCancelTempBasal(

View file

@ -1,9 +1,11 @@
package info.nightscout.androidaps.queue.commands
package info.nightscout.implementation.queue.commands
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.queue.commands.Command
import info.nightscout.androidaps.queue.commands.CustomCommand
import info.nightscout.shared.logging.LTag
import javax.inject.Inject
class CommandCustomCommand(

View file

@ -1,10 +1,11 @@
package info.nightscout.androidaps.queue.commands
package info.nightscout.implementation.queue.commands
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.queue.commands.Command
import info.nightscout.implementation.R
import info.nightscout.shared.logging.LTag
import javax.inject.Inject
class CommandExtendedBolus constructor(

View file

@ -1,10 +1,11 @@
package info.nightscout.androidaps.queue.commands
package info.nightscout.implementation.queue.commands
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin
import info.nightscout.androidaps.interfaces.Insight
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.queue.commands.Command
import info.nightscout.implementation.R
import javax.inject.Inject
class CommandInsightSetTBROverNotification constructor(
@ -17,14 +18,14 @@ class CommandInsightSetTBROverNotification constructor(
override fun execute() {
val pump = activePlugin.activePump
if (pump is LocalInsightPlugin) {
if (pump is Insight) {
val result = pump.setTBROverNotification(enabled)
callback?.result(result)?.run()
}
}
@Suppress("SpellCheckingInspection")
override fun status(): String = rh.gs(R.string.insight_set_tbr_over_notification)
@Suppress("SpellCheckingInspection")
override fun log(): String = "INSIGHTSETTBROVERNOTIFICATION"
}

View file

@ -1,12 +1,13 @@
package info.nightscout.androidaps.queue.commands
package info.nightscout.implementation.queue.commands
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.Dana
import info.nightscout.androidaps.interfaces.Diaconn
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.queue.commands.Command
import info.nightscout.implementation.R
import info.nightscout.shared.logging.LTag
import javax.inject.Inject
class CommandLoadEvents(

View file

@ -1,12 +1,13 @@
package info.nightscout.androidaps.queue.commands
package info.nightscout.implementation.queue.commands
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.Dana
import info.nightscout.androidaps.interfaces.Diaconn
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.queue.commands.Command
import info.nightscout.implementation.R
import info.nightscout.shared.logging.LTag
import javax.inject.Inject
class CommandLoadHistory(

View file

@ -1,10 +1,11 @@
package info.nightscout.androidaps.queue.commands
package info.nightscout.implementation.queue.commands
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.queue.commands.Command
import info.nightscout.implementation.R
import info.nightscout.shared.logging.LTag
import javax.inject.Inject
class CommandLoadTDDs(

View file

@ -1,13 +1,14 @@
package info.nightscout.androidaps.queue.commands
package info.nightscout.implementation.queue.commands
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.interfaces.LocalAlertUtils
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.LocalAlertUtils
import info.nightscout.androidaps.queue.commands.Command
import info.nightscout.androidaps.utils.T
import info.nightscout.implementation.R
import info.nightscout.shared.logging.LTag
import javax.inject.Inject
class CommandReadStatus(

View file

@ -1,14 +1,15 @@
package info.nightscout.androidaps.queue.commands
package info.nightscout.implementation.queue.commands
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.queue.commands.Command
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.T
import info.nightscout.implementation.R
import info.nightscout.shared.logging.LTag
import javax.inject.Inject
class CommandSMBBolus(

View file

@ -1,17 +1,19 @@
package info.nightscout.androidaps.queue.commands
package info.nightscout.implementation.queue.commands
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.CommandQueue
import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.interfaces.PluginBase
import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin
import info.nightscout.androidaps.interfaces.SmsCommunicator
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.queue.commands.Command
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.implementation.R
import info.nightscout.shared.logging.LTag
import javax.inject.Inject
class CommandSetProfile constructor(
@ -21,7 +23,7 @@ class CommandSetProfile constructor(
callback: Callback?
) : Command(injector, CommandType.BASAL_PROFILE, callback) {
@Inject lateinit var smsCommunicatorPlugin: SmsCommunicatorPlugin
@Inject lateinit var smsCommunicatorPlugin: SmsCommunicator
@Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var dateUtil: DateUtil
@Inject lateinit var commandQueue: CommandQueue
@ -39,7 +41,7 @@ class CommandSetProfile constructor(
// Send SMS notification if ProfileSwitch is coming from NS
val profileSwitch = repository.getEffectiveProfileSwitchActiveAt(dateUtil.now()).blockingGet()
if (profileSwitch is ValueWrapper.Existing && r.enacted && hasNsId && !config.NSCLIENT) {
if (smsCommunicatorPlugin.isEnabled())
if ((smsCommunicatorPlugin as PluginBase).isEnabled())
smsCommunicatorPlugin.sendNotificationToAllNumbers(rh.gs(R.string.profile_set_ok))
}
}

View file

@ -1,12 +1,13 @@
package info.nightscout.androidaps.queue.commands
package info.nightscout.implementation.queue.commands
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.Dana
import info.nightscout.androidaps.interfaces.Diaconn
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.queue.commands.Command
import info.nightscout.implementation.R
import info.nightscout.shared.logging.LTag
import javax.inject.Inject
class CommandSetUserSettings(

View file

@ -1,10 +1,11 @@
package info.nightscout.androidaps.queue.commands
package info.nightscout.implementation.queue.commands
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin
import info.nightscout.androidaps.interfaces.Insight
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.queue.commands.Command
import info.nightscout.implementation.R
import javax.inject.Inject
class CommandStartPump(
@ -16,7 +17,7 @@ class CommandStartPump(
override fun execute() {
val pump = activePlugin.activePump
if (pump is LocalInsightPlugin) {
if (pump is Insight) {
val result = pump.startPump()
callback?.result(result)?.run()
}

View file

@ -1,10 +1,11 @@
package info.nightscout.androidaps.queue.commands
package info.nightscout.implementation.queue.commands
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin
import info.nightscout.androidaps.interfaces.Insight
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.queue.commands.Command
import info.nightscout.implementation.R
import javax.inject.Inject
class CommandStopPump(
@ -16,7 +17,7 @@ class CommandStopPump(
override fun execute() {
val pump = activePlugin.activePump
if (pump is LocalInsightPlugin) {
if (pump is Insight) {
val result = pump.stopPump()
callback?.result(result)?.run()
}

View file

@ -1,12 +1,13 @@
package info.nightscout.androidaps.queue.commands
package info.nightscout.implementation.queue.commands
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.interfaces.PumpSync
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.queue.commands.Command
import info.nightscout.implementation.R
import info.nightscout.shared.logging.LTag
import javax.inject.Inject
class CommandTempBasalAbsolute(

View file

@ -1,12 +1,13 @@
package info.nightscout.androidaps.queue.commands
package info.nightscout.implementation.queue.commands
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.interfaces.PumpSync
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.queue.commands.Command
import info.nightscout.implementation.R
import info.nightscout.shared.logging.LTag
import javax.inject.Inject
class CommandTempBasalPercent(

View file

@ -4,6 +4,7 @@
<string name="calibration_sent">Calibration sent to xDrip+</string>
<string name="bg_label">BG</string>
<string name="missed_bg_readings">Missed BG readings</string>
<string name="time_to_eat">Time to eat</string>
<string name="enable_bolus_advisor">Enable bolus advisor</string>
@ -11,5 +12,15 @@
<string name="bolus_advisor">Bolus advisor</string>
<string name="bolus_advisor_message">You have high glycemia. Instead of eating now it\'s recommended to wait for better glycemia. Do you want to do a correction bolus now and remind you when it\'s time to eat? In this case no carbs will be recorded and you must use wizard again when we remind you.</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="request">Request</string>
<string name="permission">Permission</string>
<string name="need_whitelisting">%1$s needs battery optimization whitelisting for proper performance</string>
<string name="need_system_window_permission">Application needs system window permission for notifications</string>
<string name="need_location_permission">Application needs location permission for BT scan and WiFi identification</string>
<string name="need_storage_permission">Application needs storage permission to be able store log files and export settings</string>
<string name="error_asking_for_permissions">Error asking for permissions</string>
<string name="alert_dialog_permission_battery_optimization_failed">This device does not appear to support battery optimization whitelisting - you may experience performance issues.</string>
</resources>

View file

@ -0,0 +1,177 @@
package info.nightscout.androidaps
import android.content.Context
import dagger.android.AndroidInjector
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.data.ProfileSealed
import info.nightscout.androidaps.database.embedments.InsulinConfiguration
import info.nightscout.androidaps.database.entities.EffectiveProfileSwitch
import info.nightscout.androidaps.extensions.pureProfileFromJson
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.interfaces.IobCobCalculator
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.interfaces.ProfileStore
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.interfaces.ResourceHelper
import org.json.JSONObject
import org.junit.Before
import org.mockito.ArgumentMatchers.anyDouble
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.anyString
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.`when`
import org.mockito.invocation.InvocationOnMock
@Suppress("SpellCheckingInspection")
open class TestBaseWithProfile : TestBase() {
@Mock lateinit var activePluginProvider: ActivePlugin
@Mock lateinit var rh: ResourceHelper
@Mock lateinit var iobCobCalculator: IobCobCalculator
@Mock lateinit var fabricPrivacy: FabricPrivacy
@Mock lateinit var profileFunction: ProfileFunction
@Mock lateinit var config: Config
@Mock lateinit var context: Context
lateinit var dateUtil: DateUtil
val rxBus = RxBus(aapsSchedulers, aapsLogger)
val profileInjector = HasAndroidInjector { AndroidInjector { } }
private lateinit var validProfileJSON: String
lateinit var validProfile: ProfileSealed.Pure
lateinit var effectiveProfileSwitch: EffectiveProfileSwitch
@Suppress("PropertyName") val TESTPROFILENAME = "someProfile"
@Before
fun prepareMock() {
validProfileJSON = "{\"dia\":\"5\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"3\"}," +
"{\"time\":\"2:00\",\"value\":\"3.4\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4.5\"}]," +
"\"target_high\":[{\"time\":\"00:00\",\"value\":\"7\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}"
dateUtil = Mockito.spy(DateUtil(context))
`when`(dateUtil.now()).thenReturn(1656358822000)
validProfile = ProfileSealed.Pure(pureProfileFromJson(JSONObject(validProfileJSON), dateUtil)!!)
effectiveProfileSwitch = EffectiveProfileSwitch(
timestamp = dateUtil.now(),
basalBlocks = validProfile.basalBlocks,
isfBlocks = validProfile.isfBlocks,
icBlocks = validProfile.icBlocks,
targetBlocks = validProfile.targetBlocks,
glucoseUnit = EffectiveProfileSwitch.GlucoseUnit.MMOL,
originalProfileName = "",
originalCustomizedName = "",
originalTimeshift = 0,
originalPercentage = 100,
originalDuration = 0,
originalEnd = 0,
insulinConfiguration = InsulinConfiguration("", 0, 0)
)
Mockito.doAnswer { invocation: InvocationOnMock ->
val string = invocation.getArgument<Int>(0)
val arg1 = invocation.getArgument<Int?>(1)
String.format(rh.gs(string), arg1)
}.`when`(rh).gs(anyInt(), anyInt())
Mockito.doAnswer { invocation: InvocationOnMock ->
val string = invocation.getArgument<Int>(0)
val arg1 = invocation.getArgument<Double?>(1)
String.format(rh.gs(string), arg1)
}.`when`(rh).gs(anyInt(), anyDouble())
Mockito.doAnswer { invocation: InvocationOnMock ->
val string = invocation.getArgument<Int>(0)
val arg1 = invocation.getArgument<String?>(1)
String.format(rh.gs(string), arg1)
}.`when`(rh).gs(anyInt(), anyString())
Mockito.doAnswer { invocation: InvocationOnMock ->
val string = invocation.getArgument<Int>(0)
val arg1 = invocation.getArgument<String?>(1)
val arg2 = invocation.getArgument<String?>(2)
String.format(rh.gs(string), arg1, arg2)
}.`when`(rh).gs(anyInt(), anyString(), anyString())
Mockito.doAnswer { invocation: InvocationOnMock ->
val string = invocation.getArgument<Int>(0)
val arg1 = invocation.getArgument<String?>(1)
val arg2 = invocation.getArgument<Int?>(2)
String.format(rh.gs(string), arg1, arg2)
}.`when`(rh).gs(anyInt(), anyString(), anyInt())
Mockito.doAnswer { invocation: InvocationOnMock ->
val string = invocation.getArgument<Int>(0)
val arg1 = invocation.getArgument<Double?>(1)
val arg2 = invocation.getArgument<String?>(2)
String.format(rh.gs(string), arg1, arg2)
}.`when`(rh).gs(anyInt(), anyDouble(), anyString())
Mockito.doAnswer { invocation: InvocationOnMock ->
val string = invocation.getArgument<Int>(0)
val arg1 = invocation.getArgument<Double?>(1)
val arg2 = invocation.getArgument<Int?>(2)
String.format(rh.gs(string), arg1, arg2)
}.`when`(rh).gs(anyInt(), anyDouble(), anyInt())
Mockito.doAnswer { invocation: InvocationOnMock ->
val string = invocation.getArgument<Int>(0)
val arg1 = invocation.getArgument<Int?>(1)
val arg2 = invocation.getArgument<Int?>(2)
String.format(rh.gs(string), arg1, arg2)
}.`when`(rh).gs(anyInt(), anyInt(), anyInt())
Mockito.doAnswer { invocation: InvocationOnMock ->
val string = invocation.getArgument<Int>(0)
val arg1 = invocation.getArgument<Int?>(1)
val arg2 = invocation.getArgument<String?>(2)
String.format(rh.gs(string), arg1, arg2)
}.`when`(rh).gs(anyInt(), anyInt(), anyString())
Mockito.doAnswer { invocation: InvocationOnMock ->
val string = invocation.getArgument<Int>(0)
val arg1 = invocation.getArgument<Int?>(1)
val arg2 = invocation.getArgument<Int?>(2)
val arg3 = invocation.getArgument<String?>(3)
String.format(rh.gs(string), arg1, arg2, arg3)
}.`when`(rh).gs(anyInt(), anyInt(), anyInt(), anyString())
Mockito.doAnswer { invocation: InvocationOnMock ->
val string = invocation.getArgument<Int>(0)
val arg1 = invocation.getArgument<Int?>(1)
val arg2 = invocation.getArgument<String?>(2)
val arg3 = invocation.getArgument<String?>(3)
String.format(rh.gs(string), arg1, arg2, arg3)
}.`when`(rh).gs(anyInt(), anyInt(), anyString(), anyString())
Mockito.doAnswer { invocation: InvocationOnMock ->
val string = invocation.getArgument<Int>(0)
val arg1 = invocation.getArgument<Double?>(1)
val arg2 = invocation.getArgument<Int?>(2)
val arg3 = invocation.getArgument<String?>(3)
String.format(rh.gs(string), arg1, arg2, arg3)
}.`when`(rh).gs(anyInt(), anyDouble(), anyInt(), anyString())
Mockito.doAnswer { invocation: InvocationOnMock ->
val string = invocation.getArgument<Int>(0)
val arg1 = invocation.getArgument<String?>(1)
val arg2 = invocation.getArgument<Int?>(2)
val arg3 = invocation.getArgument<String?>(3)
String.format(rh.gs(string), arg1, arg2, arg3)
}.`when`(rh).gs(anyInt(), anyString(), anyInt(), anyString())
}
fun getValidProfileStore(): ProfileStore {
val json = JSONObject()
val store = JSONObject()
store.put(TESTPROFILENAME, JSONObject(validProfileJSON))
json.put("defaultProfile", TESTPROFILENAME)
json.put("store", store)
return ProfileStore(profileInjector, json, dateUtil)
}
}

View file

@ -0,0 +1,68 @@
package info.nightscout.androidaps
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.interfaces.PumpDescription
import info.nightscout.androidaps.interfaces.Pump
import info.nightscout.androidaps.interfaces.PumpSync
import info.nightscout.androidaps.plugins.common.ManufacturerType
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
import info.nightscout.androidaps.utils.TimeChangeType
import org.json.JSONObject
@Suppress("MemberVisibilityCanBePrivate")
class TestPumpPlugin(val injector: HasAndroidInjector) : Pump {
var connected = false
var isProfileSet = true
override fun isConnected() = connected
override fun isConnecting() = false
override fun isHandshakeInProgress() = false
val lastData = 0L
val baseBasal = 0.0
override val pumpDescription = PumpDescription()
override fun isInitialized(): Boolean = true
override fun isSuspended(): Boolean = false
override fun isBusy(): Boolean = false
override fun connect(reason: String) {
connected = true
}
override fun disconnect(reason: String) {
connected = false
}
override fun stopConnecting() {
connected = false
}
override fun waitForDisconnectionInSeconds(): Int = 0
override fun getPumpStatus(reason: String) {}
override fun setNewBasalProfile(profile: Profile): PumpEnactResult = PumpEnactResult(injector)
override fun isThisProfileSet(profile: Profile): Boolean = isProfileSet
override fun lastDataTime(): Long = lastData
override val baseBasalRate: Double = baseBasal
override val reservoirLevel: Double = 0.0
override val batteryLevel: Int = 0
override fun deliverTreatment(detailedBolusInfo: DetailedBolusInfo): PumpEnactResult = PumpEnactResult(injector).success(true)
override fun stopBolusDelivering() {}
override fun setTempBasalAbsolute(absoluteRate: Double, durationInMinutes: Int, profile: Profile, enforceNew: Boolean, tbrType: PumpSync.TemporaryBasalType): PumpEnactResult = PumpEnactResult(injector).success(true)
override fun setTempBasalPercent(percent: Int, durationInMinutes: Int, profile: Profile, enforceNew: Boolean, tbrType: PumpSync.TemporaryBasalType): PumpEnactResult = PumpEnactResult(injector).success(true)
override fun setExtendedBolus(insulin: Double, durationInMinutes: Int): PumpEnactResult = PumpEnactResult(injector).success(true)
override fun cancelTempBasal(enforceNew: Boolean): PumpEnactResult = PumpEnactResult(injector).success(true)
override fun cancelExtendedBolus(): PumpEnactResult = PumpEnactResult(injector).success(true)
override fun getJSONStatus(profile: Profile, profileName: String, version: String): JSONObject = JSONObject()
override fun manufacturer(): ManufacturerType = ManufacturerType.AAPS
override fun model(): PumpType = PumpType.GENERIC_AAPS
override fun serialNumber(): String = "1"
override fun shortStatus(veryShort: Boolean): String = ""
override val isFakingTempsByExtendedBoluses: Boolean = false
override fun loadTDDs(): PumpEnactResult = PumpEnactResult(injector).success(true)
override fun canHandleDST(): Boolean = true
override fun timezoneOrDSTChanged(timeChangeType: TimeChangeType) {}
}

View file

@ -1,10 +1,10 @@
package info.nightscout.androidaps.queue
package info.nightscout.implementation.queue
import android.content.Context
import android.os.PowerManager
import dagger.android.AndroidInjector
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.implementation.R
import info.nightscout.androidaps.TestBaseWithProfile
import info.nightscout.androidaps.TestPumpPlugin
import info.nightscout.androidaps.data.DetailedBolusInfo
@ -13,30 +13,35 @@ import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.database.entities.Bolus
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.AndroidPermission
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.interfaces.PumpSync
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.general.maintenance.PrefFileListProvider
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.queue.commands.*
import info.nightscout.androidaps.utils.AndroidPermission
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.androidaps.utils.buildHelper.BuildHelperImpl
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.implementation.queue.commands.CommandBolus
import info.nightscout.implementation.queue.commands.CommandCustomCommand
import info.nightscout.implementation.queue.commands.CommandExtendedBolus
import info.nightscout.implementation.queue.commands.CommandLoadHistory
import info.nightscout.implementation.queue.commands.CommandTempBasalPercent
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.rxjava3.core.Single
import org.junit.Assert
import org.junit.Before
import org.junit.Test
import org.mockito.Mock
import org.mockito.Mockito.`when`
import org.mockito.Mockito.anyLong
import org.mockito.Mockito.`when`
import java.util.*
class CommandQueueImplementationTest : TestBaseWithProfile() {
@ -47,6 +52,7 @@ class CommandQueueImplementationTest : TestBaseWithProfile() {
@Mock lateinit var powerManager: PowerManager
@Mock lateinit var repository: AppRepository
@Mock lateinit var fileListProvider: PrefFileListProvider
@Mock lateinit var buildHelper: BuildHelper
@Mock lateinit var androidPermission: AndroidPermission
class CommandQueueMocked(
@ -66,8 +72,10 @@ class CommandQueueImplementationTest : TestBaseWithProfile() {
fabricPrivacy: FabricPrivacy,
config: Config,
androidPermission: AndroidPermission
) : CommandQueueImplementation(injector, aapsLogger, rxBus, aapsSchedulers, rh, constraintChecker, profileFunction,
activePlugin, context, sp, buildHelper, dateUtil, repository, fabricPrivacy, config, androidPermission) {
) : CommandQueueImplementation(
injector, aapsLogger, rxBus, aapsSchedulers, rh, constraintChecker, profileFunction,
activePlugin, context, sp, buildHelper, dateUtil, repository, fabricPrivacy, config, androidPermission
) {
override fun notifyAboutNewCommand() {}
@ -95,7 +103,7 @@ class CommandQueueImplementationTest : TestBaseWithProfile() {
if (it is CommandLoadHistory) {
it.activePlugin = activePlugin
}
if (it is PumpEnactResult) {
if (it is PumpEnactResult) {
it.rh = rh
}
}
@ -106,11 +114,13 @@ class CommandQueueImplementationTest : TestBaseWithProfile() {
@Before
fun prepare() {
commandQueue = CommandQueueMocked(injector, aapsLogger, rxBus, aapsSchedulers, rh,
constraintChecker, profileFunction, activePlugin, context, sp,
BuildHelperImpl(config, fileListProvider), dateUtil,
repository,
fabricPrivacy, config, androidPermission)
commandQueue = CommandQueueMocked(
injector, aapsLogger, rxBus, aapsSchedulers, rh,
constraintChecker, profileFunction, activePlugin, context, sp,
buildHelper, dateUtil,
repository,
fabricPrivacy, config, androidPermission
)
testPumpPlugin = TestPumpPlugin(injector)
testPumpPlugin.pumpDescription.basalMinimumRate = 0.1
@ -136,18 +146,20 @@ class CommandQueueImplementationTest : TestBaseWithProfile() {
`when`(constraintChecker.applyBasalConstraints(anyObject(), anyObject())).thenReturn(rateConstraint)
val percentageConstraint = Constraint(0)
`when`(constraintChecker.applyBasalPercentConstraints(anyObject(), anyObject())).thenReturn(percentageConstraint)
`when`(rh.gs(R.string.connectiontimedout)).thenReturn("Connection timed out")
val thenReturn = `when`(rh.gs(R.string.connectiontimedout)).thenReturn("Connection timed out")
`when`(rh.gs(R.string.formatinsulinunits)).thenReturn("%1\$.2f U")
`when`(rh.gs(R.string.bolusrequested)).thenReturn("Going to deliver %1\$.2f U")
`when`(rh.gs(R.string.goingtodeliver)).thenReturn("Going to deliver %1\$.2f U")
}
@Test
fun commandIsPickedUp() {
val commandQueue = CommandQueueImplementation(injector, aapsLogger, rxBus, aapsSchedulers, rh,
constraintChecker, profileFunction, activePlugin, context, sp,
BuildHelperImpl(config, fileListProvider),
dateUtil, repository,
fabricPrivacy, config, androidPermission)
val commandQueue = CommandQueueImplementation(
injector, aapsLogger, rxBus, aapsSchedulers, rh,
constraintChecker, profileFunction, activePlugin, context, sp,
buildHelper,
dateUtil, repository,
fabricPrivacy, config, androidPermission
)
// start with empty queue
Assert.assertEquals(0, commandQueue.size())

View file

@ -1,23 +1,22 @@
package info.nightscout.androidaps.queue
package info.nightscout.implementation.queue
import android.content.Context
import android.os.PowerManager
import dagger.android.AndroidInjector
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.TestBaseWithProfile
import info.nightscout.androidaps.TestPumpPlugin
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.AndroidPermission
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.interfaces.PumpDescription
import info.nightscout.androidaps.interfaces.PumpSync
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.general.maintenance.PrefFileListProvider
import info.nightscout.androidaps.queue.commands.Command
import info.nightscout.androidaps.queue.commands.CommandTempBasalAbsolute
import info.nightscout.androidaps.utils.AndroidPermission
import info.nightscout.androidaps.utils.buildHelper.BuildHelperImpl
import info.nightscout.implementation.R
import info.nightscout.implementation.queue.commands.CommandTempBasalAbsolute
import info.nightscout.shared.sharedPreferences.SP
import org.junit.Assert
import org.junit.Before
@ -31,9 +30,9 @@ class QueueThreadTest : TestBaseWithProfile() {
@Mock lateinit var constraintChecker: ConstraintChecker
@Mock lateinit var activePlugin: ActivePlugin
@Mock lateinit var sp: SP
@Mock lateinit var fileListProvider: PrefFileListProvider
@Mock lateinit var powerManager: PowerManager
@Mock lateinit var repository: AppRepository
@Mock lateinit var buildHelper: BuildHelper
@Mock lateinit var androidPermission: AndroidPermission
val injector = HasAndroidInjector {
@ -59,7 +58,7 @@ class QueueThreadTest : TestBaseWithProfile() {
commandQueue = CommandQueueImplementation(
injector, aapsLogger, rxBus, aapsSchedulers, rh, constraintChecker,
profileFunction, activePlugin, context, sp,
BuildHelperImpl(config, fileListProvider), dateUtil, repository, fabricPrivacy, config, androidPermission
buildHelper, dateUtil, repository, fabricPrivacy, config, androidPermission
)
val pumpDescription = PumpDescription()

View file

@ -31,6 +31,7 @@ import javax.inject.Singleton;
import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.interfaces.Insight;
import info.nightscout.androidaps.interfaces.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.events.EventInitializationChanged;
@ -134,7 +135,8 @@ import info.nightscout.androidaps.interfaces.ResourceHelper;
import info.nightscout.shared.sharedPreferences.SP;
@Singleton
public class LocalInsightPlugin extends PumpPluginBase implements Pump, Constraints, InsightConnectionService.StateCallback {
public class LocalInsightPlugin extends PumpPluginBase implements Pump, Insight, Constraints,
InsightConnectionService.StateCallback {
private final AAPSLogger aapsLogger;
private final RxBus rxBus;