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.app.DatePickerDialog
import android.content.Context
import android.graphics.Color
import android.os.Bundle
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.SensitivityOref1Plugin
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin
import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.DefaultValueHelper
import info.nightscout.androidaps.utils.FabricPrivacy
@ -69,6 +71,8 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
@Inject lateinit var loop: Loop
@Inject lateinit var nsDeviceStatus: NSDeviceStatus
@Inject lateinit var translator: Translator
@Inject lateinit var context: Context
@Inject lateinit var dataWorker: DataWorker
private val disposable = CompositeDisposable()
@ -106,7 +110,9 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
sensitivityWeightedAveragePlugin,
fabricPrivacy,
dateUtil,
repository
repository,
context,
dataWorker
)
overviewData =
OverviewData(
@ -336,11 +342,7 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
}
private fun runCalculation(from: String) {
Thread {
iobCobCalculator.stopCalculation(from)
iobCobCalculator.stopCalculationTrigger = false
iobCobCalculator.runCalculation(from, overviewData.toTime, bgDataReload = true, limitDataToOldestAvailable = false, cause = EventCustomCalculationFinished())
}.start()
}
@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.DetermineBasalResultSMB
import info.nightscout.androidaps.plugins.aps.openAPSSMBDynamicISF.DetermineBasalAdapterSMBDynamicISFJS
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobOref1Thread
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobThread
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobOref1Worker
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobOrefWorker
@Module
@Suppress("unused")
@ -21,6 +21,6 @@ abstract class APSModule {
@ContributesAndroidInjector abstract fun determineBasalAdapterAMAJSInjector(): DetermineBasalAdapterAMAJS
@ContributesAndroidInjector abstract fun determineBasalAdapterSMBJSInjector(): DetermineBasalAdapterSMBJS
@ContributesAndroidInjector abstract fun determineBasalAdapterSMBAutoISFJSInjector(): DetermineBasalAdapterSMBDynamicISFJS
@ContributesAndroidInjector abstract fun iobCobThreadInjector(): IobCobThread
@ContributesAndroidInjector abstract fun iobCobOref1ThreadInjector(): IobCobOref1Thread
@ContributesAndroidInjector abstract fun iobCobWorkerInjector(): IobCobOrefWorker
@ContributesAndroidInjector abstract fun iobCobOref1WorkerInjector(): IobCobOref1Worker
}

View file

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

View file

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

View file

