IobCobThread -> IobCobWorker

This commit is contained in:
Milos Kozak 2022-03-29 18:48:02 +02:00
parent 75cb6d466c
commit 6b01c933a7
7 changed files with 173 additions and 128 deletions

View file

@ -2,6 +2,7 @@ package info.nightscout.androidaps.activities
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.DatePickerDialog import android.app.DatePickerDialog
import android.content.Context
import android.graphics.Color import android.graphics.Color
import android.os.Bundle import android.os.Bundle
import android.util.DisplayMetrics import android.util.DisplayMetrics
@ -33,6 +34,7 @@ import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCa
import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin
import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.DefaultValueHelper import info.nightscout.androidaps.utils.DefaultValueHelper
import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.FabricPrivacy
@ -69,6 +71,8 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
@Inject lateinit var loop: Loop @Inject lateinit var loop: Loop
@Inject lateinit var nsDeviceStatus: NSDeviceStatus @Inject lateinit var nsDeviceStatus: NSDeviceStatus
@Inject lateinit var translator: Translator @Inject lateinit var translator: Translator
@Inject lateinit var context: Context
@Inject lateinit var dataWorker: DataWorker
private val disposable = CompositeDisposable() private val disposable = CompositeDisposable()
@ -106,7 +110,9 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
sensitivityWeightedAveragePlugin, sensitivityWeightedAveragePlugin,
fabricPrivacy, fabricPrivacy,
dateUtil, dateUtil,
repository repository,
context,
dataWorker
) )
overviewData = overviewData =
OverviewData( OverviewData(
@ -336,11 +342,7 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
} }
private fun runCalculation(from: String) { private fun runCalculation(from: String) {
Thread { iobCobCalculator.runCalculation(from, overviewData.toTime, bgDataReload = true, limitDataToOldestAvailable = false, cause = EventCustomCalculationFinished())
iobCobCalculator.stopCalculation(from)
iobCobCalculator.stopCalculationTrigger = false
iobCobCalculator.runCalculation(from, overviewData.toTime, bgDataReload = true, limitDataToOldestAvailable = false, cause = EventCustomCalculationFinished())
}.start()
} }
@Volatile @Volatile

View file

@ -8,8 +8,8 @@ import info.nightscout.androidaps.plugins.aps.openAPSAMA.DetermineBasalResultAMA
import info.nightscout.androidaps.plugins.aps.openAPSSMB.DetermineBasalAdapterSMBJS import info.nightscout.androidaps.plugins.aps.openAPSSMB.DetermineBasalAdapterSMBJS
import info.nightscout.androidaps.plugins.aps.openAPSSMB.DetermineBasalResultSMB import info.nightscout.androidaps.plugins.aps.openAPSSMB.DetermineBasalResultSMB
import info.nightscout.androidaps.plugins.aps.openAPSSMBDynamicISF.DetermineBasalAdapterSMBDynamicISFJS import info.nightscout.androidaps.plugins.aps.openAPSSMBDynamicISF.DetermineBasalAdapterSMBDynamicISFJS
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobOref1Thread import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobOref1Worker
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobThread import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobOrefWorker
@Module @Module
@Suppress("unused") @Suppress("unused")
@ -21,6 +21,6 @@ abstract class APSModule {
@ContributesAndroidInjector abstract fun determineBasalAdapterAMAJSInjector(): DetermineBasalAdapterAMAJS @ContributesAndroidInjector abstract fun determineBasalAdapterAMAJSInjector(): DetermineBasalAdapterAMAJS
@ContributesAndroidInjector abstract fun determineBasalAdapterSMBJSInjector(): DetermineBasalAdapterSMBJS @ContributesAndroidInjector abstract fun determineBasalAdapterSMBJSInjector(): DetermineBasalAdapterSMBJS
@ContributesAndroidInjector abstract fun determineBasalAdapterSMBAutoISFJSInjector(): DetermineBasalAdapterSMBDynamicISFJS @ContributesAndroidInjector abstract fun determineBasalAdapterSMBAutoISFJSInjector(): DetermineBasalAdapterSMBDynamicISFJS
@ContributesAndroidInjector abstract fun iobCobThreadInjector(): IobCobThread @ContributesAndroidInjector abstract fun iobCobWorkerInjector(): IobCobOrefWorker
@ContributesAndroidInjector abstract fun iobCobOref1ThreadInjector(): IobCobOref1Thread @ContributesAndroidInjector abstract fun iobCobOref1WorkerInjector(): IobCobOref1Worker
} }

View file

