Add settings, and setting sync with pump

This commit is contained in:
jbr7rr 2023-06-13 21:42:05 +02:00
parent 419def7f6b
commit 49de6a9c32
14 changed files with 153 additions and 37 deletions

View file

@ -135,6 +135,7 @@ open class Notification {
const val COMBO_UNKNOWN_TBR = 81
const val BLUETOOTH_NOT_ENABLED = 82
const val PATCH_NOT_ACTIVE = 83
const val PUMP_SETTINGS_FAILED = 84
const val USER_MESSAGE = 1000

View file

@ -6,4 +6,5 @@ package info.nightscout.interfaces.pump
interface Medtrum {
fun loadEvents(): PumpEnactResult // events history to build treatments from
fun setUserOptions(): PumpEnactResult // set user settings
}

View file

@ -4,6 +4,7 @@ import dagger.android.HasAndroidInjector
import info.nightscout.interfaces.plugin.ActivePlugin
import info.nightscout.interfaces.pump.Dana
import info.nightscout.interfaces.pump.Diaconn
import info.nightscout.interfaces.pump.Medtrum
import info.nightscout.interfaces.pump.PumpEnactResult
import info.nightscout.interfaces.queue.Callback
import info.nightscout.interfaces.queue.Command
@ -30,6 +31,12 @@ class CommandSetUserSettings(
aapsLogger.debug(LTag.PUMPQUEUE, "Result success: ${r.success} enacted: ${r.enacted}")
callback?.result(r)?.run()
}
if (pump is Medtrum) {
val r = pump.setUserOptions()
aapsLogger.debug(LTag.PUMPQUEUE, "Result success: ${r.success} enacted: ${r.enacted}")
callback?.result(r)?.run()
}
}
override fun status(): String = rh.gs(info.nightscout.core.ui.R.string.set_user_settings)

View file

@ -373,4 +373,14 @@ import kotlin.math.round
val connectionOK = medtrumService?.loadEvents() ?: false
return PumpEnactResult(injector).success(connectionOK)
}
override fun setUserOptions(): PumpEnactResult {
if (!isInitialized()) {
val result = PumpEnactResult(injector).success(false)
result.comment = "pump not initialized"
return result
}
val connectionOK = medtrumService?.setUserSettings() ?: false
return PumpEnactResult(injector).success(connectionOK)
}
}

View file