@ -1,8 +1,10 @@
package info.nightscout.androidaps.plugins.iob.iobCobCalculator
import android.content.Context
import android.os.PowerManager
import android.os.SystemClock
import androidx.work.Worker
import androidx.work.WorkerParameters
import androidx.work.workDataOf
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Constants
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.extensions.target
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.IobCobCalculator
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.bus.RxBus
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.sensitivity.SensitivityAAPSPlugin
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin
import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.DecimalFormatter
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.buildHelper.BuildHelper
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 java.util.*
import javax.inject.Inject
@ -38,15 +42,10 @@ import kotlin.math.max
import kotlin.math.min
import kotlin.math.roundToLong
class IobCobOref1Thread internal constructor(
private val injector: HasAndroidInjector,
private val iobCobCalculatorPlugin: IobCobCalculatorPlugin, // cannot be injected : HistoryBrowser uses different instance
private val from: String,
private val end: Long,
private val bgDataReload: Boolean,
private val limitDataToOldestAvailable: Boolean,
private val cause: Event?
) : Thread() {
class IobCobOref1Worker(
context: Context,
params: WorkerParameters
) : Worker(context, params) {
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var sp: SP
@ -62,48 +61,58 @@ class IobCobOref1Thread internal constructor(
@Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var dateUtil: DateUtil
@Inject lateinit var repository: AppRepository
private var mWakeLock: PowerManager.WakeLock? = null
@Inject lateinit var dataWorker: DataWorker
init {
injector.androidInjector().inject(this)
mWakeLock = (context.applicationContext.getSystemService(Context.POWER_SERVICE) as PowerManager).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, rh.gs(R.string.app_name) + ":iobCobThread")
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
}
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()
mWakeLock?.acquire(T.mins(10).msecs())
try {
aapsLogger.debug(LTag.AUTOSENS, "AUTOSENSDATA thread started: $from")
aapsLogger.debug(LTag.AUTOSENS, "AUTOSENSDATA thread started: ${data.from}")
if (!profileFunction.isProfileValid("IobCobThread")) {
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (No profile): $from")
return // app still initializing
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (No profile): ${data.from}")
return Result.failure(workDataOf("Error" to "app still initializing"))
}
//log.debug("Locking calculateSensitivityData");
val oldestTimeWithData = iobCobCalculatorPlugin.calculateDetectionStart(end, limitDataToOldestAvailable)
if (bgDataReload) {
iobCobCalculatorPlugin.ads.loadBgData(end, repository, aapsLogger, dateUtil, rxBus)
iobCobCalculatorPlugin.clearCache()
val oldestTimeWithData = data.iobCobCalculatorPlugin.calculateDetectionStart(data.end, data.limitDataToOldestAvailable)
if (data.bgDataReload) {
data.iobCobCalculatorPlugin.ads.loadBgData(data.end, repository, aapsLogger, dateUtil, rxBus)
data.iobCobCalculatorPlugin.clearCache()
}
// 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 autosensDataTable = ads.autosensDataTable
if (bucketedData == null || bucketedData.size < 3) {
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (No bucketed data available): $from")
return
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (No bucketed data available): ${data.from}")
return Result.failure(workDataOf("Error" to "Aborting calculation thread (No bucketed data available): ${data.from}"))
}
val prevDataTime = ads.roundUpTime(bucketedData[bucketedData.size - 3].timestamp)
aapsLogger.debug(LTag.AUTOSENS, "Prev data time: " + dateUtil.dateAndTimeString(prevDataTime))
var previous = autosensDataTable[prevDataTime]
// start from oldest to be able sub cob
for (i in bucketedData.size - 4 downTo 0) {
val progress = i.toString() + if (buildHelper.isDev()) " ($from)" else ""
rxBus.send(EventIobCalculationProgress(progress, cause))
if (iobCobCalculatorPlugin.stopCalculationTrigger) {
iobCobCalculatorPlugin.stopCalculationTrigger = false
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (trigger): $from")
return
val progress = i.toString() + if (buildHelper.isDev()) " (${data.from})" else ""
rxBus.send(EventIobCalculationProgress(progress, data.cause))
if (isStopped) {
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (trigger): ${data.from}")
return Result.failure(workDataOf("Error" to "Aborting calculation thread (trigger): ${data.from}"))
}
// check if data already exists
var bgTime = bucketedData[i].timestamp
@ -116,12 +125,12 @@ class IobCobOref1Thread internal constructor(
}
val profile = profileFunction.getProfile(bgTime)
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
}
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 autosensData = AutosensData(injector)
val autosensData = AutosensData(data.injector)
autosensData.time = bgTime
if (previous != null) autosensData.activeCarbsList = previous.cloneCarbsList() else autosensData.activeCarbsList = ArrayList()
@ -136,7 +145,7 @@ class IobCobOref1Thread internal constructor(
autosensData.bg = bg
delta = bg - bucketedData[i + 1].value
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 deviation = delta - bgi
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)
previous = 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)
aapsLogger.debug(LTag.AUTOSENS, "Sensitivity result: $sensitivity")
autosensData.autosensResult = sensitivity
aapsLogger.debug(LTag.AUTOSENS, autosensData.toString())
}
iobCobCalculatorPlugin.ads = ads
data.iobCobCalculatorPlugin.ads = ads
Thread {
SystemClock.sleep(1000)
rxBus.send(EventAutosensCalculationFinished(cause))
rxBus.send(EventAutosensCalculationFinished(data.cause))
}.start()
} finally {
mWakeLock?.release()
rxBus.send(EventIobCalculationProgress("", cause))
aapsLogger.debug(LTag.AUTOSENS, "AUTOSENSDATA thread ended: $from")
rxBus.send(EventIobCalculationProgress("", data.cause))
aapsLogger.debug(LTag.AUTOSENS, "AUTOSENSDATA thread ended: ${data.from}")
profiler.log(LTag.AUTOSENS, "IobCobOref1Thread", start)
}
return Result.success()
}
}

View file

