Merge pull request #73 from 0pen-dash/avereha/stats
add connection quality and delivery status
This commit is contained in:
commit
6cda6e9a9a
23 changed files with 276 additions and 107 deletions
|
@ -3,27 +3,10 @@
|
|||
<option name="AUTODETECT_INDENTS" value="false" />
|
||||
<option name="WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN" value="true" />
|
||||
<JetCodeStyleSettings>
|
||||
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
|
||||
<value>
|
||||
<package name="java.util" alias="false" withSubpackages="false" />
|
||||
<package name="kotlinx.android.synthetic" alias="false" withSubpackages="true" />
|
||||
<package name="io.ktor" alias="false" withSubpackages="true" />
|
||||
</value>
|
||||
</option>
|
||||
<option name="PACKAGES_IMPORT_LAYOUT">
|
||||
<value>
|
||||
<package name="" alias="false" withSubpackages="true" />
|
||||
<package name="java" alias="false" withSubpackages="true" />
|
||||
<package name="javax" alias="false" withSubpackages="true" />
|
||||
<package name="kotlin" alias="false" withSubpackages="true" />
|
||||
<package name="" alias="true" withSubpackages="true" />
|
||||
</value>
|
||||
</option>
|
||||
<option name="ALIGN_IN_COLUMNS_CASE_BRANCH" value="true" />
|
||||
<option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="6" />
|
||||
<option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="6" />
|
||||
<option name="BLANK_LINES_AROUND_BLOCK_WHEN_BRANCHES" value="1" />
|
||||
<option name="WRAP_EXPRESSION_BODY_FUNCTIONS" value="1" />
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
</JetCodeStyleSettings>
|
||||
<codeStyleSettings language="JAVA">
|
||||
|
@ -143,8 +126,8 @@
|
|||
</arrangement>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="kotlin">
|
||||
<option name="RIGHT_MARGIN" value="120" />
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
<option name="RIGHT_MARGIN" value="120" />
|
||||
<option name="LINE_COMMENT_AT_FIRST_COLUMN" value="false" />
|
||||
<option name="LINE_COMMENT_ADD_SPACE" value="true" />
|
||||
<option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1" />
|
||||
|
@ -152,13 +135,6 @@
|
|||
<option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="1" />
|
||||
<option name="BLANK_LINES_AFTER_CLASS_HEADER" value="1" />
|
||||
<option name="ALIGN_MULTILINE_PARAMETERS_IN_CALLS" value="true" />
|
||||
<option name="CALL_PARAMETERS_WRAP" value="5" />
|
||||
<option name="CALL_PARAMETERS_LPAREN_ON_NEXT_LINE" value="true" />
|
||||
<option name="CALL_PARAMETERS_RPAREN_ON_NEXT_LINE" value="true" />
|
||||
<option name="METHOD_PARAMETERS_WRAP" value="5" />
|
||||
<option name="METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE" value="true" />
|
||||
<option name="METHOD_PARAMETERS_RPAREN_ON_NEXT_LINE" value="true" />
|
||||
<option name="METHOD_CALL_CHAIN_WRAP" value="1" />
|
||||
<option name="ASSIGNMENT_WRAP" value="5" />
|
||||
<option name="METHOD_ANNOTATION_WRAP" value="5" />
|
||||
<option name="CLASS_ANNOTATION_WRAP" value="1" />
|
||||
|
@ -171,4 +147,4 @@
|
|||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
||||
</component>
|
||||
</component>
|
|
@ -15,6 +15,7 @@ import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
|
|||
import info.nightscout.androidaps.plugins.configBuilder.PluginStore
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctionImplementation
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.ImportExportPrefsImpl
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.PrefFileListProvider
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.DataSyncSelectorImplementation
|
||||
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
|
||||
|
@ -22,6 +23,8 @@ import info.nightscout.androidaps.plugins.pump.PumpSyncImplementation
|
|||
import info.nightscout.androidaps.queue.CommandQueue
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.androidNotification.NotificationHolderImpl
|
||||
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
|
||||
import info.nightscout.androidaps.utils.buildHelper.BuildHelperImpl
|
||||
import info.nightscout.androidaps.utils.buildHelper.ConfigImpl
|
||||
import info.nightscout.androidaps.utils.resources.IconsProviderImplementation
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
|
@ -56,6 +59,10 @@ open class AppModule {
|
|||
@Singleton
|
||||
fun provideStorage(): Storage = FileStorage()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideBuildHelper(config: Config, fileListProvider: PrefFileListProvider): BuildHelper = BuildHelperImpl(config, fileListProvider)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
internal fun provideSchedulers(): AapsSchedulers = DefaultAapsSchedulers()
|
||||
|
|
|
@ -4,14 +4,11 @@ import info.nightscout.androidaps.BuildConfig
|
|||
import info.nightscout.androidaps.interfaces.Config
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.PrefFileListProvider
|
||||
import java.io.File
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class BuildHelper @Inject constructor(
|
||||
class BuildHelperImpl constructor(
|
||||
private val config: Config,
|
||||
fileListProvider: PrefFileListProvider
|
||||
) {
|
||||
) : BuildHelper {
|
||||
|
||||
private var devBranch = false
|
||||
private var engineeringMode = false
|
||||
|
@ -23,11 +20,10 @@ class BuildHelper @Inject constructor(
|
|||
devBranch = BuildConfig.VERSION.contains("-") || BuildConfig.VERSION.matches(Regex(".*[a-zA-Z]+.*"))
|
||||
}
|
||||
|
||||
fun isEngineeringModeOrRelease(): Boolean =
|
||||
override fun isEngineeringModeOrRelease(): Boolean =
|
||||
if (!config.APS) true else engineeringMode || !devBranch
|
||||
|
||||
fun isEngineeringMode(): Boolean =
|
||||
engineeringMode
|
||||
override fun isEngineeringMode(): Boolean = engineeringMode
|
||||
|
||||
fun isDev(): Boolean = devBranch
|
||||
override fun isDev(): Boolean = devBranch
|
||||
}
|
|
@ -19,7 +19,6 @@ import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
|||
import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin
|
||||
import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective
|
||||
import info.nightscout.androidaps.plugins.constraints.safety.SafetyPlugin
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.LoggerUtils
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.PrefFileListProvider
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider
|
||||
import info.nightscout.androidaps.plugins.pump.combo.ComboPlugin
|
||||
|
|
|
@ -12,7 +12,6 @@ import info.nightscout.androidaps.interfaces.Constraint
|
|||
import info.nightscout.androidaps.interfaces.PumpDescription
|
||||
import info.nightscout.androidaps.interfaces.PumpSync
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.LoggerUtils
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.PrefFileListProvider
|
||||
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin
|
||||
import info.nightscout.androidaps.queue.commands.Command
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
package info.nightscout.androidaps.utils.buildHelper
|
||||
|
||||
interface BuildHelper {
|
||||
|
||||
fun isEngineeringModeOrRelease(): Boolean
|
||||
fun isEngineeringMode(): Boolean
|
||||
fun isDev(): Boolean
|
||||
}
|
|
@ -147,13 +147,12 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
|||
} else {
|
||||
rxBus.send(EventDismissNotification(Notification.OMNIPOD_POD_NOT_ATTACHED))
|
||||
if (podStateManager.isSuspended) {
|
||||
val notification =
|
||||
Notification(
|
||||
Notification.OMNIPOD_POD_SUSPENDED,
|
||||
"Insulin delivery suspended",
|
||||
Notification.NORMAL
|
||||
)
|
||||
rxBus.send(EventNewNotification(notification))
|
||||
showNotification(
|
||||
Notification.OMNIPOD_POD_SUSPENDED,
|
||||
"Insulin delivery suspended",
|
||||
Notification.NORMAL,
|
||||
R.raw.boluserror
|
||||
)
|
||||
} else {
|
||||
rxBus.send(EventDismissNotification(Notification.OMNIPOD_POD_SUSPENDED))
|
||||
if (!podStateManager.sameTimeZone) {
|
||||
|
@ -246,13 +245,13 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
|||
|
||||
override fun disconnect(reason: String) {
|
||||
aapsLogger.info(LTag.PUMP, "disconnect reason=$reason")
|
||||
stopConnecting?.let { it.countDown() }
|
||||
stopConnecting?.countDown()
|
||||
omnipodManager.disconnect(false)
|
||||
}
|
||||
|
||||
override fun stopConnecting() {
|
||||
aapsLogger.info(LTag.PUMP, "stopConnecting")
|
||||
stopConnecting?.let { it.countDown() }
|
||||
stopConnecting?.countDown()
|
||||
omnipodManager.disconnect(true)
|
||||
}
|
||||
|
||||
|
@ -328,6 +327,15 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
|||
Notification.URGENT,
|
||||
R.raw.boluserror
|
||||
)
|
||||
if (!podStateManager.alarmSynced) {
|
||||
pumpSync.insertAnnouncement(
|
||||
error = podStateManager.alarmType?.toString() ?: "Unknown pod failure",
|
||||
pumpId = Random.Default.nextLong(),
|
||||
pumpType = PumpType.OMNIPOD_DASH,
|
||||
pumpSerial = serialNumber()
|
||||
)
|
||||
podStateManager.alarmSynced = true
|
||||
}
|
||||
}
|
||||
Completable.complete()
|
||||
}
|
||||
|
@ -817,7 +825,7 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
|||
val ret = pumpSync.syncTemporaryBasalWithPumpId(
|
||||
timestamp = historyEntry.createdAt,
|
||||
rate = absoluteRate,
|
||||
duration = T.mins(durationInMinutes.toLong()).msecs(),
|
||||
duration = T.mins(durationInMinutes).msecs(),
|
||||
isAbsolute = true,
|
||||
type = tbrType,
|
||||
pumpId = historyEntry.pumpId(),
|
||||
|
@ -833,7 +841,7 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
|||
when {
|
||||
podStateManager.deliveryStatus !in
|
||||
arrayOf(DeliveryStatus.TEMP_BASAL_ACTIVE, DeliveryStatus.BOLUS_AND_TEMP_BASAL_ACTIVE) -> {
|
||||
// TODO: what happens if we try to cancel inexistent temp basal?
|
||||
// TODO: what happens if we try to cancel nonexistent temp basal?
|
||||
aapsLogger.info(LTag.PUMP, "No temporary basal to cancel")
|
||||
Completable.complete()
|
||||
}
|
||||
|
@ -841,7 +849,7 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
|||
!enforceNew ->
|
||||
Completable.error(
|
||||
IllegalStateException(
|
||||
"Temporary basal already active and enforeNew is not set."
|
||||
"Temporary basal already active and enforceNew is not set."
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -979,7 +987,7 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
|||
aapsLogger.warn(LTag.PUMP, "Unsupported custom action: $customActionType")
|
||||
}
|
||||
|
||||
override fun executeCustomCommand(customCommand: CustomCommand): PumpEnactResult? {
|
||||
override fun executeCustomCommand(customCommand: CustomCommand): PumpEnactResult {
|
||||
return when (customCommand) {
|
||||
is CommandSilenceAlerts ->
|
||||
silenceAlerts()
|
||||
|
@ -1068,7 +1076,8 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
|||
private fun deactivatePod(): PumpEnactResult {
|
||||
val ret = executeProgrammingCommand(
|
||||
historyEntry = history.createRecord(OmnipodCommandType.DEACTIVATE_POD),
|
||||
command = omnipodManager.deactivatePod().ignoreElements()
|
||||
command = omnipodManager.deactivatePod().ignoreElements(),
|
||||
checkNoActiveCommand = false,
|
||||
).doOnComplete {
|
||||
rxBus.send(EventDismissNotification(Notification.OMNIPOD_POD_FAULT))
|
||||
}.toPumpEnactResult()
|
||||
|
@ -1381,11 +1390,9 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
|||
sp.getBoolean(R.string.key_omnipod_common_notification_uncertain_tbr_sound_enabled, true)
|
||||
Notification.OMNIPOD_UNCERTAIN_SMB ->
|
||||
sp.getBoolean(R.string.key_omnipod_common_notification_uncertain_smb_sound_enabled, true)
|
||||
Notification.OMNIPOD_POD_SUSPENDED ->
|
||||
sp.getBoolean(R.string.key_omnipod_common_notification_delivery_suspended_sound_enabled, true)
|
||||
else -> true
|
||||
}
|
||||
}
|
||||
|
||||
private fun dismissNotification(id: Int) {
|
||||
rxBus.send(EventDismissNotification(id))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -166,7 +166,7 @@ class OmnipodDashBleManagerImpl @Inject constructor(
|
|||
throw SessionEstablishmentException("Received resynchronization SQN for the second time")
|
||||
}
|
||||
}
|
||||
|
||||
podState.successfulConnections++
|
||||
podState.commitEapAkaSequenceNumber()
|
||||
}
|
||||
|
||||
|
@ -223,6 +223,7 @@ class OmnipodDashBleManagerImpl @Inject constructor(
|
|||
}
|
||||
emitter.onNext(PodEvent.EstablishingSession)
|
||||
establishSession(pairResult.msgSeq)
|
||||
podState.successfulConnections++
|
||||
emitter.onNext(PodEvent.Connected)
|
||||
emitter.onComplete()
|
||||
} catch (ex: Exception) {
|
||||
|
|
|
@ -211,8 +211,8 @@ class BleCommCallbacks(
|
|||
|
||||
fun resetConnection() {
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "Reset connection")
|
||||
connected?.countDown()
|
||||
serviceDiscoveryComplete?.countDown()
|
||||
connected.countDown()
|
||||
serviceDiscoveryComplete.countDown()
|
||||
connected = CountDownLatch(1)
|
||||
serviceDiscoveryComplete = CountDownLatch(1)
|
||||
flushConfirmationQueue()
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions
|
||||
|
||||
open class FailedToConnectException : Exception {
|
||||
constructor(message: String? = null) : super("Failed to connect: ${message ?: ""}")
|
||||
}
|
||||
open class FailedToConnectException(message: String? = null) : Exception("Failed to connect: ${message ?: ""}")
|
||||
|
|
|
@ -37,8 +37,8 @@ class MessageIO(
|
|||
fun sendMessage(msg: MessagePacket): MessageSendResult {
|
||||
val foundRTS = cmdBleIO.flushIncomingQueue()
|
||||
if (foundRTS) {
|
||||
val msg = receiveMessage(false)
|
||||
aapsLogger.warn(LTag.PUMPBTCOMM, "sendMessage received message=$msg")
|
||||
val receivedMessage = receiveMessage(false)
|
||||
aapsLogger.warn(LTag.PUMPBTCOMM, "sendMessage received message=$receivedMessage")
|
||||
throw IllegalStateException("Received message while trying to send")
|
||||
}
|
||||
dataBleIO.flushIncomingQueue()
|
||||
|
|
|
@ -2,6 +2,5 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.scan
|
|||
|
||||
import android.os.ParcelUuid
|
||||
|
||||
class DiscoveredInvalidPodException : Exception {
|
||||
constructor(message: String, serviceUUIds: List<ParcelUuid?>) : super("$message service UUIDs: $serviceUUIds")
|
||||
}
|
||||
class DiscoveredInvalidPodException(message: String, serviceUUIds: List<ParcelUuid?>) :
|
||||
Exception("$message service UUIDs: $serviceUUIds")
|
||||
|
|
|
@ -64,7 +64,7 @@ class Connection(
|
|||
|
||||
fun connect(connectionWaitCond: ConnectionWaitCondition) {
|
||||
aapsLogger.debug("Connecting connectionWaitCond=$connectionWaitCond")
|
||||
|
||||
podState.connectionAttempts++
|
||||
podState.bluetoothConnectionState = OmnipodDashPodStateManager.BluetoothConnectionState.CONNECTING
|
||||
val autoConnect = false
|
||||
val gatt = gattConnection
|
||||
|
|
|
@ -15,8 +15,6 @@ class BasalProgram(
|
|||
|
||||
fun hasZeroUnitSegments() = segments.any { it.basalRateInHundredthUnitsPerHour == 0 }
|
||||
|
||||
fun isZeroBasal() = segments.sumBy(Segment::basalRateInHundredthUnitsPerHour) == 0
|
||||
|
||||
fun rateAt(date: Date): Double {
|
||||
val instance = Calendar.getInstance()
|
||||
instance.time = date
|
||||
|
|
|
@ -8,6 +8,6 @@ enum class BeepRepetitionType(
|
|||
XXX(0x01.toByte()), // Used in lump of coal alert, LOW_RESERVOIR
|
||||
XXX2(0x03.toByte()), // Used in USER_SET_EXPIRATION
|
||||
XXX3(0x05.toByte()), // published system expiration alert
|
||||
XXX4(0x06.toByte()), // Used in imminent pod expiration alert
|
||||
XXX4(0x06.toByte()), // Used in imminent pod expiration alert, suspend in progress
|
||||
XXX5(0x08.toByte()); // Lump of coal alert
|
||||
}
|
||||
|
|
|
@ -4,5 +4,6 @@ enum class BeepType(val value: Byte) {
|
|||
|
||||
SILENT(0x00.toByte()),
|
||||
FOUR_TIMES_BIP_BEEP(0x02.toByte()), // Used in low reservoir alert, user expiration alert, expiration alert, imminent expiration alert, lump of coal alert
|
||||
XXX(0x04.toByte()), // Used during suspend
|
||||
LONG_SINGLE_BEEP(0x06.toByte()); // Used in stop delivery command
|
||||
}
|
||||
|
|
|
@ -4,6 +4,6 @@ import java.time.Duration
|
|||
|
||||
class PodConstants {
|
||||
companion object {
|
||||
val MAX_POD_LIFETIME = Duration.ofMinutes(80)
|
||||
val MAX_POD_LIFETIME = Duration.ofHours(80)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,8 @@ interface OmnipodDashPodStateManager {
|
|||
val isPodRunning: Boolean
|
||||
val isPodKaput: Boolean
|
||||
var bluetoothConnectionState: BluetoothConnectionState
|
||||
var connectionAttempts: Int
|
||||
var successfulConnections: Int
|
||||
|
||||
var timeZone: TimeZone
|
||||
val sameTimeZone: Boolean // The TimeZone is the same on the phone and on the pod
|
||||
|
@ -39,6 +41,7 @@ interface OmnipodDashPodStateManager {
|
|||
val time: ZonedDateTime?
|
||||
val timeDrift: java.time.Duration?
|
||||
val expiry: ZonedDateTime?
|
||||
var alarmSynced: Boolean
|
||||
|
||||
val messageSequenceNumber: Short
|
||||
val sequenceNumberOfLastProgrammingCommand: Short?
|
||||
|
@ -81,6 +84,7 @@ interface OmnipodDashPodStateManager {
|
|||
fun updateFromAlarmStatusResponse(response: AlarmStatusResponse)
|
||||
fun updateFromPairing(uniqueId: Id, pairResult: PairResult)
|
||||
fun reset()
|
||||
fun connectionSuccessRatio(): Float
|
||||
|
||||
fun createActiveCommand(
|
||||
historyId: String,
|
||||
|
|
|
@ -98,6 +98,22 @@ class OmnipodDashPodStateManagerImpl @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
override var connectionAttempts: Int
|
||||
@Synchronized
|
||||
get() = podState.connectionAttempts
|
||||
@Synchronized
|
||||
set(value) {
|
||||
podState.connectionAttempts = value
|
||||
}
|
||||
|
||||
override var successfulConnections: Int
|
||||
@Synchronized
|
||||
get() = podState.successfulConnections
|
||||
@Synchronized
|
||||
set(value) {
|
||||
podState.successfulConnections = value
|
||||
}
|
||||
|
||||
override var timeZone: TimeZone
|
||||
get() = TimeZone.getTimeZone(podState.timeZone)
|
||||
set(tz) {
|
||||
|
@ -108,7 +124,19 @@ class OmnipodDashPodStateManagerImpl @Inject constructor(
|
|||
override val sameTimeZone: Boolean
|
||||
get() {
|
||||
val now = System.currentTimeMillis()
|
||||
return TimeZone.getDefault().getOffset(now) == timeZone.getOffset(now)
|
||||
val currentTimezone = TimeZone.getDefault()
|
||||
val currentOffset = currentTimezone.getOffset(now)
|
||||
val podOffset = timeZone.getOffset(now)
|
||||
logger.debug(
|
||||
LTag.PUMPCOMM,
|
||||
"sameTimeZone currentTimezone=${currentTimezone.getDisplayName(
|
||||
true,
|
||||
TimeZone.SHORT
|
||||
)} " +
|
||||
"currentOffset=$currentOffset " +
|
||||
"podOffset=$podOffset"
|
||||
)
|
||||
return currentOffset == podOffset
|
||||
}
|
||||
|
||||
override val bluetoothVersion: SoftwareVersion?
|
||||
|
@ -217,6 +245,13 @@ class OmnipodDashPodStateManagerImpl @Inject constructor(
|
|||
return null
|
||||
}
|
||||
|
||||
override var alarmSynced: Boolean
|
||||
get() = podState.alarmSynced
|
||||
set(value) {
|
||||
podState.alarmSynced = value
|
||||
store()
|
||||
}
|
||||
|
||||
override var bluetoothConnectionState: OmnipodDashPodStateManager.BluetoothConnectionState
|
||||
@Synchronized
|
||||
get() = podState.bluetoothConnectionState
|
||||
|
@ -482,8 +517,10 @@ class OmnipodDashPodStateManagerImpl @Inject constructor(
|
|||
podState.lastStatusResponseReceived = 0
|
||||
}
|
||||
|
||||
CommandSendingFailure, NoActiveCommand ->
|
||||
CommandSendingFailure, NoActiveCommand -> {
|
||||
podState.activeCommand = null
|
||||
podState.lastStatusResponseReceived = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -560,7 +597,7 @@ class OmnipodDashPodStateManagerImpl @Inject constructor(
|
|||
override fun updateFromAlarmStatusResponse(response: AlarmStatusResponse) {
|
||||
logger.info(
|
||||
LTag.PUMP,
|
||||
"Received AlarmStatusReponse: $response"
|
||||
"Received AlarmStatusResponse: $response"
|
||||
)
|
||||
podState.deliveryStatus = response.deliveryStatus
|
||||
podState.podStatus = response.podStatus
|
||||
|
@ -588,6 +625,14 @@ class OmnipodDashPodStateManagerImpl @Inject constructor(
|
|||
podState.uniqueId = uniqueId.toLong()
|
||||
}
|
||||
|
||||
override fun connectionSuccessRatio(): Float {
|
||||
val attempts = connectionAttempts
|
||||
if (attempts == 0) {
|
||||
return 1.0F
|
||||
}
|
||||
return successfulConnections.toFloat() * 100 / attempts.toFloat()
|
||||
}
|
||||
|
||||
override fun reset() {
|
||||
podState = PodState()
|
||||
store()
|
||||
|
@ -625,6 +670,8 @@ class OmnipodDashPodStateManagerImpl @Inject constructor(
|
|||
var lastStatusResponseReceived: Long = 0
|
||||
var bluetoothConnectionState: OmnipodDashPodStateManager.BluetoothConnectionState =
|
||||
OmnipodDashPodStateManager.BluetoothConnectionState.DISCONNECTED
|
||||
var connectionAttempts = 0
|
||||
var successfulConnections = 0
|
||||
var messageSequenceNumber: Short = 0
|
||||
var sequenceNumberOfLastProgrammingCommand: Short? = null
|
||||
var activationTime: Long? = null
|
||||
|
@ -634,6 +681,7 @@ class OmnipodDashPodStateManagerImpl @Inject constructor(
|
|||
var eapAkaSequenceNumber: Long = 1
|
||||
var bolusPulsesRemaining: Short = 0
|
||||
var timeZone: String = "" // TimeZone ID (e.g. "Europe/Amsterdam")
|
||||
var alarmSynced: Boolean = false
|
||||
|
||||
var bleVersion: SoftwareVersion? = null
|
||||
var firmwareVersion: SoftwareVersion? = null
|
||||
|
|
|
@ -24,7 +24,6 @@ import info.nightscout.androidaps.plugins.pump.omnipod.common.queue.command.Comm
|
|||
import info.nightscout.androidaps.plugins.pump.omnipod.common.queue.command.CommandResumeDelivery
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.common.queue.command.CommandSilenceAlerts
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.common.queue.command.CommandSuspendDelivery
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.BuildConfig
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.EventOmnipodDashPumpValuesChanged
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.OmnipodDashPumpPlugin
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.R
|
||||
|
@ -37,6 +36,7 @@ import info.nightscout.androidaps.queue.events.EventQueueChanged
|
|||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||
|
@ -63,6 +63,7 @@ class OmnipodDashOverviewFragment : DaggerFragment() {
|
|||
@Inject lateinit var dateUtil: DateUtil
|
||||
@Inject lateinit var aapsSchedulers: AapsSchedulers
|
||||
@Inject lateinit var pumpSync: PumpSync
|
||||
@Inject lateinit var buildHelper: BuildHelper
|
||||
|
||||
companion object {
|
||||
|
||||
|
@ -83,17 +84,17 @@ class OmnipodDashOverviewFragment : DaggerFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
var _binding: OmnipodDashOverviewBinding? = null
|
||||
var _bluetoothStatusBinding: OmnipodDashOverviewBluetoothStatusBinding? = null
|
||||
var _podInfoBinding: OmnipodCommonOverviewPodInfoBinding? = null
|
||||
var _buttonBinding: OmnipodCommonOverviewButtonsBinding? = null
|
||||
private var _binding: OmnipodDashOverviewBinding? = null
|
||||
private var _bluetoothStatusBinding: OmnipodDashOverviewBluetoothStatusBinding? = null
|
||||
private var _podInfoBinding: OmnipodCommonOverviewPodInfoBinding? = null
|
||||
private var _buttonBinding: OmnipodCommonOverviewButtonsBinding? = null
|
||||
|
||||
// These properties are only valid between onCreateView and
|
||||
// onDestroyView.
|
||||
val binding get() = _binding!!
|
||||
val bluetoothStatusBinding get() = _bluetoothStatusBinding!!
|
||||
val podInfoBinding get() = _podInfoBinding!!
|
||||
val buttonBinding get() = _buttonBinding!!
|
||||
private val podInfoBinding get() = _podInfoBinding!!
|
||||
private val buttonBinding get() = _buttonBinding!!
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
||||
OmnipodDashOverviewBinding.inflate(inflater, container, false).also {
|
||||
|
@ -166,6 +167,10 @@ class OmnipodDashOverviewFragment : DaggerFragment() {
|
|||
.messageOnSuccess(resourceHelper.gs(R.string.omnipod_common_confirmation_time_on_pod_updated))
|
||||
)
|
||||
}
|
||||
if (buildHelper.isEngineeringMode()) {
|
||||
bluetoothStatusBinding.deliveryStatus.visibility = View.VISIBLE
|
||||
bluetoothStatusBinding.connectionQuality.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
|
@ -213,6 +218,9 @@ class OmnipodDashOverviewFragment : DaggerFragment() {
|
|||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
_bluetoothStatusBinding = null
|
||||
_buttonBinding = null
|
||||
_podInfoBinding = null
|
||||
}
|
||||
|
||||
private fun updateUi() {
|
||||
|
@ -234,6 +242,24 @@ class OmnipodDashOverviewFragment : DaggerFragment() {
|
|||
OmnipodDashPodStateManager.BluetoothConnectionState.CONNECTING ->
|
||||
"{fa-bluetooth-b spin}"
|
||||
}
|
||||
|
||||
val connectionSuccessPercentage = podStateManager.connectionSuccessRatio() * 100
|
||||
val successPercentageString = String.format("%.2f %%", podStateManager.connectionSuccessRatio())
|
||||
val quality =
|
||||
"${podStateManager.successfulConnections}/${podStateManager.connectionAttempts} :: $successPercentageString"
|
||||
bluetoothStatusBinding.omnipodDashBluetoothConnectionQuality.text = quality
|
||||
val connectionStatsColor = when {
|
||||
connectionSuccessPercentage > 90 ->
|
||||
Color.WHITE
|
||||
connectionSuccessPercentage > 60 ->
|
||||
Color.YELLOW
|
||||
else ->
|
||||
Color.RED
|
||||
}
|
||||
bluetoothStatusBinding.omnipodDashBluetoothConnectionQuality.setTextColor(connectionStatsColor)
|
||||
bluetoothStatusBinding.omnipodDashDeliveryStatus.text = podStateManager.deliveryStatus?.let {
|
||||
podStateManager.deliveryStatus.toString()
|
||||
} ?: PLACEHOLDER
|
||||
}
|
||||
|
||||
private fun updateOmnipodStatus() {
|
||||
|
@ -316,15 +342,16 @@ class OmnipodDashOverviewFragment : DaggerFragment() {
|
|||
}
|
||||
|
||||
// base basal rate
|
||||
podInfoBinding.baseBasalRate.text = if (podStateManager.basalProgram != null && !podStateManager.isSuspended) {
|
||||
resourceHelper.gs(
|
||||
R.string.pump_basebasalrate,
|
||||
omnipodDashPumpPlugin.model()
|
||||
.determineCorrectBasalSize(podStateManager.basalProgram!!.rateAt(Date()))
|
||||
)
|
||||
} else {
|
||||
PLACEHOLDER
|
||||
}
|
||||
podInfoBinding.baseBasalRate.text =
|
||||
if (podStateManager.basalProgram != null && !podStateManager.isSuspended) {
|
||||
resourceHelper.gs(
|
||||
R.string.pump_basebasalrate,
|
||||
omnipodDashPumpPlugin.model()
|
||||
.determineCorrectBasalSize(podStateManager.basalProgram!!.rateAt(Date()))
|
||||
)
|
||||
} else {
|
||||
PLACEHOLDER
|
||||
}
|
||||
|
||||
// total delivered
|
||||
podInfoBinding.totalDelivered.text =
|
||||
|
@ -361,8 +388,8 @@ class OmnipodDashOverviewFragment : DaggerFragment() {
|
|||
)
|
||||
}
|
||||
|
||||
podInfoBinding.podActiveAlerts.text = podStateManager.activeAlerts?.let {
|
||||
it.map { it.toString() }.joinToString(",")
|
||||
podInfoBinding.podActiveAlerts.text = podStateManager.activeAlerts?.let { it ->
|
||||
it.joinToString(",") { it.toString() }
|
||||
} ?: PLACEHOLDER
|
||||
}
|
||||
|
||||
|
@ -415,12 +442,8 @@ class OmnipodDashOverviewFragment : DaggerFragment() {
|
|||
if (podStateManager.isSuspended) {
|
||||
resourceHelper.gs(R.string.omnipod_common_pod_status_suspended)
|
||||
} else {
|
||||
resourceHelper.gs(R.string.omnipod_common_pod_status_running) +
|
||||
if (BuildConfig.DEBUG)
|
||||
podStateManager.deliveryStatus?.let { " " + podStateManager.deliveryStatus.toString() }
|
||||
else ""
|
||||
resourceHelper.gs(R.string.omnipod_common_pod_status_running)
|
||||
}
|
||||
// TODO
|
||||
/*
|
||||
} else if (podStateManager.podStatus == PodProgressStatus.FAULT_EVENT_OCCURRED) {
|
||||
resourceHelper.gs(R.string.omnipod_common_pod_status_pod_fault)
|
||||
|
@ -466,10 +489,10 @@ class OmnipodDashOverviewFragment : DaggerFragment() {
|
|||
podInfoBinding.lastBolus.setTextColor(textColor)
|
||||
podStateManager.lastBolus?.let {
|
||||
// display requested units if delivery is in progress
|
||||
var bolusSize = it.deliveredUnits()
|
||||
val bolusSize = it.deliveredUnits()
|
||||
?: it.requestedUnits
|
||||
|
||||
var text = resourceHelper.gs(
|
||||
val text = resourceHelper.gs(
|
||||
R.string.omnipod_common_overview_last_bolus_value,
|
||||
omnipodDashPumpPlugin.model().determineCorrectBolusSize(bolusSize),
|
||||
resourceHelper.gs(R.string.insulin_unit_shortname),
|
||||
|
@ -623,7 +646,10 @@ class OmnipodDashOverviewFragment : DaggerFragment() {
|
|||
}
|
||||
|
||||
seconds < 60 * 60 -> { // < 1 hour
|
||||
return resourceHelper.gs(R.string.omnipod_common_time_ago, resourceHelper.gq(R.plurals.omnipod_common_minutes, minutes, minutes))
|
||||
return resourceHelper.gs(
|
||||
R.string.omnipod_common_time_ago,
|
||||
resourceHelper.gq(R.plurals.omnipod_common_minutes, minutes, minutes)
|
||||
)
|
||||
}
|
||||
|
||||
seconds < 24 * 60 * 60 -> { // < 1 day
|
||||
|
@ -631,9 +657,16 @@ class OmnipodDashOverviewFragment : DaggerFragment() {
|
|||
if (minutesLeft > 0)
|
||||
return resourceHelper.gs(
|
||||
R.string.omnipod_common_time_ago,
|
||||
resourceHelper.gs(R.string.omnipod_common_composite_time, resourceHelper.gq(R.plurals.omnipod_common_hours, hours, hours), resourceHelper.gq(R.plurals.omnipod_common_minutes, minutesLeft, minutesLeft))
|
||||
resourceHelper.gs(
|
||||
R.string.omnipod_common_composite_time,
|
||||
resourceHelper.gq(R.plurals.omnipod_common_hours, hours, hours),
|
||||
resourceHelper.gq(R.plurals.omnipod_common_minutes, minutesLeft, minutesLeft)
|
||||
)
|
||||
)
|
||||
return resourceHelper.gs(R.string.omnipod_common_time_ago, resourceHelper.gq(R.plurals.omnipod_common_hours, hours, hours))
|
||||
return resourceHelper.gs(
|
||||
R.string.omnipod_common_time_ago,
|
||||
resourceHelper.gq(R.plurals.omnipod_common_hours, hours, hours)
|
||||
)
|
||||
}
|
||||
|
||||
else -> {
|
||||
|
@ -642,9 +675,16 @@ class OmnipodDashOverviewFragment : DaggerFragment() {
|
|||
if (hoursLeft > 0)
|
||||
return resourceHelper.gs(
|
||||
R.string.omnipod_common_time_ago,
|
||||
resourceHelper.gs(R.string.omnipod_common_composite_time, resourceHelper.gq(R.plurals.omnipod_common_days, days, days), resourceHelper.gq(R.plurals.omnipod_common_hours, hoursLeft, hoursLeft))
|
||||
resourceHelper.gs(
|
||||
R.string.omnipod_common_composite_time,
|
||||
resourceHelper.gq(R.plurals.omnipod_common_days, days, days),
|
||||
resourceHelper.gq(R.plurals.omnipod_common_hours, hoursLeft, hoursLeft)
|
||||
)
|
||||
)
|
||||
return resourceHelper.gs(R.string.omnipod_common_time_ago, resourceHelper.gq(R.plurals.omnipod_common_days, days, days))
|
||||
return resourceHelper.gs(
|
||||
R.string.omnipod_common_time_ago,
|
||||
resourceHelper.gq(R.plurals.omnipod_common_days, days, days)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
android:gravity="end"
|
||||
android:paddingStart="5dp"
|
||||
android:paddingEnd="5dp"
|
||||
android:text="@string/omnipod_dash_overview_bluetooth_status"
|
||||
android:text="@string/omnipod_dash_overview_bluetooth_address"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<TextView
|
||||
|
@ -51,7 +51,7 @@
|
|||
android:gravity="end"
|
||||
android:paddingStart="5dp"
|
||||
android:paddingEnd="5dp"
|
||||
android:text="@string/omnipod_dash_overview_bluetooth_address"
|
||||
android:text="@string/omnipod_dash_overview_bluetooth_status"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<TextView
|
||||
|
@ -78,6 +78,85 @@
|
|||
tools:ignore="HardcodedText" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/connectionQuality"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:visibility="gone">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1.5"
|
||||
android:gravity="end"
|
||||
android:paddingStart="5dp"
|
||||
android:paddingEnd="5dp"
|
||||
android:text="@string/omnipod_dash_overview_bluetooth_connection_quality"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="5dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0"
|
||||
android:gravity="center_horizontal"
|
||||
android:paddingStart="2dp"
|
||||
android:paddingEnd="2dp"
|
||||
android:text=":"
|
||||
android:textSize="14sp"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<com.joanzapata.iconify.widget.IconTextView
|
||||
android:id="@+id/omnipod_dash_bluetooth_connection_quality"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="start"
|
||||
android:paddingStart="5dp"
|
||||
android:paddingEnd="5dp"
|
||||
android:textSize="14sp"
|
||||
tools:ignore="HardcodedText" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/deliveryStatus"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:visibility="gone">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1.5"
|
||||
android:gravity="end"
|
||||
android:paddingStart="5dp"
|
||||
android:paddingEnd="5dp"
|
||||
android:text="@string/omnipod_dash_overview_delivery_status"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="5dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0"
|
||||
android:gravity="center_horizontal"
|
||||
android:paddingStart="2dp"
|
||||
android:paddingEnd="2dp"
|
||||
android:text=":"
|
||||
android:textSize="14sp"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<com.joanzapata.iconify.widget.IconTextView
|
||||
android:id="@+id/omnipod_dash_delivery_status"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="start"
|
||||
android:paddingStart="5dp"
|
||||
android:paddingEnd="5dp"
|
||||
android:textSize="14sp"
|
||||
tools:ignore="HardcodedText" />
|
||||
</LinearLayout>
|
||||
<View
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="2dip"
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
<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_firmware_version_value">Firmware %1$s / Bluetooth %2$s</string>
|
||||
<string name="omnipod_dash_overview_bluetooth_connection_quality">Connection quality</string>
|
||||
<string name="omnipod_dash_overview_delivery_status">Delivery Status</string>
|
||||
|
||||
<!-- Omnipod Dash - Pod Activation Wizard -->
|
||||
<string name="omnipod_dash_pod_activation_wizard_start_pod_activation_text">Fill a new Pod with enough insulin for 3 days.\n\nListen for two beeps from the Pod during the filling process. These indicate that the minimum amount of 85U has been inserted. Be sure to completely empty the fill syringe, even after hearing the two beeps.\n\nAfter filling the Pod, please press <b>Next</b>.\n\n<b>Note:</b> do not remove the Pod\'s needle cap at this time.</string>
|
||||
|
@ -19,4 +21,6 @@
|
|||
|
||||
<string name="key_omnipod_common_preferences_category_confirmation_beeps" translatable="false">omnipod_common_preferences_category_confirmation</string>
|
||||
<string name="key_common_preferences_category_other_settings" translatable="false">common_preferences_category_other</string>
|
||||
</resources>
|
||||
<string name="key_omnipod_common_notification_delivery_suspended_sound_enabled">AAPS.Omnipod.notification_delivery_suspended_sound_enabled</string>
|
||||
<string name="omnipod_common_preferences_notification_delivery_suspended_sound_enabled">Sound when delivery suspended notification enabled</string>
|
||||
</resources>
|
||||
|
|
|
@ -93,6 +93,11 @@
|
|||
android:key="@string/key_omnipod_common_notification_uncertain_bolus_sound_enabled"
|
||||
android:title="@string/omnipod_common_preferences_notification_uncertain_bolus_sound_enabled" />
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="@string/key_omnipod_common_notification_delivery_suspended_sound_enabled"
|
||||
android:title="@string/omnipod_common_preferences_notification_delivery_suspended_sound_enabled" />
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
|
|
Loading…
Reference in a new issue