Merge branch '0pen-dash-dash-history' into dev

This commit is contained in:
Milos Kozak 2021-10-28 21:07:57 +02:00
commit 7365986286
27 changed files with 545 additions and 86 deletions

View file

@ -1,36 +0,0 @@
package info.nightscout.androidaps.plugins.pump.omnipod.common.definition;
import info.nightscout.androidaps.plugins.pump.omnipod.common.R;
/**
* Created by andy on 4.8.2019
*/
public enum OmnipodCommandType {
INITIALIZE_POD(R.string.omnipod_common_cmd_initialize_pod), // First step of Pod activation
INSERT_CANNULA(R.string.omnipod_common_cmd_insert_cannula), // Second step of Pod activation
DEACTIVATE_POD(R.string.omnipod_common_cmd_deactivate_pod), //
SET_BASAL_PROFILE(R.string.omnipod_common_cmd_set_basal_schedule), //
SET_BOLUS(R.string.omnipod_common_cmd_set_bolus), //
CANCEL_BOLUS(R.string.omnipod_common_cmd_cancel_bolus), //
SET_TEMPORARY_BASAL(R.string.omnipod_common_cmd_set_tbr), //
CANCEL_TEMPORARY_BASAL(R.string.omnipod_common_cmd_cancel_tbr_by_driver), //
DISCARD_POD(R.string.omnipod_common_cmd_discard_pod), //
GET_POD_STATUS(R.string.omnipod_common_cmd_get_pod_status), //
SET_TIME(R.string.omnipod_common_cmd_set_time), //
CONFIGURE_ALERTS(R.string.omnipod_common_cmd_configure_alerts), //
ACKNOWLEDGE_ALERTS(R.string.omnipod_common_cmd_silence_alerts), //
READ_POD_PULSE_LOG(R.string.omnipod_common_cmd_read_pulse_log), //
SUSPEND_DELIVERY(R.string.omnipod_common_cmd_suspend_delivery),
RESUME_DELIVERY(R.string.omnipod_common_cmd_resume_delivery),
PLAY_TEST_BEEP(R.string.omnipod_common_cmd_play_test_beep);
private final int resourceId;
OmnipodCommandType(int resourceId) {
this.resourceId = resourceId;
}
public int getResourceId() {
return resourceId;
}
}

View file

@ -0,0 +1,26 @@
package info.nightscout.androidaps.plugins.pump.omnipod.common.definition
import info.nightscout.androidaps.plugins.pump.omnipod.common.R
/**
* Created by andy on 4.8.2019
*/
enum class OmnipodCommandType(val resourceId: Int) {
INITIALIZE_POD(R.string.omnipod_common_cmd_initialize_pod), // First step of Pod activation
INSERT_CANNULA(R.string.omnipod_common_cmd_insert_cannula), // Second step of Pod activation
DEACTIVATE_POD(R.string.omnipod_common_cmd_deactivate_pod), //
SET_BASAL_PROFILE(R.string.omnipod_common_cmd_set_basal_schedule), //
SET_BOLUS(R.string.omnipod_common_cmd_set_bolus), //
CANCEL_BOLUS(R.string.omnipod_common_cmd_cancel_bolus), //
SET_TEMPORARY_BASAL(R.string.omnipod_common_cmd_set_tbr), //
CANCEL_TEMPORARY_BASAL(R.string.omnipod_common_cmd_cancel_tbr_by_driver), //
DISCARD_POD(R.string.omnipod_common_cmd_discard_pod), //
GET_POD_STATUS(R.string.omnipod_common_cmd_get_pod_status), //
SET_TIME(R.string.omnipod_common_cmd_set_time), //
CONFIGURE_ALERTS(R.string.omnipod_common_cmd_configure_alerts), //
ACKNOWLEDGE_ALERTS(R.string.omnipod_common_cmd_silence_alerts), //
READ_POD_PULSE_LOG(R.string.omnipod_common_cmd_read_pulse_log), //
SUSPEND_DELIVERY(R.string.omnipod_common_cmd_suspend_delivery), RESUME_DELIVERY(R.string.omnipod_common_cmd_resume_delivery), PLAY_TEST_BEEP(R.string.omnipod_common_cmd_play_test_beep);
}

View file

