Skip to content
Open
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
8013f90
sms command to send insulin wip
jgr-lab Oct 4, 2024
7dd7c3f
- fix compilation issues
jgr-lab Oct 10, 2024
793c36e
- working dialog from insulindialog.kt
jgr-lab Oct 17, 2024
e6d87d5
- calc wizard working
jgr-lab Oct 23, 2024
9c86d09
cleanup and formatting
jgr-lab Oct 23, 2024
d18ab0d
- improve sms option placement in menu
jgr-lab Oct 31, 2024
a3107c0
fix some sonarscan issues
jgr-lab Oct 31, 2024
7991263
review fixes
jgr-lab Nov 1, 2024
b093f7f
add warning regarding IOB synchronization
jgr-lab Nov 15, 2024
9f2a45e
- move sms related settings to Button menu
jgr-lab Dec 8, 2024
e5319cc
compilation fix
jgr-lab Dec 10, 2024
80a7ea6
Merge remote-tracking branch 'upstream/dev' into mushroom/sms_bolus
jgr-lab Jan 8, 2025
3fff443
WIP extend sms bolus command
jgr-lab Jan 10, 2025
36d09dc
Merge remote-tracking branch 'upstream/dev' into mushroom/sms_bolus
jgr-lab Jan 12, 2025
a8d5b73
- Introduce new BOLUSCARBS command
jgr-lab Jan 28, 2025
b1f2cd8
Merge remote-tracking branch 'upstream/dev' into mushroom/sms_bolus
jgr-lab Jan 28, 2025
ff2907e
don't allow to set alarm on aapsclient's phone, minor fixes
jgr-lab Jan 30, 2025
4f72df7
- fix double response for boluscarbs command
jgr-lab Feb 3, 2025
8fa040b
Merge remote-tracking branch 'upstream/dev' into mushroom/sms_bolus
jgr-lab Feb 12, 2025
28da6c7
Handle bolus advisor (exit with explanation)
jgr-lab Feb 12, 2025
d747a0f
Merge remote-tracking branch 'upstream/dev' into mushroom/sms_bolus
jgr-lab Feb 20, 2025
7992971
Support for comma separator in boluscarbs command
jgr-lab Feb 25, 2025
7a4239a
Merge remote-tracking branch 'upstream/dev' into mushroom/sms_bolus
jgr-lab Feb 25, 2025
b37521a
Merge remote-tracking branch 'upstream/dev' into mushroom/sms_bolus
jgr-lab Mar 3, 2025
98d4c68
tests impl
jgr-lab Mar 3, 2025
32e42aa
cleanup
jgr-lab Mar 8, 2025
8fb66e5
Merge remote-tracking branch 'upstream/dev' into mushroom/sms_bolus
jgr-lab Mar 9, 2025
1f5aaf3
Merge remote-tracking branch 'upstream/dev' into mushroom/sms_bolus
jgr-lab Mar 26, 2025
3260089
Merge remote-tracking branch 'upstream/dev' into mushroom/sms_bolus
jgr-lab Mar 27, 2025
0c78c70
Merge remote-tracking branch 'upstream/dev' into mushroom/sms_bolus
jgr-lab Apr 6, 2025
f7deff2
Merge remote-tracking branch 'upstream/dev' into mushroom/sms_bolus
jgr-lab Apr 12, 2025
e26ffd7
Merge remote-tracking branch 'upstream/dev' into mushroom/sms_bolus
jgr-lab Sep 19, 2025
f4df8df
Merge remote-tracking branch 'upstream/dev' into mushroom/sms_bolus
jgr-lab Sep 24, 2025
659759c
merge fix
jgr-lab Sep 24, 2025
21bbf38
Merge remote-tracking branch 'upstream/dev' into mushroom/sms_bolus
jgr-lab Oct 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ object Constants {
const val notificationID = 556677

// SMS COMMUNICATOR
const val remoteBolusMinDistance = 15 * 60 * 1000L
const val remoteBolusMinDistance = 5 * 60 * 1000L

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

15 minutes seems to be too much. In my case I've set some max carbs limit for single meal. It's intended to limit bolus to make sure carbs absorption kicks in on time. When meal is bigger than max carb then I split calculations into 2 meal with 5 minutes delay. 5 should also prevent accidental bolus at the same time from multiple caregivers

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Totally agree. I have the same process in place with the treatment on my two kids. Set bolus limit for safety, leading to mandatory split bolus for regular meals.


// Circadian Percentage Profile
const val CPP_MIN_PERCENTAGE = 30
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package app.aaps.core.interfaces.smsCommunicator

fun formatBolusCarbsCommand(insulin: Double, carbs: Int, time: String? = null, set_alarm: Boolean = false): String {
var msg = "Boluscarbs " + "%.2f ".format(insulin) + carbs.toString()
if (!time.isNullOrEmpty()) {
if (time.all { it.isDigit() })
// xx min offset
msg += " +" + time
else
// either of -yy, +xx, 1:23, 2:34PM
msg += " " + time

if (set_alarm == true)
msg += " alarm"
}
return msg
}
2 changes: 1 addition & 1 deletion core/keys/src/main/kotlin/app/aaps/core/keys/BooleanKey.kt
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ enum class BooleanKey(
AutotuneCircadianIcIsf("autotune_circadian_ic_isf", false),
AutotuneAdditionalLog("autotune_additional_log", false),

SmsAllowRemoteCommands("smscommunicator_remotecommandsallowed", false),
SmsAllowRemoteCommands("smscommunicator_remotecommandsallowed", false, showInApsMode = false, showInPumpControlMode = false),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This plugin is intended only for AAPSClient. It sends SMS commands to phone running AAPS. Both AAPS and control app are on the pump controlling phone so presence of that plugin would be confusing.

SmsReportPumpUnreachable("smscommunicator_report_pump_unreachable", true),

VirtualPumpStatusUpload("virtualpump_uploadstatus", false, showInNsClientMode = false),
Expand Down
1 change: 1 addition & 0 deletions core/keys/src/main/kotlin/app/aaps/core/keys/StringKey.kt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ enum class StringKey(
AutomationLocation("location", "PASSIVE", hideParentScreenIfHidden = true),

SmsAllowedNumbers("smscommunicator_allowednumbers", ""),
SmsReceiverNumber("sms_communicator_receiver_number", "", showInApsMode = false, showInPumpControlMode = false, dependency = BooleanKey.SmsAllowRemoteCommands),
SmsOtpPassword("smscommunicator_otp_password", "", dependency = BooleanKey.SmsAllowRemoteCommands, isPassword = true),
SmsOtpSecret("smscommunicator_otp_secret", ""), // Move to StringNonKey

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,16 @@ import app.aaps.core.interfaces.resources.ResourceHelper
import app.aaps.core.interfaces.rx.bus.RxBus
import app.aaps.core.interfaces.rx.events.EventRefreshOverview
import app.aaps.core.interfaces.sharedPreferences.SP
import app.aaps.core.interfaces.smsCommunicator.Sms
import app.aaps.core.interfaces.smsCommunicator.SmsCommunicator
import app.aaps.core.interfaces.smsCommunicator.formatBolusCarbsCommand
import app.aaps.core.interfaces.ui.UiInteraction
import app.aaps.core.interfaces.utils.DateUtil
import app.aaps.core.interfaces.utils.DecimalFormatter
import app.aaps.core.interfaces.utils.Round
import app.aaps.core.keys.BooleanKey
import app.aaps.core.keys.Preferences
import app.aaps.core.keys.StringKey
import app.aaps.core.objects.constraints.ConstraintObject
import app.aaps.core.objects.extensions.formatColor
import app.aaps.core.objects.extensions.highValueToUnitsToString
Expand All @@ -63,6 +67,7 @@ class BolusWizard @Inject constructor(
val injector: HasAndroidInjector
) {

@Inject lateinit var smsCommunicator: SmsCommunicator
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var rh: ResourceHelper
@Inject lateinit var rxBus: RxBus
Expand All @@ -86,9 +91,12 @@ class BolusWizard @Inject constructor(
@Inject lateinit var processedDeviceStatusData: ProcessedDeviceStatusData

var timeStamp: Long
// var phoneNumber: String

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


init {
injector.androidInjector().inject(this)
// why this@BolusWizar.phoneNumber not visible in scoped DetailedBolusInfo().apply
// phoneNumber = preferences.get(StringKey.SmsReceiverNumber)
timeStamp = dateUtil.now()
}

Expand Down Expand Up @@ -330,7 +338,7 @@ class BolusWizard @Inject constructor(
}

private fun confirmMessageAfterConstraints(context: Context, advisor: Boolean, quickWizardEntry: QuickWizardEntry? = null): Spanned {

val phoneNumber = preferences.get(StringKey.SmsReceiverNumber)
val actions: LinkedList<String> = LinkedList()
if (insulinAfterConstraints > 0) {
val pct = if (percentageCorrection != 100) " ($percentageCorrection%)" else ""
Expand Down Expand Up @@ -370,8 +378,12 @@ class BolusWizard @Inject constructor(
rh.gs(app.aaps.core.ui.R.string.bolus_constraint_applied_warn, calculatedTotalInsulin, insulinAfterConstraints)
.formatColor(context, rh, app.aaps.core.ui.R.attr.warningColor)
)
if (config.AAPSCLIENT && insulinAfterConstraints > 0)
actions.add(rh.gs(app.aaps.core.ui.R.string.bolus_recorded_only).formatColor(context, rh, app.aaps.core.ui.R.attr.warningColor))
val bolusOrCarbs = (insulinAfterConstraints > 0 || carbs > 0)
if (config.AAPSCLIENT && bolusOrCarbs)
if (preferences.get(BooleanKey.SmsAllowRemoteCommands) && !phoneNumber.isNullOrBlank() && bolusOrCarbs)
actions.add(rh.gs(app.aaps.core.ui.R.string.sms_request_notification).formatColor(context, rh, app.aaps.core.ui.R.attr.warningColor))
else
actions.add(rh.gs(app.aaps.core.ui.R.string.bolus_recorded_only).formatColor(context, rh, app.aaps.core.ui.R.attr.warningColor))
if (useAlarm && !advisor && carbs > 0 && carbTime > 0)
actions.add(rh.gs(app.aaps.core.ui.R.string.alarminxmin, carbTime).formatColor(context, rh, app.aaps.core.ui.R.attr.infoColor))
if (advisor)
Expand Down Expand Up @@ -421,6 +433,14 @@ class BolusWizard @Inject constructor(
}

private fun bolusAdvisorProcessing(ctx: Context) {
val phoneNumber = preferences.get(StringKey.SmsReceiverNumber)
if (preferences.get(BooleanKey.SmsAllowRemoteCommands) && !phoneNumber.isNullOrBlank()) {
// Bolus advisor is not supported because automation.scheduleAutomationEventEatReminder() can't be set on AAPSClient phone.
// In order to do so AAPSClient phone would need to wait in pooling for bolus confirmation message. I don't want to block app on that.
OKDialog.show(ctx, rh.gs(app.aaps.core.ui.R.string.boluswizard), rh.gs(app.aaps.core.ui.R.string.bolus_advisor_not_supported))
return
}

val confirmMessage = confirmMessageAfterConstraints(ctx, advisor = true)
OKDialog.showConfirmation(ctx, rh.gs(app.aaps.core.ui.R.string.boluswizard), confirmMessage, {
DetailedBolusInfo().apply {
Expand Down Expand Up @@ -538,15 +558,21 @@ class BolusWizard @Inject constructor(
ValueWithUnit.Minute(carbTime).takeIf { carbTime != 0 }
).filterNotNull()
)
commandQueue.bolus(this, object : Callback() {
override fun run() {
if (!result.success) {
uiInteraction.runAlarm(result.comment, rh.gs(app.aaps.core.ui.R.string.treatmentdeliveryerror), app.aaps.core.ui.R.raw.boluserror)
} else if (useAlarm && carbs > 0 && carbTime > 0) {
automation.scheduleTimeToEatReminder(T.mins(carbTime.toLong()).secs().toInt())
val phoneNumber = preferences.get(StringKey.SmsReceiverNumber)
if (preferences.get(BooleanKey.SmsAllowRemoteCommands) && !phoneNumber.isNullOrBlank()) {
Comment thread
jgr-lab marked this conversation as resolved.
Outdated
rh.gs(app.aaps.core.ui.R.string.sms_request_notification).formatColor(context, rh, app.aaps.core.ui.R.attr.warningColor)
smsCommunicator.sendSMS(Sms(phoneNumber, formatBolusCarbsCommand(insulin, this@BolusWizard.carbs, this@BolusWizard.carbTime.toString(), useAlarm)))
} else {
commandQueue.bolus(this, object : Callback() {
override fun run() {
if (!result.success) {
uiInteraction.runAlarm(result.comment, rh.gs(app.aaps.core.ui.R.string.treatmentdeliveryerror), app.aaps.core.ui.R.raw.boluserror)
} else if (config.APS && useAlarm && carbs > 0 && carbTime > 0) {
automation.scheduleTimeToEatReminder(T.mins(carbTime.toLong()).secs().toInt())
}
}
}
})
})
}
}
bolusCalculatorResult?.let { persistenceLayer.insertOrUpdateBolusCalculatorResult(it).blockingGet() }
}
Expand Down
3 changes: 3 additions & 0 deletions core/ui/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -454,13 +454,16 @@
<!-- BolusWizard -->
<string name="bolus_advisor">Bolus advisor</string>
<string name="bolus_advisor_message">You have high glycemia. Instead of eating now it\'s recommended to wait for better glycemia. Do you want to do a correction bolus now and remind you when it\'s time to eat? In this case no carbs will be recorded and you must use wizard again when we remind you.</string>
<string name="bolus_advisor_not_supported">Bolus advisor doesn\'t work with SMS commands. Wait till BG drops or provide correction bolus using Insulin or Treatment buttons.</string>

<string name="cobvsiob">COB vs IOB</string>
<string name="slowabsorptiondetected"><![CDATA[<font color=\'%1$s\'>!!!!! Slow carbs absorption detected: %2$d%% of time. Double check your calculation. COB can be overestimated thus more insulin could be given !!!!!</font>]]></string>
<string name="partialboluswizard">Deliver this part of bolus wizard result [%]</string>
<string name="sms_receiver_number">Receiver phone number for sms commands sent from AAPSClient phone</string>
<string name="partialboluswizard_reset_time">Old glycemia time threshold [min]</string>
<string name="bolus_constraint_applied_warn">Bolus constraint applied: %1$.2f U to %2$.2f U</string>
<string name="bolus_recorded_only">Bolus will be recorded only (not delivered by pump)</string>
<string name="sms_request_notification">SMS command will be sent</string>
<string name="advisoralarm">Run alarm when is time to eat</string>
<string name="no_action_selected">No action selected, nothing will happen</string>
<string name="carb_equal_zero_no_action">Carbs = 0. No action taken!</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,13 @@ import app.aaps.core.objects.extensions.putString
import app.aaps.core.objects.extensions.store
import app.aaps.core.objects.extensions.storeBoolean
import app.aaps.core.objects.extensions.storeString
import app.aaps.core.validators.DefaultEditTextValidator
import app.aaps.core.validators.EditTextValidator
import app.aaps.core.validators.preferences.AdaptiveClickPreference
import app.aaps.core.validators.preferences.AdaptiveDoublePreference
import app.aaps.core.validators.preferences.AdaptiveIntPreference
import app.aaps.core.validators.preferences.AdaptiveIntentPreference
import app.aaps.core.validators.preferences.AdaptiveStringPreference
import app.aaps.core.validators.preferences.AdaptiveSwitchPreference
import app.aaps.core.validators.preferences.AdaptiveUnitPreference
import app.aaps.plugins.main.R
Expand Down Expand Up @@ -235,6 +238,13 @@ class OverviewPlugin @Inject constructor(
addPreference(AdaptiveSwitchPreference(ctx = context, booleanKey = BooleanKey.OverviewShowTreatmentButton, title = R.string.treatments))
addPreference(AdaptiveSwitchPreference(ctx = context, booleanKey = BooleanKey.OverviewShowWizardButton, title = R.string.calculator_label))
addPreference(AdaptiveSwitchPreference(ctx = context, booleanKey = BooleanKey.OverviewShowInsulinButton, title = app.aaps.core.ui.R.string.configbuilder_insulin))
addPreference(AdaptiveSwitchPreference(ctx = context, booleanKey = BooleanKey.SmsAllowRemoteCommands, summary = R.string.client_allow_sms_warning, title = R.string.client_allow_sms))
addPreference(
AdaptiveStringPreference(
ctx = context, stringKey = StringKey.SmsReceiverNumber, dialogMessage = R.string.sms_receiver_number_dialog, title = app.aaps.core.ui.R.string.sms_receiver_number,
validatorParams = DefaultEditTextValidator.Parameters(testType = EditTextValidator.TEST_PHONE)
)
)
addPreference(AdaptiveDoublePreference(ctx = context, doubleKey = DoubleKey.OverviewInsulinButtonIncrement1, dialogMessage = R.string.insulin_increment_button_message, title = R.string.firstinsulinincrement))
addPreference(AdaptiveDoublePreference(ctx = context, doubleKey = DoubleKey.OverviewInsulinButtonIncrement2, dialogMessage = R.string.insulin_increment_button_message, title = R.string.secondinsulinincrement))
addPreference(AdaptiveDoublePreference(ctx = context, doubleKey = DoubleKey.OverviewInsulinButtonIncrement3, dialogMessage = R.string.insulin_increment_button_message, title = R.string.thirdinsulinincrement))
Expand Down Expand Up @@ -306,6 +316,8 @@ class OverviewPlugin @Inject constructor(
)
})
addPreference(AdaptiveIntPreference(ctx = context, intKey = IntKey.OverviewBolusPercentage, dialogMessage = R.string.deliverpartofboluswizard, title = app.aaps.core.ui.R.string.partialboluswizard))


addPreference(AdaptiveIntPreference(ctx = context, intKey = IntKey.OverviewResetBolusPercentageTime, dialogMessage = R.string.deliver_part_of_boluswizard_reset_time, title = app.aaps.core.ui.R.string.partialboluswizard_reset_time))
addPreference(AdaptiveSwitchPreference(ctx = context, booleanKey = BooleanKey.OverviewUseBolusAdvisor, summary = R.string.enable_bolus_advisor_summary, title = R.string.enable_bolus_advisor))
addPreference(AdaptiveSwitchPreference(ctx = context, booleanKey = BooleanKey.OverviewUseBolusReminder, summary = R.string.enablebolusreminder_summary, title = R.string.enablebolusreminder))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ abstract class SmsAction(val pumpCommand: Boolean) : Runnable {

var aDouble: Double? = null
var anInteger: Int? = null
private var aLong: Long? = null
private var secondInteger: Int? = null
private var secondLong: Long? = null
private var aString: String? = null
Expand Down Expand Up @@ -31,8 +32,15 @@ abstract class SmsAction(val pumpCommand: Boolean) : Runnable {
this.secondInteger = secondInteger
}

internal constructor(pumpCommand: Boolean, anInteger: Int, secondLong: Long) : this(pumpCommand) {
internal constructor(pumpCommand: Boolean, anInteger: Int, aLong: Long) : this(pumpCommand) {
this.anInteger = anInteger
this.aLong = aLong
}

internal constructor(pumpCommand: Boolean, aDouble: Double, anInteger: Int, aLong: Long, secondLong: Long) : this(pumpCommand) {
this.aDouble = aDouble
this.anInteger = anInteger
this.aLong = aLong
this.secondLong = secondLong
}

Expand All @@ -54,6 +62,12 @@ abstract class SmsAction(val pumpCommand: Boolean) : Runnable {
} ?: throw IllegalStateException()
}

fun aLong(): Long {
return aLong?.let {
aLong
} ?: throw IllegalStateException()
}

fun secondLong(): Long {
return secondLong?.let {
secondLong
Expand Down
Loading