@ -177,14 +177,13 @@ class MedtrumPump @Inject constructor(
var lastStopSequence = 0
var lastStopPatchId = 0L
// TODO set these setting on init
// User settings (desired values, to be set on pump)
var desiredPatchExpiration = false
var desiredAlarmSetting = AlarmSetting.LIGHT_VIBRATE_AND_BEEP.code
var desiredAlarmSetting = AlarmSetting.LIGHT_VIBRATE_AND_BEEP
var desiredHourlyMaxInsulin: Int = 40
var desiredDailyMaxInsulin: Int = 180
init {
fun loadFromSP() {
// Load stuff from SP
_patchSessionToken = sp.getLong(R.string.key_session_token, 0L)
_currentSequenceNumber = sp.getInt(R.string.key_current_sequence_number, 0)
@ -203,14 +202,14 @@ class MedtrumPump @Inject constructor(
}
fun loadUserSettingsFromSP() {
// TODO
// desiredPatchExpiration = sp.getBoolean(R.string.key_patch_expiration, false)
// desiredAlarmSetting = sp.getInt(R.string.key_alarm_setting, AlarmSetting.LIGHT_VIBRATE_AND_BEEP.code)
// desiredHourlyMaxInsulin = sp.getInt(R.string.key_hourly_max_insulin, 40)
// desiredDailyMaxInsulin = sp.getInt(R.string.key_daily_max_insulin, 180)
desiredPatchExpiration = sp.getBoolean(info.nightscout.pump.medtrum.R.string.key_patch_expiration, false)
val alarmSettingCode = sp.getString(info.nightscout.pump.medtrum.R.string.key_alarm_setting, AlarmSetting.LIGHT_VIBRATE_AND_BEEP.code.toString())?.toByte()
desiredAlarmSetting = AlarmSetting.values().firstOrNull { it.code == alarmSettingCode } ?: AlarmSetting.LIGHT_VIBRATE_AND_BEEP
desiredHourlyMaxInsulin = sp.getInt(info.nightscout.pump.medtrum.R.string.key_hourly_max_insulin, 40)
desiredDailyMaxInsulin = sp.getInt(info.nightscout.pump.medtrum.R.string.key_daily_max_insulin, 180)
try {
_pumpSN = sp.getString(info.nightscout.pump.medtrum.R.string.key_snInput, " ").toLong(radix = 16)
_pumpSN = sp.getString(info.nightscout.pump.medtrum.R.string.key_sn_input, " ").toLong(radix = 16)
} catch (e: NumberFormatException) {
aapsLogger.debug(LTag.PUMP, "changePump: Invalid input!")
}

View file

@ -65,7 +65,7 @@ class ActivatePacket(injector: HasAndroidInjector, private val basalProfile: Byt
val autoSuspendTime: Byte = 12 // Not sure why, but pump needs this in order to activate
val patchExpiration: Byte = medtrumPump.desiredPatchExpiration.toByte()
val alarmSetting: Byte = medtrumPump.desiredAlarmSetting
val alarmSetting: Byte = medtrumPump.desiredAlarmSetting.code
val lowSuspend: Byte = 0
val predictiveLowSuspend: Byte = 0

View file

@ -2,6 +2,7 @@ package info.nightscout.pump.medtrum.comm.packets
import dagger.android.HasAndroidInjector
import info.nightscout.pump.medtrum.MedtrumPump
import info.nightscout.pump.medtrum.comm.enums.AlarmSetting
import info.nightscout.pump.medtrum.comm.enums.CommandType.SET_PATCH
import info.nightscout.pump.medtrum.extension.toByte
import info.nightscout.pump.medtrum.extension.toByteArray
@ -20,8 +21,8 @@ class SetPatchPacket(injector: HasAndroidInjector) : MedtrumPacket(injector) {
/**
* byte 0: opCode
* byte 1: alarmSetting // See AlarmSetting
* byte 2-3: hourlyMaxInsulin // Max hourly dose of insulin not used for now, divided by 0.05
* byte 4-5: dailyMaxSet // Max daily dose of insulin not used for now, divided by 0.05
* byte 2-3: hourlyMaxInsulin // Max hourly dose of insulin, divided by 0.05
* byte 4-5: dailyMaxSet // Max daily dose of insulin, divided by 0.05
* byte 6: expirationTimer // Expiration timer, 0 = no expiration 1 = 12 hour reminder and expiration
* byte 7: autoSuspendEnable // Value for auto mode, not used for AAPS
* byte 8: autoSuspendTime // Value for auto mode, not used for AAPS
@ -30,11 +31,16 @@ class SetPatchPacket(injector: HasAndroidInjector) : MedtrumPacket(injector) {
* byte 11: predictiveLowSuspendRange // Value for auto mode, not used for AAPS
*/
val alarmSetting: Byte = medtrumPump.desiredAlarmSetting
val alarmSetting: AlarmSetting = medtrumPump.desiredAlarmSetting
val hourlyMaxInsulin: Int = round(medtrumPump.desiredHourlyMaxInsulin / 0.05).toInt()
val dailyMaxInsulin: Int = round(medtrumPump.desiredDailyMaxInsulin / 0.05).toInt()
val patchExpiration: Byte = medtrumPump.desiredPatchExpiration.toByte()
val autoSuspendEnable: Byte = 0
val autoSuspendTime: Byte = 12 // Not sure why, but pump needs this
val lowSuspend: Byte = 0
val predictiveLowSuspend: Byte = 0
val predictiveLowSuspendRange: Byte = 30 // Not sure why, but pump needs this
return byteArrayOf(opCode) + alarmSetting + hourlyMaxInsulin.toByteArray(2) + dailyMaxInsulin.toByteArray(2) + patchExpiration + 0.toByteArray(5)
return byteArrayOf(opCode) + alarmSetting.code + hourlyMaxInsulin.toByteArray(2) + dailyMaxInsulin.toByteArray(2) + patchExpiration + autoSuspendEnable + autoSuspendTime + lowSuspend + predictiveLowSuspend + predictiveLowSuspendRange
}
}

View file

@ -103,8 +103,26 @@ class MedtrumService : DaggerService(), BLECommCallback {
.toObservable(EventPreferenceChange::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ event ->
if (event.isChanged(rh.gs(info.nightscout.pump.medtrum.R.string.key_snInput))) {
changePump()
if (event.isChanged(rh.gs(info.nightscout.pump.medtrum.R.string.key_sn_input))) {
medtrumPump.loadUserSettingsFromSP()
}
if (event.isChanged(rh.gs(info.nightscout.pump.medtrum.R.string.key_alarm_setting))
|| event.isChanged(rh.gs(info.nightscout.pump.medtrum.R.string.key_patch_expiration))
|| event.isChanged(rh.gs(info.nightscout.pump.medtrum.R.string.key_hourly_max_insulin))
|| event.isChanged(rh.gs(info.nightscout.pump.medtrum.R.string.key_daily_max_insulin))
) {
medtrumPump.loadUserSettingsFromSP()
commandQueue.setUserOptions(object : Callback() {
override fun run() {
if (medtrumPlugin.isInitialized() && this.result.success == false) {
uiInteraction.addNotification(
Notification.PUMP_SETTINGS_FAILED,
rh.gs(R.string.pump_setting_failed),
Notification.NORMAL,
)
}
}
})
}
}, fabricPrivacy::logException)
scope.launch {
@ -173,7 +191,7 @@ class MedtrumService : DaggerService(), BLECommCallback {
}
}
changePump()
medtrumPump.loadFromSP()
}
override fun onDestroy() {
@ -247,6 +265,11 @@ class MedtrumService : DaggerService(), BLECommCallback {
return result
}
fun setUserSettings(): Boolean {
rxBus.send(EventPumpStatusChanged(rh.gs(info.nightscout.pump.medtrum.R.string.settingpumpsettings)))
return sendPacketAndGetResponse(SetPatchPacket(injector))
}
fun setBolus(insulin: Double, t: EventOverviewBolusProgress.Treatment): Boolean {
if (!isConnected) return false
val result = sendPacketAndGetResponse(SetBolusPacket(injector, insulin))
@ -355,11 +378,6 @@ class MedtrumService : DaggerService(), BLECommCallback {
return result
}
fun changePump() {
aapsLogger.debug(LTag.PUMP, "changePump: called!")
medtrumPump.loadUserSettingsFromSP()
}
/** This gets the history records from the pump */
private fun syncRecords(): Boolean {
aapsLogger.debug(LTag.PUMP, "syncRecords: called!, syncedSequenceNumber: ${medtrumPump.syncedSequenceNumber}, currentSequenceNumber: ${medtrumPump.currentSequenceNumber}")

View file

@ -67,6 +67,7 @@ class MedtrumViewModel @Inject constructor(
if (patchStep.value == PatchStep.START_DEACTIVATION) {
updateSetupStep(SetupStep.READY_DEACTIVATE)
}
medtrumPump.lastConnection = System.currentTimeMillis()
}
ConnectionState.DISCONNECTED -> {

View file

@ -0,0 +1,23 @@
<resources>
<string-array name="alarmSettings">
<!-- Nano doesnt have lights, other patches not yet supported -->
<!-- <item>Light, vibrate and beep</item> -->
<!-- <item>Light and vibrate</item> -->
<!-- <item>Light and beep</item> -->
<!-- <item>Light only</item> -->
<item>Vibrate and beep</item>
<item>Vibrate only</item>
<item>Beep only</item>
<item>None</item>
</string-array>
<string-array name="alarmSettingsValues" translatable="false">
<!-- <item>0</item> -->
<!-- <item>1</item> -->
<!-- <item>2</item> -->
<!-- <item>3</item> -->
<item>4</item>
<item>5</item>
<item>6</item>
<item>7</item>
</string-array>
</resources>

View file

@ -1,7 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- MedtrumPump -->
<string name="key_snInput" translatable="false">snInput</string>
<string name="key_sn_input" translatable="false">sn_input</string>
<string name="key_alarm_setting" translatable="false">alarm_setting</string>
<string name="key_patch_expiration" translatable="false">patch_expiration</string>
<string name="key_hourly_max_insulin" translatable="false">hourly_max_insulin</string>
<string name="key_daily_max_insulin" translatable="false">daily_max_insulin</string>
<string name="key_medtrumpump_settings" translatable="false">medtrumpump_settings</string>
<string name="key_pump_state" translatable="false">pump_state</string>
<string name="key_session_token" translatable="false">medtrum_session_token</string>
@ -17,6 +22,7 @@
<string name="pump_error">Pump error: %1$s !! </string>
<string name="pump_is_suspended">Pump is suspended</string>
<string name="patch_not_active">Patch not activated</string>
<string name="pump_setting_failed">Setting user settings to pump failed!</string>
<!-- overview fragment -->
<string name="medtrum_ble_status">BLE Status</string>
@ -45,13 +51,22 @@
<string name ="step_deactivate">Deactivation</string>
<!-- settings-->
<string name="snInput_title">SN</string>
<string name="snInput_summary">Serial number pump base</string>
<string name="sn_input_title">Serial Number</string>
<string name="sn_input_summary">Enter the serial number of your pump base.</string>
<string name="alarm_setting_title">Alarm Settings</string>
<string name="alarm_setting_summary">Select your preferred pump alarm settings.</string>
<string name="patch_expiration_title">Patch Expiration</string>
<string name="patch_expiration_summary">Turn this on to get an alert 12 hours before the patch expiration. When enabled, the patch will expire after 3 days.</string>
<string name="hourly_max_insulin_title">Hourly Maximum Insulin</string>
<string name="hourly_max_insulin_summary">Specify the maximum units of insulin allowed per hour. If exceeded, the pump will suspend.</string>
<string name="daily_max_insulin_title">Daily Maximum Insulin</string>
<string name="daily_max_insulin_summary">Specify the maximum units of insulin allowed per day. If exceeded, the pump will suspend.</string>
<!-- treatment state-->
<string name="waitingforestimatedbolusend">Waiting for bolus end. Remaining %1$d sec.</string>
<string name="gettingpumpstatus">Getting pump status</string>
<string name="gettingbolusstatus">Getting bolus status</string>
<string name="gettingtempbasalstatus">Getting temporary basal status</string>
<string name="settingpumpsettings">Setting user options</string>
</resources>

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:validate="http://schemas.android.com/apk/res-auto">
<PreferenceCategory
android:key="@string/key_medtrumpump_settings"
@ -8,10 +8,45 @@
app:initialExpandedChildrenCount="0">
<EditTextPreference
android:key="@string/key_snInput"
android:summary="@string/snInput_summary"
android:key="@string/key_sn_input"
android:summary="@string/sn_input_summary"
android:singleLine="true"
android:title="@string/snInput_title" />
android:title="@string/sn_input_title" />
<SwitchPreference
android:defaultValue="false"
android:key="@string/key_patch_expiration"
android:title="@string/patch_expiration_title"
android:summary="@string/patch_expiration_summary" />
<ListPreference
android:defaultValue="4"
android:key="@string/key_alarm_setting"
android:title="@string/alarm_setting_title"
android:dialogTitle="@string/alarm_setting_summary"
android:entries="@array/alarmSettings"
android:entryValues="@array/alarmSettingsValues" />
<info.nightscout.core.validators.ValidatingEditTextPreference
android:defaultValue="30"
android:inputType="number"
android:key="@string/key_hourly_max_insulin"
android:title="@string/hourly_max_insulin_title"
android:dialogMessage="@string/hourly_max_insulin_summary"
validate:maxNumber="40"
validate:minNumber="10"
validate:testType="numericRange" />
<info.nightscout.core.validators.ValidatingEditTextPreference
android:defaultValue="100"
android:inputType="number"
android:key="@string/key_daily_max_insulin"
android:title="@string/daily_max_insulin_title"
android:dialogMessage="@string/daily_max_insulin_summary"
validate:maxNumber="180"
validate:minNumber="25"
validate:testType="numericRange" />
</PreferenceCategory>
</androidx.preference.PreferenceScreen>

View file

@ -26,7 +26,7 @@ class ActivatePacketTest : MedtrumTestBase() {
@Test fun getRequestGivenPacketWhenValuesSetThenReturnCorrectByteArray() {
// Inputs
medtrumPump.desiredPatchExpiration = true
medtrumPump.desiredAlarmSetting = AlarmSetting.BEEP_ONLY.code
medtrumPump.desiredAlarmSetting = AlarmSetting.BEEP_ONLY
medtrumPump.desiredDailyMaxInsulin = 40
medtrumPump.desiredDailyMaxInsulin = 180
@ -44,7 +44,7 @@ class ActivatePacketTest : MedtrumTestBase() {
@Test fun handleResponseGivenPacketWhenValuesSetThenReturnCorrectValues() {
// Inputs
medtrumPump.desiredPatchExpiration = true
medtrumPump.desiredAlarmSetting = AlarmSetting.BEEP_ONLY.code
medtrumPump.desiredAlarmSetting = AlarmSetting.BEEP_ONLY
medtrumPump.desiredDailyMaxInsulin = 40
medtrumPump.desiredDailyMaxInsulin = 180

View file

@ -23,7 +23,7 @@ class SetPatchPacketTest : MedtrumTestBase() {
@Test fun getRequestGivenValuesWhenCalledThenReturnValidArray() {
// Inputs
medtrumPump.desiredPatchExpiration = false
medtrumPump.desiredAlarmSetting = AlarmSetting.LIGHT_AND_VIBRATE.code
medtrumPump.desiredAlarmSetting = AlarmSetting.LIGHT_AND_VIBRATE
medtrumPump.desiredDailyMaxInsulin = 40
medtrumPump.desiredDailyMaxInsulin = 180
@ -32,7 +32,7 @@ class SetPatchPacketTest : MedtrumTestBase() {
val result = packet.getRequest()
// Expected values
val expected = byteArrayOf(35, 1, 32, 3, 16, 14, 0, 0, 0, 0, 0, 0)
val expected = byteArrayOf(35, 1, 32, 3, 16, 14, 0, 0, 12, 0, 0, 30)
assertEquals(expected.contentToString(), result.contentToString())
}
}