diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManager.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManager.kt index 3063c6de12..c567702331 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManager.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManager.kt @@ -2,7 +2,7 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.event.PodEvent import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertConfiguration -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertSlot +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertType import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.BasalProgram import io.reactivex.Observable import java.util.* @@ -33,7 +33,7 @@ interface OmnipodDashManager { fun programAlerts(alertConfigurations: List): Observable - fun silenceAlerts(alerts: EnumSet): Observable + fun silenceAlerts(alerts: EnumSet): Observable fun deactivatePod(): Observable } \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt index f40dace292..19660bf9d7 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt @@ -8,7 +8,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.G import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.GetVersionCommand.Companion.DEFAULT_UNIQUE_ID import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.ActivationProgress import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertConfiguration -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertSlot +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertType import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.BasalProgram import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.AlarmStatusResponse import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.DefaultStatusResponse @@ -119,7 +119,7 @@ class OmnipodDashManagerImpl @Inject constructor( return Observable.empty() } - override fun silenceAlerts(alerts: EnumSet): Observable { + override fun silenceAlerts(alerts: EnumSet): Observable { // TODO return Observable.empty() } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramAlertsCommand.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramAlertsCommand.kt index 4f0424988b..44c8505a49 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramAlertsCommand.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramAlertsCommand.kt @@ -53,14 +53,14 @@ class ProgramAlertsCommand private constructor( private var alertConfigurations: List? = null - fun setAlertConfigurations(alertConfigurations: List?): Builder { + fun setAlertConfigurations(alertConfigurations: List): Builder { this.alertConfigurations = alertConfigurations return this } override fun buildCommand(): ProgramAlertsCommand { - requireNotNull(alertConfigurations) { "alertConfigurations can not be null" } // !!? - return ProgramAlertsCommand(uniqueId!!, sequenceNumber!!, multiCommandFlag, alertConfigurations!!, nonce!!) // TODO this might crash if not all are set + requireNotNull(alertConfigurations) { "alertConfigurations can not be null" } + return ProgramAlertsCommand(uniqueId!!, sequenceNumber!!, multiCommandFlag, alertConfigurations!!, nonce!!) } } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramBasalCommand.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramBasalCommand.kt index 5758fe9377..9e9afdd3d3 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramBasalCommand.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramBasalCommand.kt @@ -77,17 +77,17 @@ class ProgramBasalCommand private constructor( private var programReminder: ProgramReminder? = null private var currentTime: Date? = null - fun setBasalProgram(basalProgram: BasalProgram?): Builder { + fun setBasalProgram(basalProgram: BasalProgram): Builder { this.basalProgram = basalProgram return this } - fun setProgramReminder(programReminder: ProgramReminder?): Builder { + fun setProgramReminder(programReminder: ProgramReminder): Builder { this.programReminder = programReminder return this } - fun setCurrentTime(currentTime: Date?): Builder { + fun setCurrentTime(currentTime: Date): Builder { this.currentTime = currentTime return this } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramBolusCommand.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramBolusCommand.kt index c6bbfcfb72..c02f1d3ef0 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramBolusCommand.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramBolusCommand.kt @@ -70,7 +70,7 @@ class ProgramBolusCommand private constructor( return this } - fun setProgramReminder(programReminder: ProgramReminder?): Builder { + fun setProgramReminder(programReminder: ProgramReminder): Builder { this.programReminder = programReminder return this } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramTempBasalCommand.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramTempBasalCommand.kt index 229138dd2d..c0179ed62e 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramTempBasalCommand.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramTempBasalCommand.kt @@ -32,7 +32,7 @@ class ProgramTempBasalCommand private constructor( private var rateInUnitsPerHour: Double? = null private var durationInMinutes: Short? = null - fun setProgramReminder(programReminder: ProgramReminder?): Builder { + fun setProgramReminder(programReminder: ProgramReminder): Builder { this.programReminder = programReminder return this } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/SetUniqueIdCommand.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/SetUniqueIdCommand.kt index 965f9a3de3..04d62e99ac 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/SetUniqueIdCommand.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/SetUniqueIdCommand.kt @@ -56,7 +56,7 @@ class SetUniqueIdCommand private constructor( return this } - fun setInitializationTime(initializationTime: Date?): Builder { + fun setInitializationTime(initializationTime: Date): Builder { this.initializationTime = initializationTime return this } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/SilenceAlertsCommand.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/SilenceAlertsCommand.kt index e838c89395..afdfa1c25b 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/SilenceAlertsCommand.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/SilenceAlertsCommand.kt @@ -3,7 +3,8 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base.CommandType import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base.NonceEnabledCommand import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base.builder.NonceEnabledCommandBuilder -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.Encodable +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertType +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.util.AlertUtil import java.nio.ByteBuffer import java.util.* @@ -11,7 +12,7 @@ class SilenceAlertsCommand private constructor( uniqueId: Int, sequenceNumber: Short, multiCommandFlag: Boolean, - private val parameters: SilenceAlertCommandParameters, + private val alertTypes: EnumSet, nonce: Int ) : NonceEnabledCommand(CommandType.SILENCE_ALERTS, uniqueId, sequenceNumber, multiCommandFlag, nonce) { @@ -22,12 +23,12 @@ class SilenceAlertsCommand private constructor( .put(commandType.value) // .put(BODY_LENGTH) // .putInt(nonce) // - .put(parameters.encoded) // + .put(AlertUtil.encodeAlertSet(alertTypes)) // .array()) override fun toString(): String { return "SilenceAlertsCommand{" + - "parameters=" + parameters + + "alterTypes=" + alertTypes + ", nonce=" + nonce + ", commandType=" + commandType + ", uniqueId=" + uniqueId + @@ -36,76 +37,18 @@ class SilenceAlertsCommand private constructor( '}' } - class SilenceAlertCommandParameters(private val silenceAutoOffAlert: Boolean, private val silenceMultiCommandAlert: Boolean, private val silenceExpirationImminentAlert: Boolean, private val silenceUserSetExpirationAlert: Boolean, private val silenceLowReservoirAlert: Boolean, private val silenceSuspendInProgressAlert: Boolean, private val silenceSuspendEndedAlert: Boolean, private val silencePodExpirationAlert: Boolean) : Encodable { - - override val encoded: ByteArray - get() { - val bitSet = BitSet(8) - bitSet[0] = silenceAutoOffAlert - bitSet[1] = silenceMultiCommandAlert - bitSet[2] = silenceExpirationImminentAlert - bitSet[3] = silenceUserSetExpirationAlert - bitSet[4] = silenceLowReservoirAlert - bitSet[5] = silenceSuspendInProgressAlert - bitSet[6] = silenceSuspendEndedAlert - bitSet[7] = silencePodExpirationAlert - return bitSet.toByteArray() - } - } - class Builder : NonceEnabledCommandBuilder() { - private var silenceAutoOffAlert = false - private var silenceMultiCommandAlert = false - private var silenceExpirationImminentAlert = false - private var silenceUserSetExpirationAlert = false - private var silenceLowReservoirAlert = false - private var silenceSuspendInProgressAlert = false - private var silenceSuspendEndedAlert = false - private var silencePodExpirationAlert = false + private var alertTypes: EnumSet? = null - fun setSilenceAutoOffAlert(silenceAutoOffAlert: Boolean): Builder { - this.silenceAutoOffAlert = silenceAutoOffAlert - return this - } - - fun setSilenceMultiCommandAlert(silenceMultiCommandAlert: Boolean): Builder { - this.silenceMultiCommandAlert = silenceMultiCommandAlert - return this - } - - fun setSilenceExpirationImminentAlert(silenceExpirationImminentAlert: Boolean): Builder { - this.silenceExpirationImminentAlert = silenceExpirationImminentAlert - return this - } - - fun setSilenceUserSetExpirationAlert(silenceUserSetExpirationAlert: Boolean): Builder { - this.silenceUserSetExpirationAlert = silenceUserSetExpirationAlert - return this - } - - fun setSilenceLowReservoirAlert(silenceLowReservoirAlert: Boolean): Builder { - this.silenceLowReservoirAlert = silenceLowReservoirAlert - return this - } - - fun setSilenceSuspendInProgressAlert(silenceSuspendInProgressAlert: Boolean): Builder { - this.silenceSuspendInProgressAlert = silenceSuspendInProgressAlert - return this - } - - fun setSilenceSuspendEndedAlert(silenceSuspendEndedAlert: Boolean): Builder { - this.silenceSuspendEndedAlert = silenceSuspendEndedAlert - return this - } - - fun setSilencePodExpirationAlert(silencePodExpirationAlert: Boolean): Builder { - this.silencePodExpirationAlert = silencePodExpirationAlert + fun setAlertTypes(alertTypes: EnumSet): Builder { + this.alertTypes = alertTypes return this } override fun buildCommand(): SilenceAlertsCommand { - return SilenceAlertsCommand(uniqueId!!, sequenceNumber!!, multiCommandFlag, SilenceAlertCommandParameters(silenceAutoOffAlert, silenceMultiCommandAlert, silenceExpirationImminentAlert, silenceUserSetExpirationAlert, silenceLowReservoirAlert, silenceSuspendInProgressAlert, silenceSuspendEndedAlert, silencePodExpirationAlert), nonce!!) + requireNotNull(alertTypes) { "alertTypes can not be null" } + return SilenceAlertsCommand(uniqueId!!, sequenceNumber!!, multiCommandFlag, alertTypes!!, nonce!!) } } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/StopDeliveryCommand.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/StopDeliveryCommand.kt index 254fd8edf3..603a7ff09d 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/StopDeliveryCommand.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/StopDeliveryCommand.kt @@ -58,12 +58,12 @@ class StopDeliveryCommand private constructor( private var deliveryType: DeliveryType? = null private var beepType: BeepType? = BeepType.LONG_SINGLE_BEEP - fun setDeliveryType(deliveryType: DeliveryType?): Builder { + fun setDeliveryType(deliveryType: DeliveryType): Builder { this.deliveryType = deliveryType return this } - fun setBeepType(beepType: BeepType?): Builder { + fun setBeepType(beepType: BeepType): Builder { this.beepType = beepType return this } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/definition/AlertConfiguration.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/definition/AlertConfiguration.kt index 9b1b3a8d4c..4040ac5831 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/definition/AlertConfiguration.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/definition/AlertConfiguration.kt @@ -4,23 +4,22 @@ import java.nio.ByteBuffer import kotlin.experimental.or class AlertConfiguration( - private val slot: AlertSlot, + private val type: AlertType, private val enabled: Boolean, private val durationInMinutes: Short, private val autoOff: Boolean, - private val triggerType: AlertTriggerType, - private val offsetInMinutesOrThresholdInMicroLiters: Short, + private val trigger: AlertTrigger, private val beepType: BeepType, private val beepRepetition: BeepRepetitionType ) : Encodable { override val encoded: ByteArray get() { - var firstByte = (slot.value.toInt() shl 4).toByte() + var firstByte = (type.index.toInt() shl 4).toByte() if (enabled) { firstByte = firstByte or (1 shl 3) } - if (triggerType == AlertTriggerType.RESERVOIR_VOLUME_TRIGGER) { + if (trigger is AlertTrigger.ReservoirVolumeTrigger) { firstByte = firstByte or (1 shl 2) } if (autoOff) { @@ -30,7 +29,15 @@ class AlertConfiguration( return ByteBuffer.allocate(6) // .put(firstByte) .put(durationInMinutes.toByte()) // - .putShort(offsetInMinutesOrThresholdInMicroLiters) // + .putShort(when (trigger) { + is AlertTrigger.ReservoirVolumeTrigger -> { + trigger.thresholdInMicroLiters + } + + is AlertTrigger.TimerTrigger -> { + trigger.offsetInMinutes + } + }) // .put(beepRepetition.value) // .put(beepType.value) // .array() @@ -38,12 +45,11 @@ class AlertConfiguration( override fun toString(): String { return "AlertConfiguration{" + - "slot=" + slot + + "type=" + type + ", enabled=" + enabled + ", durationInMinutes=" + durationInMinutes + ", autoOff=" + autoOff + - ", triggerType=" + triggerType + - ", offsetInMinutesOrThresholdInMicroLiters=" + offsetInMinutesOrThresholdInMicroLiters + + ", trigger=" + trigger + ", beepType=" + beepType + ", beepRepetition=" + beepRepetition + '}' diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/definition/AlertTrigger.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/definition/AlertTrigger.kt new file mode 100644 index 0000000000..48df9b25bf --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/definition/AlertTrigger.kt @@ -0,0 +1,6 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition + +sealed class AlertTrigger { + class TimerTrigger(val offsetInMinutes: Short) : AlertTrigger() + class ReservoirVolumeTrigger(val thresholdInMicroLiters: Short) : AlertTrigger() +} \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/definition/AlertTriggerType.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/definition/AlertTriggerType.kt deleted file mode 100644 index 7dc7a16f1a..0000000000 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/definition/AlertTriggerType.kt +++ /dev/null @@ -1,6 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition - -enum class AlertTriggerType { - TIME_TRIGGER, - RESERVOIR_VOLUME_TRIGGER -} \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/definition/AlertSlot.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/definition/AlertType.kt similarity index 69% rename from omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/definition/AlertSlot.kt rename to omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/definition/AlertType.kt index 3735e550cd..ec6d472066 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/definition/AlertSlot.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/definition/AlertType.kt @@ -2,7 +2,7 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definiti import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.util.HasValue -enum class AlertSlot(override val value: Byte) : HasValue { +enum class AlertType(val index: Byte) : HasValue { AUTO_OFF(0x00.toByte()), MULTI_COMMAND(0x01.toByte()), @@ -13,4 +13,11 @@ enum class AlertSlot(override val value: Byte) : HasValue { SUSPEND_ENDED(0x06.toByte()), EXPIRATION(0x07.toByte()), UNKNOWN(0xff.toByte()); + + override val value: Byte + get() = if (this == UNKNOWN) { + 0xff.toByte() + } else { + (1 shl index.toInt()).toByte() + } } \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/response/AlarmStatusResponse.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/response/AlarmStatusResponse.kt index df22e3a23a..847eaa903c 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/response/AlarmStatusResponse.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/response/AlarmStatusResponse.kt @@ -1,11 +1,14 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlarmType +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertType import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.DeliveryStatus import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.PodStatus import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.ResponseType.StatusResponseType +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.util.AlertUtil import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.util.byValue import java.nio.ByteBuffer +import java.util.* import kotlin.experimental.and class AlarmStatusResponse( @@ -24,14 +27,7 @@ class AlarmStatusResponse( val alarmTime: Short = ByteBuffer.wrap(byteArrayOf(encoded[11], encoded[12])).short val reservoirPulsesRemaining: Short = ByteBuffer.wrap(byteArrayOf(encoded[13], encoded[14])).short val minutesSinceActivation: Short = ByteBuffer.wrap(byteArrayOf(encoded[15], encoded[16])).short - val alert0Active: Boolean - val alert1Active: Boolean - val alert2Active: Boolean - val alert3Active: Boolean - val alert4Active: Boolean - val alert5Active: Boolean - val alert6Active: Boolean - val alert7Active: Boolean + val activeAlerts: EnumSet = AlertUtil.decodeAlertSet(encoded[17]) val occlusionAlarm: Boolean val pulseInfoInvalid: Boolean val podStatusWhenAlarmOccurred: PodStatus @@ -44,15 +40,6 @@ class AlarmStatusResponse( val returnAddressOfPodAlarmHandlerCaller: Short init { - val activeAlerts = encoded[17].toInt() - alert0Active = activeAlerts and 1 == 1 - alert1Active = activeAlerts ushr 1 and 1 == 1 - alert2Active = activeAlerts ushr 2 and 1 == 1 - alert3Active = activeAlerts ushr 3 and 1 == 1 - alert4Active = activeAlerts ushr 4 and 1 == 1 - alert5Active = activeAlerts ushr 5 and 1 == 1 - alert6Active = activeAlerts ushr 6 and 1 == 1 - alert7Active = activeAlerts ushr 7 and 1 == 1 val alarmFlags = encoded[18] occlusionAlarm = (alarmFlags.toInt() and 1) == 1 pulseInfoInvalid = alarmFlags shr 1 and 1 == 1 @@ -69,44 +56,33 @@ class AlarmStatusResponse( } override fun toString(): String { - return "AlarmStatusResponse{" + - "messageType=" + messageType + - ", messageLength=" + messageLength + - ", additionalStatusResponseType=" + additionalStatusResponseType + - ", podStatus=" + podStatus + - ", deliveryStatus=" + deliveryStatus + - ", bolusPulsesRemaining=" + bolusPulsesRemaining + - ", sequenceNumberOfLastProgrammingCommand=" + sequenceNumberOfLastProgrammingCommand + - ", totalPulsesDelivered=" + totalPulsesDelivered + - ", alarmType=" + alarmType + - ", alarmTime=" + alarmTime + - ", reservoirPulsesRemaining=" + reservoirPulsesRemaining + - ", minutesSinceActivation=" + minutesSinceActivation + - ", alert0Active=" + alert0Active + - ", alert1Active=" + alert1Active + - ", alert2Active=" + alert2Active + - ", alert3Active=" + alert3Active + - ", alert4Active=" + alert4Active + - ", alert5Active=" + alert5Active + - ", alert6Active=" + alert6Active + - ", alert7Active=" + alert7Active + - ", occlusionAlarm=" + occlusionAlarm + - ", pulseInfoInvalid=" + pulseInfoInvalid + - ", podStatusWhenAlarmOccurred=" + podStatusWhenAlarmOccurred + - ", immediateBolusWhenAlarmOccurred=" + immediateBolusWhenAlarmOccurred + - ", occlusionType=" + occlusionType + - ", occurredWhenFetchingImmediateBolusActiveInformation=" + occurredWhenFetchingImmediateBolusActiveInformation + - ", rssi=" + rssi + - ", receiverLowerGain=" + receiverLowerGain + - ", podStatusWhenAlarmOccurred2=" + podStatusWhenAlarmOccurred2 + - ", returnAddressOfPodAlarmHandlerCaller=" + returnAddressOfPodAlarmHandlerCaller + - ", statusResponseType=" + statusResponseType + - ", responseType=" + responseType + - ", encoded=" + encoded.contentToString() + - '}' + return "AlarmStatusResponse(" + + "messageType=$messageType, " + + "messageLength=$messageLength, " + + "additionalStatusResponseType=$additionalStatusResponseType, " + + "podStatus=$podStatus, " + + "deliveryStatus=$deliveryStatus, " + + "bolusPulsesRemaining=$bolusPulsesRemaining, " + + "sequenceNumberOfLastProgrammingCommand=$sequenceNumberOfLastProgrammingCommand, " + + "totalPulsesDelivered=$totalPulsesDelivered, " + + "alarmType=$alarmType, " + + "alarmTime=$alarmTime, " + + "reservoirPulsesRemaining=$reservoirPulsesRemaining, " + + "minutesSinceActivation=$minutesSinceActivation, " + + "activeAlerts=$activeAlerts, " + + "occlusionAlarm=$occlusionAlarm, " + + "pulseInfoInvalid=$pulseInfoInvalid, " + + "podStatusWhenAlarmOccurred=$podStatusWhenAlarmOccurred, " + + "immediateBolusWhenAlarmOccurred=$immediateBolusWhenAlarmOccurred, " + + "occlusionType=$occlusionType, " + + "occurredWhenFetchingImmediateBolusActiveInformation=$occurredWhenFetchingImmediateBolusActiveInformation, " + + "rssi=$rssi, " + + "receiverLowerGain=$receiverLowerGain, " + + "podStatusWhenAlarmOccurred2=$podStatusWhenAlarmOccurred2, " + + "returnAddressOfPodAlarmHandlerCaller=$returnAddressOfPodAlarmHandlerCaller" + + ")" } infix fun Byte.shr(i: Int): Int = toInt() shr i -} - +} \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/response/DefaultStatusResponse.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/response/DefaultStatusResponse.kt index cfe5a0af70..fde2951b31 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/response/DefaultStatusResponse.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/response/DefaultStatusResponse.kt @@ -1,8 +1,11 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertType import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.DeliveryStatus import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.PodStatus +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.util.AlertUtil import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.util.byValue +import java.util.* import kotlin.experimental.and class DefaultStatusResponse( @@ -15,42 +18,24 @@ class DefaultStatusResponse( val totalPulsesDelivered: Short = ((encoded[2] and 0x0f shl 12 or (encoded[3].toInt() and 0xff shl 1) or (encoded[4].toInt() and 0xff ushr 7)).toShort()) val sequenceNumberOfLastProgrammingCommand: Short = (encoded[4] ushr 3 and 0x0f).toShort() val bolusPulsesRemaining: Short = ((encoded[4] and 0x07 shl 10 or (encoded[5].toInt() and 0xff) and 2047).toShort()) - val activeAlerts = (encoded[6].toInt() and 0xff shl 1 or (encoded[7] ushr 7)).toShort() - val occlusionAlertActive: Boolean = (activeAlerts and 1).toInt() == 1 - val alert1Active: Boolean = activeAlerts shr 1 and 1 == 1 - val alert2Active: Boolean = activeAlerts shr 2 and 1 == 1 - val alert3Active: Boolean = activeAlerts shr 3 and 1 == 1 - val alert4Active: Boolean = activeAlerts shr 4 and 1 == 1 - val alert5Active: Boolean = activeAlerts shr 5 and 1 == 1 - val alert6Active: Boolean = activeAlerts shr 6 and 1 == 1 - val alert7Active: Boolean = activeAlerts shr 7 and 1 == 1 + val activeAlerts: EnumSet = AlertUtil.decodeAlertSet((encoded[6].toInt() and 0xff shl 1 or (encoded[7] ushr 7)).toByte()) val minutesSinceActivation: Short = (encoded[7] and 0x7f shl 6 or (encoded[8].toInt() and 0xff ushr 2 and 0x3f)).toShort() val reservoirPulsesRemaining: Short = (encoded[8] shl 8 or encoded[9].toInt() and 0x3ff).toShort() override fun toString(): String { - return "DefaultStatusResponse{" + - "messageType=" + messageType + - ", deliveryStatus=" + deliveryStatus + - ", podStatus=" + podStatus + - ", totalPulsesDelivered=" + totalPulsesDelivered + - ", sequenceNumberOfLastProgrammingCommand=" + sequenceNumberOfLastProgrammingCommand + - ", bolusPulsesRemaining=" + bolusPulsesRemaining + - ", occlusionAlertActive=" + occlusionAlertActive + - ", alert1Active=" + alert1Active + - ", alert2Active=" + alert2Active + - ", alert3Active=" + alert3Active + - ", alert4Active=" + alert4Active + - ", alert5Active=" + alert5Active + - ", alert6Active=" + alert6Active + - ", alert7Active=" + alert7Active + - ", minutesSinceActivation=" + minutesSinceActivation + - ", reservoirPulsesRemaining=" + reservoirPulsesRemaining + - ", responseType=" + responseType + - ", encoded=" + encoded.contentToString() + - '}' + return "DefaultStatusResponse(" + + "messageType=$messageType" + + ", deliveryStatus=$deliveryStatus" + + ", podStatus=$podStatus" + + ", totalPulsesDelivered=$totalPulsesDelivered" + + ", sequenceNumberOfLastProgrammingCommand=$sequenceNumberOfLastProgrammingCommand" + + ", bolusPulsesRemaining=$bolusPulsesRemaining" + + ", activeAlerts=$activeAlerts" + + ", minutesSinceActivation=$minutesSinceActivation" + + ", reservoirPulsesRemaining=$reservoirPulsesRemaining)" } + } infix fun Byte.ushr(i: Int) = toInt() ushr i -infix fun Short.shr(i: Int): Int = toInt() shr i infix fun Byte.shl(i: Int): Int = toInt() shl i diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt index bcfe894f5e..b0a069b5bc 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt @@ -39,7 +39,7 @@ interface OmnipodDashPodStateManager { val podStatus: PodStatus? val deliveryStatus: DeliveryStatus? val minutesSinceActivation: Short? - val activeAlerts: EnumSet? + val activeAlerts: EnumSet? val tempBasal: TempBasal? val tempBasalActive: Boolean diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt index 04370dad68..229109a6d2 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt @@ -130,7 +130,7 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( override val minutesSinceActivation: Short? get() = podState.minutesSinceActivation - override val activeAlerts: EnumSet? + override val activeAlerts: EnumSet? get() = podState.activeAlerts override val tempBasal: OmnipodDashPodStateManager.TempBasal? @@ -247,7 +247,7 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( var podStatus: PodStatus? = null var deliveryStatus: DeliveryStatus? = null var minutesSinceActivation: Short? = null - var activeAlerts: EnumSet? = null + var activeAlerts: EnumSet? = null var basalProgram: BasalProgram? = null var tempBasal: OmnipodDashPodStateManager.TempBasal? = null diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/util/AlertUtil.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/util/AlertUtil.kt new file mode 100644 index 0000000000..04cc4e3ce0 --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/util/AlertUtil.kt @@ -0,0 +1,29 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.util + +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertType +import java.util.* + +object AlertUtil { + + fun decodeAlertSet(encoded: Byte): EnumSet { + val encodedInt = encoded.toInt() and 0xff + + val alertList = AlertType.values().filter { + (it.value.toInt() and 0xff) and encodedInt != 0 + }.toList() + + return if (alertList.isEmpty()) { + EnumSet.noneOf(AlertType::class.java) + } else { + EnumSet.copyOf(alertList) + } + } + + fun encodeAlertSet(alertSet: EnumSet): Byte { + var out = 0 + alertSet.forEach { slot -> + out = out or (slot.value.toInt() and 0xff) + } + return out.toByte() + } +} \ No newline at end of file diff --git a/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramAlertsCommandTest.kt b/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramAlertsCommandTest.kt index 7fca25cfd7..63c5063c0e 100644 --- a/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramAlertsCommandTest.kt +++ b/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramAlertsCommandTest.kt @@ -1,8 +1,8 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertConfiguration -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertSlot -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertTriggerType +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertType +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertTrigger import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.BeepRepetitionType import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.BeepType import org.apache.commons.codec.DecoderException @@ -15,8 +15,8 @@ class ProgramAlertsCommandTest { @Test @Throws(DecoderException::class) fun testExpirationAlerts() { val configurations: MutableList = ArrayList() - configurations.add(AlertConfiguration(AlertSlot.EXPIRATION, true, 420.toShort(), false, AlertTriggerType.TIME_TRIGGER, 4305.toShort(), BeepType.FOUR_TIMES_BIP_BEEP, BeepRepetitionType.XXX3)) - configurations.add(AlertConfiguration(AlertSlot.EXPIRATION_IMMINENT, true, 0.toShort(), false, AlertTriggerType.TIME_TRIGGER, 4725.toShort(), BeepType.FOUR_TIMES_BIP_BEEP, BeepRepetitionType.XXX4)) + configurations.add(AlertConfiguration(AlertType.EXPIRATION, true, 420.toShort(), false, AlertTrigger.TimerTrigger(4305.toShort()), BeepType.FOUR_TIMES_BIP_BEEP, BeepRepetitionType.XXX3)) + configurations.add(AlertConfiguration(AlertType.EXPIRATION_IMMINENT, true, 0.toShort(), false, AlertTrigger.TimerTrigger(4725.toShort()), BeepType.FOUR_TIMES_BIP_BEEP, BeepRepetitionType.XXX4)) val encoded = ProgramAlertsCommand.Builder() // .setUniqueId(37879811) // @@ -32,7 +32,7 @@ class ProgramAlertsCommandTest { @Test @Throws(DecoderException::class) fun testLowReservoirAlert() { val configurations: MutableList = ArrayList() - configurations.add(AlertConfiguration(AlertSlot.LOW_RESERVOIR, true, 0.toShort(), false, AlertTriggerType.RESERVOIR_VOLUME_TRIGGER, 200.toShort(), BeepType.FOUR_TIMES_BIP_BEEP, BeepRepetitionType.XXX)) + configurations.add(AlertConfiguration(AlertType.LOW_RESERVOIR, true, 0.toShort(), false, AlertTrigger.ReservoirVolumeTrigger(200.toShort()), BeepType.FOUR_TIMES_BIP_BEEP, BeepRepetitionType.XXX)) val encoded = ProgramAlertsCommand.Builder() // .setUniqueId(37879811) // @@ -47,7 +47,7 @@ class ProgramAlertsCommandTest { @Test @Throws(DecoderException::class) fun testUserExpirationAlert() { val configurations: MutableList = ArrayList() - configurations.add(AlertConfiguration(AlertSlot.USER_SET_EXPIRATION, true, 0.toShort(), false, AlertTriggerType.TIME_TRIGGER, 4079.toShort(), BeepType.FOUR_TIMES_BIP_BEEP, BeepRepetitionType.XXX2)) + configurations.add(AlertConfiguration(AlertType.USER_SET_EXPIRATION, true, 0.toShort(), false, AlertTrigger.TimerTrigger(4079.toShort()), BeepType.FOUR_TIMES_BIP_BEEP, BeepRepetitionType.XXX2)) val encoded = ProgramAlertsCommand.Builder() // .setUniqueId(37879811) // @@ -62,7 +62,7 @@ class ProgramAlertsCommandTest { @Test @Throws(DecoderException::class) fun testLumpOfCoalAlert() { val configurations: MutableList = ArrayList() - configurations.add(AlertConfiguration(AlertSlot.EXPIRATION, true, 55.toShort(), false, AlertTriggerType.TIME_TRIGGER, 5.toShort(), BeepType.FOUR_TIMES_BIP_BEEP, BeepRepetitionType.XXX5)) + configurations.add(AlertConfiguration(AlertType.EXPIRATION, true, 55.toShort(), false, AlertTrigger.TimerTrigger(5.toShort()), BeepType.FOUR_TIMES_BIP_BEEP, BeepRepetitionType.XXX5)) val encoded = ProgramAlertsCommand.Builder() // .setUniqueId(37879811) // diff --git a/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/SilenceAlertsCommandTest.kt b/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/SilenceAlertsCommandTest.kt index f901594225..0f9c267578 100644 --- a/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/SilenceAlertsCommandTest.kt +++ b/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/SilenceAlertsCommandTest.kt @@ -1,9 +1,11 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertType import org.apache.commons.codec.DecoderException import org.apache.commons.codec.binary.Hex import org.junit.Assert import org.junit.Test +import java.util.* class SilenceAlertsCommandTest { @@ -12,7 +14,7 @@ class SilenceAlertsCommandTest { .setUniqueId(37879811) // .setSequenceNumber(1.toShort()) // .setNonce(1229869870) // - .setSilenceLowReservoirAlert(true) // + .setAlertTypes(EnumSet.of(AlertType.LOW_RESERVOIR)) // .build() // .encoded diff --git a/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/response/AlarmStatusResponseTest.kt b/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/response/AlarmStatusResponseTest.kt index 2095cbbf8a..06e6337afd 100644 --- a/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/response/AlarmStatusResponseTest.kt +++ b/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/response/AlarmStatusResponseTest.kt @@ -29,14 +29,7 @@ class AlarmStatusResponseTest { Assert.assertEquals(0.toShort(), response.alarmTime) Assert.assertEquals(1023.toShort(), response.reservoirPulsesRemaining) Assert.assertEquals(405.toShort(), response.minutesSinceActivation) - Assert.assertFalse(response.alert0Active) - Assert.assertFalse(response.alert1Active) - Assert.assertFalse(response.alert2Active) - Assert.assertFalse(response.alert3Active) - Assert.assertFalse(response.alert4Active) - Assert.assertFalse(response.alert5Active) - Assert.assertFalse(response.alert6Active) - Assert.assertFalse(response.alert7Active) + Assert.assertEquals(0, response.activeAlerts.size) Assert.assertFalse(response.occlusionAlarm) Assert.assertFalse(response.pulseInfoInvalid) Assert.assertEquals(PodStatus.UNINITIALIZED, response.podStatusWhenAlarmOccurred) diff --git a/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/response/DefaultStatusResponseTest.kt b/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/response/DefaultStatusResponseTest.kt index da375beab1..f925642d38 100644 --- a/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/response/DefaultStatusResponseTest.kt +++ b/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/response/DefaultStatusResponseTest.kt @@ -2,7 +2,6 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.DeliveryStatus import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.PodStatus -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.ResponseType import org.apache.commons.codec.DecoderException import org.apache.commons.codec.binary.Hex import org.junit.Assert @@ -22,14 +21,7 @@ class DefaultStatusResponseTest { Assert.assertEquals(320.toShort(), response.totalPulsesDelivered) Assert.assertEquals(5.toShort(), response.sequenceNumberOfLastProgrammingCommand) Assert.assertEquals(0.toShort(), response.bolusPulsesRemaining) - Assert.assertFalse(response.occlusionAlertActive) - Assert.assertFalse(response.alert1Active) - Assert.assertFalse(response.alert2Active) - Assert.assertFalse(response.alert3Active) - Assert.assertFalse(response.alert4Active) - Assert.assertFalse(response.alert5Active) - Assert.assertFalse(response.alert6Active) - Assert.assertFalse(response.alert7Active) + Assert.assertEquals(0, response.activeAlerts.size) Assert.assertEquals(280.toShort(), response.minutesSinceActivation) Assert.assertEquals(1023.toShort(), response.reservoirPulsesRemaining) }