Merge branch 'AddActionCP' into dev
This commit is contained in:
commit
65a14c8eca
10 changed files with 320 additions and 1 deletions
|
@ -130,7 +130,6 @@
|
||||||
<string name="overview">Overview</string>
|
<string name="overview">Overview</string>
|
||||||
<string name="treatments">Treatments</string>
|
<string name="treatments">Treatments</string>
|
||||||
<string name="virtualpump">Virtual Pump</string>
|
<string name="virtualpump">Virtual Pump</string>
|
||||||
<string name="careportal">Careportal</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="configbuilder_pump">Pump</string>
|
<string name="configbuilder_pump">Pump</string>
|
||||||
|
|
|
@ -39,6 +39,7 @@ abstract class AutomationModule {
|
||||||
@ContributesAndroidInjector abstract fun actionLoopSuspendInjector(): ActionLoopSuspend
|
@ContributesAndroidInjector abstract fun actionLoopSuspendInjector(): ActionLoopSuspend
|
||||||
@ContributesAndroidInjector abstract fun actionNotificationInjector(): ActionNotification
|
@ContributesAndroidInjector abstract fun actionNotificationInjector(): ActionNotification
|
||||||
@ContributesAndroidInjector abstract fun actionAlarmInjector(): ActionAlarm
|
@ContributesAndroidInjector abstract fun actionAlarmInjector(): ActionAlarm
|
||||||
|
@ContributesAndroidInjector abstract fun actionCarePortalEventInjector(): ActionCarePortalEvent
|
||||||
@ContributesAndroidInjector abstract fun actionProfileSwitchInjector(): ActionProfileSwitch
|
@ContributesAndroidInjector abstract fun actionProfileSwitchInjector(): ActionProfileSwitch
|
||||||
@ContributesAndroidInjector abstract fun actionProfileSwitchPercentInjector(): ActionProfileSwitchPercent
|
@ContributesAndroidInjector abstract fun actionProfileSwitchPercentInjector(): ActionProfileSwitchPercent
|
||||||
@ContributesAndroidInjector abstract fun actionSendSMSInjector(): ActionSendSMS
|
@ContributesAndroidInjector abstract fun actionSendSMSInjector(): ActionSendSMS
|
||||||
|
|
|
@ -293,6 +293,7 @@ class AutomationPlugin @Inject constructor(
|
||||||
ActionStopTempTarget(injector),
|
ActionStopTempTarget(injector),
|
||||||
ActionNotification(injector),
|
ActionNotification(injector),
|
||||||
ActionAlarm(injector),
|
ActionAlarm(injector),
|
||||||
|
ActionCarePortalEvent(injector),
|
||||||
ActionProfileSwitchPercent(injector),
|
ActionProfileSwitchPercent(injector),
|
||||||
ActionProfileSwitch(injector),
|
ActionProfileSwitch(injector),
|
||||||
ActionSendSMS(injector)
|
ActionSendSMS(injector)
|
||||||
|
|
|
@ -51,6 +51,8 @@ abstract class Action(val injector: HasAndroidInjector) {
|
||||||
return when (type) {
|
return when (type) {
|
||||||
ActionAlarm::class.java.name, // backward compatibility
|
ActionAlarm::class.java.name, // backward compatibility
|
||||||
ActionAlarm::class.java.simpleName -> ActionAlarm(injector).fromJSON(data.toString())
|
ActionAlarm::class.java.simpleName -> ActionAlarm(injector).fromJSON(data.toString())
|
||||||
|
ActionCarePortalEvent::class.java.name,
|
||||||
|
ActionCarePortalEvent::class.java.simpleName -> ActionCarePortalEvent(injector).fromJSON(data.toString())
|
||||||
ActionDummy::class.java.name,
|
ActionDummy::class.java.name,
|
||||||
ActionDummy::class.java.simpleName -> ActionDummy(injector).fromJSON(data.toString())
|
ActionDummy::class.java.simpleName -> ActionDummy(injector).fromJSON(data.toString())
|
||||||
ActionLoopDisable::class.java.name,
|
ActionLoopDisable::class.java.name,
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.actions
|
||||||
|
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import androidx.annotation.DrawableRes
|
||||||
|
import dagger.android.HasAndroidInjector
|
||||||
|
import info.nightscout.androidaps.automation.R
|
||||||
|
import info.nightscout.androidaps.database.AppRepository
|
||||||
|
import info.nightscout.androidaps.database.entities.TherapyEvent
|
||||||
|
import info.nightscout.androidaps.database.entities.UserEntry
|
||||||
|
import info.nightscout.androidaps.database.entities.ValueWithUnit
|
||||||
|
import info.nightscout.androidaps.database.transactions.InsertIfNewByTimestampTherapyEventTransaction
|
||||||
|
import info.nightscout.androidaps.extensions.fromConstant
|
||||||
|
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||||
|
import info.nightscout.androidaps.logging.LTag
|
||||||
|
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.*
|
||||||
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider
|
||||||
|
import info.nightscout.androidaps.queue.Callback
|
||||||
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper
|
||||||
|
import info.nightscout.androidaps.utils.T
|
||||||
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
|
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||||
|
import io.reactivex.disposables.CompositeDisposable
|
||||||
|
import io.reactivex.rxkotlin.plusAssign
|
||||||
|
import org.json.JSONObject
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class ActionCarePortalEvent(injector: HasAndroidInjector) : Action(injector) {
|
||||||
|
|
||||||
|
@Inject lateinit var resourceHelper: ResourceHelper
|
||||||
|
@Inject lateinit var repository: AppRepository
|
||||||
|
@Inject lateinit var profileFunction: ProfileFunction
|
||||||
|
@Inject lateinit var dateUtil: DateUtil
|
||||||
|
@Inject lateinit var sp: SP
|
||||||
|
@Inject lateinit var glucoseStatusProvider: GlucoseStatusProvider
|
||||||
|
@Inject lateinit var uel: UserEntryLogger
|
||||||
|
|
||||||
|
|
||||||
|
private val disposable = CompositeDisposable()
|
||||||
|
|
||||||
|
var note = InputString()
|
||||||
|
var duration = InputDuration(0, InputDuration.TimeUnit.MINUTES)
|
||||||
|
var cpEvent = InputCarePortalMenu(resourceHelper)
|
||||||
|
private var valuesWithUnit = mutableListOf<ValueWithUnit?>()
|
||||||
|
|
||||||
|
private constructor(injector: HasAndroidInjector, actionCPEvent: ActionCarePortalEvent) : this(injector) {
|
||||||
|
cpEvent = InputCarePortalMenu(resourceHelper, actionCPEvent.cpEvent.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun friendlyName(): Int = R.string.careportal
|
||||||
|
override fun shortDescription(): String = resourceHelper.gs(cpEvent.value.stringRes, note.value)
|
||||||
|
|
||||||
|
@DrawableRes override fun icon(): Int = cpEvent.value.drawableRes
|
||||||
|
|
||||||
|
override fun doAction(callback: Callback) {
|
||||||
|
val enteredBy = sp.getString("careportal_enteredby", "AndroidAPS")
|
||||||
|
val eventTime = dateUtil.now()
|
||||||
|
val therapyEvent = TherapyEvent(
|
||||||
|
timestamp = eventTime,
|
||||||
|
type = cpEvent.value.therapyEventType,
|
||||||
|
glucoseUnit = TherapyEvent.GlucoseUnit.fromConstant(profileFunction.getUnits())
|
||||||
|
)
|
||||||
|
valuesWithUnit.add(ValueWithUnit.TherapyEventType(therapyEvent.type))
|
||||||
|
|
||||||
|
therapyEvent.enteredBy = enteredBy
|
||||||
|
if ( therapyEvent.type == TherapyEvent.Type.QUESTION || therapyEvent.type == TherapyEvent.Type.ANNOUNCEMENT) {
|
||||||
|
val glucoseStatus = glucoseStatusProvider.glucoseStatusData
|
||||||
|
if (glucoseStatus != null) {
|
||||||
|
therapyEvent.glucose = glucoseStatus.glucose
|
||||||
|
therapyEvent.glucoseType = TherapyEvent.MeterType.SENSOR
|
||||||
|
valuesWithUnit.add(ValueWithUnit.fromGlucoseUnit(glucoseStatus.glucose, profileFunction.getUnits().asText))
|
||||||
|
valuesWithUnit.add(ValueWithUnit.TherapyEventMeterType(TherapyEvent.MeterType.SENSOR))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
therapyEvent.duration = T.mins(duration.value.toLong()).msecs()
|
||||||
|
valuesWithUnit.add(ValueWithUnit.Minute(duration.value).takeIf { !duration.value.equals(0) } )
|
||||||
|
}
|
||||||
|
therapyEvent.note = note.value
|
||||||
|
valuesWithUnit.add(ValueWithUnit.SimpleString(note.value).takeIf { note.value.isNotBlank() } )
|
||||||
|
disposable += repository.runTransactionForResult(InsertIfNewByTimestampTherapyEventTransaction(therapyEvent))
|
||||||
|
.subscribe(
|
||||||
|
{ result -> result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted therapy event $it") } },
|
||||||
|
{ aapsLogger.error(LTag.DATABASE, "Error while saving therapy event", it) }
|
||||||
|
)
|
||||||
|
uel.log(UserEntry.Action.CAREPORTAL, UserEntry.Sources.Automation, title, valuesWithUnit)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toJSON(): String {
|
||||||
|
val data = JSONObject()
|
||||||
|
.put("cpEvent", cpEvent.value)
|
||||||
|
.put("note", note.value)
|
||||||
|
.put("durationInMinutes", duration.value)
|
||||||
|
return JSONObject()
|
||||||
|
.put("type", this.javaClass.name)
|
||||||
|
.put("data", data)
|
||||||
|
.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun fromJSON(data: String): Action {
|
||||||
|
val o = JSONObject(data)
|
||||||
|
cpEvent.value = InputCarePortalMenu.EventType.valueOf(JsonHelper.safeGetString(o, "cpEvent")!!)
|
||||||
|
note.value = JsonHelper.safeGetString(o, "note", "")
|
||||||
|
duration.value = JsonHelper.safeGetInt(o, "durationInMinutes")
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hasDialog(): Boolean = true
|
||||||
|
|
||||||
|
override fun generateDialog(root: LinearLayout) {
|
||||||
|
LayoutBuilder()
|
||||||
|
.add(cpEvent)
|
||||||
|
.add(LabelWithElement(resourceHelper, resourceHelper.gs(R.string.duration_min_label), "", duration))
|
||||||
|
.add(LabelWithElement(resourceHelper, resourceHelper.gs(R.string.notes_label), "", note))
|
||||||
|
.build(root)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isValid(): Boolean = true
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.AdapterView
|
||||||
|
import android.widget.ArrayAdapter
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.Spinner
|
||||||
|
import androidx.annotation.DrawableRes
|
||||||
|
import androidx.annotation.LayoutRes
|
||||||
|
import androidx.annotation.StringRes
|
||||||
|
import androidx.core.graphics.drawable.IconCompat
|
||||||
|
import info.nightscout.androidaps.automation.R
|
||||||
|
import info.nightscout.androidaps.database.entities.TherapyEvent
|
||||||
|
import info.nightscout.androidaps.database.entities.UserEntry
|
||||||
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
|
|
||||||
|
class InputCarePortalMenu(private val resourceHelper: ResourceHelper) : Element() {
|
||||||
|
|
||||||
|
enum class EventType (val therapyEventType: TherapyEvent.Type) {
|
||||||
|
NOTE (TherapyEvent.Type.NOTE),
|
||||||
|
EXERCISE (TherapyEvent.Type.EXERCISE),
|
||||||
|
QUESTION (TherapyEvent.Type.QUESTION),
|
||||||
|
ANNOUNCEMENT (TherapyEvent.Type.ANNOUNCEMENT);
|
||||||
|
|
||||||
|
@get:StringRes val stringRes: Int
|
||||||
|
get() = when (this) {
|
||||||
|
NOTE -> R.string.careportal_note_message
|
||||||
|
EXERCISE -> R.string.careportal_exercise_message
|
||||||
|
QUESTION -> R.string.careportal_question_message
|
||||||
|
ANNOUNCEMENT -> R.string.careportal_announcement_message
|
||||||
|
}
|
||||||
|
|
||||||
|
@get:DrawableRes val drawableRes: Int
|
||||||
|
get() = when (this) {
|
||||||
|
NOTE -> R.drawable.ic_cp_note
|
||||||
|
EXERCISE -> R.drawable.ic_cp_exercise
|
||||||
|
QUESTION -> R.drawable.ic_cp_question
|
||||||
|
ANNOUNCEMENT -> R.drawable.ic_cp_announcement
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun labels(resourceHelper: ResourceHelper): List<String> {
|
||||||
|
val list: MutableList<String> = ArrayList()
|
||||||
|
for (e in values()) {
|
||||||
|
list.add(resourceHelper.gs(e.stringRes))
|
||||||
|
}
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(resourceHelper: ResourceHelper, value: EventType) : this(resourceHelper) {
|
||||||
|
this.value = value
|
||||||
|
}
|
||||||
|
|
||||||
|
var value = EventType.NOTE
|
||||||
|
|
||||||
|
override fun addToLayout(root: LinearLayout) {
|
||||||
|
val spinner = Spinner(root.context)
|
||||||
|
val spinnerArrayAdapter = ArrayAdapter(root.context, R.layout.spinner_centered, EventType.labels(resourceHelper))
|
||||||
|
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||||
|
spinner.adapter = spinnerArrayAdapter
|
||||||
|
val spinnerParams = LinearLayout.LayoutParams(
|
||||||
|
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||||
|
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||||
|
)
|
||||||
|
spinnerParams.setMargins(0, resourceHelper.dpToPx(4), 0, resourceHelper.dpToPx(4))
|
||||||
|
spinner.layoutParams = spinnerParams
|
||||||
|
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||||
|
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||||
|
value = EventType.values()[position]
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||||
|
}
|
||||||
|
spinner.setSelection(value.ordinal)
|
||||||
|
root.addView(spinner)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setValue(eventType: EventType): InputCarePortalMenu {
|
||||||
|
value = eventType
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.actions
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.automation.R
|
||||||
|
import info.nightscout.androidaps.database.transactions.InsertIfNewByTimestampTherapyEventTransaction
|
||||||
|
import info.nightscout.androidaps.database.transactions.Transaction
|
||||||
|
import info.nightscout.androidaps.interfaces.GlucoseUnit
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.InputCarePortalMenu
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.InputDuration
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.InputString
|
||||||
|
import info.nightscout.androidaps.queue.Callback
|
||||||
|
import io.reactivex.Single
|
||||||
|
import org.junit.Assert
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.mockito.ArgumentMatchers
|
||||||
|
import org.mockito.Mockito.`when`
|
||||||
|
|
||||||
|
class ActionCarePortalEventTest : ActionsTestBase() {
|
||||||
|
|
||||||
|
private lateinit var sut: ActionCarePortalEvent
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setup() {
|
||||||
|
`when`(sp.getString(ArgumentMatchers.anyString(), ArgumentMatchers.anyString())).thenReturn("AndroidAPS")
|
||||||
|
`when`(
|
||||||
|
resourceHelper.gs(
|
||||||
|
ArgumentMatchers.eq(R.string.careportal_note_message),
|
||||||
|
ArgumentMatchers.anyString()
|
||||||
|
)
|
||||||
|
).thenReturn("Note : %s")
|
||||||
|
`when`(dateUtil.now()).thenReturn(0)
|
||||||
|
`when`(profileFunction.getUnits()).thenReturn(GlucoseUnit.MGDL)
|
||||||
|
`when`(repository.runTransactionForResult(anyObject<Transaction<InsertIfNewByTimestampTherapyEventTransaction.TransactionResult>>()))
|
||||||
|
.thenReturn(Single.just(InsertIfNewByTimestampTherapyEventTransaction.TransactionResult().apply {
|
||||||
|
}))
|
||||||
|
sut = ActionCarePortalEvent(injector)
|
||||||
|
sut.cpEvent = InputCarePortalMenu(resourceHelper)
|
||||||
|
sut.cpEvent.value = InputCarePortalMenu.EventType.NOTE
|
||||||
|
sut.note = InputString("Asd")
|
||||||
|
sut.duration = InputDuration(5, InputDuration.TimeUnit.MINUTES)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test fun friendlyNameTest() {
|
||||||
|
Assert.assertEquals(R.string.careportal, sut.friendlyName())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test fun shortDescriptionTest() {
|
||||||
|
Assert.assertEquals("Note : %s", sut.shortDescription())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test fun iconTest() {
|
||||||
|
Assert.assertEquals(R.drawable.ic_cp_note, sut.icon())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test fun doActionTest() {
|
||||||
|
sut.doAction(object : Callback() {
|
||||||
|
override fun run() {
|
||||||
|
Assert.assertTrue(result.success)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test fun hasDialogTest() {
|
||||||
|
Assert.assertTrue(sut.hasDialog())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test fun toJSONTest() {
|
||||||
|
Assert.assertEquals(
|
||||||
|
"{\"data\":{\"note\":\"Asd\",\"cpEvent\":\"NOTE\",\"durationInMinutes\":5},\"type\":\"info.nightscout.androidaps.plugins.general.automation.actions.ActionCarePortalEvent\"}",
|
||||||
|
sut.toJSON()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test fun fromJSONTest() {
|
||||||
|
sut.note = InputString("Asd")
|
||||||
|
sut.fromJSON("{\"note\":\"Asd\",\"cpEvent\":\"NOTE\",\"durationInMinutes\":5}")
|
||||||
|
Assert.assertEquals("Asd", sut.note.value)
|
||||||
|
Assert.assertEquals(5, sut.duration.value)
|
||||||
|
Assert.assertEquals(InputCarePortalMenu.EventType.NOTE, sut.cpEvent.value)
|
||||||
|
}
|
||||||
|
}
|
|
@ -131,6 +131,14 @@ open class ActionsTestBase : TestBaseWithProfile() {
|
||||||
it.rxBus = rxBus
|
it.rxBus = rxBus
|
||||||
it.uel = uel
|
it.uel = uel
|
||||||
}
|
}
|
||||||
|
if (it is ActionCarePortalEvent) {
|
||||||
|
it.resourceHelper = resourceHelper
|
||||||
|
it.repository = repository
|
||||||
|
it.sp = sp
|
||||||
|
it.dateUtil = dateUtil
|
||||||
|
it.profileFunction = profileFunction
|
||||||
|
it.uel = uel
|
||||||
|
}
|
||||||
if (it is PumpEnactResult) {
|
if (it is PumpEnactResult) {
|
||||||
it.resourceHelper = resourceHelper
|
it.resourceHelper = resourceHelper
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerTestBase
|
||||||
|
import org.junit.Assert
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class InputCarePortalEventTest : TriggerTestBase() {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun labelsTest() {
|
||||||
|
Assert.assertEquals(4, InputCarePortalMenu.EventType.labels(resourceHelper).size)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun setValueTest() {
|
||||||
|
val cp = InputCarePortalMenu(resourceHelper, InputCarePortalMenu.EventType.EXERCISE)
|
||||||
|
Assert.assertEquals(InputCarePortalMenu.EventType.EXERCISE, cp.value)
|
||||||
|
}
|
||||||
|
}
|
|
@ -250,12 +250,17 @@
|
||||||
<string name="activitymonitorformat"><![CDATA[<b><span style=\"color:yellow\">%1$s:</span></b> <b>%2$s</b> in <b>%3$d</b> days<br>]]></string>
|
<string name="activitymonitorformat"><![CDATA[<b><span style=\"color:yellow\">%1$s:</span></b> <b>%2$s</b> in <b>%3$d</b> days<br>]]></string>
|
||||||
|
|
||||||
<!-- Translator-->
|
<!-- Translator-->
|
||||||
|
<string name="careportal">Careportal</string>
|
||||||
<string name="careportal_bgcheck">BG Check</string>
|
<string name="careportal_bgcheck">BG Check</string>
|
||||||
<string name="careportal_mbg">Manual BG or Calibration</string>
|
<string name="careportal_mbg">Manual BG or Calibration</string>
|
||||||
<string name="careportal_announcement">Announcement</string>
|
<string name="careportal_announcement">Announcement</string>
|
||||||
<string name="careportal_note">Note</string>
|
<string name="careportal_note">Note</string>
|
||||||
<string name="careportal_question">Question</string>
|
<string name="careportal_question">Question</string>
|
||||||
<string name="careportal_exercise">Exercise</string>
|
<string name="careportal_exercise">Exercise</string>
|
||||||
|
<string name="careportal_announcement_message">Announcement : %1$s</string>
|
||||||
|
<string name="careportal_note_message">Note : %1$s</string>
|
||||||
|
<string name="careportal_question_message">Question : %1$s</string>
|
||||||
|
<string name="careportal_exercise_message">Exercise : %1$s</string>
|
||||||
<string name="careportal_pumpsitechange">Pump Site Change</string>
|
<string name="careportal_pumpsitechange">Pump Site Change</string>
|
||||||
<string name="careportal_cgmsensorinsert">CGM Sensor Insert</string>
|
<string name="careportal_cgmsensorinsert">CGM Sensor Insert</string>
|
||||||
<string name="careportal_cgmsensorstart">CGM Sensor Start</string>
|
<string name="careportal_cgmsensorstart">CGM Sensor Start</string>
|
||||||
|
|
Loading…
Reference in a new issue