KeepAlive -> WorkManager

This commit is contained in:
Milos Kozak 2022-03-30 20:13:38 +02:00
parent 1c3ba6b380
commit 784cd37528
5 changed files with 188 additions and 213 deletions

View file

@ -126,9 +126,6 @@
</intent-filter> </intent-filter>
</receiver> </receiver>
<!-- Receiver keep alive, scheduled every 30 min -->
<receiver android:name=".receivers.KeepAliveReceiver" />
<!-- Receive ignore 5m, 15m, 30m requests for carb notifications --> <!-- Receive ignore 5m, 15m, 30m requests for carb notifications -->
<receiver android:name=".plugins.aps.loop.CarbSuggestionReceiver" /> <receiver android:name=".plugins.aps.loop.CarbSuggestionReceiver" />

View file

@ -7,6 +7,10 @@ import android.net.ConnectivityManager
import android.net.wifi.WifiManager import android.net.wifi.WifiManager
import android.os.Build import android.os.Build
import androidx.lifecycle.ProcessLifecycleOwner import androidx.lifecycle.ProcessLifecycleOwner
import androidx.work.Data
import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.PeriodicWorkRequest
import androidx.work.WorkManager
import com.uber.rxdogtag.RxDogTag import com.uber.rxdogtag.RxDogTag
import dagger.android.AndroidInjector import dagger.android.AndroidInjector
import dagger.android.DaggerApplication import dagger.android.DaggerApplication
@ -27,14 +31,11 @@ import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionChec
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationStore import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationStore
import info.nightscout.androidaps.plugins.general.themes.ThemeSwitcherPlugin import info.nightscout.androidaps.plugins.general.themes.ThemeSwitcherPlugin
import info.nightscout.androidaps.receivers.BTReceiver import info.nightscout.androidaps.receivers.*
import info.nightscout.androidaps.receivers.ChargingStateReceiver
import info.nightscout.androidaps.receivers.KeepAliveReceiver.KeepAliveManager
import info.nightscout.androidaps.receivers.NetworkChangeReceiver
import info.nightscout.androidaps.receivers.TimeDateOrTZChangeReceiver
import info.nightscout.androidaps.services.AlarmSoundServiceHelper import info.nightscout.androidaps.services.AlarmSoundServiceHelper
import info.nightscout.androidaps.utils.ActivityMonitor import info.nightscout.androidaps.utils.ActivityMonitor
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.LocalAlertUtils
import info.nightscout.androidaps.utils.ProcessLifecycleListener import info.nightscout.androidaps.utils.ProcessLifecycleListener
import info.nightscout.androidaps.utils.buildHelper.BuildHelper import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.locale.LocaleHelper import info.nightscout.androidaps.utils.locale.LocaleHelper
@ -48,6 +49,7 @@ import io.reactivex.rxjava3.plugins.RxJavaPlugins
import net.danlew.android.joda.JodaTimeAndroid import net.danlew.android.joda.JodaTimeAndroid
import java.io.IOException import java.io.IOException
import java.net.SocketException import java.net.SocketException
import java.util.concurrent.TimeUnit
import javax.inject.Inject import javax.inject.Inject
class MainApp : DaggerApplication() { class MainApp : DaggerApplication() {
@ -62,7 +64,6 @@ class MainApp : DaggerApplication() {
@Inject lateinit var config: Config @Inject lateinit var config: Config
@Inject lateinit var buildHelper: BuildHelper @Inject lateinit var buildHelper: BuildHelper
@Inject lateinit var configBuilder: ConfigBuilder @Inject lateinit var configBuilder: ConfigBuilder
@Inject lateinit var keepAliveManager: KeepAliveManager
@Inject lateinit var plugins: List<@JvmSuppressWildcards PluginBase> @Inject lateinit var plugins: List<@JvmSuppressWildcards PluginBase>
@Inject lateinit var compatDBHelper: CompatDBHelper @Inject lateinit var compatDBHelper: CompatDBHelper
@Inject lateinit var repository: AppRepository @Inject lateinit var repository: AppRepository
@ -73,6 +74,7 @@ class MainApp : DaggerApplication() {
@Inject lateinit var notificationStore: NotificationStore @Inject lateinit var notificationStore: NotificationStore
@Inject lateinit var processLifecycleListener: ProcessLifecycleListener @Inject lateinit var processLifecycleListener: ProcessLifecycleListener
@Inject lateinit var profileSwitchPlugin: ThemeSwitcherPlugin @Inject lateinit var profileSwitchPlugin: ThemeSwitcherPlugin
@Inject lateinit var localAlertUtils: LocalAlertUtils
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
@ -118,7 +120,17 @@ class MainApp : DaggerApplication() {
// Register all tabs in app here // Register all tabs in app here
pluginStore.plugins = plugins pluginStore.plugins = plugins
configBuilder.initialize() configBuilder.initialize()
keepAliveManager.setAlarm(this)
WorkManager.getInstance(this).enqueueUniquePeriodicWork(
"KeepAlive",
ExistingPeriodicWorkPolicy.REPLACE,
PeriodicWorkRequest.Builder(KeepAliveWorker::class.java, 15, TimeUnit.MINUTES)
.setInputData(Data.Builder().putString("schedule", "KeepAlive").build())
.setInitialDelay(5, TimeUnit.SECONDS)
.build()
)
localAlertUtils.shortenSnoozeInterval()
localAlertUtils.preSnoozeAlarms()
doMigrations() doMigrations()
uel.log(UserEntry.Action.START_AAPS, UserEntry.Sources.Aaps) uel.log(UserEntry.Action.START_AAPS, UserEntry.Sources.Aaps)
} }
@ -190,7 +202,6 @@ class MainApp : DaggerApplication() {
override fun onTerminate() { override fun onTerminate() {
aapsLogger.debug(LTag.CORE, "onTerminate") aapsLogger.debug(LTag.CORE, "onTerminate")
unregisterActivityLifecycleCallbacks(activityMonitor) unregisterActivityLifecycleCallbacks(activityMonitor)
keepAliveManager.cancelAlarm(this)
alarmSoundServiceHelper.stopService(this) alarmSoundServiceHelper.stopService(this)
super.onTerminate() super.onTerminate()
} }

View file

@ -2,12 +2,11 @@ package info.nightscout.androidaps.di
import dagger.Module import dagger.Module
import dagger.android.ContributesAndroidInjector import dagger.android.ContributesAndroidInjector
import info.nightscout.androidaps.plugins.aps.loop.CarbSuggestionReceiver
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkBluetoothStateReceiver import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkBluetoothStateReceiver
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkBroadcastReceiver import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkBroadcastReceiver
import info.nightscout.androidaps.plugins.aps.loop.CarbSuggestionReceiver
import info.nightscout.androidaps.receivers.* import info.nightscout.androidaps.receivers.*
@Module @Module
@Suppress("unused") @Suppress("unused")
abstract class ReceiversModule { abstract class ReceiversModule {
@ -16,8 +15,7 @@ abstract class ReceiversModule {
@ContributesAndroidInjector abstract fun contributesBTReceiver(): BTReceiver @ContributesAndroidInjector abstract fun contributesBTReceiver(): BTReceiver
@ContributesAndroidInjector abstract fun contributesChargingStateReceiver(): ChargingStateReceiver @ContributesAndroidInjector abstract fun contributesChargingStateReceiver(): ChargingStateReceiver
@ContributesAndroidInjector abstract fun contributesDataReceiver(): DataReceiver @ContributesAndroidInjector abstract fun contributesDataReceiver(): DataReceiver
@ContributesAndroidInjector abstract fun contributesKeepAliveReceiver(): KeepAliveReceiver @ContributesAndroidInjector abstract fun contributesKeepAliveWorker(): KeepAliveWorker
@ContributesAndroidInjector abstract fun contributesKeepAliveWorker(): KeepAliveReceiver.KeepAliveWorker
@ContributesAndroidInjector abstract fun contributesRileyLinkBluetoothStateReceiver(): RileyLinkBluetoothStateReceiver @ContributesAndroidInjector abstract fun contributesRileyLinkBluetoothStateReceiver(): RileyLinkBluetoothStateReceiver
@ContributesAndroidInjector abstract fun contributesSmsReceiver(): SmsReceiver @ContributesAndroidInjector abstract fun contributesSmsReceiver(): SmsReceiver
@ContributesAndroidInjector abstract fun contributesTimeDateOrTZChangeReceiver(): TimeDateOrTZChangeReceiver @ContributesAndroidInjector abstract fun contributesTimeDateOrTZChangeReceiver(): TimeDateOrTZChangeReceiver

View file

@ -1,198 +0,0 @@
package info.nightscout.androidaps.receivers
import android.app.AlarmManager
import android.app.PendingIntent
import android.app.PendingIntent.CanceledException
import android.app.PendingIntent.FLAG_IMMUTABLE
import android.content.Context
import android.content.Intent
import android.os.SystemClock
import androidx.work.*
import com.google.common.util.concurrent.ListenableFuture
import dagger.android.DaggerBroadcastReceiver
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.BuildConfig
import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.ProfileSealed
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.events.EventProfileSwitchChanged
import info.nightscout.androidaps.extensions.buildDeviceStatus
import info.nightscout.androidaps.interfaces.*
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.configBuilder.RunningConfiguration
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.utils.resources.ResourceHelper
import javax.inject.Inject
import kotlin.math.abs
class KeepAliveReceiver : DaggerBroadcastReceiver() {
@Inject lateinit var aapsLogger: AAPSLogger
companion object {
private val KEEP_ALIVE_MILLISECONDS = T.mins(5).msecs()
}
override fun onReceive(context: Context, intent: Intent) {
super.onReceive(context, intent)
aapsLogger.debug(LTag.CORE, "KeepAlive received")
WorkManager.getInstance(context)
.enqueue(OneTimeWorkRequest.Builder(KeepAliveWorker::class.java).build())
}
class KeepAliveWorker(
private val context: Context,
params: WorkerParameters
) : Worker(context, params) {
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var localAlertUtils: LocalAlertUtils
@Inject lateinit var repository: AppRepository
@Inject lateinit var config: Config
@Inject lateinit var iobCobCalculator: IobCobCalculator
@Inject lateinit var loop: Loop
@Inject lateinit var dateUtil: DateUtil
@Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var runningConfiguration: RunningConfiguration
@Inject lateinit var receiverStatusStore: ReceiverStatusStore
@Inject lateinit var rxBus: RxBus
@Inject lateinit var commandQueue: CommandQueue
@Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var maintenancePlugin: MaintenancePlugin
@Inject lateinit var rh: ResourceHelper
init {
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
}
companion object {
private val STATUS_UPDATE_FREQUENCY = T.mins(15).msecs()
private const val IOB_UPDATE_FREQUENCY_IN_MINUTES = 5L
private var lastReadStatus: Long = 0
private var lastRun: Long = 0
private var lastIobUpload: Long = 0
}
override fun doWork(): Result {
localAlertUtils.shortenSnoozeInterval()
localAlertUtils.checkStaleBGAlert()
checkPump()
checkAPS()
maintenancePlugin.deleteLogs(30)
workerDbStatus()
return Result.success()
}
// When Worker DB grows too much, work operations become slow
// Library is cleaning DB every 7 days which may not be sufficient for NSClient full sync
private fun workerDbStatus() {
val workQuery = WorkQuery.Builder
.fromStates(listOf(WorkInfo.State.FAILED, WorkInfo.State.SUCCEEDED))
.build()
val workInfo: ListenableFuture<List<WorkInfo>> = WorkManager.getInstance(context).getWorkInfos(workQuery)
aapsLogger.debug(LTag.CORE, "WorkManager size is ${workInfo.get().size}")
if (workInfo.get().size > 1000) {
WorkManager.getInstance(context).pruneWork()
aapsLogger.debug(LTag.CORE, "WorkManager pruning ....")
}
}
// Usually deviceStatus is uploaded through LoopPlugin after every loop cycle.
// if there is no BG available, we have to upload anyway to have correct
// IOB displayed in NS
private fun checkAPS() {
var shouldUploadStatus = false
if (config.NSCLIENT) return
if (config.PUMPCONTROL) shouldUploadStatus = true
else if (!(loop as PluginBase).isEnabled() || iobCobCalculator.ads.actualBg() == null)
shouldUploadStatus = true
else if (dateUtil.isOlderThan(activePlugin.activeAPS.lastAPSRun, 5)) shouldUploadStatus = true
if (dateUtil.isOlderThan(lastIobUpload, IOB_UPDATE_FREQUENCY_IN_MINUTES) && shouldUploadStatus) {
lastIobUpload = dateUtil.now()
buildDeviceStatus(dateUtil, loop, iobCobCalculator, profileFunction,
activePlugin.activePump, receiverStatusStore, runningConfiguration,
BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION)?.also {
repository.insert(it)
}
}
}
private fun checkPump() {
val pump = activePlugin.activePump
val ps = profileFunction.getRequestedProfile() ?: return
val requestedProfile = ProfileSealed.PS(ps)
val runningProfile = profileFunction.getProfile()
val lastConnection = pump.lastDataTime()
val isStatusOutdated = lastConnection + STATUS_UPDATE_FREQUENCY < System.currentTimeMillis()
val isBasalOutdated = abs(requestedProfile.getBasal() - pump.baseBasalRate) > pump.pumpDescription.basalStep
aapsLogger.debug(LTag.CORE, "Last connection: " + dateUtil.dateAndTimeString(lastConnection))
// sometimes keep alive broadcast stops
// as as workaround test if readStatus was requested before an alarm is generated
if (lastReadStatus != 0L && lastReadStatus > System.currentTimeMillis() - T.mins(5).msecs()) {
localAlertUtils.checkPumpUnreachableAlarm(lastConnection, isStatusOutdated, loop.isDisconnected)
}
if (loop.isDisconnected) {
// do nothing if pump is disconnected
} else if (runningProfile == null || ((!pump.isThisProfileSet(requestedProfile) || !requestedProfile.isEqual(runningProfile)) && !commandQueue.isRunning(Command.CommandType.BASAL_PROFILE))) {
rxBus.send(EventProfileSwitchChanged())
} else if (isStatusOutdated && !pump.isBusy()) {
lastReadStatus = System.currentTimeMillis()
commandQueue.readStatus(rh.gs(R.string.keepalive_status_outdated), null)
} else if (isBasalOutdated && !pump.isBusy()) {
lastReadStatus = System.currentTimeMillis()
commandQueue.readStatus(rh.gs(R.string.keepalive_basal_outdated), null)
}
if (lastRun != 0L && System.currentTimeMillis() - lastRun > T.mins(10).msecs()) {
aapsLogger.error(LTag.CORE, "KeepAlive fail")
fabricPrivacy.logCustom("KeepAliveFail")
}
lastRun = System.currentTimeMillis()
}
}
class KeepAliveManager @Inject constructor(
private val aapsLogger: AAPSLogger,
private val localAlertUtils: LocalAlertUtils
) {
//called by MainApp at first app start
fun setAlarm(context: Context) {
aapsLogger.debug(LTag.CORE, "KeepAlive scheduled")
SystemClock.sleep(5000) // wait for app initialization
localAlertUtils.shortenSnoozeInterval()
localAlertUtils.preSnoozeAlarms()
val am = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
val i = Intent(context, KeepAliveReceiver::class.java)
val pi = PendingIntent.getBroadcast(context, 0, i, FLAG_IMMUTABLE)
try {
pi.send()
} catch (e: CanceledException) {
}
am.cancel(pi)
am.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), KEEP_ALIVE_MILLISECONDS, pi)
}
fun cancelAlarm(context: Context) {
aapsLogger.debug(LTag.CORE, "KeepAlive canceled")
val intent = Intent(context, KeepAliveReceiver::class.java)
val sender = PendingIntent.getBroadcast(context, 0, intent, FLAG_IMMUTABLE)
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmManager.cancel(sender)
}
}
}

View file

@ -0,0 +1,167 @@
package info.nightscout.androidaps.receivers
import android.content.Context
import androidx.work.*
import com.google.common.util.concurrent.ListenableFuture
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.BuildConfig
import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.ProfileSealed
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.events.EventProfileSwitchChanged
import info.nightscout.androidaps.extensions.buildDeviceStatus
import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.configBuilder.RunningConfiguration
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.utils.resources.ResourceHelper
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import kotlin.math.abs
class KeepAliveWorker(
private val context: Context,
params: WorkerParameters
) : Worker(context, params) {
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var localAlertUtils: LocalAlertUtils
@Inject lateinit var repository: AppRepository
@Inject lateinit var config: Config
@Inject lateinit var iobCobCalculator: IobCobCalculator
@Inject lateinit var loop: Loop
@Inject lateinit var dateUtil: DateUtil
@Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var runningConfiguration: RunningConfiguration
@Inject lateinit var receiverStatusStore: ReceiverStatusStore
@Inject lateinit var rxBus: RxBus
@Inject lateinit var commandQueue: CommandQueue
@Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var maintenancePlugin: MaintenancePlugin
@Inject lateinit var rh: ResourceHelper
init {
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
}
companion object {
private val STATUS_UPDATE_FREQUENCY = T.mins(15).msecs()
private const val IOB_UPDATE_FREQUENCY_IN_MINUTES = 5L
private var lastReadStatus: Long = 0
private var lastRun: Long = 0
private var lastIobUpload: Long = 0
}
override fun doWork(): Result {
aapsLogger.debug(LTag.CORE, "KeepAlive received from: " + inputData.getString("schedule"))
// 15 min interval is WorkManager minimum so schedule another instances to have 5 min interval
if (inputData.getString("schedule") == "KeepAlive") {
WorkManager.getInstance(context).enqueueUniqueWork(
"KeepAlive_5",
ExistingWorkPolicy.REPLACE,
OneTimeWorkRequest.Builder(KeepAliveWorker::class.java)
.setInputData(Data.Builder().putString("schedule", "KeepAlive_5").build())
.setInitialDelay(5, TimeUnit.MINUTES)
.build()
)
WorkManager.getInstance(context).enqueueUniqueWork(
"KeepAlive_10",
ExistingWorkPolicy.REPLACE,
OneTimeWorkRequest.Builder(KeepAliveWorker::class.java)
.setInputData(Data.Builder().putString("schedule", "KeepAlive_10").build())
.setInitialDelay(10, TimeUnit.MINUTES)
.build()
)
}
localAlertUtils.shortenSnoozeInterval()
localAlertUtils.checkStaleBGAlert()
checkPump()
checkAPS()
maintenancePlugin.deleteLogs(30)
workerDbStatus()
return Result.success()
}
// When Worker DB grows too much, work operations become slow
// Library is cleaning DB every 7 days which may not be sufficient for NSClient full sync
private fun workerDbStatus() {
val workQuery = WorkQuery.Builder
.fromStates(listOf(WorkInfo.State.FAILED, WorkInfo.State.SUCCEEDED))
.build()
val workInfo: ListenableFuture<List<WorkInfo>> = WorkManager.getInstance(context).getWorkInfos(workQuery)
aapsLogger.debug(LTag.CORE, "WorkManager size is ${workInfo.get().size}")
if (workInfo.get().size > 1000) {
WorkManager.getInstance(context).pruneWork()
aapsLogger.debug(LTag.CORE, "WorkManager pruning ....")
}
}
// Usually deviceStatus is uploaded through LoopPlugin after every loop cycle.
// if there is no BG available, we have to upload anyway to have correct
// IOB displayed in NS
private fun checkAPS() {
var shouldUploadStatus = false
if (config.NSCLIENT) return
if (config.PUMPCONTROL) shouldUploadStatus = true
else if (!(loop as PluginBase).isEnabled() || iobCobCalculator.ads.actualBg() == null)
shouldUploadStatus = true
else if (dateUtil.isOlderThan(activePlugin.activeAPS.lastAPSRun, 5)) shouldUploadStatus = true
if (dateUtil.isOlderThan(lastIobUpload, IOB_UPDATE_FREQUENCY_IN_MINUTES) && shouldUploadStatus) {
lastIobUpload = dateUtil.now()
buildDeviceStatus(
dateUtil, loop, iobCobCalculator, profileFunction,
activePlugin.activePump, receiverStatusStore, runningConfiguration,
BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION
)?.also {
repository.insert(it)
}
}
}
private fun checkPump() {
val pump = activePlugin.activePump
val ps = profileFunction.getRequestedProfile() ?: return
val requestedProfile = ProfileSealed.PS(ps)
val runningProfile = profileFunction.getProfile()
val lastConnection = pump.lastDataTime()
val isStatusOutdated = lastConnection + STATUS_UPDATE_FREQUENCY < System.currentTimeMillis()
val isBasalOutdated = abs(requestedProfile.getBasal() - pump.baseBasalRate) > pump.pumpDescription.basalStep
aapsLogger.debug(LTag.CORE, "Last connection: " + dateUtil.dateAndTimeString(lastConnection))
// sometimes keep alive broadcast stops
// as as workaround test if readStatus was requested before an alarm is generated
if (lastReadStatus != 0L && lastReadStatus > System.currentTimeMillis() - T.mins(5).msecs()) {
localAlertUtils.checkPumpUnreachableAlarm(lastConnection, isStatusOutdated, loop.isDisconnected)
}
if (loop.isDisconnected) {
// do nothing if pump is disconnected
} else if (runningProfile == null || ((!pump.isThisProfileSet(requestedProfile) || !requestedProfile.isEqual(runningProfile)) && !commandQueue.isRunning(Command.CommandType.BASAL_PROFILE))) {
rxBus.send(EventProfileSwitchChanged())
} else if (isStatusOutdated && !pump.isBusy()) {
lastReadStatus = System.currentTimeMillis()
commandQueue.readStatus(rh.gs(R.string.keepalive_status_outdated), null)
} else if (isBasalOutdated && !pump.isBusy()) {
lastReadStatus = System.currentTimeMillis()
commandQueue.readStatus(rh.gs(R.string.keepalive_basal_outdated), null)
}
if (lastRun != 0L && System.currentTimeMillis() - lastRun > T.mins(10).msecs()) {
aapsLogger.error(LTag.CORE, "KeepAlive fail")
fabricPrivacy.logCustom("KeepAliveFail")
}
lastRun = System.currentTimeMillis()
}
}