@ -190,7 +190,7 @@ class NSClientService : DaggerService() {
lastAckTime = dateUtil.now() lastAckTime = dateUtil.now()
dataWorker.enqueue( dataWorker.enqueue(
OneTimeWorkRequest.Builder(NSClientAddAckWorker::class.java) OneTimeWorkRequest.Builder(NSClientAddAckWorker::class.java)
.setInputData(dataWorker.storeInputData(ack, null)) .setInputData(dataWorker.storeInputData(ack))
.build() .build()
) )
} }
@ -199,7 +199,7 @@ class NSClientService : DaggerService() {
lastAckTime = dateUtil.now() lastAckTime = dateUtil.now()
dataWorker.enqueue( dataWorker.enqueue(
OneTimeWorkRequest.Builder(NSClientUpdateRemoveAckWorker::class.java) OneTimeWorkRequest.Builder(NSClientUpdateRemoveAckWorker::class.java)
.setInputData(dataWorker.storeInputData(ack, null)) .setInputData(dataWorker.storeInputData(ack))
.build() .build()
) )
} }
@ -483,7 +483,7 @@ class NSClientService : DaggerService() {
rxBus.send(EventNSClientNewLog("PROFILE", "profile received")) rxBus.send(EventNSClientNewLog("PROFILE", "profile received"))
dataWorker.enqueue( dataWorker.enqueue(
OneTimeWorkRequest.Builder(LocalProfilePlugin.NSProfileWorker::class.java) OneTimeWorkRequest.Builder(LocalProfilePlugin.NSProfileWorker::class.java)
.setInputData(dataWorker.storeInputData(profileStoreJson, null)) .setInputData(dataWorker.storeInputData(profileStoreJson))
.build() .build()
) )
xDripBroadcast.sendProfile(profileStoreJson) xDripBroadcast.sendProfile(profileStoreJson)
@ -502,7 +502,7 @@ class NSClientService : DaggerService() {
if (addedOrUpdatedTreatments.length() > 0) { if (addedOrUpdatedTreatments.length() > 0) {
dataWorker.enqueue( dataWorker.enqueue(
OneTimeWorkRequest.Builder(NSClientAddUpdateWorker::class.java) OneTimeWorkRequest.Builder(NSClientAddUpdateWorker::class.java)
.setInputData(dataWorker.storeInputData(addedOrUpdatedTreatments, null)) .setInputData(dataWorker.storeInputData(addedOrUpdatedTreatments))
.build() .build()
) )
xDripBroadcast.sendTreatments(addedOrUpdatedTreatments) xDripBroadcast.sendTreatments(addedOrUpdatedTreatments)
@ -520,7 +520,7 @@ class NSClientService : DaggerService() {
if (foods.length() > 0) rxBus.send(EventNSClientNewLog("DATA", "received " + foods.length() + " foods")) if (foods.length() > 0) rxBus.send(EventNSClientNewLog("DATA", "received " + foods.length() + " foods"))
dataWorker.enqueue( dataWorker.enqueue(
OneTimeWorkRequest.Builder(FoodWorker::class.java) OneTimeWorkRequest.Builder(FoodWorker::class.java)
.setInputData(dataWorker.storeInputData(foods, null)) .setInputData(dataWorker.storeInputData(foods))
.build() .build()
) )
} }
@ -529,7 +529,7 @@ class NSClientService : DaggerService() {
if (mbgArray.length() > 0) rxBus.send(EventNSClientNewLog("DATA", "received " + mbgArray.length() + " mbgs")) if (mbgArray.length() > 0) rxBus.send(EventNSClientNewLog("DATA", "received " + mbgArray.length() + " mbgs"))
dataWorker.enqueue( dataWorker.enqueue(
OneTimeWorkRequest.Builder(NSClientMbgWorker::class.java) OneTimeWorkRequest.Builder(NSClientMbgWorker::class.java)
.setInputData(dataWorker.storeInputData(mbgArray, null)) .setInputData(dataWorker.storeInputData(mbgArray))
.build() .build()
) )
} }
@ -546,7 +546,7 @@ class NSClientService : DaggerService() {
sp.putBoolean(R.string.key_ObjectivesbgIsAvailableInNS, true) sp.putBoolean(R.string.key_ObjectivesbgIsAvailableInNS, true)
dataWorker.enqueue( dataWorker.enqueue(
OneTimeWorkRequest.Builder(NSClientSourceWorker::class.java) OneTimeWorkRequest.Builder(NSClientSourceWorker::class.java)
.setInputData(dataWorker.storeInputData(sgvs, null)) .setInputData(dataWorker.storeInputData(sgvs))
.build() .build()
) )
xDripBroadcast.sendSgvs(sgvs) xDripBroadcast.sendSgvs(sgvs)

View file

@ -1,7 +1,12 @@
package info.nightscout.androidaps.plugins.iob.iobCobCalculator package info.nightscout.androidaps.plugins.iob.iobCobCalculator
import android.content.Context
import android.os.SystemClock import android.os.SystemClock
import androidx.collection.LongSparseArray import androidx.collection.LongSparseArray
import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequest
import androidx.work.WorkInfo
import androidx.work.WorkManager
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
@ -27,6 +32,7 @@ import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventNewHi
import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin
import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.DecimalFormatter import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.FabricPrivacy
@ -62,7 +68,9 @@ class IobCobCalculatorPlugin @Inject constructor(
private val sensitivityWeightedAveragePlugin: SensitivityWeightedAveragePlugin, private val sensitivityWeightedAveragePlugin: SensitivityWeightedAveragePlugin,
private val fabricPrivacy: FabricPrivacy, private val fabricPrivacy: FabricPrivacy,
private val dateUtil: DateUtil, private val dateUtil: DateUtil,
private val repository: AppRepository private val repository: AppRepository,
private val context: Context,
private val dataWorker: DataWorker
) : PluginBase( ) : PluginBase(
PluginDescription() PluginDescription()
.mainType(PluginType.GENERAL) .mainType(PluginType.GENERAL)
@ -81,9 +89,10 @@ class IobCobCalculatorPlugin @Inject constructor(
override var ads: AutosensDataStore = AutosensDataStore() override var ads: AutosensDataStore = AutosensDataStore()
private val dataLock = Any() private val dataLock = Any()
var stopCalculationTrigger = false
private var thread: Thread? = null private var thread: Thread? = null
private val jobGroupName = "calculation"
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
// EventConfigBuilderChange // EventConfigBuilderChange
@ -168,10 +177,9 @@ class IobCobCalculatorPlugin @Inject constructor(
return oldestTime return oldestTime
} }
fun calculateDetectionStart(from: Long, limitDataToOldestAvailable: Boolean): Long { override fun calculateDetectionStart(from: Long, limitDataToOldestAvailable: Boolean): Long {
val profile = profileFunction.getProfile(from) val profile = profileFunction.getProfile(from)
var dia = Constants.defaultDIA val dia = profile?.dia ?: Constants.defaultDIA
if (profile != null) dia = profile.dia
val oldestDataAvailable = oldestDataAvailable() val oldestDataAvailable = oldestDataAvailable()
val getBGDataFrom: Long val getBGDataFrom: Long
if (limitDataToOldestAvailable) { if (limitDataToOldestAvailable) {
@ -367,24 +375,31 @@ class IobCobCalculatorPlugin @Inject constructor(
} }
fun stopCalculation(from: String) { fun stopCalculation(from: String) {
if (thread?.state != Thread.State.TERMINATED) { aapsLogger.debug(LTag.AUTOSENS, "Stopping calculation thread: $from")
stopCalculationTrigger = true WorkManager.getInstance(context).cancelUniqueWork(jobGroupName)
aapsLogger.debug(LTag.AUTOSENS, "Stopping calculation thread: $from") val workStatus = WorkManager.getInstance(context).getWorkInfosForUniqueWork(jobGroupName).get()
while (thread != null && thread?.state != Thread.State.TERMINATED) { while (workStatus.size >= 1 && workStatus[0].state == WorkInfo.State.RUNNING)
SystemClock.sleep(100) SystemClock.sleep(100)
} aapsLogger.debug(LTag.AUTOSENS, "Calculation thread stopped: $from")
aapsLogger.debug(LTag.AUTOSENS, "Calculation thread stopped: $from")
}
} }
fun runCalculation(from: String, end: Long, bgDataReload: Boolean, limitDataToOldestAvailable: Boolean, cause: Event?) { fun runCalculation(from: String, end: Long, bgDataReload: Boolean, limitDataToOldestAvailable: Boolean, cause: Event?) {
aapsLogger.debug(LTag.AUTOSENS, "Starting calculation thread: " + from + " to " + dateUtil.dateAndTimeAndSecondsString(end)) aapsLogger.debug(LTag.AUTOSENS, "Starting calculation worker: $from to ${dateUtil.dateAndTimeAndSecondsString(end)}")
if (thread == null || thread?.state == Thread.State.TERMINATED) {
thread = val iobCalculation =
if (sensitivityOref1Plugin.isEnabled()) IobCobOref1Thread(injector, this, from, end, bgDataReload, limitDataToOldestAvailable, cause) if (sensitivityOref1Plugin.isEnabled())
else IobCobThread(injector, this, from, end, bgDataReload, limitDataToOldestAvailable, cause) OneTimeWorkRequest.Builder(IobCobOref1Worker::class.java)
thread?.start() .setInputData(
} dataWorker.storeInputData(IobCobOref1Worker.IobCobOref1WorkerData(injector, this, from, end, bgDataReload, limitDataToOldestAvailable, cause))
).build()
else
OneTimeWorkRequest.Builder(IobCobOref1Worker::class.java)
.setInputData(
dataWorker.storeInputData(IobCobOrefWorker.IobCobOrefWorkerData(injector, this, from, end, bgDataReload, limitDataToOldestAvailable, cause))
).build()
WorkManager.getInstance(context)
.enqueueUniqueWork(jobGroupName, ExistingWorkPolicy.REPLACE, iobCalculation)
} }
// Limit rate of EventNewHistoryData // Limit rate of EventNewHistoryData

View file

@ -1,8 +1,10 @@
package info.nightscout.androidaps.plugins.iob.iobCobCalculator package info.nightscout.androidaps.plugins.iob.iobCobCalculator
import android.content.Context import android.content.Context
import android.os.PowerManager
import android.os.SystemClock import android.os.SystemClock
import androidx.work.Worker
import androidx.work.WorkerParameters
import androidx.work.workDataOf
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
@ -12,9 +14,8 @@ import info.nightscout.androidaps.events.Event
import info.nightscout.androidaps.events.EventAutosensCalculationFinished import info.nightscout.androidaps.events.EventAutosensCalculationFinished
import info.nightscout.androidaps.extensions.target import info.nightscout.androidaps.extensions.target
import info.nightscout.androidaps.interfaces.ActivePlugin import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.IobCobCalculator
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults
import info.nightscout.androidaps.plugins.bus.RxBus import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
@ -23,6 +24,7 @@ import info.nightscout.androidaps.plugins.iob.iobCobCalculator.data.AutosensData
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress
import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin
import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.DecimalFormatter import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.FabricPrivacy
@ -30,6 +32,8 @@ import info.nightscout.androidaps.utils.Profiler
import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.buildHelper.BuildHelper import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.shared.sharedPreferences.SP import info.nightscout.shared.sharedPreferences.SP
import java.util.* import java.util.*
import javax.inject.Inject import javax.inject.Inject
@ -38,15 +42,10 @@ import kotlin.math.max
import kotlin.math.min import kotlin.math.min
import kotlin.math.roundToLong import kotlin.math.roundToLong
class IobCobOref1Thread internal constructor( class IobCobOref1Worker(
private val injector: HasAndroidInjector, context: Context,
private val iobCobCalculatorPlugin: IobCobCalculatorPlugin, // cannot be injected : HistoryBrowser uses different instance params: WorkerParameters
private val from: String, ) : Worker(context, params) {
private val end: Long,
private val bgDataReload: Boolean,
private val limitDataToOldestAvailable: Boolean,
private val cause: Event?
) : Thread() {
@Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var sp: SP @Inject lateinit var sp: SP
@ -62,48 +61,58 @@ class IobCobOref1Thread internal constructor(
@Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var dateUtil: DateUtil @Inject lateinit var dateUtil: DateUtil
@Inject lateinit var repository: AppRepository @Inject lateinit var repository: AppRepository
@Inject lateinit var dataWorker: DataWorker
private var mWakeLock: PowerManager.WakeLock? = null
init { init {
injector.androidInjector().inject(this) (context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
mWakeLock = (context.applicationContext.getSystemService(Context.POWER_SERVICE) as PowerManager).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, rh.gs(R.string.app_name) + ":iobCobThread")
} }
override fun run() { class IobCobOref1WorkerData(
val injector: HasAndroidInjector,
val iobCobCalculatorPlugin: IobCobCalculator, // cannot be injected : HistoryBrowser uses different instance
val from: String,
val end: Long,
val bgDataReload: Boolean,
val limitDataToOldestAvailable: Boolean,
val cause: Event?
)
override fun doWork(): Result {
val data = dataWorker.pickupObject(inputData.getLong(DataWorker.STORE_KEY, -1)) as IobCobOref1WorkerData?
?: return Result.failure(workDataOf("Error" to "missing input data"))
val start = dateUtil.now() val start = dateUtil.now()
mWakeLock?.acquire(T.mins(10).msecs())
try { try {
aapsLogger.debug(LTag.AUTOSENS, "AUTOSENSDATA thread started: $from") aapsLogger.debug(LTag.AUTOSENS, "AUTOSENSDATA thread started: ${data.from}")
if (!profileFunction.isProfileValid("IobCobThread")) { if (!profileFunction.isProfileValid("IobCobThread")) {
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (No profile): $from") aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (No profile): ${data.from}")
return // app still initializing return Result.failure(workDataOf("Error" to "app still initializing"))
} }
//log.debug("Locking calculateSensitivityData"); //log.debug("Locking calculateSensitivityData");
val oldestTimeWithData = iobCobCalculatorPlugin.calculateDetectionStart(end, limitDataToOldestAvailable) val oldestTimeWithData = data.iobCobCalculatorPlugin.calculateDetectionStart(data.end, data.limitDataToOldestAvailable)
if (bgDataReload) { if (data.bgDataReload) {
iobCobCalculatorPlugin.ads.loadBgData(end, repository, aapsLogger, dateUtil, rxBus) data.iobCobCalculatorPlugin.ads.loadBgData(data.end, repository, aapsLogger, dateUtil, rxBus)
iobCobCalculatorPlugin.clearCache() data.iobCobCalculatorPlugin.clearCache()
} }
// work on local copy and set back when finished // work on local copy and set back when finished
val ads = iobCobCalculatorPlugin.ads.clone() val ads = data.iobCobCalculatorPlugin.ads.clone()
val bucketedData = ads.bucketedData val bucketedData = ads.bucketedData
val autosensDataTable = ads.autosensDataTable val autosensDataTable = ads.autosensDataTable
if (bucketedData == null || bucketedData.size < 3) { if (bucketedData == null || bucketedData.size < 3) {
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (No bucketed data available): $from") aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (No bucketed data available): ${data.from}")
return return Result.failure(workDataOf("Error" to "Aborting calculation thread (No bucketed data available): ${data.from}"))
} }
val prevDataTime = ads.roundUpTime(bucketedData[bucketedData.size - 3].timestamp) val prevDataTime = ads.roundUpTime(bucketedData[bucketedData.size - 3].timestamp)
aapsLogger.debug(LTag.AUTOSENS, "Prev data time: " + dateUtil.dateAndTimeString(prevDataTime)) aapsLogger.debug(LTag.AUTOSENS, "Prev data time: " + dateUtil.dateAndTimeString(prevDataTime))
var previous = autosensDataTable[prevDataTime] var previous = autosensDataTable[prevDataTime]
// start from oldest to be able sub cob // start from oldest to be able sub cob
for (i in bucketedData.size - 4 downTo 0) { for (i in bucketedData.size - 4 downTo 0) {
val progress = i.toString() + if (buildHelper.isDev()) " ($from)" else "" val progress = i.toString() + if (buildHelper.isDev()) " (${data.from})" else ""
rxBus.send(EventIobCalculationProgress(progress, cause)) rxBus.send(EventIobCalculationProgress(progress, data.cause))
if (iobCobCalculatorPlugin.stopCalculationTrigger) { if (isStopped) {
iobCobCalculatorPlugin.stopCalculationTrigger = false aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (trigger): ${data.from}")
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (trigger): $from") return Result.failure(workDataOf("Error" to "Aborting calculation thread (trigger): ${data.from}"))
return
} }
// check if data already exists // check if data already exists
var bgTime = bucketedData[i].timestamp var bgTime = bucketedData[i].timestamp
@ -116,12 +125,12 @@ class IobCobOref1Thread internal constructor(
} }
val profile = profileFunction.getProfile(bgTime) val profile = profileFunction.getProfile(bgTime)
if (profile == null) { if (profile == null) {
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (no profile): $from") aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (no profile): ${data.from}")
continue // profile not set yet continue // profile not set yet
} }
aapsLogger.debug(LTag.AUTOSENS, "Processing calculation thread: " + from + " (" + i + "/" + bucketedData.size + ")") aapsLogger.debug(LTag.AUTOSENS, "Processing calculation thread: ${data.from} ($i/${bucketedData.size})")
val sens = profile.getIsfMgdl(bgTime) val sens = profile.getIsfMgdl(bgTime)
val autosensData = AutosensData(injector) val autosensData = AutosensData(data.injector)
autosensData.time = bgTime autosensData.time = bgTime
if (previous != null) autosensData.activeCarbsList = previous.cloneCarbsList() else autosensData.activeCarbsList = ArrayList() if (previous != null) autosensData.activeCarbsList = previous.cloneCarbsList() else autosensData.activeCarbsList = ArrayList()
@ -136,7 +145,7 @@ class IobCobOref1Thread internal constructor(
autosensData.bg = bg autosensData.bg = bg
delta = bg - bucketedData[i + 1].value delta = bg - bucketedData[i + 1].value
avgDelta = (bg - bucketedData[i + 3].value) / 3 avgDelta = (bg - bucketedData[i + 3].value) / 3
val iob = iobCobCalculatorPlugin.calculateFromTreatmentsAndTemps(bgTime, profile) val iob = data.iobCobCalculatorPlugin.calculateFromTreatmentsAndTemps(bgTime, profile)
val bgi = -iob.activity * sens * 5 val bgi = -iob.activity * sens * 5
val deviation = delta - bgi val deviation = delta - bgi
val avgDeviation = ((avgDelta - bgi) * 1000).roundToLong() / 1000.0 val avgDeviation = ((avgDelta - bgi) * 1000).roundToLong() / 1000.0
@ -312,22 +321,27 @@ class IobCobOref1Thread internal constructor(
if (min in 0..4 && hours % 2 == 0) autosensData.extraDeviation.add(0.0) if (min in 0..4 && hours % 2 == 0) autosensData.extraDeviation.add(0.0)
previous = autosensData previous = autosensData
if (bgTime < dateUtil.now()) autosensDataTable.put(bgTime, autosensData) if (bgTime < dateUtil.now()) autosensDataTable.put(bgTime, autosensData)
aapsLogger.debug(LTag.AUTOSENS, "Running detectSensitivity from: " + dateUtil.dateAndTimeString(oldestTimeWithData) + " to: " + dateUtil.dateAndTimeString(bgTime) + " lastDataTime:" + ads.lastDataTime(dateUtil)) aapsLogger.debug(
LTag.AUTOSENS,
"Running detectSensitivity from: " + dateUtil.dateAndTimeString(oldestTimeWithData) + " to: " + dateUtil.dateAndTimeString(bgTime) + " lastDataTime:" + ads.lastDataTime(
dateUtil
)
)
val sensitivity = activePlugin.activeSensitivity.detectSensitivity(ads, oldestTimeWithData, bgTime) val sensitivity = activePlugin.activeSensitivity.detectSensitivity(ads, oldestTimeWithData, bgTime)
aapsLogger.debug(LTag.AUTOSENS, "Sensitivity result: $sensitivity") aapsLogger.debug(LTag.AUTOSENS, "Sensitivity result: $sensitivity")
autosensData.autosensResult = sensitivity autosensData.autosensResult = sensitivity
aapsLogger.debug(LTag.AUTOSENS, autosensData.toString()) aapsLogger.debug(LTag.AUTOSENS, autosensData.toString())
} }
iobCobCalculatorPlugin.ads = ads data.iobCobCalculatorPlugin.ads = ads
Thread { Thread {
SystemClock.sleep(1000) SystemClock.sleep(1000)
rxBus.send(EventAutosensCalculationFinished(cause)) rxBus.send(EventAutosensCalculationFinished(data.cause))
}.start() }.start()
} finally { } finally {
mWakeLock?.release() rxBus.send(EventIobCalculationProgress("", data.cause))
rxBus.send(EventIobCalculationProgress("", cause)) aapsLogger.debug(LTag.AUTOSENS, "AUTOSENSDATA thread ended: ${data.from}")
aapsLogger.debug(LTag.AUTOSENS, "AUTOSENSDATA thread ended: $from")
profiler.log(LTag.AUTOSENS, "IobCobOref1Thread", start) profiler.log(LTag.AUTOSENS, "IobCobOref1Thread", start)
} }
return Result.success()
} }
} }

View file

@ -1,8 +1,10 @@
package info.nightscout.androidaps.plugins.iob.iobCobCalculator package info.nightscout.androidaps.plugins.iob.iobCobCalculator
import android.content.Context import android.content.Context
import android.os.PowerManager
import android.os.SystemClock import android.os.SystemClock
import androidx.work.Worker
import androidx.work.WorkerParameters
import androidx.work.workDataOf
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
@ -10,9 +12,8 @@ import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.events.Event import info.nightscout.androidaps.events.Event
import info.nightscout.androidaps.events.EventAutosensCalculationFinished import info.nightscout.androidaps.events.EventAutosensCalculationFinished
import info.nightscout.androidaps.interfaces.ActivePlugin import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.IobCobCalculator
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults
import info.nightscout.androidaps.plugins.bus.RxBus import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
@ -21,6 +22,7 @@ import info.nightscout.androidaps.plugins.iob.iobCobCalculator.data.AutosensData
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress
import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin
import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.DecimalFormatter import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.FabricPrivacy
@ -28,23 +30,19 @@ import info.nightscout.androidaps.utils.Profiler
import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.buildHelper.BuildHelper import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.shared.sharedPreferences.SP import info.nightscout.shared.sharedPreferences.SP
import java.util.*
import javax.inject.Inject import javax.inject.Inject
import kotlin.math.abs import kotlin.math.abs
import kotlin.math.max import kotlin.math.max
import kotlin.math.min import kotlin.math.min
import kotlin.math.roundToLong import kotlin.math.roundToLong
class IobCobThread @Inject internal constructor( class IobCobOrefWorker @Inject internal constructor(
private val injector: HasAndroidInjector, context: Context,
private val iobCobCalculatorPlugin: IobCobCalculatorPlugin, // cannot be injected : HistoryBrowser uses different instance params: WorkerParameters
private val from: String, ) : Worker(context, params) {
private val end: Long,
private val bgDataReload: Boolean,
private val limitDataToOldestAvailable: Boolean,
private val cause: Event?
) : Thread() {
@Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var sp: SP @Inject lateinit var sp: SP
@ -60,48 +58,57 @@ class IobCobThread @Inject internal constructor(
@Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var dateUtil: DateUtil @Inject lateinit var dateUtil: DateUtil
@Inject lateinit var repository: AppRepository @Inject lateinit var repository: AppRepository
@Inject lateinit var dataWorker: DataWorker
private var mWakeLock: PowerManager.WakeLock? = null
init { init {
injector.androidInjector().inject(this) (context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
mWakeLock = (context.applicationContext.getSystemService(Context.POWER_SERVICE) as PowerManager).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, rh.gs(R.string.app_name) + ":iobCobThread")
} }
override fun run() { class IobCobOrefWorkerData(
val injector: HasAndroidInjector,
val iobCobCalculatorPlugin: IobCobCalculator, // cannot be injected : HistoryBrowser uses different instance
val from: String,
val end: Long,
val bgDataReload: Boolean,
val limitDataToOldestAvailable: Boolean,
val cause: Event?
)
override fun doWork(): Result {
val data = dataWorker.pickupObject(inputData.getLong(DataWorker.STORE_KEY, -1)) as IobCobOrefWorkerData?
?: return Result.failure(workDataOf("Error" to "missing input data"))
val start = dateUtil.now() val start = dateUtil.now()
mWakeLock?.acquire(T.mins(10).msecs())
try { try {
aapsLogger.debug(LTag.AUTOSENS, "AUTOSENSDATA thread started: $from") aapsLogger.debug(LTag.AUTOSENS, "AUTOSENSDATA thread started: ${data.from}")
if (!profileFunction.isProfileValid("IobCobThread")) { if (!profileFunction.isProfileValid("IobCobThread")) {
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (No profile): $from") aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (No profile): ${data.from}")
return // app still initializing return Result.failure(workDataOf("Error" to "app still initializing"))
} }
//log.debug("Locking calculateSensitivityData"); //log.debug("Locking calculateSensitivityData");
val oldestTimeWithData = iobCobCalculatorPlugin.calculateDetectionStart(end, limitDataToOldestAvailable) val oldestTimeWithData = data.iobCobCalculatorPlugin.calculateDetectionStart(data.end, data.limitDataToOldestAvailable)
if (bgDataReload) { if (data.bgDataReload) {
iobCobCalculatorPlugin.ads.loadBgData(end, repository, aapsLogger, dateUtil, rxBus) data.iobCobCalculatorPlugin.ads.loadBgData(data.end, repository, aapsLogger, dateUtil, rxBus)
iobCobCalculatorPlugin.clearCache() data.iobCobCalculatorPlugin.clearCache()
} }
// work on local copy and set back when finished // work on local copy and set back when finished
val ads = iobCobCalculatorPlugin.ads.clone() val ads = data.iobCobCalculatorPlugin.ads.clone()
val bucketedData = ads.bucketedData val bucketedData = ads.bucketedData
val autosensDataTable = ads.autosensDataTable val autosensDataTable = ads.autosensDataTable
if (bucketedData == null || bucketedData.size < 3) { if (bucketedData == null || bucketedData.size < 3) {
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (No bucketed data available): $from") aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (No bucketed data available): ${data.from}")
return return Result.failure(workDataOf("Error" to "Aborting calculation thread (No bucketed data available): ${data.from}"))
} }
val prevDataTime = ads.roundUpTime(bucketedData[bucketedData.size - 3].timestamp) val prevDataTime = ads.roundUpTime(bucketedData[bucketedData.size - 3].timestamp)
aapsLogger.debug(LTag.AUTOSENS, "Prev data time: " + dateUtil.dateAndTimeString(prevDataTime)) aapsLogger.debug(LTag.AUTOSENS, "Prev data time: " + dateUtil.dateAndTimeString(prevDataTime))
var previous = autosensDataTable[prevDataTime] var previous = autosensDataTable[prevDataTime]
// start from oldest to be able sub cob // start from oldest to be able sub cob
for (i in bucketedData.size - 4 downTo 0) { for (i in bucketedData.size - 4 downTo 0) {
val progress = i.toString() + if (buildHelper.isDev()) " ($from)" else "" val progress = i.toString() + if (buildHelper.isDev()) " (${data.from})" else ""
rxBus.send(EventIobCalculationProgress(progress, cause)) rxBus.send(EventIobCalculationProgress(progress, data.cause))
if (iobCobCalculatorPlugin.stopCalculationTrigger) { if (isStopped) {
iobCobCalculatorPlugin.stopCalculationTrigger = false aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (trigger): ${data.from}")
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (trigger): $from") return Result.failure(workDataOf("Error" to "Aborting calculation thread (trigger): ${data.from}"))
return
} }
// check if data already exists // check if data already exists
var bgTime = bucketedData[i].timestamp var bgTime = bucketedData[i].timestamp
@ -114,12 +121,12 @@ class IobCobThread @Inject internal constructor(
} }
val profile = profileFunction.getProfile(bgTime) val profile = profileFunction.getProfile(bgTime)
if (profile == null) { if (profile == null) {
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (no profile): $from") aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (no profile): ${data.from}")
continue // profile not set yet continue // profile not set yet
} }
aapsLogger.debug(LTag.AUTOSENS, "Processing calculation thread: " + from + " (" + i + "/" + bucketedData.size + ")") aapsLogger.debug(LTag.AUTOSENS, "Processing calculation thread: ${data.from} ($i/${bucketedData.size})")
val sens = profile.getIsfMgdl(bgTime) val sens = profile.getIsfMgdl(bgTime)
val autosensData = AutosensData(injector) val autosensData = AutosensData(data.injector)
autosensData.time = bgTime autosensData.time = bgTime
if (previous != null) autosensData.activeCarbsList = previous.cloneCarbsList() else autosensData.activeCarbsList = ArrayList() if (previous != null) autosensData.activeCarbsList = previous.cloneCarbsList() else autosensData.activeCarbsList = ArrayList()
@ -134,7 +141,7 @@ class IobCobThread @Inject internal constructor(
autosensData.bg = bg autosensData.bg = bg
delta = bg - bucketedData[i + 1].value delta = bg - bucketedData[i + 1].value
avgDelta = (bg - bucketedData[i + 3].value) / 3 avgDelta = (bg - bucketedData[i + 3].value) / 3
val iob = iobCobCalculatorPlugin.calculateFromTreatmentsAndTemps(bgTime, profile) val iob = data.iobCobCalculatorPlugin.calculateFromTreatmentsAndTemps(bgTime, profile)
val bgi = -iob.activity * sens * 5 val bgi = -iob.activity * sens * 5
val deviation = delta - bgi val deviation = delta - bgi
val avgDeviation = ((avgDelta - bgi) * 1000).roundToLong() / 1000.0 val avgDeviation = ((avgDelta - bgi) * 1000).roundToLong() / 1000.0
@ -158,7 +165,7 @@ class IobCobThread @Inject internal constructor(
if (ad == null) { if (ad == null) {
aapsLogger.debug(LTag.AUTOSENS, autosensDataTable.toString()) aapsLogger.debug(LTag.AUTOSENS, autosensDataTable.toString())
aapsLogger.debug(LTag.AUTOSENS, bucketedData.toString()) aapsLogger.debug(LTag.AUTOSENS, bucketedData.toString())
//aapsLogger.debug(LTag.AUTOSENS, iobCobCalculatorPlugin.getBgReadingsDataTable().toString()) //aapsLogger.debug(LTag.AUTOSENS, data.iobCobCalculatorPlugin.getBgReadingsDataTable().toString())
val notification = Notification(Notification.SEND_LOGFILES, rh.gs(R.string.sendlogfiles), Notification.LOW) val notification = Notification(Notification.SEND_LOGFILES, rh.gs(R.string.sendlogfiles), Notification.LOW)
rxBus.send(EventNewNotification(notification)) rxBus.send(EventNewNotification(notification))
sp.putBoolean("log_AUTOSENS", true) sp.putBoolean("log_AUTOSENS", true)
@ -181,7 +188,7 @@ class IobCobThread @Inject internal constructor(
fabricPrivacy.logException(e) fabricPrivacy.logException(e)
aapsLogger.debug(autosensDataTable.toString()) aapsLogger.debug(autosensDataTable.toString())
aapsLogger.debug(bucketedData.toString()) aapsLogger.debug(bucketedData.toString())
//aapsLogger.debug(iobCobCalculatorPlugin.getBgReadingsDataTable().toString()) //aapsLogger.debug(data.iobCobCalculatorPlugin.getBgReadingsDataTable().toString())
val notification = Notification(Notification.SEND_LOGFILES, rh.gs(R.string.sendlogfiles), Notification.LOW) val notification = Notification(Notification.SEND_LOGFILES, rh.gs(R.string.sendlogfiles), Notification.LOW)
rxBus.send(EventNewNotification(notification)) rxBus.send(EventNewNotification(notification))
sp.putBoolean("log_AUTOSENS", true) sp.putBoolean("log_AUTOSENS", true)
@ -258,22 +265,27 @@ class IobCobThread @Inject internal constructor(
} }
previous = autosensData previous = autosensData
if (bgTime < dateUtil.now()) autosensDataTable.put(bgTime, autosensData) if (bgTime < dateUtil.now()) autosensDataTable.put(bgTime, autosensData)
aapsLogger.debug(LTag.AUTOSENS, "Running detectSensitivity from: " + dateUtil.dateAndTimeString(oldestTimeWithData) + " to: " + dateUtil.dateAndTimeString(bgTime) + " lastDataTime:" + ads.lastDataTime(dateUtil)) aapsLogger.debug(
LTag.AUTOSENS,
"Running detectSensitivity from: " + dateUtil.dateAndTimeString(oldestTimeWithData) + " to: " + dateUtil.dateAndTimeString(bgTime) + " lastDataTime:" + ads.lastDataTime(
dateUtil
)
)
val sensitivity = activePlugin.activeSensitivity.detectSensitivity(ads, oldestTimeWithData, bgTime) val sensitivity = activePlugin.activeSensitivity.detectSensitivity(ads, oldestTimeWithData, bgTime)
aapsLogger.debug(LTag.AUTOSENS, "Sensitivity result: $sensitivity") aapsLogger.debug(LTag.AUTOSENS, "Sensitivity result: $sensitivity")
autosensData.autosensResult = sensitivity autosensData.autosensResult = sensitivity
aapsLogger.debug(LTag.AUTOSENS, autosensData.toString()) aapsLogger.debug(LTag.AUTOSENS, autosensData.toString())
} }
iobCobCalculatorPlugin.ads = ads data.iobCobCalculatorPlugin.ads = ads
Thread { Thread {
SystemClock.sleep(1000) SystemClock.sleep(1000)
rxBus.send(EventAutosensCalculationFinished(cause)) rxBus.send(EventAutosensCalculationFinished(data.cause))
}.start() }.start()
} finally { } finally {
mWakeLock?.release() rxBus.send(EventIobCalculationProgress("", data.cause))
rxBus.send(EventIobCalculationProgress("", cause)) aapsLogger.debug(LTag.AUTOSENS, "AUTOSENSDATA thread ended: ${data.from}")
aapsLogger.debug(LTag.AUTOSENS, "AUTOSENSDATA thread ended: $from")
profiler.log(LTag.AUTOSENS, "IobCobThread", start) profiler.log(LTag.AUTOSENS, "IobCobThread", start)
} }
return Result.success()
} }
} }

View file

@ -20,6 +20,8 @@ interface IobCobCalculator {
fun calculateFromTreatmentsAndTemps(toTime: Long, profile: Profile): IobTotal fun calculateFromTreatmentsAndTemps(toTime: Long, profile: Profile): IobTotal
fun calculateDetectionStart(from: Long, limitDataToOldestAvailable: Boolean): Long
fun getBasalData(profile: Profile, fromTime: Long): BasalData fun getBasalData(profile: Profile, fromTime: Long): BasalData
fun calculateIobArrayInDia(profile: Profile): Array<IobTotal> fun calculateIobArrayInDia(profile: Profile): Array<IobTotal>