Merge pull request #73 from 0pen-dash/avereha/stats

add connection quality and delivery status
This commit is contained in:
Andrei Vereha 2021-08-05 21:38:16 +02:00 committed by GitHub
commit 6cda6e9a9a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 276 additions and 107 deletions

View file

@ -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>

View file

@ -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()

View file

@ -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
}

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,8 @@
package info.nightscout.androidaps.utils.buildHelper
interface BuildHelper {
fun isEngineeringModeOrRelease(): Boolean
fun isEngineeringMode(): Boolean
fun isDev(): Boolean
}

View file

@ -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))
}
}

View file

@ -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) {

View file

@ -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()

View file

@ -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 ?: ""}")

View file

@ -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()

View file

@ -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")

View file

@ -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

View file

@ -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

View file

@ -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
}

View file

@ -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
}

View file

@ -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)
}
}

View file

@ -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,

View file

@ -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

View file

@ -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)
)
}
}
}

View file

@ -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"

View file

@ -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>

View file

@ -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