@ -22,10 +22,12 @@ detekt { // TODO move to `subprojects` section in global build.gradle
dependencies { dependencies {
implementation project(':core') implementation project(':core')
implementation project(':pump-common')
implementation project(':omnipod-common') implementation project(':omnipod-common')
implementation "androidx.room:room-runtime:$room_version" implementation "androidx.room:room-runtime:$room_version"
implementation "androidx.room:room-rxjava2:$room_version" implementation "androidx.room:room-rxjava2:$room_version"
implementation project(path: ':pump-common')
kapt "androidx.room:room-compiler:$room_version" kapt "androidx.room:room-compiler:$room_version"
implementation 'com.github.guepardoapps:kulid:2.0.0.0' implementation 'com.github.guepardoapps:kulid:2.0.0.0'
} }

View file

@ -11,5 +11,6 @@
<activity android:name=".ui.wizard.activation.DashPodActivationWizardActivity" /> <activity android:name=".ui.wizard.activation.DashPodActivationWizardActivity" />
<activity android:name=".ui.wizard.deactivation.DashPodDeactivationWizardActivity" /> <activity android:name=".ui.wizard.deactivation.DashPodDeactivationWizardActivity" />
<activity android:name=".ui.DashPodManagementActivity" /> <activity android:name=".ui.DashPodManagementActivity" />
<activity android:name=".ui.DashPodHistoryActivity" />
</application> </application>
</manifest> </manifest>

View file

@ -36,6 +36,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.state.CommandConfirmed import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.state.CommandConfirmed
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.BolusRecord import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.BolusRecord
import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.BolusType import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.BolusType
import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.TempBasalRecord import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.TempBasalRecord
@ -363,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) {
@ -372,7 +377,10 @@ class OmnipodDashPumpPlugin @Inject constructor(
deliverySuspended = true deliverySuspended = true
} }
}, },
historyEntry = history.createRecord(commandType = OmnipodCommandType.SET_BASAL_PROFILE), historyEntry = history.createRecord(
commandType = historyType,
basalProfileRecord = BasalValuesRecord(profile.getBasalValues().toList())
),
activeCommandEntry = { historyId -> activeCommandEntry = { historyId ->
podStateManager.createActiveCommand(historyId, basalProgram = basalProgram) podStateManager.createActiveCommand(historyId, basalProgram = basalProgram)
}, },
@ -1139,7 +1147,7 @@ class OmnipodDashPumpPlugin @Inject constructor(
return profileFunction.getProfile()?.let { return profileFunction.getProfile()?.let {
executeProgrammingCommand( executeProgrammingCommand(
pre = observeDeliverySuspended(), pre = observeDeliverySuspended(),
historyEntry = history.createRecord(OmnipodCommandType.RESUME_DELIVERY), historyEntry = history.createRecord(OmnipodCommandType.RESUME_DELIVERY, basalProfileRecord = BasalValuesRecord(it.getBasalValues().toList())),
command = omnipodManager.setBasalProgram(mapProfileToBasalProgram(it), hasBasalBeepEnabled()) command = omnipodManager.setBasalProgram(mapProfileToBasalProgram(it), hasBasalBeepEnabled())
.ignoreElements() .ignoreElements()
).doFinally { ).doFinally {
@ -1153,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
@ -1170,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")
} }
@ -1181,7 +1193,7 @@ class OmnipodDashPumpPlugin @Inject constructor(
val lowReservoirAlertEnabled = sp.getBoolean(R.string.key_omnipod_common_low_reservoir_alert_enabled, true) val lowReservoirAlertEnabled = sp.getBoolean(R.string.key_omnipod_common_low_reservoir_alert_enabled, true)
val lowReservoirAlertUnits = sp.getInt(R.string.key_omnipod_common_low_reservoir_alert_units, 10) val lowReservoirAlertUnits = sp.getInt(R.string.key_omnipod_common_low_reservoir_alert_units, 10)
if (!podStateManager.differentAlertSettings( if (podStateManager.sameAlertSettings(
expirationReminderEnabled, expirationReminderEnabled,
expirationHours, expirationHours,
lowReservoirAlertEnabled, lowReservoirAlertEnabled,

View file

@ -11,6 +11,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.OmnipodD
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.OmnipodDashBleManagerImpl import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.OmnipodDashBleManagerImpl
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.driver.pod.state.OmnipodDashPodStateManagerImpl import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManagerImpl
import info.nightscout.androidaps.plugins.pump.omnipod.dash.ui.DashPodHistoryActivity
import info.nightscout.androidaps.plugins.pump.omnipod.dash.ui.DashPodManagementActivity import info.nightscout.androidaps.plugins.pump.omnipod.dash.ui.DashPodManagementActivity
import info.nightscout.androidaps.plugins.pump.omnipod.dash.ui.OmnipodDashOverviewFragment import info.nightscout.androidaps.plugins.pump.omnipod.dash.ui.OmnipodDashOverviewFragment
import info.nightscout.androidaps.plugins.pump.omnipod.dash.ui.wizard.activation.DashPodActivationWizardActivity import info.nightscout.androidaps.plugins.pump.omnipod.dash.ui.wizard.activation.DashPodActivationWizardActivity
@ -21,6 +22,9 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.ui.wizard.deactivati
abstract class OmnipodDashModule { abstract class OmnipodDashModule {
// ACTIVITIES // ACTIVITIES
@ContributesAndroidInjector
abstract fun contributesDashPodHistoryActivity(): DashPodHistoryActivity
@ContributesAndroidInjector @ContributesAndroidInjector
abstract fun contributesDashPodManagementActivity(): DashPodManagementActivity abstract fun contributesDashPodManagementActivity(): DashPodManagementActivity

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

@ -105,7 +105,7 @@ interface OmnipodDashPodStateManager {
- after getPodStatus was successful(we have an up-to-date podStatus) - after getPodStatus was successful(we have an up-to-date podStatus)
*/ */
fun recoverActivationFromPodStatus(): String? fun recoverActivationFromPodStatus(): String?
fun differentAlertSettings(expirationReminderEnabled: Boolean, expirationHours: Int, lowReservoirAlertEnabled: Boolean, lowReservoirAlertUnits: Int): Boolean fun sameAlertSettings(expirationReminderEnabled: Boolean, expirationHours: Int, lowReservoirAlertEnabled: Boolean, lowReservoirAlertUnits: Int): Boolean
fun updateExpirationAlertSettings(expirationReminderEnabled: Boolean, expirationHours: Int): Completable fun updateExpirationAlertSettings(expirationReminderEnabled: Boolean, expirationHours: Int): Completable
fun updateLowReservoirAlertSettings(lowReservoirAlertEnabled: Boolean, lowReservoirAlertUnits: Int): Completable fun updateLowReservoirAlertSettings(lowReservoirAlertEnabled: Boolean, lowReservoirAlertUnits: Int): Completable

View file

@ -435,7 +435,7 @@ class OmnipodDashPodStateManagerImpl @Inject constructor(
} }
} }
override fun differentAlertSettings( override fun sameAlertSettings(
expirationReminderEnabled: Boolean, expirationReminderEnabled: Boolean,
expirationHours: Int, expirationHours: Int,
lowReservoirAlertEnabled: Boolean, lowReservoirAlertEnabled: Boolean,

View file

@ -7,11 +7,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.common.definition.Omnipod
import info.nightscout.androidaps.plugins.pump.omnipod.common.definition.OmnipodCommandType.SET_BOLUS import info.nightscout.androidaps.plugins.pump.omnipod.common.definition.OmnipodCommandType.SET_BOLUS
import info.nightscout.androidaps.plugins.pump.omnipod.common.definition.OmnipodCommandType.SET_TEMPORARY_BASAL import info.nightscout.androidaps.plugins.pump.omnipod.common.definition.OmnipodCommandType.SET_TEMPORARY_BASAL
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.state.* import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.state.*
import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.BolusRecord import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.*
import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.HistoryRecord
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.history.data.TempBasalRecord
import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.database.HistoryRecordDao import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.database.HistoryRecordDao
import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.database.HistoryRecordEntity import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.database.HistoryRecordEntity
import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.mapper.HistoryMapper import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.mapper.HistoryMapper
@ -40,19 +36,18 @@ 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)
} }
@Suppress("ReturnCount") @Suppress("ReturnCount")
fun createRecord( fun createRecord(
commandType: OmnipodCommandType, commandType: OmnipodCommandType,
date: Long = System.currentTimeMillis(), date: Long = currentTimeMillis(),
initialResult: InitialResult = InitialResult.NOT_SENT, initialResult: InitialResult = InitialResult.NOT_SENT,
tempBasalRecord: TempBasalRecord? = null, tempBasalRecord: TempBasalRecord? = null,
bolusRecord: BolusRecord? = null, bolusRecord: BolusRecord? = null,
basalProfileRecord: BasalValuesRecord? = null,
resolveResult: ResolvedResult? = null, resolveResult: ResolvedResult? = null,
resolvedAt: Long? = null resolvedAt: Long? = null
): Single<String> = Single.defer { ): Single<String> = Single.defer {
@ -72,6 +67,7 @@ class DashHistory @Inject constructor(
commandType = commandType, commandType = commandType,
tempBasalRecord = tempBasalRecord, tempBasalRecord = tempBasalRecord,
bolusRecord = bolusRecord, bolusRecord = bolusRecord,
basalProfileRecord = basalProfileRecord,
initialResult = initialResult, initialResult = initialResult,
resolvedResult = resolveResult, resolvedResult = resolveResult,
resolvedAt = resolvedAt resolvedAt = resolvedAt
@ -83,7 +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>> = dao.allSince(time) fun getRecordsAfter(time: Long): Single<List<HistoryRecord>> =
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,12 @@ 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 {
return date
}
fun isSuccess(): Boolean {
return initialResult == InitialResult.SENT && resolvedResult == ResolvedResult.SUCCESS
}
} }

View file

@ -1,6 +1,7 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data package info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data
import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.interfaces.Profile
sealed class Record sealed class Record
@ -8,6 +9,8 @@ data class BolusRecord(val amout: Double, val bolusType: BolusType) : Record()
data class TempBasalRecord(val duration: Int, val rate: Double) : Record() data class TempBasalRecord(val duration: Int, val rate: Double) : Record()
data class BasalValuesRecord(val segments: List<Profile.ProfileValue>) : Record()
enum class BolusType { enum class BolusType {
DEFAULT, SMB; DEFAULT, SMB;

View file

@ -1,7 +1,7 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data package info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data
enum class InitialResult { enum class InitialResult {
NOT_SENT, FAILURE_SENDING, UNCONFIRMED, SENT NOT_SENT, FAILURE_SENDING, SENT
} }
enum class ResolvedResult { enum class ResolvedResult {

View file

@ -1,6 +1,8 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.history.database package info.nightscout.androidaps.plugins.pump.omnipod.dash.history.database
import androidx.room.TypeConverter import androidx.room.TypeConverter
import com.google.gson.GsonBuilder
import info.nightscout.androidaps.interfaces.Profile
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.history.data.BolusType import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.BolusType
import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.InitialResult import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.InitialResult
@ -31,4 +33,17 @@ class Converters {
@TypeConverter @TypeConverter
fun fromOmnipodCommandType(omnipodCommandType: OmnipodCommandType) = omnipodCommandType.name fun fromOmnipodCommandType(omnipodCommandType: OmnipodCommandType) = omnipodCommandType.name
@TypeConverter
fun toSegments(s: String?): List<Profile.ProfileValue> {
s ?: return emptyList()
val gson = GsonBuilder().create()
return gson.fromJson(s, Array<Profile.ProfileValue>::class.java).toList()
}
@TypeConverter
fun fromBasalValues(segments: List<Profile.ProfileValue>): String {
val gson = GsonBuilder().create()
return gson.toJson(segments)
}
} }

View file

@ -18,13 +18,13 @@ abstract class DashHistoryDatabase : RoomDatabase() {
companion object { companion object {
const val VERSION = 1 const val VERSION = 2
fun build(context: Context) = fun build(context: Context) =
Room.databaseBuilder( Room.databaseBuilder(
context.applicationContext, context.applicationContext,
DashHistoryDatabase::class.java, DashHistoryDatabase::class.java,
"omnipod_dash_history_database.db" "omnipod_dash_history_database.db",
) )
.fallbackToDestructiveMigration() .fallbackToDestructiveMigration()
.build() .build()

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

@ -4,6 +4,7 @@ import androidx.room.Embedded
import androidx.room.Entity import androidx.room.Entity
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
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.history.data.BasalValuesRecord
import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.BolusRecord import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.BolusRecord
import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.InitialResult 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.history.data.ResolvedResult
@ -18,6 +19,7 @@ data class HistoryRecordEntity(
val initialResult: InitialResult, val initialResult: InitialResult,
@Embedded(prefix = "tempBasalRecord_") val tempBasalRecord: TempBasalRecord?, @Embedded(prefix = "tempBasalRecord_") val tempBasalRecord: TempBasalRecord?,
@Embedded(prefix = "bolusRecord_") val bolusRecord: BolusRecord?, @Embedded(prefix = "bolusRecord_") val bolusRecord: BolusRecord?,
@Embedded(prefix = "basalprofile_") val basalProfileRecord: BasalValuesRecord?,
val resolvedResult: ResolvedResult?, val resolvedResult: ResolvedResult?,
val resolvedAt: Long? val resolvedAt: Long?
) )

View file

@ -1,5 +1,6 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.history.mapper package info.nightscout.androidaps.plugins.pump.omnipod.dash.history.mapper
import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.BasalValuesRecord
import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.BolusRecord import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.BolusRecord
import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.HistoryRecord import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.HistoryRecord
import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.TempBasalRecord import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.TempBasalRecord
@ -17,7 +18,8 @@ class HistoryMapper {
tempBasalRecord = historyRecord.record as? TempBasalRecord, tempBasalRecord = historyRecord.record as? TempBasalRecord,
bolusRecord = historyRecord.record as? BolusRecord, bolusRecord = historyRecord.record as? BolusRecord,
resolvedResult = historyRecord.resolvedResult, resolvedResult = historyRecord.resolvedResult,
resolvedAt = historyRecord.resolvedAt resolvedAt = historyRecord.resolvedAt,
basalProfileRecord = historyRecord.record as? BasalValuesRecord
) )
fun entityToDomain(entity: HistoryRecordEntity): HistoryRecord = fun entityToDomain(entity: HistoryRecordEntity): HistoryRecord =
@ -27,7 +29,7 @@ class HistoryMapper {
date = entity.date, date = entity.date,
initialResult = entity.initialResult, initialResult = entity.initialResult,
commandType = entity.commandType, commandType = entity.commandType,
record = entity.bolusRecord ?: entity.tempBasalRecord, record = entity.bolusRecord ?: entity.tempBasalRecord ?: entity.basalProfileRecord,
resolvedResult = entity.resolvedResult, resolvedResult = entity.resolvedResult,
resolvedAt = entity.resolvedAt resolvedAt = entity.resolvedAt
) )

View file

@ -0,0 +1,279 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.ui
// import info.nightscout.androidaps.plugins.pump.omnipod.dash.definition.PodHistoryEntryType;
// import info.nightscout.androidaps.plugins.pump.omnipod.dash.util.AapsOmnipodUtil;
import android.os.Bundle
import android.os.SystemClock
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.Spinner
import android.widget.TextView
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import info.nightscout.androidaps.activities.NoSplashAppCompatActivity
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
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.ProfileUtil
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.history.DashHistory
import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.*
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import java.util.*
import javax.inject.Inject
class DashPodHistoryActivity : NoSplashAppCompatActivity() {
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var dashHistory: DashHistory
@Inject lateinit var aapsSchedulers: AapsSchedulers
private var historyTypeSpinner: Spinner? = null
private var statusView: TextView? = null
private var recyclerView: RecyclerView? = null
private var linearLayoutManager: LinearLayoutManager? = null
private val fullHistoryList: MutableList<HistoryRecord> = ArrayList<HistoryRecord>()
private val filteredHistoryList: MutableList<HistoryRecord> = ArrayList<HistoryRecord>()
private var recyclerViewAdapter: RecyclerViewAdapter? = null
private var manualChange = false
private var typeListFull: List<TypeList>? = null
private fun prepareData() {
val gc = GregorianCalendar()
gc.add(Calendar.DAY_OF_MONTH, -DAYS_TO_DISPLAY)
val since = gc.timeInMillis
val records = dashHistory.getRecordsAfter(since)
.subscribeOn(aapsSchedulers.io)
.blockingGet()
fullHistoryList.addAll(records)
}
private fun groupForCommandType(type: OmnipodCommandType): PumpHistoryEntryGroup {
return when (type) {
OmnipodCommandType.INITIALIZE_POD ->
PumpHistoryEntryGroup.Prime
OmnipodCommandType.INSERT_CANNULA ->
PumpHistoryEntryGroup.Prime
OmnipodCommandType.DEACTIVATE_POD ->
PumpHistoryEntryGroup.Prime
OmnipodCommandType.DISCARD_POD ->
PumpHistoryEntryGroup.Prime
OmnipodCommandType.CANCEL_TEMPORARY_BASAL ->
PumpHistoryEntryGroup.Basal
OmnipodCommandType.SET_BASAL_PROFILE ->
PumpHistoryEntryGroup.Basal
OmnipodCommandType.SET_TEMPORARY_BASAL ->
PumpHistoryEntryGroup.Basal
OmnipodCommandType.RESUME_DELIVERY ->
PumpHistoryEntryGroup.Basal
OmnipodCommandType.SUSPEND_DELIVERY ->
PumpHistoryEntryGroup.Basal
OmnipodCommandType.SET_BOLUS ->
PumpHistoryEntryGroup.Bolus
OmnipodCommandType.CANCEL_BOLUS ->
PumpHistoryEntryGroup.Bolus
OmnipodCommandType.ACKNOWLEDGE_ALERTS ->
PumpHistoryEntryGroup.Alarm
OmnipodCommandType.CONFIGURE_ALERTS ->
PumpHistoryEntryGroup.Alarm
OmnipodCommandType.PLAY_TEST_BEEP ->
PumpHistoryEntryGroup.Alarm
OmnipodCommandType.GET_POD_STATUS ->
PumpHistoryEntryGroup.Configuration
OmnipodCommandType.SET_TIME ->
PumpHistoryEntryGroup.Configuration
OmnipodCommandType.READ_POD_PULSE_LOG ->
PumpHistoryEntryGroup.Unknown
}
}
private fun filterHistory(group: PumpHistoryEntryGroup) {
filteredHistoryList.clear()
aapsLogger.debug(LTag.PUMP, "Items on full list: {}", fullHistoryList.size)
if (group === PumpHistoryEntryGroup.All) {
filteredHistoryList.addAll(fullHistoryList)
} else {
filteredHistoryList.addAll(fullHistoryList.filter { groupForCommandType(it.commandType) == group })
}
recyclerViewAdapter?.let {
it.historyList = filteredHistoryList
it.notifyDataSetChanged()
}
aapsLogger.debug(LTag.PUMP, "Items on filtered list: {}", filteredHistoryList.size)
}
override fun onResume() {
super.onResume()
filterHistory(selectedGroup)
setHistoryTypeSpinner()
}
private fun setHistoryTypeSpinner() {
manualChange = true
val typeList = typeListFull
typeList?.let {
for (i in it.indices) {
if (it[i].entryGroup === selectedGroup) {
historyTypeSpinner!!.setSelection(i)
break
}
}
}
SystemClock.sleep(200)
manualChange = false
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.omnipod_dash_pod_history_activity)
prepareData()
recyclerView = findViewById(R.id.omnipod_history_recyclerview)
recyclerViewAdapter = RecyclerViewAdapter(filteredHistoryList)
linearLayoutManager = LinearLayoutManager(this)
recyclerView?.run {
setHasFixedSize(true)
layoutManager = linearLayoutManager
adapter = recyclerViewAdapter
}
statusView = findViewById(R.id.omnipod_historystatus)
statusView?.run { visibility = View.GONE }
historyTypeSpinner = findViewById(R.id.omnipod_historytype)
typeListFull = getTypeList(PumpHistoryEntryGroup.Companion.getTranslatedList(resourceHelper))
val spinnerAdapter: ArrayAdapter<TypeList> = ArrayAdapter<TypeList>(this, R.layout.spinner_centered, typeListFull!!)
historyTypeSpinner?.run {
adapter = spinnerAdapter
onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>?, view: View, position: Int, id: Long) {
if (manualChange) return
val selected = selectedItem as TypeList
selectedGroup = selected.entryGroup
filterHistory(selectedGroup)
}
override fun onNothingSelected(parent: AdapterView<*>?) {
if (manualChange) return
filterHistory(PumpHistoryEntryGroup.All)
}
}
}
}
private fun getTypeList(list: List<PumpHistoryEntryGroup>): List<TypeList> {
val typeList = ArrayList<TypeList>()
for (pumpHistoryEntryGroup in list) {
typeList.add(TypeList(pumpHistoryEntryGroup))
}
return typeList
}
internal class TypeList(entryGroup: PumpHistoryEntryGroup) {
val entryGroup: PumpHistoryEntryGroup = entryGroup
val name: String = entryGroup.translated ?: "XXX TODO"
override fun toString(): String {
return name
}
}
inner class RecyclerViewAdapter internal constructor(historyList: List<HistoryRecord>) : RecyclerView.Adapter<RecyclerViewAdapter.HistoryViewHolder>() {
var historyList: List<HistoryRecord> = historyList
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): HistoryViewHolder {
val v: View = LayoutInflater.from(viewGroup.context).inflate(
R.layout.omnipod_dash_pod_history_item,
viewGroup, false
)
return HistoryViewHolder(v)
}
override fun onBindViewHolder(holder: HistoryViewHolder, position: Int) {
val record: HistoryRecord = historyList[position]
record?.let {
holder.timeView.text = DateTimeUtil.toStringFromTimeInMillis(it.displayTimestamp())
setValue(it, holder.valueView)
setType(it, holder.typeView)
}
}
private fun setType(record: HistoryRecord, typeView: TextView) {
typeView.text = resourceHelper.gs(record.commandType.resourceId)
}
private fun setValue(historyEntry: HistoryRecord, valueView: TextView) {
valueView.text = historyEntry.toString()
// val entryType = historyEntry.commandType
if (!historyEntry.isSuccess()) {
valueView.text = resourceHelper.gs(translatedFailure(historyEntry))
return
}
valueView.text = when (historyEntry.commandType) {
OmnipodCommandType.SET_TEMPORARY_BASAL -> {
val tbr = historyEntry.record as TempBasalRecord
tbr?.let {
resourceHelper.gs(R.string.omnipod_common_history_tbr_value, it.rate, it.duration)
} ?: "n/a"
}
OmnipodCommandType.SET_BOLUS -> {
val bolus = historyEntry.record as BolusRecord
bolus?.let {
resourceHelper.gs(R.string.omnipod_common_history_bolus_value, it.amout)
} ?: "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 ->
""
}
}
override fun getItemCount(): Int {
return historyList.size
}
inner class HistoryViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val timeView: TextView = itemView.findViewById(R.id.omnipod_history_time)
val typeView: TextView = itemView.findViewById(R.id.omnipod_history_source)
val valueView: TextView = itemView.findViewById(R.id.omnipod_history_description)
}
}
private fun translatedFailure(historyEntry: HistoryRecord): Int {
return when {
historyEntry.initialResult == InitialResult.FAILURE_SENDING ->
R.string.omnipod_dash_failed_to_send
historyEntry.initialResult == InitialResult.NOT_SENT ->
R.string.omnipod_dash_command_not_sent
historyEntry.initialResult == InitialResult.SENT &&
historyEntry.resolvedResult == ResolvedResult.FAILURE ->
R.string.omnipod_dash_command_not_received_by_the_pod
else ->
R.string.omnipod_dash_unknown
}
}
companion object {
private var selectedGroup: PumpHistoryEntryGroup = PumpHistoryEntryGroup.All
const val DAYS_TO_DISPLAY = 5
}
}

View file

@ -96,6 +96,10 @@ class DashPodManagementActivity : NoSplashAppCompatActivity() {
} }
) )
} }
binding.buttonPodHistory.setOnClickListener {
startActivity(Intent(this, DashPodHistoryActivity::class.java))
}
} }
override fun onResume() { override fun onResume() {

View file

@ -5,11 +5,15 @@ import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.data.PumpEnactResult
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.omnipod.common.definition.OmnipodCommandType
import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.activation.viewmodel.action.InitializePodViewModel import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.activation.viewmodel.action.InitializePodViewModel
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.driver.OmnipodDashManager import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.OmnipodDashManager
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.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
@ -24,7 +28,9 @@ class DashInitializePodViewModel @Inject constructor(
logger: AAPSLogger, logger: AAPSLogger,
private val sp: SP, private val sp: SP,
private val podStateManager: OmnipodDashPodStateManager, private val podStateManager: OmnipodDashPodStateManager,
private val resourceHelper: ResourceHelper private val resourceHelper: ResourceHelper,
private val history: DashHistory,
) : InitializePodViewModel(injector, logger) { ) : InitializePodViewModel(injector, logger) {
override fun isPodInAlarm(): Boolean = false // TODO override fun isPodInAlarm(): Boolean = false // TODO
@ -41,13 +47,18 @@ class DashInitializePodViewModel @Inject constructor(
} else } else
null null
super.disposable += omnipodManager.activatePodPart1(lowReservoirAlertTrigger).subscribeBy( super.disposable += omnipodManager.activatePodPart1(lowReservoirAlertTrigger)
onNext = { podEvent -> .ignoreElements()
logger.debug( .andThen(podStateManager.updateLowReservoirAlertSettings(lowReservoirAlertEnabled, lowReservoirAlertUnits))
LTag.PUMP, .andThen(
"Received PodEvent in Pod activation part 1: $podEvent" history.createRecord(
OmnipodCommandType.INITIALIZE_POD,
initialResult = InitialResult.SENT,
resolveResult = ResolvedResult.SUCCESS,
resolvedAt = System.currentTimeMillis(),
).ignoreElement()
) )
}, .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)
source.onSuccess( source.onSuccess(
@ -58,7 +69,6 @@ class DashInitializePodViewModel @Inject constructor(
}, },
onComplete = { onComplete = {
logger.debug("Pod activation part 1 completed") logger.debug("Pod activation part 1 completed")
podStateManager.updateLowReservoirAlertSettings(lowReservoirAlertEnabled, lowReservoirAlertUnits)
source.onSuccess(PumpEnactResult(injector).success(true)) source.onSuccess(PumpEnactResult(injector).success(true))
} }
) )

View file

@ -12,10 +12,15 @@ import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
import info.nightscout.androidaps.plugins.pump.omnipod.common.definition.OmnipodCommandType
import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.activation.viewmodel.action.InsertCannulaViewModel import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.activation.viewmodel.action.InsertCannulaViewModel
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.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.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
@ -36,6 +41,7 @@ class DashInsertCannulaViewModel @Inject constructor(
private val sp: SP, private val sp: SP,
private val resourceHelper: ResourceHelper, private val resourceHelper: ResourceHelper,
private val fabricPrivacy: FabricPrivacy, private val fabricPrivacy: FabricPrivacy,
private val history: DashHistory,
injector: HasAndroidInjector, injector: HasAndroidInjector,
logger: AAPSLogger logger: AAPSLogger
@ -69,6 +75,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,
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)
@ -100,7 +115,6 @@ class DashInsertCannulaViewModel @Inject constructor(
pumpType = PumpType.OMNIPOD_DASH, pumpType = PumpType.OMNIPOD_DASH,
pumpSerial = podStateManager.uniqueId?.toString() ?: "n/a" pumpSerial = podStateManager.uniqueId?.toString() ?: "n/a"
) )
rxBus.send(EventDismissNotification(Notification.OMNIPOD_POD_NOT_ATTACHED)) rxBus.send(EventDismissNotification(Notification.OMNIPOD_POD_NOT_ATTACHED))
fabricPrivacy.logCustom("OmnipodDashPodActivated") fabricPrivacy.logCustom("OmnipodDashPodActivated")
source.onSuccess(PumpEnactResult(injector).success(true)) source.onSuccess(PumpEnactResult(injector).success(true))

