history updates: auto resolve history entried for activation. update history on deactivation. use the right history name for set_time

This commit is contained in:
Andrei Vereha 2021-10-26 22:19:22 +02:00
parent a51c49f81c
commit 45fb0a5a21
9 changed files with 76 additions and 66 deletions

View file

@ -364,8 +364,12 @@ class OmnipodDashPumpPlugin @Inject constructor(
return PumpEnactResult(injector).success(true).enacted(true) return PumpEnactResult(injector).success(true).enacted(true)
} }
aapsLogger.debug(LTag.PUMP, "setNewBasalProfile profile=$profile") aapsLogger.debug(LTag.PUMP, "setNewBasalProfile profile=$profile")
val basalProgram = mapProfileToBasalProgram(profile) return setNewBasalProfile(profile, OmnipodCommandType.SET_BASAL_PROFILE)
}
private fun setNewBasalProfile(profile: Profile, historyType: OmnipodCommandType): PumpEnactResult {
var deliverySuspended = false var deliverySuspended = false
val basalProgram = mapProfileToBasalProgram(profile)
return executeProgrammingCommand( return executeProgrammingCommand(
pre = suspendDeliveryIfActive().doOnComplete { pre = suspendDeliveryIfActive().doOnComplete {
if (podStateManager.activeCommand == null) { if (podStateManager.activeCommand == null) {
@ -374,7 +378,7 @@ class OmnipodDashPumpPlugin @Inject constructor(
} }
}, },
historyEntry = history.createRecord( historyEntry = history.createRecord(
commandType = OmnipodCommandType.SET_BASAL_PROFILE, commandType = historyType,
basalProfileRecord = BasalValuesRecord(profile.getBasalValues().toList()) basalProfileRecord = BasalValuesRecord(profile.getBasalValues().toList())
), ),
activeCommandEntry = { historyId -> activeCommandEntry = { historyId ->
@ -1157,16 +1161,20 @@ class OmnipodDashPumpPlugin @Inject constructor(
} }
private fun deactivatePod(): PumpEnactResult { private fun deactivatePod(): PumpEnactResult {
var success = true
val ret = executeProgrammingCommand( val ret = executeProgrammingCommand(
historyEntry = history.createRecord(OmnipodCommandType.DEACTIVATE_POD), historyEntry = history.createRecord(OmnipodCommandType.DEACTIVATE_POD),
command = omnipodManager.deactivatePod().ignoreElements(), command = omnipodManager.deactivatePod().ignoreElements(),
checkNoActiveCommand = false, checkNoActiveCommand = false,
post = createFakeTBRWhenNoActivePod(), post = createFakeTBRWhenNoActivePod(),
).doOnComplete { ).doOnComplete {
if (podStateManager.activeCommand != null) {
success = false
}
podStateManager.reset()
rxBus.send(EventDismissNotification(Notification.OMNIPOD_POD_FAULT)) rxBus.send(EventDismissNotification(Notification.OMNIPOD_POD_FAULT))
}.toPumpEnactResult() }.toPumpEnactResult()
if (!success) {
if (podStateManager.activeCommand != null) {
ret.success(false) ret.success(false)
} }
return ret return ret
@ -1174,7 +1182,7 @@ class OmnipodDashPumpPlugin @Inject constructor(
private fun handleTimeChange(): PumpEnactResult { private fun handleTimeChange(): PumpEnactResult {
return profileFunction.getProfile()?.let { return profileFunction.getProfile()?.let {
setNewBasalProfile(it) setNewBasalProfile(it, OmnipodCommandType.SET_TIME)
} ?: PumpEnactResult(injector).success(true).enacted(false).comment("No profile active") } ?: PumpEnactResult(injector).success(true).enacted(false).comment("No profile active")
} }

View file

@ -641,7 +641,6 @@ class OmnipodDashManagerImpl @Inject constructor(
observeConnectToPod, observeConnectToPod,
observeSendDeactivateCommand observeSendDeactivateCommand
).interceptPodEvents() ).interceptPodEvents()
.doOnComplete(podStateManager::reset)
} }
inner class PodEventInterceptor : Consumer<PodEvent> { inner class PodEventInterceptor : Consumer<PodEvent> {

View file

@ -36,9 +36,7 @@ class DashHistory @Inject constructor(
fun getById(id: String): HistoryRecord { fun getById(id: String): HistoryRecord {
val entry = dao.byIdBlocking(id) val entry = dao.byIdBlocking(id)
if (entry == null) { ?: throw java.lang.IllegalArgumentException("history entry [$id] not found")
throw java.lang.IllegalArgumentException("history entry [$id] not found")
}
return historyMapper.entityToDomain(entry) return historyMapper.entityToDomain(entry)
} }
@ -81,8 +79,8 @@ class DashHistory @Inject constructor(
fun getRecords(): Single<List<HistoryRecord>> = fun getRecords(): Single<List<HistoryRecord>> =
dao.all().map { list -> list.map(historyMapper::entityToDomain) } dao.all().map { list -> list.map(historyMapper::entityToDomain) }
fun getRecordsAfter(time: Long): Single<List<HistoryRecordEntity>> = fun getRecordsAfter(time: Long): Single<List<HistoryRecord>> =
dao.allSince(time) dao.allSince(time).map { list -> list.map(historyMapper::entityToDomain) }
fun updateFromState(podState: OmnipodDashPodStateManager) = Completable.defer { fun updateFromState(podState: OmnipodDashPodStateManager) = Completable.defer {
val historyId = podState.activeCommand?.historyId val historyId = podState.activeCommand?.historyId

View file

@ -18,4 +18,15 @@ data class HistoryRecord(
val entropy = ULID.getEntropy(id) val entropy = ULID.getEntropy(id)
return ByteBuffer.wrap(entropy).long return ByteBuffer.wrap(entropy).long
} }
fun displayTimestamp(): Long {
resolvedAt?.let {
return it
}
return date
}
fun isSuccess(): Boolean {
return initialResult == InitialResult.SENT && resolvedResult == ResolvedResult.SUCCESS
}
} }

View file

@ -19,7 +19,7 @@ abstract class HistoryRecordDao {
@Query("SELECT * from historyrecords") @Query("SELECT * from historyrecords")
abstract fun allBlocking(): List<HistoryRecordEntity> abstract fun allBlocking(): List<HistoryRecordEntity>
@Query("SELECT * from historyrecords WHERE createdAt >= :since") @Query("SELECT * from historyrecords WHERE createdAt >= :since ORDER BY createdAt DESC")
abstract fun allSince(since: Long): Single<List<HistoryRecordEntity>> abstract fun allSince(since: Long): Single<List<HistoryRecordEntity>>
@Query("SELECT * FROM historyrecords WHERE id = :id LIMIT 1") @Query("SELECT * FROM historyrecords WHERE id = :id LIMIT 1")

View file

@ -22,15 +22,4 @@ data class HistoryRecordEntity(
@Embedded(prefix = "basalprofile_") val basalProfileRecord: BasalValuesRecord?, @Embedded(prefix = "basalprofile_") val basalProfileRecord: BasalValuesRecord?,
val resolvedResult: ResolvedResult?, val resolvedResult: ResolvedResult?,
val resolvedAt: Long? val resolvedAt: Long?
) { )
fun displayTimestamp(): Long {
resolvedAt?.let {
return it
}
return date
}
fun isSuccess(): Boolean {
return initialResult == InitialResult.SENT && resolvedResult == ResolvedResult.SUCCESS
}
}

View file

@ -16,13 +16,13 @@ import info.nightscout.androidaps.activities.NoSplashAppCompatActivity
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.pump.common.defs.PumpHistoryEntryGroup import info.nightscout.androidaps.plugins.pump.common.defs.PumpHistoryEntryGroup
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil
import info.nightscout.androidaps.plugins.pump.common.utils.ProfileUtil
import info.nightscout.androidaps.plugins.pump.omnipod.common.definition.OmnipodCommandType import info.nightscout.androidaps.plugins.pump.omnipod.common.definition.OmnipodCommandType
import info.nightscout.androidaps.plugins.pump.omnipod.dash.R import info.nightscout.androidaps.plugins.pump.omnipod.dash.R
import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.DashHistory import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.DashHistory
import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.InitialResult import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.*
import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.ResolvedResult
import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.database.HistoryRecordEntity
import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.rx.AapsSchedulers
import java.util.* import java.util.*
import javax.inject.Inject import javax.inject.Inject
@ -37,16 +37,15 @@ class DashPodHistoryActivity : NoSplashAppCompatActivity() {
private var statusView: TextView? = null private var statusView: TextView? = null
private var recyclerView: RecyclerView? = null private var recyclerView: RecyclerView? = null
private var linearLayoutManager: LinearLayoutManager? = null private var linearLayoutManager: LinearLayoutManager? = null
private val fullHistoryList: MutableList<HistoryRecordEntity> = ArrayList<HistoryRecordEntity>() private val fullHistoryList: MutableList<HistoryRecord> = ArrayList<HistoryRecord>()
private val filteredHistoryList: MutableList<HistoryRecordEntity> = ArrayList<HistoryRecordEntity>() private val filteredHistoryList: MutableList<HistoryRecord> = ArrayList<HistoryRecord>()
private var recyclerViewAdapter: RecyclerViewAdapter? = null private var recyclerViewAdapter: RecyclerViewAdapter? = null
private var manualChange = false private var manualChange = false
private var typeListFull: List<TypeList>? = null private var typeListFull: List<TypeList>? = null
private fun prepareData() { private fun prepareData() {
val gc = GregorianCalendar() val gc = GregorianCalendar()
// TODO: limit to the last 3 days. Using 30days here for testing gc.add(Calendar.DAY_OF_MONTH, -DAYS_TO_DISPLAY)
gc.add(Calendar.DAY_OF_MONTH, -30)
val since = gc.timeInMillis val since = gc.timeInMillis
val records = dashHistory.getRecordsAfter(since) val records = dashHistory.getRecordsAfter(since)
@ -134,10 +133,6 @@ class DashPodHistoryActivity : NoSplashAppCompatActivity() {
manualChange = false manualChange = false
} }
override fun onPause() {
super.onPause()
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -195,9 +190,9 @@ class DashPodHistoryActivity : NoSplashAppCompatActivity() {
} }
} }
inner class RecyclerViewAdapter internal constructor(historyList: List<HistoryRecordEntity>) : RecyclerView.Adapter<RecyclerViewAdapter.HistoryViewHolder>() { inner class RecyclerViewAdapter internal constructor(historyList: List<HistoryRecord>) : RecyclerView.Adapter<RecyclerViewAdapter.HistoryViewHolder>() {
var historyList: List<HistoryRecordEntity> = historyList var historyList: List<HistoryRecord> = historyList
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): HistoryViewHolder { override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): HistoryViewHolder {
val v: View = LayoutInflater.from(viewGroup.context).inflate( val v: View = LayoutInflater.from(viewGroup.context).inflate(
@ -208,19 +203,19 @@ class DashPodHistoryActivity : NoSplashAppCompatActivity() {
} }
override fun onBindViewHolder(holder: HistoryViewHolder, position: Int) { override fun onBindViewHolder(holder: HistoryViewHolder, position: Int) {
val record: HistoryRecordEntity = historyList[position] val record: HistoryRecord = historyList[position]
record?.let { record?.let {
holder.timeView.text = DateTimeUtil.toStringFromTimeInMillis(record.displayTimestamp()) holder.timeView.text = DateTimeUtil.toStringFromTimeInMillis(it.displayTimestamp())
setValue(record, holder.valueView) setValue(it, holder.valueView)
setType(record, holder.typeView) setType(it, holder.typeView)
} }
} }
private fun setType(record: HistoryRecordEntity, typeView: TextView) { private fun setType(record: HistoryRecord, typeView: TextView) {
typeView.text = resourceHelper.gs(record.commandType.resourceId) typeView.text = resourceHelper.gs(record.commandType.resourceId)
} }
private fun setValue(historyEntry: HistoryRecordEntity, valueView: TextView) { private fun setValue(historyEntry: HistoryRecord, valueView: TextView) {
valueView.text = historyEntry.toString() valueView.text = historyEntry.toString()
// val entryType = historyEntry.commandType // val entryType = historyEntry.commandType
if (!historyEntry.isSuccess()) { if (!historyEntry.isSuccess()) {
@ -229,44 +224,33 @@ class DashPodHistoryActivity : NoSplashAppCompatActivity() {
} }
valueView.text = when (historyEntry.commandType) { valueView.text = when (historyEntry.commandType) {
OmnipodCommandType.SET_TEMPORARY_BASAL -> { OmnipodCommandType.SET_TEMPORARY_BASAL -> {
val tbr = historyEntry.tempBasalRecord val tbr = historyEntry.record as TempBasalRecord
tbr?.let { tbr?.let {
resourceHelper.gs(R.string.omnipod_common_history_tbr_value, it.rate, it.duration) resourceHelper.gs(R.string.omnipod_common_history_tbr_value, it.rate, it.duration)
} ?: "n/a" } ?: "n/a"
} }
OmnipodCommandType.SET_BOLUS -> { OmnipodCommandType.SET_BOLUS -> {
val bolus = historyEntry.bolusRecord val bolus = historyEntry.record as BolusRecord
bolus?.let { bolus?.let {
resourceHelper.gs(R.string.omnipod_common_history_bolus_value, it.amout) resourceHelper.gs(R.string.omnipod_common_history_bolus_value, it.amout)
} ?: "n/a" } ?: "n/a"
} }
OmnipodCommandType.SET_BASAL_PROFILE,
OmnipodCommandType.SET_TIME,
OmnipodCommandType.INSERT_CANNULA,
OmnipodCommandType.RESUME_DELIVERY -> {
val basal = historyEntry.record as BasalValuesRecord
ProfileUtil.getBasalProfilesDisplayable(basal.segments.toTypedArray(), PumpType.OMNIPOD_DASH)
}
else -> else ->
"" ""
} }
} }
private fun setProfileValue(data: String, valueView: TextView) {
aapsLogger.debug(LTag.PUMP, "Profile json:\n$data")
valueView.text = "Profile informations from history"
/*
try {
Profile.ProfileValue[] profileValuesArray = aapsOmnipodUtil.getGsonInstance().fromJson(data, Profile.ProfileValue[].class);
valueView.setText(ProfileUtil.INSTANCE.getBasalProfilesDisplayable(profileValuesArray, PumpType.OMNIPOD_EROS));
} catch (Exception e) {
aapsLogger.error(LTag.PUMP, "Problem parsing Profile json. Ex: {}, Data:\n{}", e.getMessage(), data);
valueView.setText("");
}
*/
}
override fun getItemCount(): Int { override fun getItemCount(): Int {
return historyList.size return historyList.size
} }
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
super.onAttachedToRecyclerView(recyclerView)
}
inner class HistoryViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { inner class HistoryViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val timeView: TextView = itemView.findViewById(R.id.omnipod_history_time) val timeView: TextView = itemView.findViewById(R.id.omnipod_history_time)
val typeView: TextView = itemView.findViewById(R.id.omnipod_history_source) val typeView: TextView = itemView.findViewById(R.id.omnipod_history_source)
@ -274,7 +258,7 @@ class DashPodHistoryActivity : NoSplashAppCompatActivity() {
} }
} }
private fun translatedFailure(historyEntry: HistoryRecordEntity): Int { private fun translatedFailure(historyEntry: HistoryRecord): Int {
return when { return when {
historyEntry.initialResult == InitialResult.FAILURE_SENDING -> historyEntry.initialResult == InitialResult.FAILURE_SENDING ->
R.string.omnipod_dash_failed_to_send R.string.omnipod_dash_failed_to_send
@ -290,5 +274,6 @@ class DashPodHistoryActivity : NoSplashAppCompatActivity() {
companion object { companion object {
private var selectedGroup: PumpHistoryEntryGroup = PumpHistoryEntryGroup.All private var selectedGroup: PumpHistoryEntryGroup = PumpHistoryEntryGroup.All
const val DAYS_TO_DISPLAY = 5
} }
} }

View file

@ -12,6 +12,8 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.OmnipodDashMa
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertTrigger import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertTrigger
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManager import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManager
import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.DashHistory import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.DashHistory
import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.InitialResult
import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.ResolvedResult
import info.nightscout.androidaps.plugins.pump.omnipod.dash.util.I8n import info.nightscout.androidaps.plugins.pump.omnipod.dash.util.I8n
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
@ -48,7 +50,14 @@ class DashInitializePodViewModel @Inject constructor(
super.disposable += omnipodManager.activatePodPart1(lowReservoirAlertTrigger) super.disposable += omnipodManager.activatePodPart1(lowReservoirAlertTrigger)
.ignoreElements() .ignoreElements()
.andThen(podStateManager.updateLowReservoirAlertSettings(lowReservoirAlertEnabled, lowReservoirAlertUnits)) .andThen(podStateManager.updateLowReservoirAlertSettings(lowReservoirAlertEnabled, lowReservoirAlertUnits))
.andThen(history.createRecord(OmnipodCommandType.INITIALIZE_POD).ignoreElement()) .andThen(
history.createRecord(
OmnipodCommandType.INITIALIZE_POD,
initialResult = InitialResult.SENT,
resolveResult = ResolvedResult.SUCCESS,
resolvedAt = System.currentTimeMillis(),
).ignoreElement()
)
.subscribeBy( .subscribeBy(
onError = { throwable -> onError = { throwable ->
logger.error(LTag.PUMP, "Error in Pod activation part 1", throwable) logger.error(LTag.PUMP, "Error in Pod activation part 1", throwable)

View file

@ -18,6 +18,9 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.R
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.OmnipodDashManager import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.OmnipodDashManager
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManager import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManager
import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.DashHistory import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.DashHistory
import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.BasalValuesRecord
import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.InitialResult
import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.ResolvedResult
import info.nightscout.androidaps.plugins.pump.omnipod.dash.util.Constants import info.nightscout.androidaps.plugins.pump.omnipod.dash.util.Constants
import info.nightscout.androidaps.plugins.pump.omnipod.dash.util.I8n import info.nightscout.androidaps.plugins.pump.omnipod.dash.util.I8n
import info.nightscout.androidaps.plugins.pump.omnipod.dash.util.mapProfileToBasalProgram import info.nightscout.androidaps.plugins.pump.omnipod.dash.util.mapProfileToBasalProgram
@ -70,7 +73,15 @@ class DashInsertCannulaViewModel @Inject constructor(
super.disposable += omnipodManager.activatePodPart2(basalProgram, expirationHoursBeforeShutdown) super.disposable += omnipodManager.activatePodPart2(basalProgram, expirationHoursBeforeShutdown)
.ignoreElements() .ignoreElements()
.andThen(podStateManager.updateExpirationAlertSettings(expirationReminderEnabled, expirationHours)) .andThen(podStateManager.updateExpirationAlertSettings(expirationReminderEnabled, expirationHours))
.andThen(history.createRecord(OmnipodCommandType.INSERT_CANNULA).ignoreElement()) .andThen(
history.createRecord(
OmnipodCommandType.INSERT_CANNULA,
basalProfileRecord = BasalValuesRecord(profile.getBasalValues().toList()),
initialResult = InitialResult.SENT,
resolveResult = ResolvedResult.SUCCESS,
resolvedAt = System.currentTimeMillis(),
).ignoreElement()
)
.subscribeBy( .subscribeBy(
onError = { throwable -> onError = { throwable ->
logger.error(LTag.PUMP, "Error in Pod activation part 2", throwable) logger.error(LTag.PUMP, "Error in Pod activation part 2", throwable)