@ -1,8 +1,10 @@
package info.nightscout.androidaps.plugins.iob.iobCobCalculator
import android.content.Context
import android.os.PowerManager
import android.os.SystemClock
import androidx.work.Worker
import androidx.work.WorkerParameters
import androidx.work.workDataOf
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Constants
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.EventAutosensCalculationFinished
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.IobCobCalculator
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.bus.RxBus
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.sensitivity.SensitivityAAPSPlugin
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin
import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.DecimalFormatter
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.buildHelper.BuildHelper
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 java.util.*
import javax.inject.Inject
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min
import kotlin.math.roundToLong
class IobCobThread @Inject internal constructor(
private val injector: HasAndroidInjector,
private val iobCobCalculatorPlugin: IobCobCalculatorPlugin, // cannot be injected : HistoryBrowser uses different instance
private val from: String,
private val end: Long,
private val bgDataReload: Boolean,
private val limitDataToOldestAvailable: Boolean,
private val cause: Event?
) : Thread() {
class IobCobOrefWorker @Inject internal constructor(
context: Context,
params: WorkerParameters
) : Worker(context, params) {
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var sp: SP
@ -60,48 +58,57 @@ class IobCobThread @Inject internal constructor(
@Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var dateUtil: DateUtil
@Inject lateinit var repository: AppRepository
private var mWakeLock: PowerManager.WakeLock? = null
@Inject lateinit var dataWorker: DataWorker
init {
injector.androidInjector().inject(this)
mWakeLock = (context.applicationContext.getSystemService(Context.POWER_SERVICE) as PowerManager).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, rh.gs(R.string.app_name) + ":iobCobThread")
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
}
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()
mWakeLock?.acquire(T.mins(10).msecs())
try {
aapsLogger.debug(LTag.AUTOSENS, "AUTOSENSDATA thread started: $from")
aapsLogger.debug(LTag.AUTOSENS, "AUTOSENSDATA thread started: ${data.from}")
if (!profileFunction.isProfileValid("IobCobThread")) {
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (No profile): $from")
return // app still initializing
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (No profile): ${data.from}")
return Result.failure(workDataOf("Error" to "app still initializing"))
}
//log.debug("Locking calculateSensitivityData");
val oldestTimeWithData = iobCobCalculatorPlugin.calculateDetectionStart(end, limitDataToOldestAvailable)
if (bgDataReload) {
iobCobCalculatorPlugin.ads.loadBgData(end, repository, aapsLogger, dateUtil, rxBus)
iobCobCalculatorPlugin.clearCache()
val oldestTimeWithData = data.iobCobCalculatorPlugin.calculateDetectionStart(data.end, data.limitDataToOldestAvailable)
if (data.bgDataReload) {
data.iobCobCalculatorPlugin.ads.loadBgData(data.end, repository, aapsLogger, dateUtil, rxBus)
data.iobCobCalculatorPlugin.clearCache()
}
// 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 autosensDataTable = ads.autosensDataTable
if (bucketedData == null || bucketedData.size < 3) {
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (No bucketed data available): $from")
return
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (No bucketed data available): ${data.from}")
return Result.failure(workDataOf("Error" to "Aborting calculation thread (No bucketed data available): ${data.from}"))
}
val prevDataTime = ads.roundUpTime(bucketedData[bucketedData.size - 3].timestamp)
aapsLogger.debug(LTag.AUTOSENS, "Prev data time: " + dateUtil.dateAndTimeString(prevDataTime))
var previous = autosensDataTable[prevDataTime]
// start from oldest to be able sub cob
for (i in bucketedData.size - 4 downTo 0) {
val progress = i.toString() + if (buildHelper.isDev()) " ($from)" else ""
rxBus.send(EventIobCalculationProgress(progress, cause))
if (iobCobCalculatorPlugin.stopCalculationTrigger) {
iobCobCalculatorPlugin.stopCalculationTrigger = false
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (trigger): $from")
return
val progress = i.toString() + if (buildHelper.isDev()) " (${data.from})" else ""
rxBus.send(EventIobCalculationProgress(progress, data.cause))
if (isStopped) {
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (trigger): ${data.from}")
return Result.failure(workDataOf("Error" to "Aborting calculation thread (trigger): ${data.from}"))
}
// check if data already exists
var bgTime = bucketedData[i].timestamp
@ -114,12 +121,12 @@ class IobCobThread @Inject internal constructor(
}
val profile = profileFunction.getProfile(bgTime)
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
}
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 autosensData = AutosensData(injector)
val autosensData = AutosensData(data.injector)
autosensData.time = bgTime
if (previous != null) autosensData.activeCarbsList = previous.cloneCarbsList() else autosensData.activeCarbsList = ArrayList()
@ -134,7 +141,7 @@ class IobCobThread @Inject internal constructor(
autosensData.bg = bg
delta = bg - bucketedData[i + 1].value
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 deviation = delta - bgi
val avgDeviation = ((avgDelta - bgi) * 1000).roundToLong() / 1000.0
@ -158,7 +165,7 @@ class IobCobThread @Inject internal constructor(
if (ad == null) {
aapsLogger.debug(LTag.AUTOSENS, autosensDataTable.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)
rxBus.send(EventNewNotification(notification))
sp.putBoolean("log_AUTOSENS", true)
@ -181,7 +188,7 @@ class IobCobThread @Inject internal constructor(
fabricPrivacy.logException(e)
aapsLogger.debug(autosensDataTable.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)
rxBus.send(EventNewNotification(notification))
sp.putBoolean("log_AUTOSENS", true)
@ -258,22 +265,27 @@ class IobCobThread @Inject internal constructor(
}
previous = 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)
aapsLogger.debug(LTag.AUTOSENS, "Sensitivity result: $sensitivity")
autosensData.autosensResult = sensitivity
aapsLogger.debug(LTag.AUTOSENS, autosensData.toString())
}
iobCobCalculatorPlugin.ads = ads
data.iobCobCalculatorPlugin.ads = ads
Thread {
SystemClock.sleep(1000)
rxBus.send(EventAutosensCalculationFinished(cause))
rxBus.send(EventAutosensCalculationFinished(data.cause))
}.start()
} finally {
mWakeLock?.release()
rxBus.send(EventIobCalculationProgress("", cause))
aapsLogger.debug(LTag.AUTOSENS, "AUTOSENSDATA thread ended: $from")
rxBus.send(EventIobCalculationProgress("", data.cause))
aapsLogger.debug(LTag.AUTOSENS, "AUTOSENSDATA thread ended: ${data.from}")
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 calculateDetectionStart(from: Long, limitDataToOldestAvailable: Boolean): Long
fun getBasalData(profile: Profile, fromTime: Long): BasalData
fun calculateIobArrayInDia(profile: Profile): Array<IobTotal>