View file

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin">
<LinearLayout
android:id="@+id/omnipod_historytop"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginEnd="20dp"
android:text="@string/omnipod_dash_history_type"
android:textAppearance="?android:attr/textAppearanceSmall" />
<Spinner
android:id="@+id/omnipod_historytype"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="20dp" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_marginEnd="5dp"
android:layout_weight="1"
android:background="@drawable/pillborder"
android:gravity="center_horizontal"
android:text="@string/omnipod_dash_history_title" />
</LinearLayout>
<TextView
android:id="@+id/omnipod_historystatus"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/omnipod_historytop"
android:layout_gravity="center_horizontal"
android:gravity="center_horizontal" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/omnipod_history_recyclerview"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_below="@+id/omnipod_historystatus" />
</RelativeLayout>

View file

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingStart="20dp"
android:paddingTop="10dp"
android:paddingEnd="20dp">
<TextView
android:id="@+id/omnipod_history_time"
android:layout_width="88dp"
android:layout_height="match_parent"
android:text="@string/omnipod_dash_history_item_date"
android:textSize="12sp" />
<TextView
android:id="@+id/omnipod_history_source"
android:layout_width="132dp"
android:layout_height="match_parent"
android:text="@string/omnipod_dash_history_item_source"
android:textSize="12sp" />
<TextView
android:id="@+id/omnipod_history_description"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:text="@string/omnipod_dash_history_item_description"
android:textSize="12sp" />
</LinearLayout>

View file

@ -111,6 +111,20 @@
app:layout_constraintRight_toLeftOf="@+id/Actions_Col_1_Row_2_vertical_guideline" app:layout_constraintRight_toLeftOf="@+id/Actions_Col_1_Row_2_vertical_guideline"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/button_pod_history"
style="?android:attr/buttonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:drawableTop="@drawable/ic_pod_management_pod_history"
android:text="@string/omnipod_common_pod_management_button_pod_history"
android:textAllCaps="false"
android:visibility="visible"
app:layout_constrainedHeight="@+id/Actions_Row_2_horizontal_guideline"
app:layout_constraintLeft_toRightOf="@+id/Actions_Col_1_Row_2_vertical_guideline"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.Guideline <androidx.constraintlayout.widget.Guideline
android:id="@+id/Actions_Col_1_Row_2_vertical_guideline" android:id="@+id/Actions_Col_1_Row_2_vertical_guideline"
android:layout_width="wrap_content" android:layout_width="wrap_content"

View file

@ -8,6 +8,16 @@
<!-- Omnipod Dash - Keys --> <!-- Omnipod Dash - Keys -->
<string name="key_omnipod_dash_pod_state" translatable="false">AAPS.OmnipodDash.pod_state</string> <string name="key_omnipod_dash_pod_state" translatable="false">AAPS.OmnipodDash.pod_state</string>
<!-- Omnipod Dash - History -->
<string name="omnipod_dash_history_title">Pod History</string>
<string name="omnipod_dash_history_item_description">Description</string>
<string name="omnipod_dash_history_item_source">Source</string>
<string name="omnipod_dash_history_item_date">Date</string>
<string name="omnipod_dash_history_type">Type:</string>
<string name="omnipod_dash_history_bolus_value">%1$.2f U</string>
<string name="omnipod_dash_history_bolus_value_with_carbs">%1$.2f U, CH=%2$.1f g</string>
<string name="omnipod_dash_history_tbr_value">Rate: %1$.2f U, duration: %2$d minutes</string>
<!-- Omnipod Dash - Overview --> <!-- Omnipod Dash - Overview -->
<string name="omnipod_dash_overview_bluetooth_status">Bluetooth Status</string> <string name="omnipod_dash_overview_bluetooth_status">Bluetooth Status</string>
<string name="omnipod_dash_overview_bluetooth_address">Bluetooth Address</string> <string name="omnipod_dash_overview_bluetooth_address">Bluetooth Address</string>
@ -30,4 +40,10 @@
<string name="omnipod_dash_found_too_many_pods">Found too many pods for activation</string> <string name="omnipod_dash_found_too_many_pods">Found too many pods for activation</string>
<string name="omnipod_dash_scan_failed">Could not find an available pod for activation</string> <string name="omnipod_dash_scan_failed">Could not find an available pod for activation</string>
<string name="omnipod_dash_generic_error">Generic error: %1$s</string> <string name="omnipod_dash_generic_error">Generic error: %1$s</string>
<string name="omnipod_dash_failed_to_send">Failed to send the command</string>
<string name="omnipod_dash_command_not_sent">Command not sent</string>
<string name="omnipod_dash_command_not_received_by_the_pod">Command not received by the pod</string>
<string name="omnipod_dash_unknown">Unknown state for the command</string>
<string name="omnipod_common_history_tbr_value">Rate: %1$.2f U, duration: %2$d minutes</string>
<string name="omnipod_common_history_bolus_value">%1$.2f U</string>
</resources> </resources>

View file

@ -25,8 +25,9 @@ object ProfileUtil {
val basalValueValue = pumpType.determineCorrectBasalSize(basalValue.value) val basalValueValue = pumpType.determineCorrectBasalSize(basalValue.value)
val hour = basalValue.timeAsSeconds / (60 * 60) val hour = basalValue.timeAsSeconds / (60 * 60)
stringBuilder.append((if (hour < 10) "0" else "") + hour + ":00") stringBuilder.append((if (hour < 10) "0" else "") + hour + ":00")
stringBuilder.append(" ")
stringBuilder.append(String.format(Locale.ENGLISH, "%.3f", basalValueValue)) stringBuilder.append(String.format(Locale.ENGLISH, "%.3f", basalValueValue))
stringBuilder.append(", ") stringBuilder.append(",\n")
} }
return if (stringBuilder.length > 3) stringBuilder.substring(0, stringBuilder.length - 2) else stringBuilder.toString() return if (stringBuilder.length > 3) stringBuilder.substring(0, stringBuilder.length - 2) else stringBuilder.toString()
} }