Wear refactor
This commit is contained in:
parent
391a471b27
commit
2dba081176
|
@ -46,6 +46,10 @@
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/AppTheme.Launcher" >
|
android:theme="@style/AppTheme.Launcher" >
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="com.google.android.gms.version"
|
||||||
|
android:value="@integer/google_play_services_version" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".widget.WidgetConfigureActivity"
|
android:name=".widget.WidgetConfigureActivity"
|
||||||
android:theme="@android:style/Theme.Material.Dialog.NoActionBar"
|
android:theme="@android:style/Theme.Material.Dialog.NoActionBar"
|
||||||
|
@ -106,14 +110,6 @@
|
||||||
android:theme="@style/AppTheme" />
|
android:theme="@style/AppTheme" />
|
||||||
<activity android:name=".activities.StatsActivity"
|
<activity android:name=".activities.StatsActivity"
|
||||||
android:theme="@style/AppTheme" />
|
android:theme="@style/AppTheme" />
|
||||||
<activity
|
|
||||||
android:name="com.google.firebase.auth.internal.FederatedSignInActivity"
|
|
||||||
android:excludeFromRecents="true"
|
|
||||||
android:exported="true"
|
|
||||||
android:launchMode="singleInstance"
|
|
||||||
android:permission="com.google.firebase.auth.api.gms.permission.LAUNCH_FEDERATED_SIGN_IN"
|
|
||||||
android:theme="@android:style/Theme.Translucent.NoTitleBar"
|
|
||||||
tools:replace="android:launchMode" />
|
|
||||||
|
|
||||||
<!-- Receive new BG readings from other local apps -->
|
<!-- Receive new BG readings from other local apps -->
|
||||||
<receiver
|
<receiver
|
||||||
|
@ -174,62 +170,38 @@
|
||||||
android:name=".plugins.general.wear.wearintegration.WatchUpdaterService"
|
android:name=".plugins.general.wear.wearintegration.WatchUpdaterService"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<!-- <action android:name="com.google.android.gms.wearable.BIND_LISTENER" /> -->
|
<action android:name="com.google.android.gms.wearable.CHANNEL_EVENT" />
|
||||||
<!-- listeners receive events that match the action and data filters -->
|
|
||||||
<action android:name="com.google.android.gms.wearable.CAPABILITY_CHANGED" />
|
|
||||||
<action android:name="com.google.android.gms.wearable.DATA_CHANGED" />
|
<action android:name="com.google.android.gms.wearable.DATA_CHANGED" />
|
||||||
|
</intent-filter>
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="com.google.android.gms.wearable.CAPABILITY_CHANGED" />
|
||||||
|
<data
|
||||||
|
android:host="*"
|
||||||
|
android:scheme="wear" />
|
||||||
|
</intent-filter>
|
||||||
|
<intent-filter>
|
||||||
|
<!-- listeners receive events that match the action and data filters -->
|
||||||
|
<action android:name="com.google.android.gms.wearable.MESSAGE_RECEIVED" />
|
||||||
|
|
||||||
<data
|
<data
|
||||||
android:host="*"
|
android:host="*"
|
||||||
android:pathPrefix="/nightscout_watch_data"
|
android:pathPrefix="@string/path_pong"
|
||||||
android:scheme="wear" />
|
android:scheme="wear" />
|
||||||
<data
|
<data
|
||||||
android:host="*"
|
android:host="*"
|
||||||
android:pathPrefix="/nightscout_watch_data_resend"
|
android:pathPrefix="@string/path_resend_data_request"
|
||||||
android:scheme="wear" />
|
android:scheme="wear" />
|
||||||
<data
|
<data
|
||||||
android:host="*"
|
android:host="*"
|
||||||
android:pathPrefix="/nightscout_watch_cancel_bolus"
|
android:pathPrefix="/@path_cancel_bolus_on_watch"
|
||||||
android:scheme="wear" />
|
android:scheme="wear" />
|
||||||
<data
|
<data
|
||||||
android:host="*"
|
android:host="*"
|
||||||
android:pathPrefix="/nightscout_watch_confirmactionstring"
|
android:pathPrefix="@string/path_confirm_action"
|
||||||
android:scheme="wear" />
|
android:scheme="wear" />
|
||||||
<data
|
<data
|
||||||
android:host="*"
|
android:host="*"
|
||||||
android:pathPrefix="/nightscout_watch_initiateactionstring"
|
android:pathPrefix="@string/path_initiate_action_on_phone"
|
||||||
android:scheme="wear" />
|
|
||||||
<data
|
|
||||||
android:host="*"
|
|
||||||
android:pathPrefix="/openwearsettings"
|
|
||||||
android:scheme="wear" />
|
|
||||||
<data
|
|
||||||
android:host="*"
|
|
||||||
android:pathPrefix="/sendstatustowear"
|
|
||||||
android:scheme="wear" />
|
|
||||||
<data
|
|
||||||
android:host="*"
|
|
||||||
android:pathPrefix="/sendpreferencestowear"
|
|
||||||
android:scheme="wear" />
|
|
||||||
<data
|
|
||||||
android:host="*"
|
|
||||||
android:pathPrefix="/nightscout_watch_basal"
|
|
||||||
android:scheme="wear" />
|
|
||||||
<data
|
|
||||||
android:host="*"
|
|
||||||
android:pathPrefix="/nightscout_watch_bolusprogress"
|
|
||||||
android:scheme="wear" />
|
|
||||||
<data
|
|
||||||
android:host="*"
|
|
||||||
android:pathPrefix="/nightscout_watch_actionconfirmationrequest"
|
|
||||||
android:scheme="wear" />
|
|
||||||
<data
|
|
||||||
android:host="*"
|
|
||||||
android:pathPrefix="/nightscout_watch_changeconfirmationrequest"
|
|
||||||
android:scheme="wear" />
|
|
||||||
<data
|
|
||||||
android:host="*"
|
|
||||||
android:pathPrefix="/nightscout_watch_cancelnotificationrequest"
|
|
||||||
android:scheme="wear" />
|
android:scheme="wear" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</service>
|
</service>
|
||||||
|
@ -247,10 +219,6 @@
|
||||||
|
|
||||||
<service android:name=".plugins.general.persistentNotification.DummyService" />
|
<service android:name=".plugins.general.persistentNotification.DummyService" />
|
||||||
|
|
||||||
<meta-data
|
|
||||||
android:name="io.fabric.ApiKey"
|
|
||||||
android:value="59d462666c664c57b29e1d79ea123e01f8057cfa" />
|
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".setupwizard.SetupWizardActivity"
|
android:name=".setupwizard.SetupWizardActivity"
|
||||||
android:configChanges="orientation|keyboardHidden|screenSize"
|
android:configChanges="orientation|keyboardHidden|screenSize"
|
||||||
|
|
|
@ -33,7 +33,11 @@ import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionChec
|
||||||
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
|
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
|
||||||
import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationStore
|
import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationStore
|
||||||
import info.nightscout.androidaps.plugins.general.themes.ThemeSwitcherPlugin
|
import info.nightscout.androidaps.plugins.general.themes.ThemeSwitcherPlugin
|
||||||
import info.nightscout.androidaps.receivers.*
|
import info.nightscout.androidaps.receivers.BTReceiver
|
||||||
|
import info.nightscout.androidaps.receivers.ChargingStateReceiver
|
||||||
|
import info.nightscout.androidaps.receivers.KeepAliveWorker
|
||||||
|
import info.nightscout.androidaps.receivers.NetworkChangeReceiver
|
||||||
|
import info.nightscout.androidaps.receivers.TimeDateOrTZChangeReceiver
|
||||||
import info.nightscout.androidaps.services.AlarmSoundServiceHelper
|
import info.nightscout.androidaps.services.AlarmSoundServiceHelper
|
||||||
import info.nightscout.androidaps.utils.ActivityMonitor
|
import info.nightscout.androidaps.utils.ActivityMonitor
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
|
|
|
@ -37,7 +37,7 @@ class SurveyActivity : NoSplashAppCompatActivity() {
|
||||||
binding = ActivitySurveyBinding.inflate(layoutInflater)
|
binding = ActivitySurveyBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
|
||||||
binding.id.text = InstanceId.instanceId()
|
binding.id.text = InstanceId.instanceId
|
||||||
|
|
||||||
val profileStore = activePlugin.activeProfileSource.profile
|
val profileStore = activePlugin.activeProfileSource.profile
|
||||||
val profileList = profileStore?.getProfileList() ?: return
|
val profileList = profileStore?.getProfileList() ?: return
|
||||||
|
@ -80,7 +80,7 @@ class SurveyActivity : NoSplashAppCompatActivity() {
|
||||||
|
|
||||||
binding.submit.setOnClickListener {
|
binding.submit.setOnClickListener {
|
||||||
val r = FirebaseRecord()
|
val r = FirebaseRecord()
|
||||||
r.id = InstanceId.instanceId()
|
r.id = InstanceId.instanceId
|
||||||
r.age = SafeParse.stringToInt(binding.age.text.toString())
|
r.age = SafeParse.stringToInt(binding.age.text.toString())
|
||||||
r.weight = SafeParse.stringToInt(binding.weight.text.toString())
|
r.weight = SafeParse.stringToInt(binding.weight.text.toString())
|
||||||
if (r.age < 1 || r.age > 120) {
|
if (r.age < 1 || r.age > 120) {
|
||||||
|
|
|
@ -2,7 +2,6 @@ package info.nightscout.androidaps.plugins.general.wear
|
||||||
|
|
||||||
import android.app.NotificationManager
|
import android.app.NotificationManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.Log
|
|
||||||
import dagger.android.HasAndroidInjector
|
import dagger.android.HasAndroidInjector
|
||||||
import info.nightscout.androidaps.Constants
|
import info.nightscout.androidaps.Constants
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
|
@ -25,8 +24,6 @@ import info.nightscout.androidaps.database.transactions.InsertAndCancelCurrentTe
|
||||||
import info.nightscout.androidaps.extensions.total
|
import info.nightscout.androidaps.extensions.total
|
||||||
import info.nightscout.androidaps.extensions.valueToUnits
|
import info.nightscout.androidaps.extensions.valueToUnits
|
||||||
import info.nightscout.androidaps.interfaces.*
|
import info.nightscout.androidaps.interfaces.*
|
||||||
import info.nightscout.shared.logging.AAPSLogger
|
|
||||||
import info.nightscout.shared.logging.LTag
|
|
||||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||||
|
@ -38,10 +35,28 @@ import info.nightscout.androidaps.queue.Callback
|
||||||
import info.nightscout.androidaps.utils.*
|
import info.nightscout.androidaps.utils.*
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
import info.nightscout.shared.sharedPreferences.SP
|
|
||||||
import info.nightscout.androidaps.utils.wizard.BolusWizard
|
import info.nightscout.androidaps.utils.wizard.BolusWizard
|
||||||
import info.nightscout.androidaps.utils.wizard.QuickWizard
|
import info.nightscout.androidaps.utils.wizard.QuickWizard
|
||||||
import info.nightscout.shared.SafeParse
|
import info.nightscout.shared.SafeParse
|
||||||
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
|
import info.nightscout.shared.logging.LTag
|
||||||
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
|
import info.nightscout.shared.weardata.ActionData
|
||||||
|
import info.nightscout.shared.weardata.WearConstants.Companion.ACTION_BOLUS
|
||||||
|
import info.nightscout.shared.weardata.WearConstants.Companion.ACTION_CANCEL_CHANGE_REQUEST
|
||||||
|
import info.nightscout.shared.weardata.WearConstants.Companion.ACTION_CHANGE_REQUEST
|
||||||
|
import info.nightscout.shared.weardata.WearConstants.Companion.ACTION_CPP_SET
|
||||||
|
import info.nightscout.shared.weardata.WearConstants.Companion.ACTION_DISMISS_OVERVIEW_NOTIF
|
||||||
|
import info.nightscout.shared.weardata.WearConstants.Companion.ACTION_E_CARBS
|
||||||
|
import info.nightscout.shared.weardata.WearConstants.Companion.ACTION_FILL
|
||||||
|
import info.nightscout.shared.weardata.WearConstants.Companion.ACTION_FILL_PRESET
|
||||||
|
import info.nightscout.shared.weardata.WearConstants.Companion.ACTION_OPEN_CPP
|
||||||
|
import info.nightscout.shared.weardata.WearConstants.Companion.ACTION_QUICK_WIZARD
|
||||||
|
import info.nightscout.shared.weardata.WearConstants.Companion.ACTION_STATUS
|
||||||
|
import info.nightscout.shared.weardata.WearConstants.Companion.ACTION_TDD_STATS
|
||||||
|
import info.nightscout.shared.weardata.WearConstants.Companion.ACTION_TEMPORARY_TARGET
|
||||||
|
import info.nightscout.shared.weardata.WearConstants.Companion.ACTION_WIZARD
|
||||||
|
import info.nightscout.shared.weardata.WearConstants.Companion.ACTION_WIZARD2
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||||
import java.text.DateFormat
|
import java.text.DateFormat
|
||||||
|
@ -96,7 +111,7 @@ class ActionStringHandler @Inject constructor(
|
||||||
disposable += rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventWearInitiateAction::class.java)
|
.toObservable(EventWearInitiateAction::class.java)
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
.subscribe({ handleInitiate(it.action) }, fabricPrivacy::logException)
|
.subscribe({ handleInitiateActionOnPhone(it.action) }, fabricPrivacy::logException)
|
||||||
|
|
||||||
disposable += rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventWearConfirmAction::class.java)
|
.toObservable(EventWearConfirmAction::class.java)
|
||||||
|
@ -109,17 +124,50 @@ class ActionStringHandler @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
private fun handleInitiate(actionString: String) {
|
private fun handleInitiateActionOnPhone(actionString: String) {
|
||||||
//TODO: i18n
|
//TODO: i18n
|
||||||
Log.i("ActionStringHandler", "handleInitiate actionString=$actionString")
|
aapsLogger.debug(LTag.WEAR, "handleInitiateActionOnPhone actionString=$actionString")
|
||||||
if (!sp.getBoolean(R.string.key_wear_control, false)) return
|
if (!sp.getBoolean(R.string.key_wear_control, false)) return
|
||||||
lastBolusWizard = null
|
lastBolusWizard = null
|
||||||
var rTitle = rh.gs(R.string.confirm).uppercase()
|
var rTitle = rh.gs(R.string.confirm).uppercase()
|
||||||
var rMessage = ""
|
var rMessage = ""
|
||||||
var rAction = ""
|
var rAction = ""
|
||||||
|
|
||||||
|
if (actionString.startsWith("{")) {
|
||||||
|
when (val command = ActionData.deserialize(actionString)) {
|
||||||
|
is ActionData.Bolus -> {
|
||||||
|
val insulinAfterConstraints = constraintChecker.applyBolusConstraints(Constraint(command.insulin)).value()
|
||||||
|
val carbsAfterConstraints = constraintChecker.applyCarbsConstraints(Constraint(command.carbs)).value()
|
||||||
|
val pump = activePlugin.activePump
|
||||||
|
if (insulinAfterConstraints > 0 && (!pump.isInitialized() || pump.isSuspended() || loop.isDisconnected)) {
|
||||||
|
sendError(rh.gs(R.string.wizard_pump_not_available))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rMessage += rh.gs(R.string.bolus) + ": " + insulinAfterConstraints + "U\n"
|
||||||
|
rMessage += rh.gs(R.string.carbs) + ": " + carbsAfterConstraints + "g"
|
||||||
|
if (insulinAfterConstraints - command.insulin != 0.0 || carbsAfterConstraints - command.carbs != 0) {
|
||||||
|
rMessage += "\n" + rh.gs(R.string.constraintapllied)
|
||||||
|
}
|
||||||
|
rAction += "bolus $insulinAfterConstraints $carbsAfterConstraints"
|
||||||
|
}
|
||||||
|
is ActionData.ProfileSwitch -> {
|
||||||
|
val activeProfileSwitch = repository.getEffectiveProfileSwitchActiveAt(dateUtil.now()).blockingGet()
|
||||||
|
if (activeProfileSwitch is ValueWrapper.Existing) {
|
||||||
|
rMessage = "Profile:" + "\n\n" +
|
||||||
|
"Timeshift: " + command.timeShift + "\n" +
|
||||||
|
"Percentage: " + command.percentage + "%"
|
||||||
|
rAction = actionString
|
||||||
|
} else { // read CPP values
|
||||||
|
sendError("No active profile switch!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
// do the parsing and check constraints
|
// do the parsing and check constraints
|
||||||
val act = actionString.split("\\s+".toRegex()).toTypedArray()
|
val act = actionString.split("\\s+".toRegex()).toTypedArray()
|
||||||
if ("fillpreset" == act[0]) { ///////////////////////////////////// PRIME/FILL
|
when (act[0]) {
|
||||||
|
ACTION_FILL_PRESET -> { ///////////////////////////////////// PRIME/FILL
|
||||||
val amount: Double = when {
|
val amount: Double = when {
|
||||||
"1" == act[1] -> sp.getDouble("fill_button1", 0.3)
|
"1" == act[1] -> sp.getDouble("fill_button1", 0.3)
|
||||||
"2" == act[1] -> sp.getDouble("fill_button2", 0.0)
|
"2" == act[1] -> sp.getDouble("fill_button2", 0.0)
|
||||||
|
@ -130,29 +178,17 @@ class ActionStringHandler @Inject constructor(
|
||||||
rMessage += rh.gs(R.string.primefill) + ": " + insulinAfterConstraints + "U"
|
rMessage += rh.gs(R.string.primefill) + ": " + insulinAfterConstraints + "U"
|
||||||
if (insulinAfterConstraints - amount != 0.0) rMessage += "\n" + rh.gs(R.string.constraintapllied)
|
if (insulinAfterConstraints - amount != 0.0) rMessage += "\n" + rh.gs(R.string.constraintapllied)
|
||||||
rAction += "fill $insulinAfterConstraints"
|
rAction += "fill $insulinAfterConstraints"
|
||||||
} else if ("fill" == act[0]) { ////////////////////////////////////////////// PRIME/FILL
|
}
|
||||||
|
|
||||||
|
ACTION_FILL -> {
|
||||||
val amount = SafeParse.stringToDouble(act[1])
|
val amount = SafeParse.stringToDouble(act[1])
|
||||||
val insulinAfterConstraints = constraintChecker.applyBolusConstraints(Constraint(amount)).value()
|
val insulinAfterConstraints = constraintChecker.applyBolusConstraints(Constraint(amount)).value()
|
||||||
rMessage += rh.gs(R.string.primefill) + ": " + insulinAfterConstraints + "U"
|
rMessage += rh.gs(R.string.primefill) + ": " + insulinAfterConstraints + "U"
|
||||||
if (insulinAfterConstraints - amount != 0.0) rMessage += "\n" + rh.gs(R.string.constraintapllied)
|
if (insulinAfterConstraints - amount != 0.0) rMessage += "\n" + rh.gs(R.string.constraintapllied)
|
||||||
rAction += "fill $insulinAfterConstraints"
|
rAction += "fill $insulinAfterConstraints"
|
||||||
} else if ("bolus" == act[0]) { ////////////////////////////////////////////// BOLUS
|
|
||||||
val insulin = SafeParse.stringToDouble(act[1])
|
|
||||||
val carbs = SafeParse.stringToInt(act[2])
|
|
||||||
val insulinAfterConstraints = constraintChecker.applyBolusConstraints(Constraint(insulin)).value()
|
|
||||||
val carbsAfterConstraints = constraintChecker.applyCarbsConstraints(Constraint(carbs)).value()
|
|
||||||
val pump = activePlugin.activePump
|
|
||||||
if (insulinAfterConstraints > 0 && (!pump.isInitialized() || pump.isSuspended() || loop.isDisconnected)) {
|
|
||||||
sendError(rh.gs(R.string.wizard_pump_not_available))
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
rMessage += rh.gs(R.string.bolus) + ": " + insulinAfterConstraints + "U\n"
|
|
||||||
rMessage += rh.gs(R.string.carbs) + ": " + carbsAfterConstraints + "g"
|
ACTION_TEMPORARY_TARGET -> {
|
||||||
if (insulinAfterConstraints - insulin != 0.0 || carbsAfterConstraints - carbs != 0) {
|
|
||||||
rMessage += "\n" + rh.gs(R.string.constraintapllied)
|
|
||||||
}
|
|
||||||
rAction += "bolus $insulinAfterConstraints $carbsAfterConstraints"
|
|
||||||
} else if ("temptarget" == act[0]) { ///////////////////////////////////////////////////////// TEMPTARGET
|
|
||||||
aapsLogger.info(LTag.WEAR, "temptarget received: $act")
|
aapsLogger.info(LTag.WEAR, "temptarget received: $act")
|
||||||
if ("cancel" == act[1]) {
|
if ("cancel" == act[1]) {
|
||||||
rMessage += rh.gs(R.string.wear_action_tempt_cancel_message)
|
rMessage += rh.gs(R.string.wear_action_tempt_cancel_message)
|
||||||
|
@ -220,7 +256,9 @@ class ActionStringHandler @Inject constructor(
|
||||||
rAction = actionString
|
rAction = actionString
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if ("status" == act[0]) { ////////////////////////////////////////////// STATUS
|
}
|
||||||
|
|
||||||
|
ACTION_STATUS -> {
|
||||||
rTitle = "STATUS"
|
rTitle = "STATUS"
|
||||||
rAction = "statusmessage"
|
rAction = "statusmessage"
|
||||||
if ("pump" == act[1]) {
|
if ("pump" == act[1]) {
|
||||||
|
@ -232,10 +270,14 @@ class ActionStringHandler @Inject constructor(
|
||||||
rMessage += "\n\n" + loopStatus
|
rMessage += "\n\n" + loopStatus
|
||||||
rMessage += "\n\nOAPS RESULT:\n$oAPSResultStatus"
|
rMessage += "\n\nOAPS RESULT:\n$oAPSResultStatus"
|
||||||
}
|
}
|
||||||
} else if ("wizard" == act[0]) {
|
}
|
||||||
|
|
||||||
|
ACTION_WIZARD -> {
|
||||||
sendError("Update APP on Watch!")
|
sendError("Update APP on Watch!")
|
||||||
return
|
return
|
||||||
} else if ("wizard2" == act[0]) { ////////////////////////////////////////////// WIZARD
|
}
|
||||||
|
|
||||||
|
ACTION_WIZARD2 -> {
|
||||||
val pump = activePlugin.activePump
|
val pump = activePlugin.activePump
|
||||||
if (!pump.isInitialized() || pump.isSuspended() || loop.isDisconnected) {
|
if (!pump.isInitialized() || pump.isSuspended() || loop.isDisconnected) {
|
||||||
sendError(rh.gs(R.string.wizard_pump_not_available))
|
sendError(rh.gs(R.string.wizard_pump_not_available))
|
||||||
|
@ -294,13 +336,15 @@ class ActionStringHandler @Inject constructor(
|
||||||
rMessage += "\n_____________"
|
rMessage += "\n_____________"
|
||||||
rMessage += "\n" + bolusWizard.explainShort()
|
rMessage += "\n" + bolusWizard.explainShort()
|
||||||
lastBolusWizard = bolusWizard
|
lastBolusWizard = bolusWizard
|
||||||
} else if ("quick_wizard" == act[0]) {
|
}
|
||||||
|
|
||||||
|
ACTION_QUICK_WIZARD -> {
|
||||||
val guid = act[1]
|
val guid = act[1]
|
||||||
val actualBg = iobCobCalculator.ads.actualBg()
|
val actualBg = iobCobCalculator.ads.actualBg()
|
||||||
val profile = profileFunction.getProfile()
|
val profile = profileFunction.getProfile()
|
||||||
val profileName = profileFunction.getProfileName()
|
val profileName = profileFunction.getProfileName()
|
||||||
val quickWizardEntry = quickWizard.get(guid)
|
val quickWizardEntry = quickWizard.get(guid)
|
||||||
Log.i("QuickWizard", "handleInitiate: quick_wizard " + quickWizardEntry?.buttonText() + " c " + quickWizardEntry?.carbs())
|
//Log.i("QuickWizard", "handleInitiate: quick_wizard " + quickWizardEntry?.buttonText() + " c " + quickWizardEntry?.carbs())
|
||||||
if (quickWizardEntry == null) {
|
if (quickWizardEntry == null) {
|
||||||
sendError(rh.gs(R.string.quick_wizard_not_available))
|
sendError(rh.gs(R.string.quick_wizard_not_available))
|
||||||
return
|
return
|
||||||
|
@ -340,12 +384,14 @@ class ActionStringHandler @Inject constructor(
|
||||||
|
|
||||||
rMessage = rh.gs(R.string.quick_wizard_message, quickWizardEntry.buttonText(), wizard.calculatedTotalInsulin, quickWizardEntry.carbs())
|
rMessage = rh.gs(R.string.quick_wizard_message, quickWizardEntry.buttonText(), wizard.calculatedTotalInsulin, quickWizardEntry.carbs())
|
||||||
rAction = "bolus $insulinAfterConstraints $carbsAfterConstraints"
|
rAction = "bolus $insulinAfterConstraints $carbsAfterConstraints"
|
||||||
Log.i("QuickWizard", "handleInitiate: quick_wizard action=$rAction")
|
//Log.i("QuickWizard", "handleInitiate: quick_wizard action=$rAction")
|
||||||
|
|
||||||
rMessage += "\n_____________"
|
rMessage += "\n_____________"
|
||||||
rMessage += "\n" + wizard.explainShort()
|
rMessage += "\n" + wizard.explainShort()
|
||||||
|
|
||||||
} else if ("opencpp" == act[0]) {
|
}
|
||||||
|
|
||||||
|
ACTION_OPEN_CPP -> {
|
||||||
val activeProfileSwitch = repository.getEffectiveProfileSwitchActiveAt(dateUtil.now()).blockingGet()
|
val activeProfileSwitch = repository.getEffectiveProfileSwitchActiveAt(dateUtil.now()).blockingGet()
|
||||||
if (activeProfileSwitch is ValueWrapper.Existing) { // read CPP values
|
if (activeProfileSwitch is ValueWrapper.Existing) { // read CPP values
|
||||||
rTitle = "opencpp"
|
rTitle = "opencpp"
|
||||||
|
@ -355,18 +401,9 @@ class ActionStringHandler @Inject constructor(
|
||||||
sendError("No active profile switch!")
|
sendError("No active profile switch!")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else if ("cppset" == act[0]) {
|
|
||||||
val activeProfileSwitch = repository.getEffectiveProfileSwitchActiveAt(dateUtil.now()).blockingGet()
|
|
||||||
if (activeProfileSwitch is ValueWrapper.Existing) {
|
|
||||||
rMessage = "CPP:" + "\n\n" +
|
|
||||||
"Timeshift: " + act[1] + "\n" +
|
|
||||||
"Percentage: " + act[2] + "%"
|
|
||||||
rAction = actionString
|
|
||||||
} else { // read CPP values
|
|
||||||
sendError("No active profile switch!")
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
} else if ("tddstats" == act[0]) {
|
|
||||||
|
ACTION_TDD_STATS -> {
|
||||||
val activePump = activePlugin.activePump
|
val activePump = activePlugin.activePump
|
||||||
// check if DB up to date
|
// check if DB up to date
|
||||||
val dummies: MutableList<TotalDailyDose> = LinkedList()
|
val dummies: MutableList<TotalDailyDose> = LinkedList()
|
||||||
|
@ -397,7 +434,9 @@ class ActionStringHandler @Inject constructor(
|
||||||
rAction = "statusmessage"
|
rAction = "statusmessage"
|
||||||
rMessage = generateTDDMessage(historyList, dummies)
|
rMessage = generateTDDMessage(historyList, dummies)
|
||||||
}
|
}
|
||||||
} else if ("ecarbs" == act[0]) { ////////////////////////////////////////////// ECARBS
|
}
|
||||||
|
|
||||||
|
ACTION_E_CARBS -> {
|
||||||
val carbs = SafeParse.stringToInt(act[1])
|
val carbs = SafeParse.stringToInt(act[1])
|
||||||
val starttime = SafeParse.stringToInt(act[2])
|
val starttime = SafeParse.stringToInt(act[2])
|
||||||
val duration = SafeParse.stringToInt(act[3])
|
val duration = SafeParse.stringToInt(act[3])
|
||||||
|
@ -414,7 +453,9 @@ class ActionStringHandler @Inject constructor(
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
rAction += "ecarbs $carbsAfterConstraints $starttimestamp $duration"
|
rAction += "ecarbs $carbsAfterConstraints $starttimestamp $duration"
|
||||||
} else if ("changeRequest" == act[0]) { ////////////////////////////////////////////// CHANGE REQUEST
|
}
|
||||||
|
|
||||||
|
ACTION_CHANGE_REQUEST -> {
|
||||||
rTitle = rh.gs(R.string.openloop_newsuggestion)
|
rTitle = rh.gs(R.string.openloop_newsuggestion)
|
||||||
rAction = "changeRequest"
|
rAction = "changeRequest"
|
||||||
loop.lastRun?.let {
|
loop.lastRun?.let {
|
||||||
|
@ -424,14 +465,20 @@ class ActionStringHandler @Inject constructor(
|
||||||
lastConfirmActionString = rAction
|
lastConfirmActionString = rAction
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
} else if ("cancelChangeRequest" == act[0]) { ////////////////////////////////////////////// CANCEL CHANGE REQUEST NOTIFICATION
|
}
|
||||||
|
|
||||||
|
ACTION_CANCEL_CHANGE_REQUEST -> {
|
||||||
rAction = "cancelChangeRequest"
|
rAction = "cancelChangeRequest"
|
||||||
wearPlugin.requestNotificationCancel(rAction)
|
wearPlugin.requestNotificationCancel(rAction)
|
||||||
return
|
return
|
||||||
} else {
|
}
|
||||||
sendError(rh.gs(R.string.wear_unknown_action_string) + act[0])
|
|
||||||
|
else -> {
|
||||||
|
sendError(rh.gs(R.string.wear_unknown_action_string) + " " + act[0])
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// send result
|
// send result
|
||||||
wearPlugin.requestActionConfirmation(rTitle, rMessage, rAction)
|
wearPlugin.requestActionConfirmation(rTitle, rMessage, rAction)
|
||||||
lastSentTimestamp = System.currentTimeMillis()
|
lastSentTimestamp = System.currentTimeMillis()
|
||||||
|
@ -594,7 +641,8 @@ class ActionStringHandler @Inject constructor(
|
||||||
lastConfirmActionString = null
|
lastConfirmActionString = null
|
||||||
// do the parsing, check constraints and enact!
|
// do the parsing, check constraints and enact!
|
||||||
val act = actionString.split("\\s+".toRegex()).toTypedArray()
|
val act = actionString.split("\\s+".toRegex()).toTypedArray()
|
||||||
if ("fill" == act[0]) {
|
when (act[0]) {
|
||||||
|
ACTION_FILL -> {
|
||||||
val amount = SafeParse.stringToDouble(act[1])
|
val amount = SafeParse.stringToDouble(act[1])
|
||||||
val insulinAfterConstraints = constraintChecker.applyBolusConstraints(Constraint(amount)).value()
|
val insulinAfterConstraints = constraintChecker.applyBolusConstraints(Constraint(amount)).value()
|
||||||
if (amount - insulinAfterConstraints != 0.0) {
|
if (amount - insulinAfterConstraints != 0.0) {
|
||||||
|
@ -603,36 +651,51 @@ class ActionStringHandler @Inject constructor(
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
doFillBolus(amount)
|
doFillBolus(amount)
|
||||||
} else if ("temptarget" == act[0]) {
|
}
|
||||||
|
|
||||||
|
ACTION_TEMPORARY_TARGET -> {
|
||||||
val duration = SafeParse.stringToInt(act[2])
|
val duration = SafeParse.stringToInt(act[2])
|
||||||
val low = SafeParse.stringToDouble(act[3])
|
val low = SafeParse.stringToDouble(act[3])
|
||||||
val high = SafeParse.stringToDouble(act[4])
|
val high = SafeParse.stringToDouble(act[4])
|
||||||
generateTempTarget(duration, low, high)
|
generateTempTarget(duration, low, high)
|
||||||
} else if ("wizard2" == act[0]) {
|
}
|
||||||
|
|
||||||
|
ACTION_WIZARD2 -> {
|
||||||
if (lastBolusWizard != null) { //use last calculation as confirmed string matches
|
if (lastBolusWizard != null) { //use last calculation as confirmed string matches
|
||||||
doBolus(lastBolusWizard!!.calculatedTotalInsulin, lastBolusWizard!!.carbs, null, 0)
|
doBolus(lastBolusWizard!!.calculatedTotalInsulin, lastBolusWizard!!.carbs, null, 0)
|
||||||
lastBolusWizard = null
|
lastBolusWizard = null
|
||||||
}
|
}
|
||||||
} else if ("bolus" == act[0]) {
|
}
|
||||||
|
|
||||||
|
ACTION_BOLUS -> {
|
||||||
val insulin = SafeParse.stringToDouble(act[1])
|
val insulin = SafeParse.stringToDouble(act[1])
|
||||||
val carbs = SafeParse.stringToInt(act[2])
|
val carbs = SafeParse.stringToInt(act[2])
|
||||||
doBolus(insulin, carbs, null, 0)
|
doBolus(insulin, carbs, null, 0)
|
||||||
} else if ("cppset" == act[0]) {
|
}
|
||||||
|
|
||||||
|
ACTION_CPP_SET -> {
|
||||||
val timeshift = SafeParse.stringToInt(act[1])
|
val timeshift = SafeParse.stringToInt(act[1])
|
||||||
val percentage = SafeParse.stringToInt(act[2])
|
val percentage = SafeParse.stringToInt(act[2])
|
||||||
setCPP(timeshift, percentage)
|
setCPP(timeshift, percentage)
|
||||||
} else if ("ecarbs" == act[0]) {
|
}
|
||||||
|
|
||||||
|
ACTION_E_CARBS -> {
|
||||||
val carbs = SafeParse.stringToInt(act[1])
|
val carbs = SafeParse.stringToInt(act[1])
|
||||||
val starttime = SafeParse.stringToLong(act[2])
|
val starttime = SafeParse.stringToLong(act[2])
|
||||||
val duration = SafeParse.stringToInt(act[3])
|
val duration = SafeParse.stringToInt(act[3])
|
||||||
doECarbs(carbs, starttime, duration)
|
doECarbs(carbs, starttime, duration)
|
||||||
} else if ("dismissoverviewnotification" == act[0]) {
|
}
|
||||||
|
|
||||||
|
ACTION_DISMISS_OVERVIEW_NOTIF -> {
|
||||||
rxBus.send(EventDismissNotification(SafeParse.stringToInt(act[1])))
|
rxBus.send(EventDismissNotification(SafeParse.stringToInt(act[1])))
|
||||||
} else if ("changeRequest" == act[0]) {
|
}
|
||||||
|
|
||||||
|
ACTION_CHANGE_REQUEST -> {
|
||||||
loop.acceptChangeRequest()
|
loop.acceptChangeRequest()
|
||||||
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||||
notificationManager.cancel(Constants.notificationID)
|
notificationManager.cancel(Constants.notificationID)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
lastBolusWizard = null
|
lastBolusWizard = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,14 +6,25 @@ import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import dagger.android.support.DaggerFragment
|
import dagger.android.support.DaggerFragment
|
||||||
import info.nightscout.androidaps.databinding.WearFragmentBinding
|
import info.nightscout.androidaps.databinding.WearFragmentBinding
|
||||||
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
|
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientUpdateGUI
|
||||||
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
|
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class WearFragment : DaggerFragment() {
|
class WearFragment : DaggerFragment() {
|
||||||
|
|
||||||
@Inject lateinit var wearPlugin: WearPlugin
|
@Inject lateinit var wearPlugin: WearPlugin
|
||||||
|
@Inject lateinit var rxBus: RxBus
|
||||||
|
@Inject lateinit var aapsSchedulers: AapsSchedulers
|
||||||
|
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
||||||
|
|
||||||
private var _binding: WearFragmentBinding? = null
|
private var _binding: WearFragmentBinding? = null
|
||||||
|
|
||||||
|
private val disposable = CompositeDisposable()
|
||||||
|
|
||||||
// This property is only valid between onCreateView and
|
// This property is only valid between onCreateView and
|
||||||
// onDestroyView.
|
// onDestroyView.
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
@ -27,7 +38,21 @@ class WearFragment : DaggerFragment() {
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
binding.resend.setOnClickListener { wearPlugin.resendDataToWatch() }
|
binding.resend.setOnClickListener { wearPlugin.resendDataToWatch() }
|
||||||
binding.opensettings.setOnClickListener { wearPlugin.openSettings() }
|
binding.openSettings.setOnClickListener { wearPlugin.openSettings() }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
disposable += rxBus
|
||||||
|
.toObservable(EventNSClientUpdateGUI::class.java)
|
||||||
|
.observeOn(aapsSchedulers.main)
|
||||||
|
.subscribe({ updateGui() }, fabricPrivacy::logException)
|
||||||
|
updateGui()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPause() {
|
||||||
|
super.onPause()
|
||||||
|
disposable.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
|
@ -35,4 +60,9 @@ class WearFragment : DaggerFragment() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
_binding = null
|
_binding = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun updateGui() {
|
||||||
|
_binding ?: return
|
||||||
|
binding.connectedDevice.text = wearPlugin.connectedDevice
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -6,12 +6,11 @@ import dagger.Lazy
|
||||||
import dagger.android.HasAndroidInjector
|
import dagger.android.HasAndroidInjector
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
import info.nightscout.androidaps.events.*
|
import info.nightscout.androidaps.events.*
|
||||||
import info.nightscout.androidaps.interfaces.Loop
|
|
||||||
import info.nightscout.androidaps.interfaces.PluginBase
|
import info.nightscout.androidaps.interfaces.PluginBase
|
||||||
import info.nightscout.androidaps.interfaces.PluginDescription
|
import info.nightscout.androidaps.interfaces.PluginDescription
|
||||||
import info.nightscout.androidaps.interfaces.PluginType
|
import info.nightscout.androidaps.interfaces.PluginType
|
||||||
import info.nightscout.shared.logging.AAPSLogger
|
|
||||||
import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateGui
|
import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateGui
|
||||||
|
import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopUpdateGui
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissBolusProgressIfRunning
|
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissBolusProgressIfRunning
|
||||||
import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress
|
import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress
|
||||||
|
@ -19,8 +18,10 @@ import info.nightscout.androidaps.plugins.general.wear.wearintegration.WatchUpda
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
import info.nightscout.shared.sharedPreferences.SP
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
|
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@ -33,11 +34,11 @@ class WearPlugin @Inject constructor(
|
||||||
private val sp: SP,
|
private val sp: SP,
|
||||||
private val ctx: Context,
|
private val ctx: Context,
|
||||||
private val fabricPrivacy: FabricPrivacy,
|
private val fabricPrivacy: FabricPrivacy,
|
||||||
private val loop: Loop,
|
|
||||||
private val rxBus: RxBus,
|
private val rxBus: RxBus,
|
||||||
private val actionStringHandler: Lazy<ActionStringHandler>
|
private val actionStringHandler: Lazy<ActionStringHandler>
|
||||||
|
|
||||||
) : PluginBase(PluginDescription()
|
) : PluginBase(
|
||||||
|
PluginDescription()
|
||||||
.mainType(PluginType.GENERAL)
|
.mainType(PluginType.GENERAL)
|
||||||
.fragmentClass(WearFragment::class.java.name)
|
.fragmentClass(WearFragment::class.java.name)
|
||||||
.pluginIcon(R.drawable.ic_watch)
|
.pluginIcon(R.drawable.ic_watch)
|
||||||
|
@ -49,33 +50,37 @@ class WearPlugin @Inject constructor(
|
||||||
) {
|
) {
|
||||||
|
|
||||||
private val disposable = CompositeDisposable()
|
private val disposable = CompositeDisposable()
|
||||||
|
|
||||||
|
var connectedDevice = "---"
|
||||||
|
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
super.onStart()
|
super.onStart()
|
||||||
disposable.add(rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventOpenAPSUpdateGui::class.java)
|
.toObservable(EventOpenAPSUpdateGui::class.java)
|
||||||
.observeOn(aapsSchedulers.io)
|
.observeOn(aapsSchedulers.io)
|
||||||
.subscribe({ sendDataToWatch(status = true, basals = true, bgValue = false) }, fabricPrivacy::logException))
|
.subscribe({ sendDataToWatch(status = true, basals = true, bgValue = false) }, fabricPrivacy::logException)
|
||||||
disposable.add(rxBus
|
|
||||||
|
disposable += rxBus
|
||||||
.toObservable(EventExtendedBolusChange::class.java)
|
.toObservable(EventExtendedBolusChange::class.java)
|
||||||
.observeOn(aapsSchedulers.io)
|
.observeOn(aapsSchedulers.io)
|
||||||
.subscribe({ sendDataToWatch(status = true, basals = true, bgValue = false) }, fabricPrivacy::logException))
|
.subscribe({ sendDataToWatch(status = true, basals = true, bgValue = false) }, fabricPrivacy::logException)
|
||||||
disposable.add(rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventTempBasalChange::class.java)
|
.toObservable(EventTempBasalChange::class.java)
|
||||||
.observeOn(aapsSchedulers.io)
|
.observeOn(aapsSchedulers.io)
|
||||||
.subscribe({ sendDataToWatch(status = true, basals = true, bgValue = false) }, fabricPrivacy::logException))
|
.subscribe({ sendDataToWatch(status = true, basals = true, bgValue = false) }, fabricPrivacy::logException)
|
||||||
disposable.add(rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventTreatmentChange::class.java)
|
.toObservable(EventTreatmentChange::class.java)
|
||||||
.observeOn(aapsSchedulers.io)
|
.observeOn(aapsSchedulers.io)
|
||||||
.subscribe({ sendDataToWatch(status = true, basals = true, bgValue = false) }, fabricPrivacy::logException))
|
.subscribe({ sendDataToWatch(status = true, basals = true, bgValue = false) }, fabricPrivacy::logException)
|
||||||
disposable.add(rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventEffectiveProfileSwitchChanged::class.java)
|
.toObservable(EventEffectiveProfileSwitchChanged::class.java)
|
||||||
.observeOn(aapsSchedulers.io)
|
.observeOn(aapsSchedulers.io)
|
||||||
.subscribe({ sendDataToWatch(status = false, basals = true, bgValue = false) }, fabricPrivacy::logException))
|
.subscribe({ sendDataToWatch(status = false, basals = true, bgValue = false) }, fabricPrivacy::logException)
|
||||||
disposable.add(rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventAutosensCalculationFinished::class.java)
|
.toObservable(EventAutosensCalculationFinished::class.java)
|
||||||
.observeOn(aapsSchedulers.io)
|
.observeOn(aapsSchedulers.io)
|
||||||
.subscribe({ sendDataToWatch(status = true, basals = true, bgValue = true) }, fabricPrivacy::logException))
|
.subscribe({ sendDataToWatch(status = true, basals = true, bgValue = true) }, fabricPrivacy::logException)
|
||||||
disposable.add(rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventPreferenceChange::class.java)
|
.toObservable(EventPreferenceChange::class.java)
|
||||||
.observeOn(aapsSchedulers.io)
|
.observeOn(aapsSchedulers.io)
|
||||||
.subscribe({
|
.subscribe({
|
||||||
|
@ -83,25 +88,24 @@ class WearPlugin @Inject constructor(
|
||||||
resendDataToWatch()
|
resendDataToWatch()
|
||||||
// status may be formatted differently
|
// status may be formatted differently
|
||||||
sendDataToWatch(status = true, basals = false, bgValue = false)
|
sendDataToWatch(status = true, basals = false, bgValue = false)
|
||||||
}, fabricPrivacy::logException))
|
}, fabricPrivacy::logException)
|
||||||
disposable.add(rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventRefreshOverview::class.java)
|
.toObservable(EventLoopUpdateGui::class.java)
|
||||||
.observeOn(aapsSchedulers.io)
|
.observeOn(aapsSchedulers.io)
|
||||||
.subscribe({
|
.subscribe({
|
||||||
if (WatchUpdaterService.shouldReportLoopStatus((loop as PluginBase).isEnabled()))
|
|
||||||
sendDataToWatch(status = true, basals = false, bgValue = false)
|
sendDataToWatch(status = true, basals = false, bgValue = false)
|
||||||
}, fabricPrivacy::logException))
|
}, fabricPrivacy::logException)
|
||||||
disposable.add(rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventBolusRequested::class.java)
|
.toObservable(EventBolusRequested::class.java)
|
||||||
.observeOn(aapsSchedulers.io)
|
.observeOn(aapsSchedulers.io)
|
||||||
.subscribe({ event: EventBolusRequested ->
|
.subscribe({ event: EventBolusRequested ->
|
||||||
val status = rh.gs(R.string.bolusrequested, event.amount)
|
val status = rh.gs(R.string.bolusrequested, event.amount)
|
||||||
val intent = Intent(ctx, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_BOLUSPROGRESS)
|
val intent = Intent(ctx, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_BOLUS_PROGRESS)
|
||||||
intent.putExtra("progresspercent", 0)
|
intent.putExtra("progresspercent", 0)
|
||||||
intent.putExtra("progressstatus", status)
|
intent.putExtra("progressstatus", status)
|
||||||
ctx.startService(intent)
|
ctx.startService(intent)
|
||||||
}, fabricPrivacy::logException))
|
}, fabricPrivacy::logException)
|
||||||
disposable.add(rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventDismissBolusProgressIfRunning::class.java)
|
.toObservable(EventDismissBolusProgressIfRunning::class.java)
|
||||||
.observeOn(aapsSchedulers.io)
|
.observeOn(aapsSchedulers.io)
|
||||||
.subscribe({ event: EventDismissBolusProgressIfRunning ->
|
.subscribe({ event: EventDismissBolusProgressIfRunning ->
|
||||||
|
@ -111,22 +115,22 @@ class WearPlugin @Inject constructor(
|
||||||
} else {
|
} else {
|
||||||
rh.gs(R.string.nosuccess)
|
rh.gs(R.string.nosuccess)
|
||||||
}
|
}
|
||||||
val intent = Intent(ctx, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_BOLUSPROGRESS)
|
val intent = Intent(ctx, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_BOLUS_PROGRESS)
|
||||||
intent.putExtra("progresspercent", 100)
|
intent.putExtra("progresspercent", 100)
|
||||||
intent.putExtra("progressstatus", status)
|
intent.putExtra("progressstatus", status)
|
||||||
ctx.startService(intent)
|
ctx.startService(intent)
|
||||||
}, fabricPrivacy::logException))
|
}, fabricPrivacy::logException)
|
||||||
disposable.add(rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventOverviewBolusProgress::class.java)
|
.toObservable(EventOverviewBolusProgress::class.java)
|
||||||
.observeOn(aapsSchedulers.io)
|
.observeOn(aapsSchedulers.io)
|
||||||
.subscribe({ event: EventOverviewBolusProgress ->
|
.subscribe({ event: EventOverviewBolusProgress ->
|
||||||
if (!event.isSMB() || sp.getBoolean("wear_notifySMB", true)) {
|
if (!event.isSMB() || sp.getBoolean("wear_notifySMB", true)) {
|
||||||
val intent = Intent(ctx, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_BOLUSPROGRESS)
|
val intent = Intent(ctx, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_BOLUS_PROGRESS)
|
||||||
intent.putExtra("progresspercent", event.percent)
|
intent.putExtra("progresspercent", event.percent)
|
||||||
intent.putExtra("progressstatus", event.status)
|
intent.putExtra("progressstatus", event.status)
|
||||||
ctx.startService(intent)
|
ctx.startService(intent)
|
||||||
}
|
}
|
||||||
}, fabricPrivacy::logException))
|
}, fabricPrivacy::logException)
|
||||||
actionStringHandler.get().setup()
|
actionStringHandler.get().setup()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,51 +141,50 @@ class WearPlugin @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun sendDataToWatch(status: Boolean, basals: Boolean, bgValue: Boolean) {
|
private fun sendDataToWatch(status: Boolean, basals: Boolean, bgValue: Boolean) {
|
||||||
//Log.d(TAG, "WR: WearPlugin:sendDataToWatch (status=" + status + ",basals=" + basals + ",bgValue=" + bgValue + ")");
|
|
||||||
if (isEnabled(getType())) {
|
|
||||||
// only start service when this plugin is enabled
|
// only start service when this plugin is enabled
|
||||||
if (bgValue) {
|
if (isEnabled()) {
|
||||||
ctx.startService(Intent(ctx, WatchUpdaterService::class.java))
|
if (bgValue) ctx.startService(Intent(ctx, WatchUpdaterService::class.java))
|
||||||
}
|
if (basals) ctx.startService(Intent(ctx, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_BASALS))
|
||||||
if (basals) {
|
if (status) ctx.startService(Intent(ctx, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_STATUS))
|
||||||
ctx.startService(Intent(ctx, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_BASALS))
|
|
||||||
}
|
|
||||||
if (status) {
|
|
||||||
ctx.startService(Intent(ctx, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_STATUS))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun resendDataToWatch() {
|
fun resendDataToWatch() {
|
||||||
//Log.d(TAG, "WR: WearPlugin:resendDataToWatch");
|
|
||||||
ctx.startService(Intent(ctx, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_RESEND))
|
ctx.startService(Intent(ctx, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_RESEND))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun openSettings() {
|
fun openSettings() {
|
||||||
//Log.d(TAG, "WR: WearPlugin:openSettings");
|
|
||||||
ctx.startService(Intent(ctx, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_OPEN_SETTINGS))
|
ctx.startService(Intent(ctx, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_OPEN_SETTINGS))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun requestNotificationCancel(actionString: String?) { //Log.d(TAG, "WR: WearPlugin:requestNotificationCancel");
|
fun requestNotificationCancel(actionString: String?) {
|
||||||
val intent = Intent(ctx, WatchUpdaterService::class.java)
|
ctx.startService(
|
||||||
|
Intent(ctx, WatchUpdaterService::class.java)
|
||||||
.setAction(WatchUpdaterService.ACTION_CANCEL_NOTIFICATION)
|
.setAction(WatchUpdaterService.ACTION_CANCEL_NOTIFICATION)
|
||||||
intent.putExtra("actionstring", actionString)
|
.also {
|
||||||
ctx.startService(intent)
|
it.putExtra("actionstring", actionString)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fun requestActionConfirmation(title: String, message: String, actionString: String) {
|
fun requestActionConfirmation(title: String, message: String, actionString: String) {
|
||||||
val intent = Intent(ctx, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_ACTIONCONFIRMATIONREQUEST)
|
ctx.startService(
|
||||||
intent.putExtra("title", title)
|
Intent(ctx, WatchUpdaterService::class.java)
|
||||||
intent.putExtra("message", message)
|
.setAction(WatchUpdaterService.ACTION_SEND_ACTION_CONFIRMATION_REQUEST)
|
||||||
intent.putExtra("actionstring", actionString)
|
.also {
|
||||||
ctx.startService(intent)
|
it.putExtra("title", title)
|
||||||
|
it.putExtra("message", message)
|
||||||
|
it.putExtra("actionstring", actionString)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fun requestChangeConfirmation(title: String, message: String, actionString: String) {
|
fun requestChangeConfirmation(title: String, message: String, actionString: String) {
|
||||||
val intent = Intent(ctx, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_CHANGECONFIRMATIONREQUEST)
|
ctx.startService(
|
||||||
intent.putExtra("title", title)
|
Intent(ctx, WatchUpdaterService::class.java)
|
||||||
intent.putExtra("message", message)
|
.setAction(WatchUpdaterService.ACTION_SEND_CHANGE_CONFIRMATION_REQUEST)
|
||||||
intent.putExtra("actionstring", actionString)
|
.also {
|
||||||
ctx.startService(intent)
|
it.putExtra("title", title)
|
||||||
|
it.putExtra("message", message)
|
||||||
|
it.putExtra("actionstring", actionString)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.wear.events
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.events.Event
|
||||||
|
|
||||||
|
class EventWearUpdateGui : Event()
|
|
@ -1,139 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.wear.wearintegration;
|
|
||||||
|
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import com.google.android.gms.common.api.GoogleApiClient;
|
|
||||||
import com.google.android.gms.wearable.DataApi;
|
|
||||||
import com.google.android.gms.wearable.DataMap;
|
|
||||||
import com.google.android.gms.wearable.Node;
|
|
||||||
import com.google.android.gms.wearable.NodeApi;
|
|
||||||
import com.google.android.gms.wearable.PutDataMapRequest;
|
|
||||||
import com.google.android.gms.wearable.PutDataRequest;
|
|
||||||
import com.google.android.gms.wearable.Wearable;
|
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by emmablack on 12/26/14.
|
|
||||||
*/
|
|
||||||
class SendToDataLayerThread extends AsyncTask<DataMap,Void,Void> {
|
|
||||||
private final GoogleApiClient googleApiClient;
|
|
||||||
private static final String TAG = "SendToDataLayerThread";
|
|
||||||
private final String path;
|
|
||||||
private final String logPrefix = ""; // "WR: ";
|
|
||||||
private static int concurrency = 0;
|
|
||||||
private static int state = 0;
|
|
||||||
private static final ReentrantLock lock = new ReentrantLock();
|
|
||||||
private static long lastlock = 0;
|
|
||||||
private static final boolean testlockup = false; // always false in production
|
|
||||||
|
|
||||||
|
|
||||||
SendToDataLayerThread(String path, GoogleApiClient pGoogleApiClient) {
|
|
||||||
// Log.d(TAG, logPrefix + "SendToDataLayerThread: " + path);
|
|
||||||
this.path = path;
|
|
||||||
googleApiClient = pGoogleApiClient;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPreExecute() {
|
|
||||||
concurrency++;
|
|
||||||
if ((concurrency > 12) || ((concurrency > 3 && (lastlock != 0) && (tsl() - lastlock) > 300000))) {
|
|
||||||
// error if 9 concurrent threads or lock held for >5 minutes with concurrency of 4
|
|
||||||
final String err = "Wear Integration deadlock detected!! " + ((lastlock != 0) ? "locked" : "") + " state:"
|
|
||||||
+ state + " @" + hourMinuteString(tsl());
|
|
||||||
// Home.toaststaticnext(err);
|
|
||||||
Log.e(TAG, logPrefix + err);
|
|
||||||
}
|
|
||||||
if (concurrency < 0)
|
|
||||||
Log.d(TAG, logPrefix + "Wear Integration impossible concurrency!!");
|
|
||||||
|
|
||||||
Log.d(TAG, logPrefix + "SendDataToLayerThread pre-execute concurrency: " + concurrency);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Void doInBackground(DataMap... params) {
|
|
||||||
if (testlockup) {
|
|
||||||
try {
|
|
||||||
Log.e(TAG, logPrefix + "WARNING RUNNING TEST LOCK UP CODE - NEVER FOR PRODUCTION");
|
|
||||||
Thread.sleep(1000000); // DEEEBBUUGGGG
|
|
||||||
} catch (Exception e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sendToWear(params);
|
|
||||||
concurrency--;
|
|
||||||
Log.d(TAG, logPrefix + "SendDataToLayerThread post-execute concurrency: " + concurrency);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Debug function to expose where it might be locking up
|
|
||||||
private synchronized void sendToWear(final DataMap... params) {
|
|
||||||
if (!lock.tryLock()) {
|
|
||||||
Log.d(TAG, logPrefix + "Concurrent access - waiting for thread unlock");
|
|
||||||
lock.lock(); // enforce single threading
|
|
||||||
Log.d(TAG, logPrefix + "Thread unlocked - proceeding");
|
|
||||||
}
|
|
||||||
lastlock = tsl();
|
|
||||||
try {
|
|
||||||
if (state != 0) {
|
|
||||||
Log.e(TAG, logPrefix + "WEAR STATE ERROR: state=" + state);
|
|
||||||
}
|
|
||||||
state = 1;
|
|
||||||
final NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes(googleApiClient).await(15,
|
|
||||||
TimeUnit.SECONDS);
|
|
||||||
|
|
||||||
Log.d(TAG, logPrefix + "Nodes: " + nodes);
|
|
||||||
|
|
||||||
state = 2;
|
|
||||||
for (Node node : nodes.getNodes()) {
|
|
||||||
state = 3;
|
|
||||||
for (DataMap dataMap : params) {
|
|
||||||
state = 4;
|
|
||||||
PutDataMapRequest putDMR = PutDataMapRequest.create(path);
|
|
||||||
state = 5;
|
|
||||||
putDMR.getDataMap().putAll(dataMap);
|
|
||||||
putDMR.setUrgent();
|
|
||||||
state = 6;
|
|
||||||
PutDataRequest request = putDMR.asPutDataRequest();
|
|
||||||
state = 7;
|
|
||||||
DataApi.DataItemResult result = Wearable.DataApi.putDataItem(googleApiClient, request).await(15,
|
|
||||||
TimeUnit.SECONDS);
|
|
||||||
state = 8;
|
|
||||||
if (result.getStatus().isSuccess()) {
|
|
||||||
Log.d(TAG, logPrefix + "DataMap: " + dataMap + " sent to: " + node.getDisplayName());
|
|
||||||
} else {
|
|
||||||
Log.e(TAG, logPrefix + "ERROR: failed to send DataMap");
|
|
||||||
result = Wearable.DataApi.putDataItem(googleApiClient, request).await(30, TimeUnit.SECONDS);
|
|
||||||
if (result.getStatus().isSuccess()) {
|
|
||||||
Log.d(TAG, logPrefix + "DataMap retry: " + dataMap + " sent to: " + node.getDisplayName());
|
|
||||||
} else {
|
|
||||||
Log.e(TAG, logPrefix + "ERROR on retry: failed to send DataMap: "
|
|
||||||
+ result.getStatus().toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
state = 9;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
state = 0;
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(TAG, logPrefix + "Got exception in sendToWear: " + e);
|
|
||||||
} finally {
|
|
||||||
lastlock = 0;
|
|
||||||
lock.unlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static long tsl() {
|
|
||||||
return System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static String hourMinuteString(long timestamp) {
|
|
||||||
return android.text.format.DateFormat.format("kk:mm", timestamp).toString();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,633 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.wear.wearintegration
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.HandlerThread
|
||||||
|
import com.google.android.gms.tasks.Tasks
|
||||||
|
import com.google.android.gms.wearable.*
|
||||||
|
import dagger.android.AndroidInjection
|
||||||
|
import info.nightscout.androidaps.Constants
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.database.AppRepository
|
||||||
|
import info.nightscout.androidaps.database.entities.Bolus
|
||||||
|
import info.nightscout.androidaps.database.entities.GlucoseValue
|
||||||
|
import info.nightscout.androidaps.database.entities.TemporaryBasal
|
||||||
|
import info.nightscout.androidaps.extensions.convertedToAbsolute
|
||||||
|
import info.nightscout.androidaps.extensions.toStringShort
|
||||||
|
import info.nightscout.androidaps.extensions.valueToUnitsString
|
||||||
|
import info.nightscout.androidaps.interfaces.*
|
||||||
|
import info.nightscout.androidaps.interfaces.Profile.Companion.fromMgdlToUnits
|
||||||
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
|
import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus
|
||||||
|
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.GlucoseValueDataPoint
|
||||||
|
import info.nightscout.androidaps.plugins.general.wear.WearPlugin
|
||||||
|
import info.nightscout.androidaps.plugins.general.wear.events.EventWearConfirmAction
|
||||||
|
import info.nightscout.androidaps.plugins.general.wear.events.EventWearInitiateAction
|
||||||
|
import info.nightscout.androidaps.plugins.general.wear.events.EventWearUpdateGui
|
||||||
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
|
||||||
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider
|
||||||
|
import info.nightscout.androidaps.receivers.ReceiverStatusStore
|
||||||
|
import info.nightscout.androidaps.utils.DecimalFormatter.to0Decimal
|
||||||
|
import info.nightscout.androidaps.utils.DecimalFormatter.to1Decimal
|
||||||
|
import info.nightscout.androidaps.utils.DecimalFormatter.to2Decimal
|
||||||
|
import info.nightscout.androidaps.utils.DefaultValueHelper
|
||||||
|
import info.nightscout.androidaps.utils.TrendCalculator
|
||||||
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
|
import info.nightscout.androidaps.utils.wizard.QuickWizard
|
||||||
|
import info.nightscout.androidaps.utils.wizard.QuickWizardEntry
|
||||||
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
|
import info.nightscout.shared.logging.LTag
|
||||||
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
|
import info.nightscout.shared.weardata.WearConstants
|
||||||
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
|
import kotlinx.coroutines.*
|
||||||
|
import kotlinx.coroutines.tasks.await
|
||||||
|
import java.util.function.Consumer
|
||||||
|
import java.util.stream.Collectors
|
||||||
|
import javax.inject.Inject
|
||||||
|
import kotlin.math.abs
|
||||||
|
|
||||||
|
class WatchUpdaterService : WearableListenerService() {
|
||||||
|
|
||||||
|
@Inject lateinit var aapsLogger: AAPSLogger
|
||||||
|
@Inject lateinit var profileFunction: ProfileFunction
|
||||||
|
@Inject lateinit var iobCobCalculator: IobCobCalculator
|
||||||
|
@Inject lateinit var rh: ResourceHelper
|
||||||
|
@Inject lateinit var loop: Loop
|
||||||
|
@Inject lateinit var wearPlugin: WearPlugin
|
||||||
|
@Inject lateinit var sp: SP
|
||||||
|
@Inject lateinit var quickWizard: QuickWizard
|
||||||
|
@Inject lateinit var config: Config
|
||||||
|
@Inject lateinit var nsDeviceStatus: NSDeviceStatus
|
||||||
|
@Inject lateinit var receiverStatusStore: ReceiverStatusStore
|
||||||
|
@Inject lateinit var repository: AppRepository
|
||||||
|
@Inject lateinit var defaultValueHelper: DefaultValueHelper
|
||||||
|
@Inject lateinit var glucoseStatusProvider: GlucoseStatusProvider
|
||||||
|
@Inject lateinit var trendCalculator: TrendCalculator
|
||||||
|
@Inject lateinit var activePlugin: ActivePlugin
|
||||||
|
@Inject lateinit var rxBus: RxBus
|
||||||
|
@Inject lateinit var wearConstants: WearConstants
|
||||||
|
|
||||||
|
private val dataClient by lazy { Wearable.getDataClient(this) }
|
||||||
|
private val messageClient by lazy { Wearable.getMessageClient(this) }
|
||||||
|
private val capabilityClient by lazy { Wearable.getCapabilityClient(this) }
|
||||||
|
//private val nodeClient by lazy { Wearable.getNodeClient(this) }
|
||||||
|
|
||||||
|
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
|
||||||
|
private var handler = Handler(HandlerThread(this::class.simpleName + "Handler").also { it.start() }.looper)
|
||||||
|
|
||||||
|
private val disposable = CompositeDisposable()
|
||||||
|
|
||||||
|
override fun onCreate() {
|
||||||
|
AndroidInjection.inject(this)
|
||||||
|
super.onCreate()
|
||||||
|
aapsLogger.debug(LTag.WEAR, "onCreate")
|
||||||
|
handler.post { updateTranscriptionCapability() }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCapabilityChanged(p0: CapabilityInfo) {
|
||||||
|
super.onCapabilityChanged(p0)
|
||||||
|
handler.post { updateTranscriptionCapability() }
|
||||||
|
aapsLogger.debug(LTag.WEAR, "onCapabilityChanged: ${p0.name} ${p0.nodes.joinToString(", ") { it.displayName + "(" + it.id + ")" }}")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
disposable.clear()
|
||||||
|
scope.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
|
aapsLogger.debug(LTag.WEAR, "onStartCommand ${intent?.action}")
|
||||||
|
if (wearPlugin.isEnabled()) {
|
||||||
|
handler.post {
|
||||||
|
when (intent?.action) {
|
||||||
|
ACTION_RESEND -> resendData()
|
||||||
|
ACTION_OPEN_SETTINGS -> sendMessage(wearConstants.M_W_OPEN_SETTINGS, byteArrayOf())
|
||||||
|
ACTION_SEND_STATUS -> sendStatus()
|
||||||
|
ACTION_SEND_BASALS -> sendBasals()
|
||||||
|
ACTION_SEND_BOLUS_PROGRESS -> sendBolusProgress(
|
||||||
|
intent.getIntExtra("progresspercent", 0),
|
||||||
|
intent.getStringExtra("progressstatus")
|
||||||
|
)
|
||||||
|
ACTION_SEND_ACTION_CONFIRMATION_REQUEST -> sendActionConfirmationRequest(
|
||||||
|
intent.getStringExtra("title"),
|
||||||
|
intent.getStringExtra("message"),
|
||||||
|
intent.getStringExtra("actionstring")
|
||||||
|
)
|
||||||
|
ACTION_SEND_CHANGE_CONFIRMATION_REQUEST -> sendChangeConfirmationRequest(
|
||||||
|
intent.getStringExtra("title"),
|
||||||
|
intent.getStringExtra("message"),
|
||||||
|
intent.getStringExtra("actionstring")
|
||||||
|
)
|
||||||
|
ACTION_CANCEL_NOTIFICATION -> sendCancelNotificationRequest(intent.getStringExtra("actionstring"))
|
||||||
|
|
||||||
|
null -> {}
|
||||||
|
|
||||||
|
else -> sendData()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return START_STICKY
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("ControlFlowWithEmptyBody", "UNUSED_EXPRESSION")
|
||||||
|
override fun onDataChanged(dataEvents: DataEventBuffer) {
|
||||||
|
//aapsLogger.debug(LTag.WEAR, "onDataChanged")
|
||||||
|
|
||||||
|
if (wearPlugin.isEnabled()) {
|
||||||
|
dataEvents.forEach { event ->
|
||||||
|
if (event.type == DataEvent.TYPE_CHANGED) {
|
||||||
|
val path = event.dataItem.uri.path
|
||||||
|
|
||||||
|
aapsLogger.debug(LTag.WEAR, "onDataChanged: Path: $path, EventDataItem=${event.dataItem}")
|
||||||
|
try {
|
||||||
|
when (path) {
|
||||||
|
}
|
||||||
|
} catch (exception: Exception) {
|
||||||
|
aapsLogger.error(LTag.WEAR, "Message failed", exception)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.onDataChanged(dataEvents)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMessageReceived(messageEvent: MessageEvent) {
|
||||||
|
super.onMessageReceived(messageEvent)
|
||||||
|
aapsLogger.debug(LTag.WEAR, "onMessageReceived: $messageEvent")
|
||||||
|
|
||||||
|
if (wearPlugin.isEnabled()) {
|
||||||
|
when (messageEvent.path) {
|
||||||
|
wearConstants.W_M_RESEND_DATA -> resendData()
|
||||||
|
wearConstants.W_M_CANCEL_BOLUS -> activePlugin.activePump.stopBolusDelivering()
|
||||||
|
|
||||||
|
wearConstants.W_M_INITIATE_ACTION ->
|
||||||
|
String(messageEvent.data).also { actionstring ->
|
||||||
|
aapsLogger.debug(LTag.WEAR, "Initiate action: $actionstring")
|
||||||
|
rxBus.send(EventWearInitiateAction(actionstring))
|
||||||
|
}
|
||||||
|
|
||||||
|
wearConstants.W_M_CONFIRM_ACTION ->
|
||||||
|
String(messageEvent.data).also { actionstring ->
|
||||||
|
aapsLogger.debug(LTag.WEAR, "Wear confirm action: $actionstring")
|
||||||
|
rxBus.send(EventWearConfirmAction(actionstring))
|
||||||
|
}
|
||||||
|
|
||||||
|
wearConstants.W_M_PONG -> aapsLogger.debug(LTag.WEAR, "Pong response from ${messageEvent.sourceNodeId}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var transcriptionNodeId: String? = null
|
||||||
|
|
||||||
|
private fun updateTranscriptionCapability() {
|
||||||
|
val capabilityInfo: CapabilityInfo = Tasks.await(
|
||||||
|
capabilityClient.getCapability(WEAR_CAPABILITY, CapabilityClient.FILTER_REACHABLE)
|
||||||
|
)
|
||||||
|
aapsLogger.debug(LTag.WEAR, "Nodes: ${capabilityInfo.nodes.joinToString(", ") { it.displayName + "(" + it.id + ")" }}")
|
||||||
|
val bestNode = pickBestNodeId(capabilityInfo.nodes)
|
||||||
|
transcriptionNodeId = bestNode?.id
|
||||||
|
wearPlugin.connectedDevice = bestNode?.displayName ?: "---"
|
||||||
|
rxBus.send(EventWearUpdateGui())
|
||||||
|
aapsLogger.debug(LTag.WEAR, "Selected node: ${bestNode?.displayName} $transcriptionNodeId")
|
||||||
|
sendMessage(wearConstants.M_W_PING, byteArrayOf())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find a nearby node or pick one arbitrarily
|
||||||
|
private fun pickBestNodeId(nodes: Set<Node>): Node? =
|
||||||
|
nodes.firstOrNull { it.isNearby } ?: nodes.firstOrNull()
|
||||||
|
|
||||||
|
private fun sendData(path: String, vararg params: DataMap) {
|
||||||
|
if (wearPlugin.isEnabled()) {
|
||||||
|
scope.launch {
|
||||||
|
try {
|
||||||
|
for (dm in params) {
|
||||||
|
val request = PutDataMapRequest.create(path).apply {
|
||||||
|
dataMap.putAll(dm)
|
||||||
|
}
|
||||||
|
.asPutDataRequest()
|
||||||
|
.setUrgent()
|
||||||
|
|
||||||
|
val result = dataClient.putDataItem(request).await()
|
||||||
|
aapsLogger.debug(LTag.WEAR, "sendData: ${result.uri} ${params.joinToString()}")
|
||||||
|
}
|
||||||
|
} catch (cancellationException: CancellationException) {
|
||||||
|
throw cancellationException
|
||||||
|
} catch (exception: Exception) {
|
||||||
|
aapsLogger.error(LTag.WEAR, "DataItem failed: $exception")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sendMessage(path: String, data: ByteArray) {
|
||||||
|
if (wearPlugin.isEnabled()) {
|
||||||
|
aapsLogger.debug(LTag.WEAR, "sendMessage: $path")
|
||||||
|
transcriptionNodeId?.also { nodeId ->
|
||||||
|
messageClient
|
||||||
|
.sendMessage(nodeId, path, data).apply {
|
||||||
|
addOnSuccessListener { }
|
||||||
|
addOnFailureListener {
|
||||||
|
aapsLogger.debug(LTag.WEAR, "sendMessage: $path failure")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sendData() {
|
||||||
|
val lastBG = iobCobCalculator.ads.lastBg() ?: return
|
||||||
|
val glucoseStatus = glucoseStatusProvider.glucoseStatusData
|
||||||
|
aapsLogger.debug(LTag.WEAR, "Sending bg data to wear")
|
||||||
|
sendData(
|
||||||
|
wearConstants.M_W_DATA,
|
||||||
|
dataMapSingleBG(lastBG, glucoseStatus)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun resendData() {
|
||||||
|
sendPreferences()
|
||||||
|
sendQuickWizard()
|
||||||
|
val startTime = System.currentTimeMillis() - (60000 * 60 * 5.5).toLong()
|
||||||
|
val lastBg = iobCobCalculator.ads.lastBg() ?: return
|
||||||
|
val graphBgs = repository.compatGetBgReadingsDataFromTime(startTime, true).blockingGet()
|
||||||
|
val glucoseStatus = glucoseStatusProvider.getGlucoseStatusData(true)
|
||||||
|
if (graphBgs.isNotEmpty()) {
|
||||||
|
val entries = dataMapSingleBG(lastBg, glucoseStatus)
|
||||||
|
val dataMaps = ArrayList<DataMap>(graphBgs.size)
|
||||||
|
for (bg in graphBgs) {
|
||||||
|
val dataMap: DataMap = dataMapSingleBG(bg, glucoseStatus)
|
||||||
|
dataMaps.add(dataMap)
|
||||||
|
}
|
||||||
|
entries.putDataMapArrayList("entries", dataMaps)
|
||||||
|
aapsLogger.debug(LTag.WEAR, "Sending graph bg data to wear")
|
||||||
|
sendData(
|
||||||
|
wearConstants.M_W_DATA,
|
||||||
|
entries
|
||||||
|
)
|
||||||
|
}
|
||||||
|
sendBasals()
|
||||||
|
sendStatus()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sendBasals() {
|
||||||
|
val now = System.currentTimeMillis()
|
||||||
|
val startTimeWindow = now - (60000 * 60 * 5.5).toLong()
|
||||||
|
val basals = java.util.ArrayList<DataMap>()
|
||||||
|
val temps = java.util.ArrayList<DataMap>()
|
||||||
|
val boluses = java.util.ArrayList<DataMap>()
|
||||||
|
val predictions = java.util.ArrayList<DataMap>()
|
||||||
|
val profile = profileFunction.getProfile() ?: return
|
||||||
|
var beginBasalSegmentTime = startTimeWindow
|
||||||
|
var runningTime = startTimeWindow
|
||||||
|
var beginBasalValue = profile.getBasal(beginBasalSegmentTime)
|
||||||
|
var endBasalValue = beginBasalValue
|
||||||
|
var tb1 = iobCobCalculator.getTempBasalIncludingConvertedExtended(runningTime)
|
||||||
|
var tb2: TemporaryBasal?
|
||||||
|
var tbBefore = beginBasalValue
|
||||||
|
var tbAmount = beginBasalValue
|
||||||
|
var tbStart = runningTime
|
||||||
|
if (tb1 != null) {
|
||||||
|
val profileTB = profileFunction.getProfile(runningTime)
|
||||||
|
if (profileTB != null) {
|
||||||
|
tbAmount = tb1.convertedToAbsolute(runningTime, profileTB)
|
||||||
|
tbStart = runningTime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (runningTime < now) {
|
||||||
|
val profileTB = profileFunction.getProfile(runningTime) ?: return
|
||||||
|
//basal rate
|
||||||
|
endBasalValue = profile.getBasal(runningTime)
|
||||||
|
if (endBasalValue != beginBasalValue) {
|
||||||
|
//push the segment we recently left
|
||||||
|
basals.add(basalMap(beginBasalSegmentTime, runningTime, beginBasalValue))
|
||||||
|
|
||||||
|
//begin new Basal segment
|
||||||
|
beginBasalSegmentTime = runningTime
|
||||||
|
beginBasalValue = endBasalValue
|
||||||
|
}
|
||||||
|
|
||||||
|
//temps
|
||||||
|
tb2 = iobCobCalculator.getTempBasalIncludingConvertedExtended(runningTime)
|
||||||
|
if (tb1 == null && tb2 == null) {
|
||||||
|
//no temp stays no temp
|
||||||
|
} else if (tb1 != null && tb2 == null) {
|
||||||
|
//temp is over -> push it
|
||||||
|
temps.add(tempMap(tbStart, tbBefore, runningTime, endBasalValue, tbAmount))
|
||||||
|
tb1 = null
|
||||||
|
} else if (tb1 == null && tb2 != null) {
|
||||||
|
//temp begins
|
||||||
|
tb1 = tb2
|
||||||
|
tbStart = runningTime
|
||||||
|
tbBefore = endBasalValue
|
||||||
|
tbAmount = tb1.convertedToAbsolute(runningTime, profileTB)
|
||||||
|
} else if (tb1 != null && tb2 != null) {
|
||||||
|
val currentAmount = tb2.convertedToAbsolute(runningTime, profileTB)
|
||||||
|
if (currentAmount != tbAmount) {
|
||||||
|
temps.add(tempMap(tbStart, tbBefore, runningTime, currentAmount, tbAmount))
|
||||||
|
tbStart = runningTime
|
||||||
|
tbBefore = tbAmount
|
||||||
|
tbAmount = currentAmount
|
||||||
|
tb1 = tb2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
runningTime += (5 * 60 * 1000).toLong()
|
||||||
|
}
|
||||||
|
if (beginBasalSegmentTime != runningTime) {
|
||||||
|
//push the remaining segment
|
||||||
|
basals.add(basalMap(beginBasalSegmentTime, runningTime, beginBasalValue))
|
||||||
|
}
|
||||||
|
if (tb1 != null) {
|
||||||
|
tb2 = iobCobCalculator.getTempBasalIncludingConvertedExtended(now) //use "now" to express current situation
|
||||||
|
if (tb2 == null) {
|
||||||
|
//express the cancelled temp by painting it down one minute early
|
||||||
|
temps.add(tempMap(tbStart, tbBefore, now - 60 * 1000, endBasalValue, tbAmount))
|
||||||
|
} else {
|
||||||
|
//express currently running temp by painting it a bit into the future
|
||||||
|
val profileNow = profileFunction.getProfile(now)
|
||||||
|
val currentAmount = tb2.convertedToAbsolute(now, profileNow!!)
|
||||||
|
if (currentAmount != tbAmount) {
|
||||||
|
temps.add(tempMap(tbStart, tbBefore, now, tbAmount, tbAmount))
|
||||||
|
temps.add(tempMap(now, tbAmount, runningTime + 5 * 60 * 1000, currentAmount, currentAmount))
|
||||||
|
} else {
|
||||||
|
temps.add(tempMap(tbStart, tbBefore, runningTime + 5 * 60 * 1000, tbAmount, tbAmount))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tb2 = iobCobCalculator.getTempBasalIncludingConvertedExtended(now) //use "now" to express current situation
|
||||||
|
if (tb2 != null) {
|
||||||
|
//onset at the end
|
||||||
|
val profileTB = profileFunction.getProfile(runningTime)
|
||||||
|
val currentAmount = tb2.convertedToAbsolute(runningTime, profileTB!!)
|
||||||
|
temps.add(tempMap(now - 60 * 1000, endBasalValue, runningTime + 5 * 60 * 1000, currentAmount, currentAmount))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
repository.getBolusesIncludingInvalidFromTime(startTimeWindow, true).blockingGet()
|
||||||
|
.stream()
|
||||||
|
.filter { (_, _, _, _, _, _, _, _, _, type) -> type !== Bolus.Type.PRIMING }
|
||||||
|
.forEach { (_, _, _, isValid, _, _, timestamp, _, amount, type) -> boluses.add(treatmentMap(timestamp, amount, 0.0, type === Bolus.Type.SMB, isValid)) }
|
||||||
|
repository.getCarbsDataFromTimeExpanded(startTimeWindow, true).blockingGet()
|
||||||
|
.forEach(Consumer { (_, _, _, isValid, _, _, timestamp, _, _, amount) -> boluses.add(treatmentMap(timestamp, 0.0, amount, false, isValid)) })
|
||||||
|
val finalLastRun = loop.lastRun
|
||||||
|
if (sp.getBoolean("wear_predictions", true) && finalLastRun?.request?.hasPredictions == true && finalLastRun.constraintsProcessed != null) {
|
||||||
|
val predArray = finalLastRun.constraintsProcessed!!.predictions
|
||||||
|
.stream().map { bg: GlucoseValue -> GlucoseValueDataPoint(bg, defaultValueHelper, profileFunction, rh) }
|
||||||
|
.collect(Collectors.toList())
|
||||||
|
if (predArray.isNotEmpty())
|
||||||
|
for (bg in predArray) if (bg.data.value > 39) predictions.add(predictionMap(bg.data.timestamp, bg.data.value, bg.color(null)))
|
||||||
|
}
|
||||||
|
aapsLogger.debug(LTag.WEAR, "Sending basal data to wear")
|
||||||
|
sendData(
|
||||||
|
wearConstants.M_W_BASAL,
|
||||||
|
DataMap().apply {
|
||||||
|
putDataMapArrayList("basals", basals)
|
||||||
|
putDataMapArrayList("temps", temps)
|
||||||
|
putDataMapArrayList("boluses", boluses)
|
||||||
|
putDataMapArrayList("predictions", predictions)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deltaString(deltaMGDL: Double, deltaMMOL: Double, units: GlucoseUnit): String {
|
||||||
|
val detailed = sp.getBoolean(R.string.key_wear_detailed_delta, false)
|
||||||
|
var deltaString = if (deltaMGDL >= 0) "+" else "-"
|
||||||
|
deltaString += if (units == GlucoseUnit.MGDL) {
|
||||||
|
if (detailed) to1Decimal(abs(deltaMGDL)) else to0Decimal(abs(deltaMGDL))
|
||||||
|
} else {
|
||||||
|
if (detailed) to2Decimal(abs(deltaMMOL)) else to1Decimal(abs(deltaMMOL))
|
||||||
|
}
|
||||||
|
return deltaString
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun dataMapSingleBG(lastBG: GlucoseValue, glucoseStatus: GlucoseStatus?): DataMap {
|
||||||
|
val units = profileFunction.getUnits()
|
||||||
|
val lowLine = Profile.toMgdl(defaultValueHelper.determineLowLine(), units)
|
||||||
|
val highLine = Profile.toMgdl(defaultValueHelper.determineHighLine(), units)
|
||||||
|
val sgvLevel = if (lastBG.value > highLine) 1L else if (lastBG.value < lowLine) -1L else 0L
|
||||||
|
val dataMap = DataMap()
|
||||||
|
dataMap.putString("sgvString", lastBG.valueToUnitsString(units))
|
||||||
|
dataMap.putString("glucoseUnits", units.asText)
|
||||||
|
dataMap.putLong("timestamp", lastBG.timestamp)
|
||||||
|
if (glucoseStatus == null) {
|
||||||
|
dataMap.putString("slopeArrow", "")
|
||||||
|
dataMap.putString("delta", "--")
|
||||||
|
dataMap.putString("avgDelta", "--")
|
||||||
|
} else {
|
||||||
|
dataMap.putString("slopeArrow", trendCalculator.getTrendArrow(lastBG).symbol)
|
||||||
|
dataMap.putString("delta", deltaString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units))
|
||||||
|
dataMap.putString("avgDelta", deltaString(glucoseStatus.shortAvgDelta, glucoseStatus.shortAvgDelta * Constants.MGDL_TO_MMOLL, units))
|
||||||
|
}
|
||||||
|
dataMap.putLong("sgvLevel", sgvLevel)
|
||||||
|
dataMap.putDouble("sgvDouble", lastBG.value)
|
||||||
|
dataMap.putDouble("high", highLine)
|
||||||
|
dataMap.putDouble("low", lowLine)
|
||||||
|
return dataMap
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun tempMap(startTime: Long, startBasal: Double, to: Long, toBasal: Double, amount: Double) =
|
||||||
|
DataMap().apply {
|
||||||
|
putLong("starttime", startTime)
|
||||||
|
putDouble("startBasal", startBasal)
|
||||||
|
putLong("endtime", to)
|
||||||
|
putDouble("endbasal", toBasal)
|
||||||
|
putDouble("amount", amount)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun basalMap(startTime: Long, endTime: Long, amount: Double) =
|
||||||
|
DataMap().apply {
|
||||||
|
putLong("starttime", startTime)
|
||||||
|
putLong("endtime", endTime)
|
||||||
|
putDouble("amount", amount)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun treatmentMap(date: Long, bolus: Double, carbs: Double, isSMB: Boolean, isValid: Boolean) =
|
||||||
|
DataMap().apply {
|
||||||
|
putLong("date", date)
|
||||||
|
putDouble("bolus", bolus)
|
||||||
|
putDouble("carbs", carbs)
|
||||||
|
putBoolean("isSMB", isSMB)
|
||||||
|
putBoolean("isValid", isValid)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun predictionMap(timestamp: Long, sgv: Double, color: Int) =
|
||||||
|
DataMap().apply {
|
||||||
|
putLong("timestamp", timestamp)
|
||||||
|
putDouble("sgv", sgv)
|
||||||
|
putInt("color", color)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun quickMap(q: QuickWizardEntry) =
|
||||||
|
DataMap().apply {
|
||||||
|
putString("guid", q.guid())
|
||||||
|
putString("button_text", q.buttonText())
|
||||||
|
putInt("carbs", q.carbs())
|
||||||
|
putInt("from", q.validFrom())
|
||||||
|
putInt("to", q.validTo())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sendBolusProgress(progressPercent: Int?, status: String?) {
|
||||||
|
progressPercent ?: return
|
||||||
|
aapsLogger.debug(LTag.WEAR, "Sending bolus progress: $progressPercent $status")
|
||||||
|
sendData(
|
||||||
|
wearConstants.M_W_BOLUS_PROGRESS,
|
||||||
|
DataMap().apply {
|
||||||
|
putLong("timestamp", System.currentTimeMillis())
|
||||||
|
putString("bolusProgress", "bolusProgress")
|
||||||
|
putString("progressstatus", status ?: "")
|
||||||
|
putInt("progresspercent", progressPercent)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sendActionConfirmationRequest(title: String?, message: String?, actionstring: String?) {
|
||||||
|
title ?: message ?: actionstring ?: return
|
||||||
|
aapsLogger.debug(LTag.WEAR, "Requesting confirmation from wear: $actionstring")
|
||||||
|
sendData(
|
||||||
|
wearConstants.M_W_ACTION_CONFIRMATION_REQUEST,
|
||||||
|
DataMap().apply {
|
||||||
|
putLong("timestamp", System.currentTimeMillis())
|
||||||
|
putString("actionConfirmationRequest", "actionConfirmationRequest")
|
||||||
|
putString("title", title)
|
||||||
|
putString("message", message)
|
||||||
|
putString("actionstring", actionstring)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sendChangeConfirmationRequest(title: String?, message: String?, actionstring: String?) {
|
||||||
|
title ?: message ?: actionstring ?: return
|
||||||
|
aapsLogger.debug(LTag.WEAR, "Requesting confirmation from wear: $actionstring")
|
||||||
|
sendData(
|
||||||
|
wearConstants.M_W_ACTION_CHANGE_CONFIRMATION_REQUEST,
|
||||||
|
DataMap().apply {
|
||||||
|
putLong("timestamp", System.currentTimeMillis())
|
||||||
|
putString("changeConfirmationRequest", "changeConfirmationRequest")
|
||||||
|
putString("title", title)
|
||||||
|
putString("message", message)
|
||||||
|
putString("actionstring", actionstring)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sendCancelNotificationRequest(actionstring: String?) {
|
||||||
|
actionstring ?: return
|
||||||
|
aapsLogger.debug(LTag.WEAR, "Canceling notification on wear: $actionstring")
|
||||||
|
sendData(
|
||||||
|
wearConstants.M_W_ACTION_CANCEL_NOTIFICATION_REQUEST,
|
||||||
|
DataMap().apply {
|
||||||
|
putLong("timestamp", System.currentTimeMillis())
|
||||||
|
putString("cancelNotificationRequest", "cancelNotificationRequest")
|
||||||
|
putString("actionstring", actionstring)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sendStatus() {
|
||||||
|
aapsLogger.debug(LTag.WEAR, "Updating status on wear")
|
||||||
|
val profile = profileFunction.getProfile()
|
||||||
|
var status = rh.gs(R.string.noprofile)
|
||||||
|
var iobSum = ""
|
||||||
|
var iobDetail = ""
|
||||||
|
var cobString = ""
|
||||||
|
var currentBasal = ""
|
||||||
|
var bgiString = ""
|
||||||
|
if (profile != null) {
|
||||||
|
val bolusIob = iobCobCalculator.calculateIobFromBolus().round()
|
||||||
|
val basalIob = iobCobCalculator.calculateIobFromTempBasalsIncludingConvertedExtended().round()
|
||||||
|
iobSum = to2Decimal(bolusIob.iob + basalIob.basaliob)
|
||||||
|
iobDetail = "(" + to2Decimal(bolusIob.iob) + "|" + to2Decimal(basalIob.basaliob) + ")"
|
||||||
|
cobString = iobCobCalculator.getCobInfo(false, "WatcherUpdaterService").generateCOBString()
|
||||||
|
currentBasal = generateBasalString()
|
||||||
|
|
||||||
|
//bgi
|
||||||
|
val bgi = -(bolusIob.activity + basalIob.activity) * 5 * fromMgdlToUnits(profile.getIsfMgdl(), profileFunction.getUnits())
|
||||||
|
bgiString = "" + (if (bgi >= 0) "+" else "") + to1Decimal(bgi)
|
||||||
|
status = generateStatusString(profile, currentBasal, iobSum, iobDetail, bgiString)
|
||||||
|
}
|
||||||
|
|
||||||
|
//batteries
|
||||||
|
val phoneBattery = receiverStatusStore.batteryLevel
|
||||||
|
val rigBattery = nsDeviceStatus.uploaderStatus.trim { it <= ' ' }
|
||||||
|
//OpenAPS status
|
||||||
|
val openApsStatus =
|
||||||
|
if (config.APS) loop.lastRun?.let { if (it.lastTBREnact != 0L) it.lastTBREnact else -1 } ?: -1
|
||||||
|
else nsDeviceStatus.openApsTimestamp
|
||||||
|
|
||||||
|
sendData(
|
||||||
|
wearConstants.M_W_STATUS,
|
||||||
|
DataMap().apply {
|
||||||
|
//unique content
|
||||||
|
putString("externalStatusString", status)
|
||||||
|
putString("iobSum", iobSum)
|
||||||
|
putString("iobDetail", iobDetail)
|
||||||
|
putBoolean("detailedIob", sp.getBoolean(R.string.key_wear_detailediob, false))
|
||||||
|
putString("cob", cobString)
|
||||||
|
putString("currentBasal", currentBasal)
|
||||||
|
putString("battery", "" + phoneBattery)
|
||||||
|
putString("rigBattery", rigBattery)
|
||||||
|
putLong("openApsStatus", openApsStatus)
|
||||||
|
putString("bgi", bgiString)
|
||||||
|
putBoolean("showBgi", sp.getBoolean(R.string.key_wear_showbgi, false))
|
||||||
|
putInt("batteryLevel", if (phoneBattery >= 30) 1 else 0)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sendPreferences() {
|
||||||
|
sendData(
|
||||||
|
wearConstants.M_W_PREFERENCES,
|
||||||
|
DataMap().apply {
|
||||||
|
putLong("timestamp", System.currentTimeMillis())
|
||||||
|
putBoolean(rh.gs(R.string.key_wear_control), sp.getBoolean(R.string.key_wear_control, false))
|
||||||
|
putBoolean(rh.gs(R.string.key_units_mgdl), profileFunction.getUnits() == GlucoseUnit.MGDL)
|
||||||
|
putInt(rh.gs(R.string.key_boluswizard_percentage), sp.getInt(R.string.key_boluswizard_percentage, 100))
|
||||||
|
putInt(rh.gs(R.string.key_treatmentssafety_maxcarbs), sp.getInt(R.string.key_treatmentssafety_maxcarbs, 48))
|
||||||
|
putDouble(rh.gs(R.string.key_treatmentssafety_maxbolus), sp.getDouble(R.string.key_treatmentssafety_maxbolus, 3.0))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sendQuickWizard() {
|
||||||
|
val entities = ArrayList<DataMap>()
|
||||||
|
for (i in 0 until quickWizard.size()) {
|
||||||
|
val q = quickWizard[i]
|
||||||
|
if (q.forDevice(QuickWizardEntry.DEVICE_WATCH)) entities.add(quickMap(q))
|
||||||
|
}
|
||||||
|
sendData(
|
||||||
|
wearConstants.M_W_QUICK_WIZARD,
|
||||||
|
DataMap().apply {
|
||||||
|
putLong("timestamp", System.currentTimeMillis())
|
||||||
|
putDataMapArrayList("quick_wizard", entities)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateStatusString(profile: Profile?, currentBasal: String, iobSum: String, iobDetail: String, bgiString: String): String {
|
||||||
|
var status = ""
|
||||||
|
if (profile == null) return rh.gs(R.string.noprofile)
|
||||||
|
if (!(loop as PluginBase).isEnabled()) status += rh.gs(R.string.disabledloop) + "\n"
|
||||||
|
|
||||||
|
val iobString =
|
||||||
|
if (sp.getBoolean(R.string.key_wear_detailediob, false)) "$iobSum $iobDetail"
|
||||||
|
else iobSum + "U"
|
||||||
|
|
||||||
|
status += "$currentBasal $iobString"
|
||||||
|
|
||||||
|
//add BGI if shown, otherwise return
|
||||||
|
if (sp.getBoolean(R.string.key_wear_showbgi, false)) status += " $bgiString"
|
||||||
|
return status
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateBasalString(): String {
|
||||||
|
val profile: Profile = profileFunction.getProfile() ?: return ""
|
||||||
|
return iobCobCalculator.getTempBasalIncludingConvertedExtended(System.currentTimeMillis())?.toStringShort() ?: to2Decimal(profile.getBasal()) + "U/h"
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
const val WEAR_CAPABILITY = "androidaps_wear"
|
||||||
|
|
||||||
|
val ACTION_RESEND = WatchUpdaterService::class.java.name + ".Resend"
|
||||||
|
val ACTION_OPEN_SETTINGS = WatchUpdaterService::class.java.name + ".OpenSettings"
|
||||||
|
val ACTION_SEND_STATUS = WatchUpdaterService::class.java.name + ".SendStatus"
|
||||||
|
val ACTION_SEND_BASALS = WatchUpdaterService::class.java.name + ".SendBasals"
|
||||||
|
val ACTION_SEND_BOLUS_PROGRESS = WatchUpdaterService::class.java.name + ".BolusProgress"
|
||||||
|
val ACTION_SEND_ACTION_CONFIRMATION_REQUEST = WatchUpdaterService::class.java.name + ".ActionConfirmationRequest"
|
||||||
|
val ACTION_SEND_CHANGE_CONFIRMATION_REQUEST = WatchUpdaterService::class.java.name + ".ChangeConfirmationRequest"
|
||||||
|
val ACTION_CANCEL_NOTIFICATION = WatchUpdaterService::class.java.name + ".CancelNotification"
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,73 +1,7 @@
|
||||||
package info.nightscout.androidaps.plugins.general.wear.wearintegration;
|
package info.nightscout.androidaps.plugins.general.wear.wearintegration;
|
||||||
|
|
||||||
import android.content.Intent;
|
/*
|
||||||
import android.os.AsyncTask;
|
public class WatchUpdaterService1 extends WearableListenerService implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.os.HandlerThread;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
import com.google.android.gms.common.ConnectionResult;
|
|
||||||
import com.google.android.gms.common.api.GoogleApiClient;
|
|
||||||
import com.google.android.gms.wearable.CapabilityApi;
|
|
||||||
import com.google.android.gms.wearable.CapabilityInfo;
|
|
||||||
import com.google.android.gms.wearable.DataMap;
|
|
||||||
import com.google.android.gms.wearable.MessageEvent;
|
|
||||||
import com.google.android.gms.wearable.Node;
|
|
||||||
import com.google.android.gms.wearable.PutDataMapRequest;
|
|
||||||
import com.google.android.gms.wearable.PutDataRequest;
|
|
||||||
import com.google.android.gms.wearable.Wearable;
|
|
||||||
import com.google.android.gms.wearable.WearableListenerService;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
import dagger.android.AndroidInjection;
|
|
||||||
import info.nightscout.androidaps.Constants;
|
|
||||||
import info.nightscout.androidaps.R;
|
|
||||||
import info.nightscout.androidaps.data.IobTotal;
|
|
||||||
import info.nightscout.androidaps.database.AppRepository;
|
|
||||||
import info.nightscout.androidaps.database.entities.Bolus;
|
|
||||||
import info.nightscout.androidaps.database.entities.GlucoseValue;
|
|
||||||
import info.nightscout.androidaps.database.entities.TemporaryBasal;
|
|
||||||
import info.nightscout.androidaps.extensions.GlucoseValueExtensionKt;
|
|
||||||
import info.nightscout.androidaps.extensions.TemporaryBasalExtensionKt;
|
|
||||||
import info.nightscout.androidaps.interfaces.ActivePlugin;
|
|
||||||
import info.nightscout.androidaps.interfaces.Config;
|
|
||||||
import info.nightscout.androidaps.interfaces.GlucoseUnit;
|
|
||||||
import info.nightscout.androidaps.interfaces.IobCobCalculator;
|
|
||||||
import info.nightscout.androidaps.interfaces.Loop;
|
|
||||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
|
||||||
import info.nightscout.androidaps.interfaces.Profile;
|
|
||||||
import info.nightscout.androidaps.interfaces.ProfileFunction;
|
|
||||||
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
|
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus;
|
|
||||||
import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus;
|
|
||||||
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.GlucoseValueDataPoint;
|
|
||||||
import info.nightscout.androidaps.plugins.general.wear.WearPlugin;
|
|
||||||
import info.nightscout.androidaps.plugins.general.wear.events.EventWearConfirmAction;
|
|
||||||
import info.nightscout.androidaps.plugins.general.wear.events.EventWearInitiateAction;
|
|
||||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus;
|
|
||||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider;
|
|
||||||
import info.nightscout.androidaps.receivers.ReceiverStatusStore;
|
|
||||||
import info.nightscout.androidaps.utils.DecimalFormatter;
|
|
||||||
import info.nightscout.androidaps.utils.DefaultValueHelper;
|
|
||||||
import info.nightscout.androidaps.utils.TrendCalculator;
|
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper;
|
|
||||||
import info.nightscout.androidaps.utils.wizard.QuickWizard;
|
|
||||||
import info.nightscout.androidaps.utils.wizard.QuickWizardEntry;
|
|
||||||
import info.nightscout.shared.logging.AAPSLogger;
|
|
||||||
import info.nightscout.shared.logging.LTag;
|
|
||||||
import info.nightscout.shared.sharedPreferences.SP;
|
|
||||||
import info.nightscout.shared.weardata.WearUris;
|
|
||||||
|
|
||||||
public class WatchUpdaterService extends WearableListenerService implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
|
|
||||||
@Inject public GlucoseStatusProvider glucoseStatusProvider;
|
@Inject public GlucoseStatusProvider glucoseStatusProvider;
|
||||||
@Inject public AAPSLogger aapsLogger;
|
@Inject public AAPSLogger aapsLogger;
|
||||||
@Inject public WearPlugin wearPlugin;
|
@Inject public WearPlugin wearPlugin;
|
||||||
|
@ -841,3 +775,4 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
|
||||||
return (lastLoopStatus != enabled);
|
return (lastLoopStatus != enabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
|
@ -29,6 +29,7 @@ import info.nightscout.androidaps.utils.T
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
import info.nightscout.androidaps.workflow.CalculationWorkflow
|
import info.nightscout.androidaps.workflow.CalculationWorkflow
|
||||||
|
import info.nightscout.androidaps.events.Event
|
||||||
import info.nightscout.shared.logging.AAPSLogger
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
import info.nightscout.shared.logging.LTag
|
import info.nightscout.shared.logging.LTag
|
||||||
import info.nightscout.shared.sharedPreferences.SP
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
|
|
|
@ -5,13 +5,13 @@ import info.nightscout.androidaps.R
|
||||||
import info.nightscout.androidaps.data.DetailedBolusInfo
|
import info.nightscout.androidaps.data.DetailedBolusInfo
|
||||||
import info.nightscout.androidaps.data.PumpEnactResult
|
import info.nightscout.androidaps.data.PumpEnactResult
|
||||||
import info.nightscout.androidaps.interfaces.*
|
import info.nightscout.androidaps.interfaces.*
|
||||||
import info.nightscout.shared.logging.AAPSLogger
|
|
||||||
import info.nightscout.shared.logging.LTag
|
|
||||||
import info.nightscout.androidaps.plugins.common.ManufacturerType
|
import info.nightscout.androidaps.plugins.common.ManufacturerType
|
||||||
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
|
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
import info.nightscout.androidaps.utils.InstanceId.instanceId
|
import info.nightscout.androidaps.utils.InstanceId
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
|
import info.nightscout.shared.logging.LTag
|
||||||
import org.json.JSONException
|
import org.json.JSONException
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -152,7 +152,7 @@ class MDIPlugin @Inject constructor(
|
||||||
|
|
||||||
override fun manufacturer(): ManufacturerType = ManufacturerType.AndroidAPS
|
override fun manufacturer(): ManufacturerType = ManufacturerType.AndroidAPS
|
||||||
override fun model(): PumpType = PumpType.MDI
|
override fun model(): PumpType = PumpType.MDI
|
||||||
override fun serialNumber(): String = instanceId()
|
override fun serialNumber(): String = InstanceId.instanceId
|
||||||
override fun shortStatus(veryShort: Boolean): String = model().model
|
override fun shortStatus(veryShort: Boolean): String = model().model
|
||||||
override fun canHandleDST(): Boolean = true
|
override fun canHandleDST(): Boolean = true
|
||||||
}
|
}
|
|
@ -11,8 +11,6 @@ import info.nightscout.androidaps.events.EventPreferenceChange
|
||||||
import info.nightscout.androidaps.extensions.convertedToAbsolute
|
import info.nightscout.androidaps.extensions.convertedToAbsolute
|
||||||
import info.nightscout.androidaps.extensions.plannedRemainingMinutes
|
import info.nightscout.androidaps.extensions.plannedRemainingMinutes
|
||||||
import info.nightscout.androidaps.interfaces.*
|
import info.nightscout.androidaps.interfaces.*
|
||||||
import info.nightscout.shared.logging.AAPSLogger
|
|
||||||
import info.nightscout.shared.logging.LTag
|
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
import info.nightscout.androidaps.plugins.common.ManufacturerType
|
import info.nightscout.androidaps.plugins.common.ManufacturerType
|
||||||
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
|
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
|
||||||
|
@ -22,11 +20,13 @@ import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
|
||||||
import info.nightscout.androidaps.plugins.pump.virtual.events.EventVirtualPumpUpdateGui
|
import info.nightscout.androidaps.plugins.pump.virtual.events.EventVirtualPumpUpdateGui
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
import info.nightscout.androidaps.utils.InstanceId.instanceId
|
import info.nightscout.androidaps.utils.InstanceId
|
||||||
import info.nightscout.androidaps.utils.T
|
import info.nightscout.androidaps.utils.T
|
||||||
import info.nightscout.androidaps.utils.TimeChangeType
|
import info.nightscout.androidaps.utils.TimeChangeType
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
|
import info.nightscout.shared.logging.LTag
|
||||||
import info.nightscout.shared.sharedPreferences.SP
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||||
|
@ -365,7 +365,7 @@ open class VirtualPumpPlugin @Inject constructor(
|
||||||
|
|
||||||
override fun model(): PumpType = pumpDescription.pumpType
|
override fun model(): PumpType = pumpDescription.pumpType
|
||||||
|
|
||||||
override fun serialNumber(): String = instanceId()
|
override fun serialNumber(): String = InstanceId.instanceId
|
||||||
|
|
||||||
override fun shortStatus(veryShort: Boolean): String = "Virtual Pump"
|
override fun shortStatus(veryShort: Boolean): String = "Virtual Pump"
|
||||||
|
|
||||||
|
|
|
@ -10,31 +10,38 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
style="@style/GrayButton"
|
<TextView
|
||||||
android:id="@+id/resend"
|
android:id="@+id/connected_device"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="3dp"
|
android:gravity="center_vertical|center_horizontal"
|
||||||
android:layout_marginLeft="10dp"
|
android:paddingTop="10dp"
|
||||||
android:layout_marginRight="10dp"
|
android:paddingBottom="10dp"
|
||||||
android:layout_marginTop="3dp"
|
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
|
||||||
android:layout_weight="0.5"
|
tools:text="---" />
|
||||||
android:text="@string/resend_all_data"
|
|
||||||
android:textColor="?attr/treatmentButton" />
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
style="@style/GrayButton"
|
android:id="@+id/resend"
|
||||||
android:id="@+id/opensettings"
|
style="@style/ButtonSmallFontStyle"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
android:layout_marginBottom="3dp"
|
android:layout_weight="1"
|
||||||
android:layout_marginLeft="10dp"
|
android:drawableTop="@drawable/ic_refresh"
|
||||||
android:layout_marginRight="10dp"
|
android:paddingLeft="0dp"
|
||||||
android:layout_marginTop="3dp"
|
android:paddingRight="0dp"
|
||||||
android:layout_weight="0.5"
|
android:text="@string/resend_all_data" />
|
||||||
android:text="@string/open_settings_on_wear"
|
|
||||||
android:textColor="?attr/treatmentButton" />
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/open_settings"
|
||||||
|
style="@style/ButtonSmallFontStyle"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:drawableTop="@drawable/ic_settings"
|
||||||
|
android:paddingLeft="0dp"
|
||||||
|
android:paddingRight="0dp"
|
||||||
|
android:text="@string/open_settings_on_wear" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
25
app/src/main/res/values/wear.xml
Normal file
25
app/src/main/res/values/wear.xml
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2021 The Android Open Source Project
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
<string-array
|
||||||
|
name="android_wear_capabilities"
|
||||||
|
translatable="false"
|
||||||
|
tools:ignore="UnusedResources">
|
||||||
|
<!-- declaring the provided capabilities -->
|
||||||
|
<item>androidaps_mobile</item>
|
||||||
|
</string-array>
|
||||||
|
</resources>
|
|
@ -10,7 +10,7 @@ buildscript {
|
||||||
room_version = '2.4.2'
|
room_version = '2.4.2'
|
||||||
lifecycle_version = '2.4.1'
|
lifecycle_version = '2.4.1'
|
||||||
dagger_version = '2.41'
|
dagger_version = '2.41'
|
||||||
coroutines_version = '1.4.1'
|
coroutines_version = '1.6.1'
|
||||||
activity_version = '1.3.1'
|
activity_version = '1.3.1'
|
||||||
fragmentktx_version = '1.3.6'
|
fragmentktx_version = '1.3.6'
|
||||||
ormLite_version = '4.46'
|
ormLite_version = '4.46'
|
||||||
|
@ -51,6 +51,7 @@ buildscript {
|
||||||
|
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
classpath "org.jetbrains.kotlin:kotlin-allopen:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-allopen:$kotlin_version"
|
||||||
|
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
|
||||||
classpath 'com.hiya:jacoco-android:0.2'
|
classpath 'com.hiya:jacoco-android:0.2'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1343,7 +1343,7 @@ public class ComboPlugin extends PumpPluginBase implements Pump, Constraints {
|
||||||
}
|
}
|
||||||
|
|
||||||
private String fakeSerialNumber() {
|
private String fakeSerialNumber() {
|
||||||
return InstanceId.INSTANCE.instanceId();
|
return InstanceId.INSTANCE.getInstanceId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull @Override
|
@NonNull @Override
|
||||||
|
|
|
@ -5,6 +5,8 @@ dependencies {
|
||||||
api "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
api "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
||||||
api "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
|
api "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
|
||||||
api "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
|
api "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
|
||||||
|
api "org.jetbrains.kotlinx:kotlinx-coroutines-guava:$coroutines_version"
|
||||||
|
api "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:$coroutines_version"
|
||||||
api "androidx.core:core-ktx:$core_version"
|
api "androidx.core:core-ktx:$core_version"
|
||||||
api 'androidx.legacy:legacy-support-v13:1.0.0'
|
api 'androidx.legacy:legacy-support-v13:1.0.0'
|
||||||
api 'androidx.legacy:legacy-support-v4:1.0.0'
|
api 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||||
|
@ -25,7 +27,7 @@ dependencies {
|
||||||
api "com.google.dagger:dagger-android-support:$dagger_version"
|
api "com.google.dagger:dagger-android-support:$dagger_version"
|
||||||
|
|
||||||
//Firebase
|
//Firebase
|
||||||
api platform('com.google.firebase:firebase-bom:25.12.0')
|
api platform('com.google.firebase:firebase-bom:29.3.0')
|
||||||
api "com.google.firebase:firebase-analytics-ktx"
|
api "com.google.firebase:firebase-analytics-ktx"
|
||||||
api "com.google.firebase:firebase-crashlytics-ktx"
|
api "com.google.firebase:firebase-crashlytics-ktx"
|
||||||
api "com.google.firebase:firebase-messaging-ktx"
|
api "com.google.firebase:firebase-messaging-ktx"
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package info.nightscout.androidaps.events
|
package info.nightscout.androidaps.events
|
||||||
|
|
||||||
import info.nightscout.androidaps.utils.StringUtils
|
|
||||||
|
|
||||||
class EventNetworkChange : Event() {
|
class EventNetworkChange : Event() {
|
||||||
|
|
||||||
var mobileConnected = false
|
var mobileConnected = false
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
package info.nightscout.androidaps.events
|
package info.nightscout.androidaps.events
|
||||||
|
|
||||||
import info.nightscout.androidaps.events.Event
|
|
||||||
|
|
||||||
class EventNtpStatus(val status: String, val percent: Int) : Event()
|
class EventNtpStatus(val status: String, val percent: Int) : Event()
|
|
@ -1,10 +1,13 @@
|
||||||
package info.nightscout.androidaps.utils
|
package info.nightscout.androidaps.utils
|
||||||
|
|
||||||
import com.google.firebase.iid.FirebaseInstanceId
|
import com.google.firebase.installations.FirebaseInstallations
|
||||||
|
|
||||||
object InstanceId {
|
object InstanceId {
|
||||||
fun instanceId(): String {
|
var instanceId : String = ""
|
||||||
var id = FirebaseInstanceId.getInstance().id
|
|
||||||
return id
|
init {
|
||||||
|
FirebaseInstallations.getInstance().id.addOnCompleteListener {
|
||||||
|
instanceId = it.result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -18,6 +18,9 @@ android {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
// shared needed for OpenForTesting
|
||||||
|
implementation project(':shared')
|
||||||
|
|
||||||
api "androidx.core:core-ktx:$core_version"
|
api "androidx.core:core-ktx:$core_version"
|
||||||
api "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
api "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ apply plugin: 'kotlin-android'
|
||||||
apply plugin: 'kotlin-kapt'
|
apply plugin: 'kotlin-kapt'
|
||||||
apply plugin: 'kotlin-allopen'
|
apply plugin: 'kotlin-allopen'
|
||||||
apply plugin: 'com.hiya.jacoco-android'
|
apply plugin: 'com.hiya.jacoco-android'
|
||||||
|
apply plugin: 'kotlinx-serialization'
|
||||||
|
|
||||||
apply from: "${project.rootDir}/gradle/android_dependencies.gradle"
|
apply from: "${project.rootDir}/gradle/android_dependencies.gradle"
|
||||||
apply from: "${project.rootDir}/gradle/android_module_dependencies.gradle"
|
apply from: "${project.rootDir}/gradle/android_module_dependencies.gradle"
|
||||||
|
@ -29,6 +30,9 @@ dependencies {
|
||||||
exclude group: "com.google.android", module: "android"
|
exclude group: "com.google.android", module: "android"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
api "org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2"
|
||||||
|
api "org.apache.commons:commons-lang3:$commonslang3_version"
|
||||||
|
|
||||||
//RxBus
|
//RxBus
|
||||||
api "io.reactivex.rxjava3:rxjava:$rxjava_version"
|
api "io.reactivex.rxjava3:rxjava:$rxjava_version"
|
||||||
api "io.reactivex.rxjava3:rxkotlin:$rxkotlin_version"
|
api "io.reactivex.rxjava3:rxkotlin:$rxkotlin_version"
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
package info.nightscout.androidaps.events
|
||||||
|
|
||||||
|
import info.nightscout.shared.weardata.ActionData
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
|
||||||
|
class EventWearToMobileAction(val actionData: ActionData) : Event()
|
|
@ -0,0 +1,7 @@
|
||||||
|
package info.nightscout.androidaps.events
|
||||||
|
|
||||||
|
import info.nightscout.shared.weardata.ActionData
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
|
||||||
|
class EventWearToMobileChange(val actionData: ActionData) : Event()
|
|
@ -0,0 +1,7 @@
|
||||||
|
package info.nightscout.androidaps.events
|
||||||
|
|
||||||
|
import info.nightscout.shared.weardata.ActionData
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
|
||||||
|
class EventWearToMobileConfirm(val actionData: ActionData) : Event()
|
|
@ -0,0 +1,33 @@
|
||||||
|
package info.nightscout.shared.weardata
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
sealed class ActionData {
|
||||||
|
|
||||||
|
fun serialize() = Json.encodeToString(serializer(), this)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
fun deserialize(json: String) = Json.decodeFromString(serializer(), json)
|
||||||
|
}
|
||||||
|
// Wear -> Mobile
|
||||||
|
@Serializable
|
||||||
|
data class Pong(val timeStamp: Long) : ActionData()
|
||||||
|
@Serializable
|
||||||
|
data class Bolus(val insulin: Double, val carbs: Int) : ActionData()
|
||||||
|
@Serializable
|
||||||
|
data class ProfileSwitch(val timeShift: Int, val percentage: Int) : ActionData()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class OpenProfileSwitch(val timeShift: Int, val percentage: Int) : ActionData()
|
||||||
|
|
||||||
|
// Mobile -> Wear
|
||||||
|
@Serializable
|
||||||
|
data class Ping(val timeStamp: Long) : ActionData()
|
||||||
|
@Serializable
|
||||||
|
data class ConfirmAction(val title: String, val message: String, val originalCommand: ActionData) : ActionData()
|
||||||
|
@Serializable
|
||||||
|
data class ChangeAction(val title: String, val message: String, val originalCommand: ActionData) : ActionData()
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
package info.nightscout.shared.weardata
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import info.nightscout.shared.R
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Suppress("PropertyName")
|
||||||
|
@Singleton
|
||||||
|
class WearConstants @Inject constructor(private val context: Context) {
|
||||||
|
|
||||||
|
// Paths must be defined in manifest
|
||||||
|
// mobile -> wear (data)
|
||||||
|
val M_W_DATA get() = context.getString(R.string.path_watch_data)
|
||||||
|
val M_W_STATUS get() = context.getString(R.string.path_status)
|
||||||
|
val M_W_PREFERENCES get() = context.getString(R.string.path_preferences)
|
||||||
|
val M_W_QUICK_WIZARD get() = context.getString(R.string.path_quick_wizard)
|
||||||
|
val M_W_BASAL get() = context.getString(R.string.path_basal)
|
||||||
|
val M_W_BOLUS_PROGRESS get() = context.getString(R.string.path_bolus_progress)
|
||||||
|
val M_W_ACTION_CONFIRMATION_REQUEST get() = context.getString(R.string.path_action_confirmation)
|
||||||
|
val M_W_ACTION_CHANGE_CONFIRMATION_REQUEST get() = context.getString(R.string.path_change_confirmation_request)
|
||||||
|
val M_W_ACTION_CANCEL_NOTIFICATION_REQUEST get() = context.getString(R.string.path_cancel_notification_request)
|
||||||
|
|
||||||
|
// mobile -> wear (message)
|
||||||
|
val M_W_OPEN_SETTINGS get() = context.getString(R.string.path_open_wear_setting)
|
||||||
|
val M_W_PING get() = context.getString(R.string.path_ping)
|
||||||
|
|
||||||
|
// wear -> mobile (message)
|
||||||
|
val W_M_RESEND_DATA get() = context.getString(R.string.path_resend_data_request)
|
||||||
|
val W_M_CANCEL_BOLUS get() = context.getString(R.string.path_cancel_bolus_on_phone)
|
||||||
|
val W_M_CONFIRM_ACTION get() = context.getString(R.string.path_confirm_action)
|
||||||
|
val W_M_INITIATE_ACTION get() = context.getString(R.string.path_initiate_action_on_phone)
|
||||||
|
val W_M_PONG get() = context.getString(R.string.path_pong)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
// actions for WEAR_INITIATE_ACTION_ON_PHONE
|
||||||
|
// used by
|
||||||
|
// DataLayerListenerService::initiateAction
|
||||||
|
// ActionStringHandler::handleInitiateActionOnPhone
|
||||||
|
// EventWearInitiateAction
|
||||||
|
const val ACTION_FILL_PRESET = "fillpreset"
|
||||||
|
const val ACTION_FILL = "fill"
|
||||||
|
const val ACTION_BOLUS = "bolus"
|
||||||
|
const val ACTION_TEMPORARY_TARGET = "temptarget"
|
||||||
|
const val ACTION_STATUS = "status"
|
||||||
|
const val ACTION_WIZARD = "wizard"
|
||||||
|
const val ACTION_WIZARD2 = "wizard2"
|
||||||
|
const val ACTION_QUICK_WIZARD = "quick_wizard"
|
||||||
|
const val ACTION_OPEN_CPP = "opencpp"
|
||||||
|
const val ACTION_CPP_SET = "cppset"
|
||||||
|
const val ACTION_TDD_STATS = "tddstats"
|
||||||
|
const val ACTION_E_CARBS = "ecarbs"
|
||||||
|
const val ACTION_CHANGE_REQUEST = "changeRequest"
|
||||||
|
const val ACTION_CANCEL_CHANGE_REQUEST = "cancelChangeRequest"
|
||||||
|
const val ACTION_DISMISS_OVERVIEW_NOTIF = "dismissoverviewnotification"
|
||||||
|
|
||||||
|
//data keys
|
||||||
|
const val KEY_ACTION_DATA = "actionData"
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,21 +0,0 @@
|
||||||
package info.nightscout.shared.weardata
|
|
||||||
|
|
||||||
object WearUris {
|
|
||||||
|
|
||||||
const val WEARABLE_DATA_PATH = "/nightscout_watch_data"
|
|
||||||
const val WEARABLE_RESEND_PATH = "/nightscout_watch_data_resend"
|
|
||||||
const val WEARABLE_CANCELBOLUS_PATH = "/nightscout_watch_cancel_bolus"
|
|
||||||
const val WEARABLE_CONFIRM_ACTIONSTRING_PATH = "/nightscout_watch_confirmactionstring"
|
|
||||||
const val WEARABLE_INITIATE_ACTIONSTRING_PATH = "/nightscout_watch_initiateactionstring"
|
|
||||||
|
|
||||||
const val OPEN_SETTINGS_PATH = "/openwearsettings"
|
|
||||||
const val NEW_STATUS_PATH = "/sendstatustowear"
|
|
||||||
const val NEW_PREFERENCES_PATH = "/sendpreferencestowear"
|
|
||||||
const val QUICK_WIZARD_PATH = "/send_quick_wizard"
|
|
||||||
const val BASAL_DATA_PATH = "/nightscout_watch_basal"
|
|
||||||
const val BOLUS_PROGRESS_PATH = "/nightscout_watch_bolusprogress"
|
|
||||||
const val ACTION_CONFIRMATION_REQUEST_PATH = "/nightscout_watch_actionconfirmationrequest"
|
|
||||||
const val ACTION_CHANGECONFIRMATION_REQUEST_PATH = "/nightscout_watch_changeconfirmationrequest"
|
|
||||||
const val ACTION_CANCELNOTIFICATION_REQUEST_PATH = "/nightscout_watch_cancelnotificationrequest"
|
|
||||||
|
|
||||||
}
|
|
19
shared/src/main/res/values/wear_paths.xml
Normal file
19
shared/src/main/res/values/wear_paths.xml
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="path_ping" translatable="false">/ping</string>
|
||||||
|
<string name="path_pong" translatable="false">/pong</string>
|
||||||
|
<string name="path_open_wear_setting" translatable="false">/openwearsettings</string>
|
||||||
|
<string name="path_resend_data_request" translatable="false">/nightscout_watch_data_resend</string>
|
||||||
|
<string name="path_initiate_action_on_phone" translatable="false">/nightscout_watch_initiateactionstring</string>
|
||||||
|
<string name="path_cancel_bolus_on_phone" translatable="false">/nightscout_watch_cancel_bolus</string>
|
||||||
|
<string name="path_confirm_action" translatable="false">/nightscout_watch_confirmactionstring</string>
|
||||||
|
<string name="path_watch_data" translatable="false">/nightscout_watch_data</string>
|
||||||
|
<string name="path_status" translatable="false">/sendstatustowear</string>
|
||||||
|
<string name="path_preferences" translatable="false">/sendpreferencestowear</string>
|
||||||
|
<string name="path_quick_wizard" translatable="false">/send_quick_wizard</string>
|
||||||
|
<string name="path_basal" translatable="false">/nightscout_watch_basal</string>
|
||||||
|
<string name="path_bolus_progress" translatable="false">/nightscout_watch_bolusprogress</string>
|
||||||
|
<string name="path_action_confirmation" translatable="false">/nightscout_watch_actionconfirmationrequest</string>
|
||||||
|
<string name="path_change_confirmation_request" translatable="false">/nightscout_watch_changeconfirmationrequest</string>
|
||||||
|
<string name="path_cancel_notification_request" translatable="false">/nightscout_watch_cancelnotificationrequest</string>
|
||||||
|
</resources>
|
|
@ -23,8 +23,7 @@ apply from: "${project.rootDir}/gradle/jacoco_global.gradle"
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
wearableVersion = "2.9.0"
|
wearableVersion = "2.9.0"
|
||||||
// playServicesWearable 17.1.0 breaks test
|
playServicesWearable = "17.1.0"
|
||||||
playServicesWearable = "17.0.0"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def generateGitBuild = { ->
|
def generateGitBuild = { ->
|
||||||
|
@ -52,7 +51,6 @@ android {
|
||||||
compileSdkVersion 31
|
compileSdkVersion 31
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "info.nightscout.androidaps"
|
|
||||||
minSdkVersion 23
|
minSdkVersion 23
|
||||||
targetSdkVersion 29
|
targetSdkVersion 29
|
||||||
versionCode 2
|
versionCode 2
|
||||||
|
@ -112,8 +110,10 @@ dependencies {
|
||||||
implementation(files('libs/wearpreferenceactivity-0.5.0.aar'))
|
implementation(files('libs/wearpreferenceactivity-0.5.0.aar'))
|
||||||
implementation('com.github.lecho:hellocharts-library:1.5.8@aar')
|
implementation('com.github.lecho:hellocharts-library:1.5.8@aar')
|
||||||
|
|
||||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1'
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
|
||||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-guava:1.6.1'
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
|
||||||
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-guava:$coroutines_version"
|
||||||
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:$coroutines_version"
|
||||||
implementation "androidx.core:core-ktx:$core_version"
|
implementation "androidx.core:core-ktx:$core_version"
|
||||||
implementation "androidx.wear.tiles:tiles:1.0.1"
|
implementation "androidx.wear.tiles:tiles:1.0.1"
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
|
|
|
@ -17,6 +17,11 @@
|
||||||
android:icon="@drawable/ic_icon"
|
android:icon="@drawable/ic_icon"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:theme="@android:style/Theme.DeviceDefault">
|
android:theme="@android:style/Theme.DeviceDefault">
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="com.google.android.wearable.standalone"
|
||||||
|
android:value="false" />
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="com.google.android.gms.version"
|
android:name="com.google.android.gms.version"
|
||||||
android:value="@integer/google_play_services_version" />
|
android:value="@integer/google_play_services_version" />
|
||||||
|
@ -25,7 +30,8 @@
|
||||||
android:name=".watchfaces.BIGChart"
|
android:name=".watchfaces.BIGChart"
|
||||||
android:allowEmbedded="true"
|
android:allowEmbedded="true"
|
||||||
android:label="@string/label_xdrip_big_chart"
|
android:label="@string/label_xdrip_big_chart"
|
||||||
android:permission="android.permission.BIND_WALLPAPER">
|
android:permission="android.permission.BIND_WALLPAPER"
|
||||||
|
android:exported="false">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.service.wallpaper"
|
android:name="android.service.wallpaper"
|
||||||
android:resource="@xml/watch_face" />
|
android:resource="@xml/watch_face" />
|
||||||
|
@ -46,7 +52,8 @@
|
||||||
android:name=".watchfaces.NOChart"
|
android:name=".watchfaces.NOChart"
|
||||||
android:allowEmbedded="true"
|
android:allowEmbedded="true"
|
||||||
android:label="@string/label_xdrip_no_chart"
|
android:label="@string/label_xdrip_no_chart"
|
||||||
android:permission="android.permission.BIND_WALLPAPER">
|
android:permission="android.permission.BIND_WALLPAPER"
|
||||||
|
android:exported="false">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.service.wallpaper"
|
android:name="android.service.wallpaper"
|
||||||
android:resource="@xml/watch_face" />
|
android:resource="@xml/watch_face" />
|
||||||
|
@ -67,7 +74,8 @@
|
||||||
android:name=".watchfaces.Home"
|
android:name=".watchfaces.Home"
|
||||||
android:allowEmbedded="true"
|
android:allowEmbedded="true"
|
||||||
android:label="@string/label_xdrip"
|
android:label="@string/label_xdrip"
|
||||||
android:permission="android.permission.BIND_WALLPAPER">
|
android:permission="android.permission.BIND_WALLPAPER"
|
||||||
|
android:exported="false">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.service.wallpaper"
|
android:name="android.service.wallpaper"
|
||||||
android:resource="@xml/watch_face" />
|
android:resource="@xml/watch_face" />
|
||||||
|
@ -91,7 +99,8 @@
|
||||||
android:name=".watchfaces.Home2"
|
android:name=".watchfaces.Home2"
|
||||||
android:allowEmbedded="true"
|
android:allowEmbedded="true"
|
||||||
android:label="@string/label_xdrip_v2"
|
android:label="@string/label_xdrip_v2"
|
||||||
android:permission="android.permission.BIND_WALLPAPER">
|
android:permission="android.permission.BIND_WALLPAPER"
|
||||||
|
android:exported="false">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.service.wallpaper"
|
android:name="android.service.wallpaper"
|
||||||
android:resource="@xml/watch_face" />
|
android:resource="@xml/watch_face" />
|
||||||
|
@ -115,7 +124,8 @@
|
||||||
android:name=".watchfaces.Cockpit"
|
android:name=".watchfaces.Cockpit"
|
||||||
android:allowEmbedded="true"
|
android:allowEmbedded="true"
|
||||||
android:label="@string/label_xdrip_cockpit"
|
android:label="@string/label_xdrip_cockpit"
|
||||||
android:permission="android.permission.BIND_WALLPAPER">
|
android:permission="android.permission.BIND_WALLPAPER"
|
||||||
|
android:exported="false">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.service.wallpaper"
|
android:name="android.service.wallpaper"
|
||||||
android:resource="@xml/watch_face" />
|
android:resource="@xml/watch_face" />
|
||||||
|
@ -139,7 +149,8 @@
|
||||||
android:name=".watchfaces.Steampunk"
|
android:name=".watchfaces.Steampunk"
|
||||||
android:allowEmbedded="true"
|
android:allowEmbedded="true"
|
||||||
android:label="@string/label_xdrip_steampunk"
|
android:label="@string/label_xdrip_steampunk"
|
||||||
android:permission="android.permission.BIND_WALLPAPER">
|
android:permission="android.permission.BIND_WALLPAPER"
|
||||||
|
android:exported="false">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.service.wallpaper"
|
android:name="android.service.wallpaper"
|
||||||
android:resource="@xml/watch_face" />
|
android:resource="@xml/watch_face" />
|
||||||
|
@ -163,7 +174,8 @@
|
||||||
android:name=".watchfaces.LargeHome"
|
android:name=".watchfaces.LargeHome"
|
||||||
android:allowEmbedded="true"
|
android:allowEmbedded="true"
|
||||||
android:label="@string/label_xdrip_large"
|
android:label="@string/label_xdrip_large"
|
||||||
android:permission="android.permission.BIND_WALLPAPER">
|
android:permission="android.permission.BIND_WALLPAPER"
|
||||||
|
android:exported="false">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.service.wallpaper"
|
android:name="android.service.wallpaper"
|
||||||
android:resource="@xml/watch_face" />
|
android:resource="@xml/watch_face" />
|
||||||
|
@ -186,7 +198,8 @@
|
||||||
android:name=".watchfaces.CircleWatchface"
|
android:name=".watchfaces.CircleWatchface"
|
||||||
android:allowEmbedded="true"
|
android:allowEmbedded="true"
|
||||||
android:label="@string/label_xdrip_circle"
|
android:label="@string/label_xdrip_circle"
|
||||||
android:permission="android.permission.BIND_WALLPAPER">
|
android:permission="android.permission.BIND_WALLPAPER"
|
||||||
|
android:exported="false">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.service.wallpaper"
|
android:name="android.service.wallpaper"
|
||||||
android:resource="@xml/watch_face" />
|
android:resource="@xml/watch_face" />
|
||||||
|
@ -207,7 +220,8 @@
|
||||||
android:name=".watchfaces.DigitalStyle"
|
android:name=".watchfaces.DigitalStyle"
|
||||||
android:allowEmbedded="true"
|
android:allowEmbedded="true"
|
||||||
android:label="@string/label_digitalstyle"
|
android:label="@string/label_digitalstyle"
|
||||||
android:permission="android.permission.BIND_WALLPAPER">
|
android:permission="android.permission.BIND_WALLPAPER"
|
||||||
|
android:exported="false">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.service.wallpaper"
|
android:name="android.service.wallpaper"
|
||||||
android:resource="@xml/watch_face" />
|
android:resource="@xml/watch_face" />
|
||||||
|
@ -227,68 +241,73 @@
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<service android:name=".data.ListenerService">
|
<service android:name=".data.DataLayerListenerService"
|
||||||
|
android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<!-- <action android:name="com.google.android.gms.wearable.BIND_LISTENER" /> -->
|
|
||||||
<!-- listeners receive events that match the action and data filters -->
|
|
||||||
<action android:name="com.google.android.gms.wearable.CAPABILITY_CHANGED" />
|
<action android:name="com.google.android.gms.wearable.CAPABILITY_CHANGED" />
|
||||||
|
<data
|
||||||
|
android:host="*"
|
||||||
|
android:scheme="wear" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
<intent-filter>
|
||||||
<action android:name="com.google.android.gms.wearable.DATA_CHANGED" />
|
<action android:name="com.google.android.gms.wearable.DATA_CHANGED" />
|
||||||
|
<data
|
||||||
|
android:host="*"
|
||||||
|
android:pathPrefix="@string/path_watch_data"
|
||||||
|
android:scheme="wear" />
|
||||||
|
<data
|
||||||
|
android:host="*"
|
||||||
|
android:pathPrefix="@string/path_status"
|
||||||
|
android:scheme="wear" />
|
||||||
|
<data
|
||||||
|
android:host="*"
|
||||||
|
android:pathPrefix="@string/path_preferences"
|
||||||
|
android:scheme="wear" />
|
||||||
|
<data
|
||||||
|
android:host="*"
|
||||||
|
android:pathPrefix="@string/path_quick_wizard"
|
||||||
|
android:scheme="wear" />
|
||||||
|
<data
|
||||||
|
android:host="*"
|
||||||
|
android:pathPrefix="@string/path_basal"
|
||||||
|
android:scheme="wear" />
|
||||||
|
<data
|
||||||
|
android:host="*"
|
||||||
|
android:pathPrefix="@string/path_bolus_progress"
|
||||||
|
android:scheme="wear" />
|
||||||
|
<data
|
||||||
|
android:host="*"
|
||||||
|
android:pathPrefix="@string/path_action_confirmation"
|
||||||
|
android:scheme="wear" />
|
||||||
|
<data
|
||||||
|
android:host="*"
|
||||||
|
android:pathPrefix="@string/path_change_confirmation_request"
|
||||||
|
android:scheme="wear" />
|
||||||
|
<data
|
||||||
|
android:host="*"
|
||||||
|
android:pathPrefix="@string/path_cancel_notification_request"
|
||||||
|
android:scheme="wear" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="com.google.android.gms.wearable.CHANNEL_EVENT" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="com.google.android.gms.wearable.MESSAGE_RECEIVED" />
|
||||||
|
|
||||||
<data
|
<data
|
||||||
android:host="*"
|
android:host="*"
|
||||||
android:pathPrefix="/nightscout_watch_data"
|
android:pathPrefix="@string/path_ping"
|
||||||
android:scheme="wear" />
|
android:scheme="wear" />
|
||||||
<data
|
<data
|
||||||
android:host="*"
|
android:host="*"
|
||||||
android:pathPrefix="/nightscout_watch_data_resend"
|
android:pathPrefix="@string/path_open_wear_setting"
|
||||||
android:scheme="wear" />
|
android:scheme="wear" />
|
||||||
<data
|
<data
|
||||||
android:host="*"
|
android:host="*"
|
||||||
android:pathPrefix="/nightscout_watch_cancel_bolus"
|
android:pathPrefix="@string/path_action_confirmation"
|
||||||
android:scheme="wear" />
|
|
||||||
<data
|
|
||||||
android:host="*"
|
|
||||||
android:pathPrefix="/nightscout_watch_confirmactionstring"
|
|
||||||
android:scheme="wear" />
|
|
||||||
<data
|
|
||||||
android:host="*"
|
|
||||||
android:pathPrefix="/nightscout_watch_initiateactionstring"
|
|
||||||
android:scheme="wear" />
|
|
||||||
<data
|
|
||||||
android:host="*"
|
|
||||||
android:pathPrefix="/openwearsettings"
|
|
||||||
android:scheme="wear" />
|
|
||||||
<data
|
|
||||||
android:host="*"
|
|
||||||
android:pathPrefix="/send_quick_wizard"
|
|
||||||
android:scheme="wear" />
|
|
||||||
<data
|
|
||||||
android:host="*"
|
|
||||||
android:pathPrefix="/sendstatustowear"
|
|
||||||
android:scheme="wear" />
|
|
||||||
<data
|
|
||||||
android:host="*"
|
|
||||||
android:pathPrefix="/sendpreferencestowear"
|
|
||||||
android:scheme="wear" />
|
|
||||||
<data
|
|
||||||
android:host="*"
|
|
||||||
android:pathPrefix="/nightscout_watch_basal"
|
|
||||||
android:scheme="wear" />
|
|
||||||
<data
|
|
||||||
android:host="*"
|
|
||||||
android:pathPrefix="/nightscout_watch_bolusprogress"
|
|
||||||
android:scheme="wear" />
|
|
||||||
<data
|
|
||||||
android:host="*"
|
|
||||||
android:pathPrefix="/nightscout_watch_actionconfirmationrequest"
|
|
||||||
android:scheme="wear" />
|
|
||||||
<data
|
|
||||||
android:host="*"
|
|
||||||
android:pathPrefix="/nightscout_watch_changeconfirmationrequest"
|
|
||||||
android:scheme="wear" />
|
|
||||||
<data
|
|
||||||
android:host="*"
|
|
||||||
android:pathPrefix="/nightscout_watch_cancelnotificationrequest"
|
|
||||||
android:scheme="wear" />
|
android:scheme="wear" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</service>
|
</service>
|
||||||
|
@ -466,7 +485,7 @@
|
||||||
<service
|
<service
|
||||||
android:name=".complications.WallpaperLightComplication"
|
android:name=".complications.WallpaperLightComplication"
|
||||||
android:icon="@drawable/ic_aaps_light"
|
android:icon="@drawable/ic_aaps_light"
|
||||||
android:label="Light Walpaper"
|
android:label="Light Wallpaper"
|
||||||
android:permission="com.google.android.wearable.permission.BIND_COMPLICATION_PROVIDER">
|
android:permission="com.google.android.wearable.permission.BIND_COMPLICATION_PROVIDER">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.support.wearable.complications.ACTION_COMPLICATION_UPDATE_REQUEST" />
|
<action android:name="android.support.wearable.complications.ACTION_COMPLICATION_UPDATE_REQUEST" />
|
||||||
|
@ -483,7 +502,7 @@
|
||||||
<service
|
<service
|
||||||
android:name=".complications.WallpaperDarkComplication"
|
android:name=".complications.WallpaperDarkComplication"
|
||||||
android:icon="@drawable/ic_aaps_dark"
|
android:icon="@drawable/ic_aaps_dark"
|
||||||
android:label="Dark Walpaper"
|
android:label="Dark Wallpaper"
|
||||||
android:permission="com.google.android.wearable.permission.BIND_COMPLICATION_PROVIDER">
|
android:permission="com.google.android.wearable.permission.BIND_COMPLICATION_PROVIDER">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.support.wearable.complications.ACTION_COMPLICATION_UPDATE_REQUEST" />
|
<action android:name="android.support.wearable.complications.ACTION_COMPLICATION_UPDATE_REQUEST" />
|
||||||
|
@ -500,7 +519,7 @@
|
||||||
<service
|
<service
|
||||||
android:name=".complications.WallpaperGrayComplication"
|
android:name=".complications.WallpaperGrayComplication"
|
||||||
android:icon="@drawable/ic_aaps_gray"
|
android:icon="@drawable/ic_aaps_gray"
|
||||||
android:label="Gray Walpaper"
|
android:label="Gray Wallpaper"
|
||||||
android:permission="com.google.android.wearable.permission.BIND_COMPLICATION_PROVIDER">
|
android:permission="com.google.android.wearable.permission.BIND_COMPLICATION_PROVIDER">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.support.wearable.complications.ACTION_COMPLICATION_UPDATE_REQUEST" />
|
<action android:name="android.support.wearable.complications.ACTION_COMPLICATION_UPDATE_REQUEST" />
|
||||||
|
@ -623,7 +642,7 @@
|
||||||
|
|
||||||
<activity android:name=".interaction.ConfigurationActivity">
|
<activity android:name=".interaction.ConfigurationActivity">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<!-- action-name must be equal with name of xml-ressource where the configuration is describe -->
|
<!-- action-name must be equal with name of xml-resource where the configuration is describe -->
|
||||||
<action android:name="watch_face_configuration_bigchart" />
|
<action android:name="watch_face_configuration_bigchart" />
|
||||||
<action android:name="watch_face_configuration_circle" />
|
<action android:name="watch_face_configuration_circle" />
|
||||||
<action android:name="watch_face_configuration_cockpit" />
|
<action android:name="watch_face_configuration_cockpit" />
|
||||||
|
|
39
wear/src/main/assets/logback.xml
Normal file
39
wear/src/main/assets/logback.xml
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
<configuration>
|
||||||
|
<!-- Create a file appender for a log in the application's data directory -->
|
||||||
|
<property name="EXT_FILES_DIR" scope="context"
|
||||||
|
value="${EXT_DIR:-/sdcard}/AAPS/logs/${PACKAGE_NAME}" />
|
||||||
|
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<file>${EXT_FILES_DIR}/AndroidAPS.log</file>
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||||
|
<!-- daily rollover. Make sure the path matches the one in the file element or else
|
||||||
|
the rollover logs are placed in the working directory. -->
|
||||||
|
<fileNamePattern>${EXT_FILES_DIR}/AndroidAPS._%d{yyyy-MM-dd}_%d{HH-mm-ss, aux}_.%i.zip
|
||||||
|
</fileNamePattern>
|
||||||
|
|
||||||
|
<timeBasedFileNamingAndTriggeringPolicy
|
||||||
|
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
|
||||||
|
<maxFileSize>5MB</maxFileSize>
|
||||||
|
</timeBasedFileNamingAndTriggeringPolicy>
|
||||||
|
<!-- keep 30 days' worth of history -->
|
||||||
|
<maxHistory>120</maxHistory>
|
||||||
|
</rollingPolicy>
|
||||||
|
<encoder>
|
||||||
|
<pattern>%d{HH:mm:ss.SSS} [%thread] %.-1level/%logger: %msg%n</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<appender name="logcat" class="ch.qos.logback.classic.android.LogcatAppender">
|
||||||
|
<tagEncoder>
|
||||||
|
<pattern>%logger{0}</pattern>
|
||||||
|
</tagEncoder>
|
||||||
|
<encoder>
|
||||||
|
<pattern>[%thread]: %msg%n</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<!-- Write INFO (and higher-level) messages to the log file -->
|
||||||
|
<root level="DEBUG">
|
||||||
|
<appender-ref ref="file" />
|
||||||
|
<appender-ref ref="logcat" />
|
||||||
|
</root>
|
||||||
|
</configuration>
|
|
@ -8,11 +8,17 @@ import androidx.preference.PreferenceManager
|
||||||
import dagger.android.AndroidInjector
|
import dagger.android.AndroidInjector
|
||||||
import dagger.android.DaggerApplication
|
import dagger.android.DaggerApplication
|
||||||
import info.nightscout.androidaps.di.DaggerWearComponent
|
import info.nightscout.androidaps.di.DaggerWearComponent
|
||||||
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
|
import info.nightscout.shared.logging.LTag
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
class Aaps : DaggerApplication(), OnSharedPreferenceChangeListener {
|
class Aaps : DaggerApplication(), OnSharedPreferenceChangeListener {
|
||||||
|
|
||||||
|
@Inject lateinit var aapsLogger: AAPSLogger
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
|
aapsLogger.debug(LTag.WEAR, "onCreate")
|
||||||
PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this)
|
PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ import javax.inject.Inject;
|
||||||
|
|
||||||
import dagger.android.AndroidInjection;
|
import dagger.android.AndroidInjection;
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.data.ListenerService;
|
import info.nightscout.androidaps.data.DataLayerListenerService;
|
||||||
import info.nightscout.androidaps.data.RawDisplayData;
|
import info.nightscout.androidaps.data.RawDisplayData;
|
||||||
import info.nightscout.androidaps.interaction.utils.Constants;
|
import info.nightscout.androidaps.interaction.utils.Constants;
|
||||||
import info.nightscout.androidaps.interaction.utils.DisplayFormat;
|
import info.nightscout.androidaps.interaction.utils.DisplayFormat;
|
||||||
|
@ -205,7 +205,7 @@ public abstract class BaseComplicationProviderService extends ComplicationProvid
|
||||||
localBroadcastManager = LocalBroadcastManager.getInstance(this);
|
localBroadcastManager = LocalBroadcastManager.getInstance(this);
|
||||||
localBroadcastManager.registerReceiver(messageReceiver, messageFilter);
|
localBroadcastManager.registerReceiver(messageReceiver, messageFilter);
|
||||||
|
|
||||||
ListenerService.requestData(this);
|
DataLayerListenerService.Companion.requestData(this);
|
||||||
checkIfUpdateNeeded();
|
checkIfUpdateNeeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,552 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2021 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package info.nightscout.androidaps.data
|
||||||
|
|
||||||
|
import android.annotation.TargetApi
|
||||||
|
import android.app.Notification
|
||||||
|
import android.app.NotificationChannel
|
||||||
|
import android.app.NotificationManager
|
||||||
|
import android.app.PendingIntent
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.HandlerThread
|
||||||
|
import android.os.SystemClock
|
||||||
|
import android.util.Base64
|
||||||
|
import androidx.core.app.NotificationCompat
|
||||||
|
import androidx.core.app.NotificationManagerCompat
|
||||||
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
||||||
|
import androidx.wear.tiles.TileService
|
||||||
|
import com.google.android.gms.tasks.Tasks
|
||||||
|
import com.google.android.gms.wearable.*
|
||||||
|
import dagger.android.AndroidInjection
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.events.EventWearToMobileAction
|
||||||
|
import info.nightscout.androidaps.events.EventWearToMobileChange
|
||||||
|
import info.nightscout.androidaps.events.EventWearToMobileConfirm
|
||||||
|
import info.nightscout.androidaps.interaction.AAPSPreferences
|
||||||
|
import info.nightscout.androidaps.interaction.actions.AcceptActivity
|
||||||
|
import info.nightscout.androidaps.interaction.actions.CPPActivity
|
||||||
|
import info.nightscout.androidaps.interaction.utils.Persistence
|
||||||
|
import info.nightscout.androidaps.interaction.utils.WearUtil
|
||||||
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
|
import info.nightscout.androidaps.tile.ActionsTileService
|
||||||
|
import info.nightscout.androidaps.tile.QuickWizardTileService
|
||||||
|
import info.nightscout.androidaps.tile.TempTargetTileService
|
||||||
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
|
import info.nightscout.shared.SafeParse.stringToInt
|
||||||
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
|
import info.nightscout.shared.logging.LTag
|
||||||
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
|
import info.nightscout.shared.weardata.ActionData
|
||||||
|
import info.nightscout.shared.weardata.WearConstants
|
||||||
|
import info.nightscout.shared.weardata.WearConstants.Companion.KEY_ACTION_DATA
|
||||||
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
|
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||||
|
import kotlinx.coroutines.*
|
||||||
|
import kotlinx.coroutines.tasks.await
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class DataLayerListenerService : WearableListenerService() {
|
||||||
|
|
||||||
|
@Inject lateinit var aapsLogger: AAPSLogger
|
||||||
|
@Inject lateinit var wearUtil: WearUtil
|
||||||
|
@Inject lateinit var persistence: Persistence
|
||||||
|
@Inject lateinit var sp: SP
|
||||||
|
@Inject lateinit var rxBus: RxBus
|
||||||
|
@Inject lateinit var aapsSchedulers: AapsSchedulers
|
||||||
|
@Inject lateinit var wearConstants: WearConstants
|
||||||
|
|
||||||
|
private val dataClient by lazy { Wearable.getDataClient(this) }
|
||||||
|
private val messageClient by lazy { Wearable.getMessageClient(this) }
|
||||||
|
private val capabilityClient by lazy { Wearable.getCapabilityClient(this) }
|
||||||
|
//private val nodeClient by lazy { Wearable.getNodeClient(this) }
|
||||||
|
|
||||||
|
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
|
||||||
|
private var handler = Handler(HandlerThread(this::class.simpleName + "Handler").also { it.start() }.looper)
|
||||||
|
|
||||||
|
private val disposable = CompositeDisposable()
|
||||||
|
|
||||||
|
override fun onCreate() {
|
||||||
|
AndroidInjection.inject(this)
|
||||||
|
super.onCreate()
|
||||||
|
handler.post { updateTranscriptionCapability() }
|
||||||
|
disposable += rxBus
|
||||||
|
.toObservable(EventWearToMobileAction::class.java)
|
||||||
|
.observeOn(aapsSchedulers.io)
|
||||||
|
.subscribe { sendMessage(wearConstants.W_M_INITIATE_ACTION, it.actionData.serialize().toByteArray()) }
|
||||||
|
disposable += rxBus
|
||||||
|
.toObservable(EventWearToMobileConfirm::class.java)
|
||||||
|
.observeOn(aapsSchedulers.io)
|
||||||
|
.subscribe {
|
||||||
|
NotificationManagerCompat.from(this).cancel(CONFIRM_NOTIF_ID)
|
||||||
|
sendMessage(wearConstants.W_M_CONFIRM_ACTION, it.actionData.serialize().toByteArray())
|
||||||
|
}
|
||||||
|
disposable += rxBus
|
||||||
|
.toObservable(EventWearToMobileChange::class.java)
|
||||||
|
.observeOn(aapsSchedulers.io)
|
||||||
|
.subscribe {
|
||||||
|
NotificationManagerCompat.from(this).cancel(CHANGE_NOTIF_ID)
|
||||||
|
sendMessage(wearConstants.W_M_CONFIRM_ACTION, it.actionData.serialize().toByteArray())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPeerConnected(p0: Node) {
|
||||||
|
super.onPeerConnected(p0)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCapabilityChanged(p0: CapabilityInfo) {
|
||||||
|
super.onCapabilityChanged(p0)
|
||||||
|
handler.post { updateTranscriptionCapability() }
|
||||||
|
aapsLogger.debug(LTag.WEAR, "onCapabilityChanged: ${p0.name} ${p0.nodes.joinToString(", ") { it.displayName + "(" + it.id + ")" }}")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
scope.cancel()
|
||||||
|
disposable.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDataChanged(dataEvents: DataEventBuffer) {
|
||||||
|
//aapsLogger.debug(LTag.WEAR, "onDataChanged")
|
||||||
|
|
||||||
|
dataEvents.forEach { event ->
|
||||||
|
if (event.type == DataEvent.TYPE_CHANGED) {
|
||||||
|
val path = event.dataItem.uri.path
|
||||||
|
|
||||||
|
aapsLogger.debug(LTag.WEAR, "onDataChanged: Path: $path, EventDataItem=${event.dataItem}")
|
||||||
|
try {
|
||||||
|
when (path) {
|
||||||
|
wearConstants.M_W_BOLUS_PROGRESS -> {
|
||||||
|
val progress = DataMapItem.fromDataItem(event.dataItem).dataMap.getInt("progresspercent", 0)
|
||||||
|
val status = DataMapItem.fromDataItem(event.dataItem).dataMap.getString("progressstatus", "")
|
||||||
|
showBolusProgress(progress, status)
|
||||||
|
}
|
||||||
|
// remove when finished -> converted to message
|
||||||
|
wearConstants.M_W_ACTION_CONFIRMATION_REQUEST -> {
|
||||||
|
val title = DataMapItem.fromDataItem(event.dataItem).dataMap.getString("title") ?: return@forEach
|
||||||
|
val message = DataMapItem.fromDataItem(event.dataItem).dataMap.getString("message") ?: return@forEach
|
||||||
|
val actionstring = DataMapItem.fromDataItem(event.dataItem).dataMap.getString("actionstring") ?: return@forEach
|
||||||
|
if ("opencpp" == title && actionstring.startsWith("opencpp")) {
|
||||||
|
val act = actionstring.split("\\s+").toTypedArray()
|
||||||
|
startActivity(Intent(this@DataLayerListenerService, CPPActivity::class.java).also { intent ->
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
intent.putExtras(Bundle().also {
|
||||||
|
it.putInt("percentage", stringToInt(act[1]))
|
||||||
|
it.putInt("timeshift", stringToInt(act[2]))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
showConfirmationDialog(title, message, actionstring)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wearConstants.M_W_STATUS -> {
|
||||||
|
val dataMap = DataMapItem.fromDataItem(event.dataItem).dataMap
|
||||||
|
val messageIntent = Intent()
|
||||||
|
messageIntent.action = Intent.ACTION_SEND
|
||||||
|
messageIntent.putExtra("status", dataMap.toBundle())
|
||||||
|
persistence.storeDataMap(RawDisplayData.STATUS_PERSISTENCE_KEY, dataMap)
|
||||||
|
LocalBroadcastManager.getInstance(this@DataLayerListenerService).sendBroadcast(messageIntent)
|
||||||
|
}
|
||||||
|
|
||||||
|
wearConstants.M_W_BASAL -> {
|
||||||
|
val dataMap = DataMapItem.fromDataItem(event.dataItem).dataMap
|
||||||
|
val messageIntent = Intent()
|
||||||
|
messageIntent.action = Intent.ACTION_SEND
|
||||||
|
messageIntent.putExtra("basals", dataMap.toBundle())
|
||||||
|
persistence.storeDataMap(RawDisplayData.BASALS_PERSISTENCE_KEY, dataMap)
|
||||||
|
LocalBroadcastManager.getInstance(this@DataLayerListenerService).sendBroadcast(messageIntent)
|
||||||
|
}
|
||||||
|
|
||||||
|
wearConstants.M_W_PREFERENCES -> {
|
||||||
|
val dataMap = DataMapItem.fromDataItem(event.dataItem).dataMap
|
||||||
|
val keyControl = getString(R.string.key_wear_control)
|
||||||
|
if (dataMap.containsKey(keyControl)) {
|
||||||
|
val previousWearControl = sp.getBoolean(keyControl, false)
|
||||||
|
val wearControl: Boolean = dataMap.getBoolean(keyControl, false)
|
||||||
|
sp.putBoolean(keyControl, wearControl)
|
||||||
|
if (wearControl != previousWearControl) {
|
||||||
|
updateTiles()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val keyPercentage = getString(R.string.key_boluswizard_percentage)
|
||||||
|
if (dataMap.containsKey(keyPercentage)) {
|
||||||
|
val wpercentage: Int = dataMap.getInt(keyPercentage, 100)
|
||||||
|
sp.putInt(keyPercentage, wpercentage)
|
||||||
|
}
|
||||||
|
val keyUnits = getString(R.string.key_units_mgdl)
|
||||||
|
if (dataMap.containsKey(keyUnits)) {
|
||||||
|
val mgdl: Boolean = dataMap.getBoolean(keyUnits, true)
|
||||||
|
sp.putBoolean(keyUnits, mgdl)
|
||||||
|
}
|
||||||
|
val keyMaxCarbs = getString(R.string.key_treatmentssafety_maxcarbs)
|
||||||
|
if (dataMap.containsKey(keyMaxCarbs)) {
|
||||||
|
val maxCarbs: Int = dataMap.getInt(keyMaxCarbs, 48)
|
||||||
|
sp.putInt(keyMaxCarbs, maxCarbs)
|
||||||
|
}
|
||||||
|
val keyMaxBolus = getString(R.string.key_treatmentssafety_maxbolus)
|
||||||
|
if (dataMap.containsKey(keyMaxBolus)) {
|
||||||
|
sp.putDouble(keyMaxBolus, dataMap.getDouble(keyMaxBolus, 3.0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wearConstants.M_W_QUICK_WIZARD -> {
|
||||||
|
val dataMap = DataMapItem.fromDataItem(event.dataItem).dataMap
|
||||||
|
aapsLogger.info(LTag.WEAR, "onDataChanged: QUICK_WIZARD_PATH$dataMap")
|
||||||
|
dataMap.remove("timestamp")
|
||||||
|
val key = getString(R.string.key_quick_wizard_data_map)
|
||||||
|
val dataString = Base64.encodeToString(dataMap.toByteArray(), Base64.DEFAULT)
|
||||||
|
if (dataString != sp.getString(key, "")) {
|
||||||
|
sp.putString(key, dataString)
|
||||||
|
// Todo maybe add debounce function, due to 20 seconds update limit?
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
TileService.getUpdater(this@DataLayerListenerService).requestUpdate(QuickWizardTileService::class.java)
|
||||||
|
}
|
||||||
|
aapsLogger.info(LTag.WEAR, "onDataChanged: updated QUICK_WIZARD")
|
||||||
|
} else {
|
||||||
|
aapsLogger.info(LTag.WEAR, "onDataChanged: ignore update")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wearConstants.M_W_ACTION_CHANGE_CONFIRMATION_REQUEST -> {
|
||||||
|
val title = DataMapItem.fromDataItem(event.dataItem).dataMap.getString("title") ?: return@forEach
|
||||||
|
val message = DataMapItem.fromDataItem(event.dataItem).dataMap.getString("message") ?: return@forEach
|
||||||
|
val actionstring = DataMapItem.fromDataItem(event.dataItem).dataMap.getString("actionstring") ?: return@forEach
|
||||||
|
notifyChangeRequest(title, message, actionstring)
|
||||||
|
}
|
||||||
|
|
||||||
|
wearConstants.M_W_ACTION_CANCEL_NOTIFICATION_REQUEST -> {
|
||||||
|
//val actionstring = DataMapItem.fromDataItem(event.getDataItem()).dataMap.getString("actionstring") ?: return@forEach
|
||||||
|
cancelNotificationRequest()
|
||||||
|
}
|
||||||
|
|
||||||
|
wearConstants.M_W_DATA -> {
|
||||||
|
val dataMap = DataMapItem.fromDataItem(event.dataItem).dataMap
|
||||||
|
val messageIntent = Intent()
|
||||||
|
messageIntent.action = Intent.ACTION_SEND
|
||||||
|
messageIntent.putExtra("data", dataMap.toBundle())
|
||||||
|
persistence.storeDataMap(RawDisplayData.DATA_PERSISTENCE_KEY, dataMap)
|
||||||
|
LocalBroadcastManager.getInstance(this@DataLayerListenerService).sendBroadcast(messageIntent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (exception: Exception) {
|
||||||
|
aapsLogger.error(LTag.WEAR, "onDataChanged failed", exception)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.onDataChanged(dataEvents)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMessageReceived(messageEvent: MessageEvent) {
|
||||||
|
super.onMessageReceived(messageEvent)
|
||||||
|
aapsLogger.debug(LTag.WEAR, "onMessageReceived: $messageEvent")
|
||||||
|
|
||||||
|
when (messageEvent.path) {
|
||||||
|
wearConstants.M_W_PING -> sendMessage(wearConstants.W_M_PONG, byteArrayOf())
|
||||||
|
wearConstants.M_W_OPEN_SETTINGS -> startActivity(Intent(this@DataLayerListenerService, AAPSPreferences::class.java).also { it.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) })
|
||||||
|
|
||||||
|
wearConstants.M_W_ACTION_CONFIRMATION_REQUEST -> {
|
||||||
|
val command = ActionData.deserialize(String(messageEvent.data)) as ActionData.ConfirmAction
|
||||||
|
if (command.originalCommand is ActionData.OpenProfileSwitch) {
|
||||||
|
val originalCommand = command.originalCommand as ActionData.OpenProfileSwitch
|
||||||
|
startActivity(Intent(this, CPPActivity::class.java).also { intent ->
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
intent.putExtras(Bundle().also {
|
||||||
|
it.putInt("percentage", originalCommand.percentage)
|
||||||
|
it.putInt("timeshift", originalCommand.timeShift)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
startActivity(
|
||||||
|
Intent(this, AcceptActivity::class.java).also { intent ->
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
intent.putExtras(
|
||||||
|
Bundle().also { bundle ->
|
||||||
|
bundle.putString("title", command.title)
|
||||||
|
bundle.putString("message", command.message)
|
||||||
|
bundle.putString(KEY_ACTION_DATA, command.originalCommand.serialize())
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
|
when (intent?.action) {
|
||||||
|
ACTION_RESEND -> sendMessage(wearConstants.W_M_RESEND_DATA, byteArrayOf())
|
||||||
|
|
||||||
|
ACTION_CANCEL_BOLUS -> {
|
||||||
|
//dismiss notification
|
||||||
|
val notificationManager = NotificationManagerCompat.from(this)
|
||||||
|
notificationManager.cancel(BOLUS_PROGRESS_NOTIF_ID)
|
||||||
|
//send cancel-request to phone.
|
||||||
|
sendMessage(wearConstants.W_M_CANCEL_BOLUS, byteArrayOf())
|
||||||
|
}
|
||||||
|
|
||||||
|
ACTION_CONFIRMATION -> {
|
||||||
|
//dismiss notification
|
||||||
|
val notificationManager = NotificationManagerCompat.from(this)
|
||||||
|
notificationManager.cancel(CONFIRM_NOTIF_ID)
|
||||||
|
intent.getStringExtra("actionstring")?.let { actionString ->
|
||||||
|
sendMessage(wearConstants.W_M_CONFIRM_ACTION, actionString.toByteArray())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ACTION_CONFIRM_CHANGE -> {
|
||||||
|
//dismiss notification
|
||||||
|
val notificationManager = NotificationManagerCompat.from(this)
|
||||||
|
notificationManager.cancel(CHANGE_NOTIF_ID)
|
||||||
|
intent.getStringExtra("actionstring")?.let { actionString ->
|
||||||
|
sendMessage(wearConstants.W_M_CONFIRM_ACTION, actionString.toByteArray())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ACTION_INITIATE_ACTION ->
|
||||||
|
if (intent.hasExtra("actionstring"))
|
||||||
|
intent.getStringExtra("actionstring")?.let { actionString ->
|
||||||
|
sendMessage(wearConstants.W_M_INITIATE_ACTION, actionString.toByteArray())
|
||||||
|
}
|
||||||
|
else if (intent.hasExtra(KEY_ACTION_DATA))
|
||||||
|
intent.getStringExtra(KEY_ACTION_DATA)?.let { actionData ->
|
||||||
|
sendMessage(wearConstants.W_M_INITIATE_ACTION, actionData.toByteArray())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return START_STICKY
|
||||||
|
}
|
||||||
|
|
||||||
|
private var transcriptionNodeId: String? = null
|
||||||
|
|
||||||
|
private fun updateTranscriptionCapability() {
|
||||||
|
val capabilityInfo: CapabilityInfo = Tasks.await(
|
||||||
|
capabilityClient.getCapability(PHONE_CAPABILITY, CapabilityClient.FILTER_REACHABLE)
|
||||||
|
)
|
||||||
|
aapsLogger.debug(LTag.WEAR, "Nodes: ${capabilityInfo.nodes.joinToString(", ") { it.displayName + "(" + it.id + ")" }}")
|
||||||
|
transcriptionNodeId = pickBestNodeId(capabilityInfo.nodes)
|
||||||
|
aapsLogger.debug(LTag.WEAR, "Selected node: $transcriptionNodeId")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find a nearby node or pick one arbitrarily
|
||||||
|
private fun pickBestNodeId(nodes: Set<Node>): String? =
|
||||||
|
nodes.firstOrNull { it.isNearby }?.id ?: nodes.firstOrNull()?.id
|
||||||
|
|
||||||
|
private fun sendData(path: String, vararg params: DataMap) {
|
||||||
|
scope.launch {
|
||||||
|
try {
|
||||||
|
for (dm in params) {
|
||||||
|
val request = PutDataMapRequest.create(path).apply {
|
||||||
|
dataMap.putAll(dm)
|
||||||
|
}
|
||||||
|
.asPutDataRequest()
|
||||||
|
.setUrgent()
|
||||||
|
|
||||||
|
val result = dataClient.putDataItem(request).await()
|
||||||
|
aapsLogger.debug(LTag.WEAR, "sendData: ${result.uri} ${params.joinToString()}")
|
||||||
|
}
|
||||||
|
} catch (cancellationException: CancellationException) {
|
||||||
|
throw cancellationException
|
||||||
|
} catch (exception: Exception) {
|
||||||
|
aapsLogger.error(LTag.WEAR, "DataItem failed: $exception")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sendMessage(path: String, data: ByteArray) {
|
||||||
|
aapsLogger.debug(LTag.WEAR, "sendMessage: $path")
|
||||||
|
transcriptionNodeId?.also { nodeId ->
|
||||||
|
messageClient
|
||||||
|
.sendMessage(nodeId, path, data).apply {
|
||||||
|
addOnSuccessListener { }
|
||||||
|
addOnFailureListener {
|
||||||
|
aapsLogger.debug(LTag.WEAR, "sendMessage: $path failure")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateTiles() {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
TileService.getUpdater(this)
|
||||||
|
.requestUpdate(ActionsTileService::class.java)
|
||||||
|
TileService.getUpdater(this)
|
||||||
|
.requestUpdate(TempTargetTileService::class.java)
|
||||||
|
TileService.getUpdater(this)
|
||||||
|
.requestUpdate(QuickWizardTileService::class.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun notifyChangeRequest(title: String, message: String, actionstring: String) {
|
||||||
|
// Create the NotificationChannel, but only on API 26+ because
|
||||||
|
// the NotificationChannel class is new and not in the support library
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
val name: CharSequence = "AAPS Open Loop"
|
||||||
|
val description = "Open Loop request notification"
|
||||||
|
val channel = NotificationChannel(AAPS_NOTIFY_CHANNEL_ID_OPENLOOP, name, NotificationManager.IMPORTANCE_HIGH)
|
||||||
|
channel.description = description
|
||||||
|
channel.enableVibration(true)
|
||||||
|
|
||||||
|
// Register the channel with the system; you can't change the importance
|
||||||
|
// or other notification behaviors after this
|
||||||
|
val notificationManager = getSystemService(NotificationManager::class.java)
|
||||||
|
notificationManager.createNotificationChannel(channel)
|
||||||
|
}
|
||||||
|
var builder = NotificationCompat.Builder(this, AAPS_NOTIFY_CHANNEL_ID_OPENLOOP)
|
||||||
|
builder = builder.setSmallIcon(R.drawable.notif_icon)
|
||||||
|
.setContentTitle(title)
|
||||||
|
.setContentText(message)
|
||||||
|
.setPriority(Notification.PRIORITY_HIGH)
|
||||||
|
.setVibrate(longArrayOf(1000, 1000, 1000, 1000, 1000))
|
||||||
|
|
||||||
|
// Creates an explicit intent for an Activity in your app
|
||||||
|
val intent = Intent(this, AcceptActivity::class.java)
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
val params = Bundle()
|
||||||
|
params.putString("title", title)
|
||||||
|
params.putString("message", message)
|
||||||
|
params.putString("actionstring", actionstring)
|
||||||
|
intent.putExtras(params)
|
||||||
|
val resultPendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT)
|
||||||
|
builder = builder.setContentIntent(resultPendingIntent)
|
||||||
|
val mNotificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
|
||||||
|
// mId allows you to update the notification later on.
|
||||||
|
mNotificationManager.notify(CHANGE_NOTIF_ID, builder.build())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun cancelNotificationRequest() {
|
||||||
|
(getSystemService(NOTIFICATION_SERVICE) as NotificationManager).cancel(CHANGE_NOTIF_ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showBolusProgress(progressPercent: Int, progresStatus: String) {
|
||||||
|
val vibratePattern: LongArray
|
||||||
|
val vibrate = sp.getBoolean("vibrateOnBolus", true)
|
||||||
|
vibratePattern = if (vibrate) longArrayOf(0, 50, 1000) else longArrayOf(0, 1, 1000)
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
createBolusProgressChannels()
|
||||||
|
}
|
||||||
|
val cancelIntent = Intent(this, DataLayerListenerService::class.java)
|
||||||
|
cancelIntent.action = ACTION_CANCEL_BOLUS
|
||||||
|
val cancelPendingIntent = PendingIntent.getService(this, 0, cancelIntent, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT)
|
||||||
|
val notificationBuilder: NotificationCompat.Builder =
|
||||||
|
NotificationCompat.Builder(this, if (vibrate) AAPS_NOTIFY_CHANNEL_ID_BOLUSPROGRESS else AAPS_NOTIFY_CHANNEL_ID_BOLUSPROGRESS_SILENT)
|
||||||
|
.setSmallIcon(R.drawable.ic_icon)
|
||||||
|
.setContentTitle(getString(R.string.bolus_progress))
|
||||||
|
.setContentText("$progressPercent% - $progresStatus")
|
||||||
|
.setSubText(getString(R.string.press_to_cancel))
|
||||||
|
.setContentIntent(cancelPendingIntent)
|
||||||
|
.setPriority(NotificationCompat.PRIORITY_MAX)
|
||||||
|
.setVibrate(vibratePattern)
|
||||||
|
.addAction(R.drawable.ic_cancel, getString(R.string.cancel_bolus), cancelPendingIntent)
|
||||||
|
val notificationManager = NotificationManagerCompat.from(this)
|
||||||
|
notificationManager.notify(BOLUS_PROGRESS_NOTIF_ID, notificationBuilder.build())
|
||||||
|
notificationManager.cancel(CONFIRM_NOTIF_ID) // multiple watch setup
|
||||||
|
if (progressPercent == 100) {
|
||||||
|
scheduleDismissBolusProgress(5)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@TargetApi(value = 26) private fun createBolusProgressChannels() {
|
||||||
|
createNotificationChannel(
|
||||||
|
longArrayOf(0, 50, 1000),
|
||||||
|
AAPS_NOTIFY_CHANNEL_ID_BOLUSPROGRESS,
|
||||||
|
getString(R.string.bolus_progress_channel_name),
|
||||||
|
getString(R.string.bolus_progress_channel_description)
|
||||||
|
)
|
||||||
|
createNotificationChannel(
|
||||||
|
longArrayOf(0, 1, 1000),
|
||||||
|
AAPS_NOTIFY_CHANNEL_ID_BOLUSPROGRESS_SILENT,
|
||||||
|
getString(R.string.bolus_progress_silent_channel_name),
|
||||||
|
getString(R.string.bolus_progress_silent_channel_description)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@TargetApi(value = 26) private fun createNotificationChannel(vibratePattern: LongArray, channelID: String, name: CharSequence, description: String) {
|
||||||
|
val channel = NotificationChannel(channelID, name, NotificationManager.IMPORTANCE_HIGH)
|
||||||
|
channel.description = description
|
||||||
|
channel.enableVibration(true)
|
||||||
|
channel.vibrationPattern = vibratePattern
|
||||||
|
|
||||||
|
// Register the channel with the system; you can't change the importance
|
||||||
|
// or other notification behaviors after this
|
||||||
|
val notificationManager = getSystemService(NotificationManager::class.java)
|
||||||
|
notificationManager.createNotificationChannel(channel)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showConfirmationDialog(title: String, message: String, actionstring: String) {
|
||||||
|
val intent = Intent(this, AcceptActivity::class.java)
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
val params = Bundle()
|
||||||
|
params.putString("title", title)
|
||||||
|
params.putString("message", message)
|
||||||
|
params.putString("actionstring", actionstring)
|
||||||
|
intent.putExtras(params)
|
||||||
|
startActivity(intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("SameParameterValue")
|
||||||
|
private fun scheduleDismissBolusProgress(seconds: Int) {
|
||||||
|
Thread {
|
||||||
|
SystemClock.sleep(seconds * 1000L)
|
||||||
|
NotificationManagerCompat.from(this@DataLayerListenerService)
|
||||||
|
.cancel(BOLUS_PROGRESS_NOTIF_ID)
|
||||||
|
}.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
const val PHONE_CAPABILITY = "androidaps_mobile"
|
||||||
|
|
||||||
|
const val ACTION_RESEND = "com.dexdrip.stephenblack.nightwatch.RESEND_DATA"
|
||||||
|
const val ACTION_CANCEL_BOLUS = "com.dexdrip.stephenblack.nightwatch.CANCELBOLUS"
|
||||||
|
const val ACTION_CONFIRMATION = "com.dexdrip.stephenblack.nightwatch.CONFIRMACTION"
|
||||||
|
const val ACTION_CONFIRM_CHANGE = "com.dexdrip.stephenblack.nightwatch.CONFIRMCHANGE"
|
||||||
|
val ACTION_INITIATE_ACTION = DataLayerListenerService::class.java.name + ".INITIATE_ACTION"
|
||||||
|
|
||||||
|
const val BOLUS_PROGRESS_NOTIF_ID = 1
|
||||||
|
const val CONFIRM_NOTIF_ID = 2
|
||||||
|
const val CHANGE_NOTIF_ID = 556677
|
||||||
|
|
||||||
|
const val AAPS_NOTIFY_CHANNEL_ID_OPENLOOP = "AndroidAPS-OpenLoop"
|
||||||
|
const val AAPS_NOTIFY_CHANNEL_ID_BOLUSPROGRESS = "bolus progress vibration"
|
||||||
|
const val AAPS_NOTIFY_CHANNEL_ID_BOLUSPROGRESS_SILENT = "bolus progress silent"
|
||||||
|
|
||||||
|
fun initiateAction(context: Context, actionstring: String) {
|
||||||
|
context.startService(
|
||||||
|
Intent(context, DataLayerListenerService::class.java).also {
|
||||||
|
it.putExtra("actionstring", actionstring)
|
||||||
|
it.action = ACTION_INITIATE_ACTION
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fun requestData(context: Context) {
|
||||||
|
context.startService(
|
||||||
|
Intent(context, DataLayerListenerService::class.java).also { it.action = ACTION_RESEND })
|
||||||
|
}
|
||||||
|
|
||||||
|
fun confirmAction(context: Context, actionstring: String) {
|
||||||
|
context.startService(
|
||||||
|
Intent(context, DataLayerListenerService::class.java).also {
|
||||||
|
it.putExtra("actionstring", actionstring)
|
||||||
|
if (actionstring == "changeRequest") it.action = ACTION_CONFIRM_CHANGE
|
||||||
|
else it.action = ACTION_CONFIRMATION
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,628 +0,0 @@
|
||||||
package info.nightscout.androidaps.data;
|
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
|
||||||
import android.app.Notification;
|
|
||||||
import android.app.NotificationChannel;
|
|
||||||
import android.app.NotificationManager;
|
|
||||||
import android.app.PendingIntent;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.SystemClock;
|
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
import android.util.Base64;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import androidx.core.app.NotificationCompat;
|
|
||||||
import androidx.core.app.NotificationManagerCompat;
|
|
||||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
|
||||||
import androidx.wear.tiles.TileService;
|
|
||||||
|
|
||||||
import com.google.android.gms.common.ConnectionResult;
|
|
||||||
import com.google.android.gms.common.api.GoogleApiClient;
|
|
||||||
import com.google.android.gms.wearable.ChannelApi;
|
|
||||||
import com.google.android.gms.wearable.DataEvent;
|
|
||||||
import com.google.android.gms.wearable.DataEventBuffer;
|
|
||||||
import com.google.android.gms.wearable.DataMap;
|
|
||||||
import com.google.android.gms.wearable.DataMapItem;
|
|
||||||
import com.google.android.gms.wearable.Node;
|
|
||||||
import com.google.android.gms.wearable.NodeApi;
|
|
||||||
import com.google.android.gms.wearable.Wearable;
|
|
||||||
import com.google.android.gms.wearable.WearableListenerService;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
import dagger.android.AndroidInjection;
|
|
||||||
import info.nightscout.androidaps.R;
|
|
||||||
import info.nightscout.androidaps.interaction.AAPSPreferences;
|
|
||||||
import info.nightscout.androidaps.interaction.actions.AcceptActivity;
|
|
||||||
import info.nightscout.androidaps.interaction.actions.CPPActivity;
|
|
||||||
import info.nightscout.androidaps.interaction.utils.Persistence;
|
|
||||||
import info.nightscout.androidaps.interaction.utils.WearUtil;
|
|
||||||
import info.nightscout.androidaps.tile.ActionsTileService;
|
|
||||||
import info.nightscout.androidaps.tile.QuickWizardTileService;
|
|
||||||
import info.nightscout.androidaps.tile.TempTargetTileService;
|
|
||||||
import info.nightscout.shared.SafeParse;
|
|
||||||
import info.nightscout.shared.weardata.WearUris;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by emmablack on 12/26/14.
|
|
||||||
*/
|
|
||||||
public class ListenerService extends WearableListenerService implements GoogleApiClient.ConnectionCallbacks,
|
|
||||||
GoogleApiClient.OnConnectionFailedListener, ChannelApi.ChannelListener {
|
|
||||||
|
|
||||||
@Inject WearUtil wearUtil;
|
|
||||||
@Inject Persistence persistence;
|
|
||||||
|
|
||||||
public static final int BOLUS_PROGRESS_NOTIF_ID = 1;
|
|
||||||
public static final int CONFIRM_NOTIF_ID = 2;
|
|
||||||
public static final int CHANGE_NOTIF_ID = 556677;
|
|
||||||
|
|
||||||
private static final String ACTION_RESEND = "com.dexdrip.stephenblack.nightwatch.RESEND_DATA";
|
|
||||||
private static final String ACTION_CANCELBOLUS = "com.dexdrip.stephenblack.nightwatch.CANCELBOLUS";
|
|
||||||
private static final String ACTION_CONFIRMATION = "com.dexdrip.stephenblack.nightwatch.CONFIRMACTION";
|
|
||||||
private static final String ACTION_CONFIRMCHANGE = "com.dexdrip.stephenblack.nightwatch.CONFIRMCHANGE";
|
|
||||||
private static final String ACTION_INITIATE_ACTION = "com.dexdrip.stephenblack.nightwatch.INITIATE_ACTION";
|
|
||||||
|
|
||||||
private static final String AAPS_NOTIFY_CHANNEL_ID_OPENLOOP = "AndroidAPS-OpenLoop";
|
|
||||||
private static final String AAPS_NOTIFY_CHANNEL_ID_BOLUSPROGRESS = "bolus progress vibration";
|
|
||||||
private static final String AAPS_NOTIFY_CHANNEL_ID_BOLUSPROGRESS_SILENT = "bolus progress silent";
|
|
||||||
|
|
||||||
GoogleApiClient googleApiClient;
|
|
||||||
|
|
||||||
private DismissThread bolusprogressThread;
|
|
||||||
private static final String TAG = "ListenerService";
|
|
||||||
|
|
||||||
private final String logPrefix = ""; // "WR: "
|
|
||||||
|
|
||||||
// Not derived from DaggerService, do injection here
|
|
||||||
@Override
|
|
||||||
public void onCreate() {
|
|
||||||
AndroidInjection.inject(this);
|
|
||||||
super.onCreate();
|
|
||||||
}
|
|
||||||
|
|
||||||
public class BolusCancelTask extends AsyncTask<Void, Void, Void> {
|
|
||||||
Context mContext;
|
|
||||||
|
|
||||||
BolusCancelTask(Context context) {
|
|
||||||
mContext = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Void doInBackground(Void... params) {
|
|
||||||
Log.d(TAG, logPrefix + "BolusCancelTask.doInBackground: " + params);
|
|
||||||
if (!googleApiClient.isConnected()) {
|
|
||||||
Log.i(TAG, "BolusCancelTask.doInBackground: not connected");
|
|
||||||
googleApiClient.blockingConnect(15, TimeUnit.SECONDS);
|
|
||||||
}
|
|
||||||
if (googleApiClient.isConnected()) {
|
|
||||||
NodeApi.GetConnectedNodesResult nodes =
|
|
||||||
Wearable.NodeApi.getConnectedNodes(googleApiClient).await();
|
|
||||||
for (Node node : nodes.getNodes()) {
|
|
||||||
Wearable.MessageApi.sendMessage(googleApiClient, node.getId(),
|
|
||||||
WearUris.WEARABLE_CANCELBOLUS_PATH, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class MessageActionTask extends AsyncTask<Void, Void, Void> {
|
|
||||||
Context mContext;
|
|
||||||
String mActionstring;
|
|
||||||
String mMessagePath;
|
|
||||||
|
|
||||||
MessageActionTask(Context context, String messagePath, String actionstring) {
|
|
||||||
mContext = context;
|
|
||||||
mActionstring = actionstring;
|
|
||||||
mMessagePath = messagePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Void doInBackground(Void... params) {
|
|
||||||
Log.i(TAG, "MessageActionTask.doInBackground: ");
|
|
||||||
|
|
||||||
if (!googleApiClient.isConnected()) {
|
|
||||||
Log.i(TAG, "MessageActionTask.doInBackground: not connected");
|
|
||||||
googleApiClient.blockingConnect(15, TimeUnit.SECONDS);
|
|
||||||
}
|
|
||||||
if (googleApiClient.isConnected()) {
|
|
||||||
NodeApi.GetConnectedNodesResult nodes =
|
|
||||||
Wearable.NodeApi.getConnectedNodes(googleApiClient).await();
|
|
||||||
for (Node node : nodes.getNodes()) {
|
|
||||||
Wearable.MessageApi.sendMessage(googleApiClient, node.getId(), mMessagePath, mActionstring.getBytes());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ResendDataTask extends AsyncTask<Void, Void, Void> {
|
|
||||||
Context mContext;
|
|
||||||
|
|
||||||
ResendDataTask(Context context) {
|
|
||||||
mContext = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Void doInBackground(Void... params) {
|
|
||||||
Log.d(TAG, logPrefix + "ResendDataTask.doInBackground: " + params);
|
|
||||||
|
|
||||||
if (!googleApiClient.isConnected()) {
|
|
||||||
Log.i(TAG, "ResendDataTask.doInBackground: not connected");
|
|
||||||
googleApiClient.blockingConnect(15, TimeUnit.SECONDS);
|
|
||||||
}
|
|
||||||
if (googleApiClient.isConnected()) {
|
|
||||||
Log.i(TAG, "ResendDataTask.doInBackground: connected");
|
|
||||||
NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes(googleApiClient).await();
|
|
||||||
for (Node node : nodes.getNodes()) {
|
|
||||||
Wearable.MessageApi.sendMessage(googleApiClient, node.getId(), WearUris.WEARABLE_RESEND_PATH, null);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Log.i(TAG, "ResendDataTask.doInBackground: could not connect");
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void requestData() {
|
|
||||||
new ResendDataTask(this).execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void cancelBolus() {
|
|
||||||
new BolusCancelTask(this).execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendConfirmActionstring(String actionstring) {
|
|
||||||
new MessageActionTask(this, WearUris.WEARABLE_CONFIRM_ACTIONSTRING_PATH, actionstring).execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendInitiateActionstring(String actionstring) {
|
|
||||||
new MessageActionTask(this, WearUris.WEARABLE_INITIATE_ACTIONSTRING_PATH, actionstring).execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void googleApiConnect() {
|
|
||||||
if (googleApiClient != null) {
|
|
||||||
// Remove old listener(s)
|
|
||||||
try {
|
|
||||||
Wearable.ChannelApi.removeListener(googleApiClient, this);
|
|
||||||
} catch (Exception e) {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
Wearable.MessageApi.removeListener(googleApiClient, this);
|
|
||||||
} catch (Exception e) {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
googleApiClient = new GoogleApiClient.Builder(this)
|
|
||||||
.addConnectionCallbacks(this)
|
|
||||||
.addOnConnectionFailedListener(this)
|
|
||||||
.addApi(Wearable.API)
|
|
||||||
.build();
|
|
||||||
Wearable.MessageApi.addListener(googleApiClient, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
|
||||||
|
|
||||||
// Log.d(TAG, logPrefix + "onStartCommand: Intent: " + intent);
|
|
||||||
|
|
||||||
if (intent != null && ACTION_RESEND.equals(intent.getAction())) {
|
|
||||||
googleApiConnect();
|
|
||||||
requestData();
|
|
||||||
} else if (intent != null && ACTION_CANCELBOLUS.equals(intent.getAction())) {
|
|
||||||
googleApiConnect();
|
|
||||||
|
|
||||||
//dismiss notification
|
|
||||||
NotificationManagerCompat notificationManager =
|
|
||||||
NotificationManagerCompat.from(ListenerService.this);
|
|
||||||
notificationManager.cancel(BOLUS_PROGRESS_NOTIF_ID);
|
|
||||||
|
|
||||||
//send cancel-request to phone.
|
|
||||||
cancelBolus();
|
|
||||||
|
|
||||||
|
|
||||||
} else if (intent != null && ACTION_CONFIRMATION.equals(intent.getAction())) {
|
|
||||||
googleApiConnect();
|
|
||||||
|
|
||||||
//dismiss notification
|
|
||||||
NotificationManagerCompat notificationManager =
|
|
||||||
NotificationManagerCompat.from(ListenerService.this);
|
|
||||||
notificationManager.cancel(CONFIRM_NOTIF_ID);
|
|
||||||
|
|
||||||
String actionstring = intent.getStringExtra("actionstring");
|
|
||||||
sendConfirmActionstring(actionstring);
|
|
||||||
|
|
||||||
} else if (intent != null && ACTION_CONFIRMCHANGE.equals(intent.getAction())) {
|
|
||||||
googleApiConnect();
|
|
||||||
|
|
||||||
//dismiss notification
|
|
||||||
NotificationManagerCompat notificationManager =
|
|
||||||
NotificationManagerCompat.from(ListenerService.this);
|
|
||||||
notificationManager.cancel(CHANGE_NOTIF_ID);
|
|
||||||
|
|
||||||
String actionstring = intent.getStringExtra("actionstring");
|
|
||||||
sendConfirmActionstring(actionstring);
|
|
||||||
|
|
||||||
} else if (intent != null && ACTION_INITIATE_ACTION.equals(intent.getAction())) {
|
|
||||||
googleApiConnect();
|
|
||||||
|
|
||||||
String actionstring = intent.getStringExtra("actionstring");
|
|
||||||
sendInitiateActionstring(actionstring);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return START_STICKY;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDataChanged(DataEventBuffer dataEvents) {
|
|
||||||
|
|
||||||
DataMap dataMap;
|
|
||||||
// Log.d(TAG, logPrefix + "onDataChanged: DataEvents=" + dataEvents);
|
|
||||||
|
|
||||||
for (DataEvent event : dataEvents) {
|
|
||||||
|
|
||||||
if (event.getType() == DataEvent.TYPE_CHANGED) {
|
|
||||||
|
|
||||||
String path = event.getDataItem().getUri().getPath();
|
|
||||||
|
|
||||||
//Log.d(TAG, "WR: onDataChanged: Path: " + path + ", EventDataItem=" + event.getDataItem());
|
|
||||||
|
|
||||||
if (path.equals(WearUris.OPEN_SETTINGS_PATH)) {
|
|
||||||
Intent intent = new Intent(this, AAPSPreferences.class);
|
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
||||||
startActivity(intent);
|
|
||||||
} else if (path.equals(WearUris.BOLUS_PROGRESS_PATH)) {
|
|
||||||
int progress = DataMapItem.fromDataItem(event.getDataItem()).getDataMap().getInt("progresspercent", 0);
|
|
||||||
String status = DataMapItem.fromDataItem(event.getDataItem()).getDataMap().getString("progressstatus", "");
|
|
||||||
showBolusProgress(progress, status);
|
|
||||||
} else if (path.equals(WearUris.ACTION_CONFIRMATION_REQUEST_PATH)) {
|
|
||||||
String title = DataMapItem.fromDataItem(event.getDataItem()).getDataMap().getString("title");
|
|
||||||
String message = DataMapItem.fromDataItem(event.getDataItem()).getDataMap().getString("message");
|
|
||||||
String actionstring = DataMapItem.fromDataItem(event.getDataItem()).getDataMap().getString("actionstring");
|
|
||||||
|
|
||||||
if ("opencpp".equals(title) && actionstring.startsWith("opencpp")) {
|
|
||||||
String[] act = actionstring.split("\\s+");
|
|
||||||
Intent intent = new Intent(this, CPPActivity.class);
|
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
||||||
//TODO adrian: parse actionstring and add parameters
|
|
||||||
Bundle params = new Bundle();
|
|
||||||
params.putInt("percentage", SafeParse.stringToInt(act[1]));
|
|
||||||
params.putInt("timeshift", SafeParse.stringToInt(act[2]));
|
|
||||||
intent.putExtras(params);
|
|
||||||
startActivity(intent);
|
|
||||||
} else {
|
|
||||||
showConfirmationDialog(title, message, actionstring);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (path.equals(WearUris.NEW_STATUS_PATH)) {
|
|
||||||
dataMap = DataMapItem.fromDataItem(event.getDataItem()).getDataMap();
|
|
||||||
Intent messageIntent = new Intent();
|
|
||||||
messageIntent.setAction(Intent.ACTION_SEND);
|
|
||||||
messageIntent.putExtra("status", dataMap.toBundle());
|
|
||||||
persistence.storeDataMap(RawDisplayData.STATUS_PERSISTENCE_KEY, dataMap);
|
|
||||||
LocalBroadcastManager.getInstance(this).sendBroadcast(messageIntent);
|
|
||||||
} else if (path.equals(WearUris.BASAL_DATA_PATH)) {
|
|
||||||
dataMap = DataMapItem.fromDataItem(event.getDataItem()).getDataMap();
|
|
||||||
Intent messageIntent = new Intent();
|
|
||||||
messageIntent.setAction(Intent.ACTION_SEND);
|
|
||||||
messageIntent.putExtra("basals", dataMap.toBundle());
|
|
||||||
persistence.storeDataMap(RawDisplayData.BASALS_PERSISTENCE_KEY, dataMap);
|
|
||||||
LocalBroadcastManager.getInstance(this).sendBroadcast(messageIntent);
|
|
||||||
} else if (path.equals(WearUris.NEW_PREFERENCES_PATH)) {
|
|
||||||
dataMap = DataMapItem.fromDataItem(event.getDataItem()).getDataMap();
|
|
||||||
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
|
|
||||||
SharedPreferences.Editor editor = sharedPreferences.edit();
|
|
||||||
String keyControl = getString(R.string.key_wear_control);
|
|
||||||
if (dataMap.containsKey(keyControl)) {
|
|
||||||
boolean previousWearControl = sharedPreferences.getBoolean(keyControl, false);
|
|
||||||
boolean wearControl = dataMap.getBoolean(keyControl, false);
|
|
||||||
editor.putBoolean(keyControl, wearControl);
|
|
||||||
editor.apply();
|
|
||||||
if (wearControl != previousWearControl) {
|
|
||||||
updateTiles();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
String keyPercentage = getString(R.string.key_boluswizard_percentage);
|
|
||||||
if (dataMap.containsKey(keyPercentage)) {
|
|
||||||
int wpercentage = dataMap.getInt(keyPercentage, 100);
|
|
||||||
editor.putInt(keyPercentage, wpercentage);
|
|
||||||
editor.apply();
|
|
||||||
}
|
|
||||||
String keyUnits = getString(R.string.key_units_mgdl);
|
|
||||||
if (dataMap.containsKey(keyUnits)) {
|
|
||||||
boolean mgdl = dataMap.getBoolean(keyUnits, true);
|
|
||||||
editor.putBoolean(keyUnits, mgdl);
|
|
||||||
editor.apply();
|
|
||||||
}
|
|
||||||
String keyMaxCarbs = getString(R.string.key_treatmentssafety_maxcarbs);
|
|
||||||
if (dataMap.containsKey(keyMaxCarbs)) {
|
|
||||||
int maxCarbs = dataMap.getInt(keyMaxCarbs, 48);
|
|
||||||
editor.putInt(keyMaxCarbs, maxCarbs);
|
|
||||||
editor.apply();
|
|
||||||
}
|
|
||||||
String keyMaxBolus = getString(R.string.key_treatmentssafety_maxbolus);
|
|
||||||
if (dataMap.containsKey(keyMaxBolus)) {
|
|
||||||
float maxBolus = (float) dataMap.getDouble(keyMaxBolus, 3.0f);
|
|
||||||
editor.putFloat(keyMaxBolus, maxBolus);
|
|
||||||
editor.apply();
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (path.equals(WearUris.QUICK_WIZARD_PATH)) {
|
|
||||||
dataMap = DataMapItem.fromDataItem(event.getDataItem()).getDataMap();
|
|
||||||
Log.i(TAG, "onDataChanged: QUICK_WIZARD_PATH" + dataMap);
|
|
||||||
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
|
|
||||||
dataMap.remove("timestamp");
|
|
||||||
String key = getString(R.string.key_quick_wizard_data_map);
|
|
||||||
String dataString = Base64.encodeToString(dataMap.toByteArray(), Base64.DEFAULT);
|
|
||||||
if (!dataString.equals(sharedPreferences.getString(key, ""))) {
|
|
||||||
SharedPreferences.Editor editor = sharedPreferences.edit();
|
|
||||||
editor.putString(key, dataString);
|
|
||||||
editor.apply();
|
|
||||||
// Todo maybe add debounce function, due to 20 seconds update limit?
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
TileService.getUpdater(this)
|
|
||||||
.requestUpdate(QuickWizardTileService.class);
|
|
||||||
}
|
|
||||||
Log.i(TAG, "onDataChanged: updated QUICK_WIZARD");
|
|
||||||
} else {
|
|
||||||
Log.i(TAG, "onDataChanged: ignore update");
|
|
||||||
}
|
|
||||||
} else if (path.equals(WearUris.ACTION_CHANGECONFIRMATION_REQUEST_PATH)) {
|
|
||||||
String title = DataMapItem.fromDataItem(event.getDataItem()).getDataMap().getString("title");
|
|
||||||
String message = DataMapItem.fromDataItem(event.getDataItem()).getDataMap().getString("message");
|
|
||||||
String actionstring = DataMapItem.fromDataItem(event.getDataItem()).getDataMap().getString("actionstring");
|
|
||||||
notifyChangeRequest(title, message, actionstring);
|
|
||||||
} else if (path.equals(WearUris.ACTION_CANCELNOTIFICATION_REQUEST_PATH)) {
|
|
||||||
String actionstring = DataMapItem.fromDataItem(event.getDataItem()).getDataMap().getString("actionstring");
|
|
||||||
cancelNotificationRequest(actionstring);
|
|
||||||
} else {
|
|
||||||
dataMap = DataMapItem.fromDataItem(event.getDataItem()).getDataMap();
|
|
||||||
Intent messageIntent = new Intent();
|
|
||||||
messageIntent.setAction(Intent.ACTION_SEND);
|
|
||||||
messageIntent.putExtra("data", dataMap.toBundle());
|
|
||||||
persistence.storeDataMap(RawDisplayData.DATA_PERSISTENCE_KEY, dataMap);
|
|
||||||
LocalBroadcastManager.getInstance(this).sendBroadcast(messageIntent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateTiles() {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
TileService.getUpdater(this)
|
|
||||||
.requestUpdate(ActionsTileService.class);
|
|
||||||
|
|
||||||
TileService.getUpdater(this)
|
|
||||||
.requestUpdate(TempTargetTileService.class);
|
|
||||||
|
|
||||||
TileService.getUpdater(this)
|
|
||||||
.requestUpdate(QuickWizardTileService.class);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void notifyChangeRequest(String title, String message, String actionstring) {
|
|
||||||
// Create the NotificationChannel, but only on API 26+ because
|
|
||||||
// the NotificationChannel class is new and not in the support library
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
CharSequence name = "AAPS Open Loop";
|
|
||||||
String description = "Open Loop request notiffication";//getString(R.string.channel_description);
|
|
||||||
NotificationChannel channel = new NotificationChannel(AAPS_NOTIFY_CHANNEL_ID_OPENLOOP, name, NotificationManager.IMPORTANCE_HIGH);
|
|
||||||
channel.setDescription(description);
|
|
||||||
channel.enableVibration(true);
|
|
||||||
|
|
||||||
// Register the channel with the system; you can't change the importance
|
|
||||||
// or other notification behaviors after this
|
|
||||||
NotificationManager notificationManager = getSystemService(NotificationManager.class);
|
|
||||||
notificationManager.createNotificationChannel(channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
NotificationCompat.Builder builder =
|
|
||||||
new NotificationCompat.Builder(this, AAPS_NOTIFY_CHANNEL_ID_OPENLOOP);
|
|
||||||
|
|
||||||
builder = builder.setSmallIcon(R.drawable.notif_icon)
|
|
||||||
.setContentTitle(title)
|
|
||||||
.setContentText(message)
|
|
||||||
.setPriority(Notification.PRIORITY_HIGH)
|
|
||||||
.setVibrate(new long[]{1000, 1000, 1000, 1000, 1000});
|
|
||||||
|
|
||||||
// Creates an explicit intent for an Activity in your app
|
|
||||||
Intent intent = new Intent(this, AcceptActivity.class);
|
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
||||||
Bundle params = new Bundle();
|
|
||||||
params.putString("title", title);
|
|
||||||
params.putString("message", message);
|
|
||||||
params.putString("actionstring", actionstring);
|
|
||||||
intent.putExtras(params);
|
|
||||||
|
|
||||||
PendingIntent resultPendingIntent =
|
|
||||||
PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
|
|
||||||
|
|
||||||
builder = builder.setContentIntent(resultPendingIntent);
|
|
||||||
|
|
||||||
NotificationManager mNotificationManager =
|
|
||||||
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
|
||||||
// mId allows you to update the notification later on.
|
|
||||||
mNotificationManager.notify(CHANGE_NOTIF_ID, builder.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void cancelNotificationRequest(String actionstring) {
|
|
||||||
NotificationManager mNotificationManager =
|
|
||||||
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
|
||||||
mNotificationManager.cancel(CHANGE_NOTIF_ID);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showBolusProgress(int progresspercent, String progresstatus) {
|
|
||||||
|
|
||||||
long[] vibratePattern;
|
|
||||||
boolean vibrate = PreferenceManager
|
|
||||||
.getDefaultSharedPreferences(this).getBoolean("vibrateOnBolus", true);
|
|
||||||
if (vibrate) {
|
|
||||||
vibratePattern = new long[]{0, 50, 1000};
|
|
||||||
} else {
|
|
||||||
vibratePattern = new long[]{0, 1, 1000};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
createBolusProgressChannels();
|
|
||||||
}
|
|
||||||
|
|
||||||
Intent cancelIntent = new Intent(this, ListenerService.class);
|
|
||||||
cancelIntent.setAction(ACTION_CANCELBOLUS);
|
|
||||||
PendingIntent cancelPendingIntent = PendingIntent.getService(this, 0, cancelIntent, 0);
|
|
||||||
|
|
||||||
NotificationCompat.Builder notificationBuilder =
|
|
||||||
new NotificationCompat.Builder(this, vibrate ? AAPS_NOTIFY_CHANNEL_ID_BOLUSPROGRESS : AAPS_NOTIFY_CHANNEL_ID_BOLUSPROGRESS_SILENT)
|
|
||||||
.setSmallIcon(R.drawable.ic_icon)
|
|
||||||
.setContentTitle(getString(R.string.bolus_progress))
|
|
||||||
.setContentText(progresspercent + "% - " + progresstatus)
|
|
||||||
.setSubText(getString(R.string.press_to_cancel))
|
|
||||||
.setContentIntent(cancelPendingIntent)
|
|
||||||
.setPriority(NotificationCompat.PRIORITY_MAX)
|
|
||||||
.setVibrate(vibratePattern)
|
|
||||||
.addAction(R.drawable.ic_cancel, getString(R.string.cancel_bolus), cancelPendingIntent);
|
|
||||||
|
|
||||||
NotificationManagerCompat notificationManager =
|
|
||||||
NotificationManagerCompat.from(this);
|
|
||||||
|
|
||||||
notificationManager.notify(BOLUS_PROGRESS_NOTIF_ID, notificationBuilder.build());
|
|
||||||
notificationManager.cancel(CONFIRM_NOTIF_ID); // multiple watch setup
|
|
||||||
|
|
||||||
|
|
||||||
if (progresspercent == 100) {
|
|
||||||
scheduleDismissBolusprogress(5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@TargetApi(value = 26)
|
|
||||||
private void createBolusProgressChannels() {
|
|
||||||
createNotificationChannel(new long[]{0, 50, 1000}, AAPS_NOTIFY_CHANNEL_ID_BOLUSPROGRESS, getString(R.string.bolus_progress_channel_name), getString(R.string.bolus_progress_channel_description));
|
|
||||||
createNotificationChannel(new long[]{0, 1, 1000}, AAPS_NOTIFY_CHANNEL_ID_BOLUSPROGRESS_SILENT, getString(R.string.bolus_progress_silent_channel_name), getString(R.string.bolus_progress_silent_channel_description));
|
|
||||||
}
|
|
||||||
|
|
||||||
@TargetApi(value = 26)
|
|
||||||
private void createNotificationChannel(long[] vibratePattern, String channelID, CharSequence name, String description) {
|
|
||||||
NotificationChannel channel = new NotificationChannel(channelID, name, NotificationManager.IMPORTANCE_HIGH);
|
|
||||||
channel.setDescription(description);
|
|
||||||
channel.enableVibration(true);
|
|
||||||
channel.setVibrationPattern(vibratePattern);
|
|
||||||
|
|
||||||
// Register the channel with the system; you can't change the importance
|
|
||||||
// or other notification behaviors after this
|
|
||||||
NotificationManager notificationManager = getSystemService(NotificationManager.class);
|
|
||||||
notificationManager.createNotificationChannel(channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showConfirmationDialog(String title, String message, String actionstring) {
|
|
||||||
Intent intent = new Intent(this, AcceptActivity.class);
|
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
||||||
Bundle params = new Bundle();
|
|
||||||
params.putString("title", title);
|
|
||||||
params.putString("message", message);
|
|
||||||
params.putString("actionstring", actionstring);
|
|
||||||
intent.putExtras(params);
|
|
||||||
startActivity(intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void scheduleDismissBolusprogress(final int seconds) {
|
|
||||||
bolusprogressThread = new DismissThread(BOLUS_PROGRESS_NOTIF_ID, seconds);
|
|
||||||
bolusprogressThread.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private class DismissThread extends Thread {
|
|
||||||
private final int notificationID;
|
|
||||||
private final int seconds;
|
|
||||||
private boolean valid = true;
|
|
||||||
|
|
||||||
DismissThread(int notificationID, int seconds) {
|
|
||||||
this.notificationID = notificationID;
|
|
||||||
this.seconds = seconds;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void invalidate() {
|
|
||||||
valid = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
SystemClock.sleep(seconds * 1000);
|
|
||||||
synchronized (this) {
|
|
||||||
if (valid) {
|
|
||||||
NotificationManagerCompat notificationManager =
|
|
||||||
NotificationManagerCompat.from(ListenerService.this);
|
|
||||||
notificationManager.cancel(notificationID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void requestData(Context context) {
|
|
||||||
Intent intent = new Intent(context, ListenerService.class);
|
|
||||||
intent.setAction(ACTION_RESEND);
|
|
||||||
context.startService(intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void initiateAction(Context context, @NotNull String actionstring) {
|
|
||||||
Intent intent = new Intent(context, ListenerService.class);
|
|
||||||
intent.putExtra("actionstring", actionstring);
|
|
||||||
intent.setAction(ACTION_INITIATE_ACTION);
|
|
||||||
context.startService(intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void confirmAction(Context context, String actionstring) {
|
|
||||||
Intent intent = new Intent(context, ListenerService.class);
|
|
||||||
intent.putExtra("actionstring", actionstring);
|
|
||||||
|
|
||||||
if (actionstring.equals("changeRequest")) {
|
|
||||||
intent.setAction(ACTION_CONFIRMCHANGE);
|
|
||||||
} else {
|
|
||||||
intent.setAction(ACTION_CONFIRMATION);
|
|
||||||
}
|
|
||||||
context.startService(intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onConnected(Bundle bundle) {
|
|
||||||
// Log.d(TAG, logPrefix + "onConnected call requestData");
|
|
||||||
|
|
||||||
Wearable.ChannelApi.addListener(googleApiClient, this);
|
|
||||||
// requestData();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onConnectionSuspended(int i) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onConnectionFailed(ConnectionResult connectionResult) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroy() {
|
|
||||||
super.onDestroy();
|
|
||||||
if (googleApiClient != null && googleApiClient.isConnected()) {
|
|
||||||
googleApiClient.disconnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (googleApiClient != null) {
|
|
||||||
Wearable.MessageApi.removeListener(googleApiClient, this);
|
|
||||||
Wearable.ChannelApi.removeListener(googleApiClient, this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -174,7 +174,7 @@ public class RawDisplayData {
|
||||||
wearUtil.releaseWakeLock(wl);
|
wearUtil.releaseWakeLock(wl);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataMap updateBasalsFromMessage(Intent intent, PowerManager.WakeLock wakeLock) {
|
public DataMap updateBasalsFromMessage(Intent intent) {
|
||||||
Bundle bundle = intent.getBundleExtra("basals");
|
Bundle bundle = intent.getBundleExtra("basals");
|
||||||
if (bundle != null) {
|
if (bundle != null) {
|
||||||
DataMap dataMap = wearUtil.bundleToDataMap(bundle);
|
DataMap dataMap = wearUtil.bundleToDataMap(bundle);
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
package info.nightscout.androidaps.di
|
||||||
|
|
||||||
|
import dagger.Module
|
||||||
|
import dagger.android.ContributesAndroidInjector
|
||||||
|
import info.nightscout.androidaps.interaction.actions.*
|
||||||
|
|
||||||
|
@Module
|
||||||
|
@Suppress("unused")
|
||||||
|
abstract class WearActivitiesModule {
|
||||||
|
|
||||||
|
@ContributesAndroidInjector abstract fun contributesBackgroundActionActivity(): BackgroundActionActivity
|
||||||
|
|
||||||
|
@ContributesAndroidInjector abstract fun contributesViewSelectorActivity(): ViewSelectorActivity
|
||||||
|
@ContributesAndroidInjector abstract fun contributesAcceptActivity(): AcceptActivity
|
||||||
|
@ContributesAndroidInjector abstract fun contributesBolusActivity(): BolusActivity
|
||||||
|
@ContributesAndroidInjector abstract fun contributesCarbActivity(): CarbActivity
|
||||||
|
@ContributesAndroidInjector abstract fun contributesCPPActivity(): CPPActivity
|
||||||
|
@ContributesAndroidInjector abstract fun contributesECarbActivity(): ECarbActivity
|
||||||
|
@ContributesAndroidInjector abstract fun contributesFillActivity(): FillActivity
|
||||||
|
@ContributesAndroidInjector abstract fun contributesTempTargetActivity(): TempTargetActivity
|
||||||
|
@ContributesAndroidInjector abstract fun contributesTreatmentActivity(): TreatmentActivity
|
||||||
|
@ContributesAndroidInjector abstract fun contributesWizardActivity(): WizardActivity
|
||||||
|
}
|
|
@ -7,6 +7,8 @@ import dagger.Module
|
||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
import dagger.android.HasAndroidInjector
|
import dagger.android.HasAndroidInjector
|
||||||
import info.nightscout.androidaps.Aaps
|
import info.nightscout.androidaps.Aaps
|
||||||
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
|
import info.nightscout.androidaps.utils.rx.DefaultAapsSchedulers
|
||||||
import info.nightscout.shared.logging.AAPSLogger
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
import info.nightscout.shared.logging.AAPSLoggerProduction
|
import info.nightscout.shared.logging.AAPSLoggerProduction
|
||||||
import info.nightscout.shared.logging.L
|
import info.nightscout.shared.logging.L
|
||||||
|
@ -16,7 +18,8 @@ import javax.inject.Singleton
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
@Module(includes = [
|
@Module(includes = [
|
||||||
WearModule.AppBindings::class
|
WearModule.AppBindings::class,
|
||||||
|
WearActivitiesModule::class
|
||||||
])
|
])
|
||||||
open class WearModule {
|
open class WearModule {
|
||||||
|
|
||||||
|
@ -28,6 +31,10 @@ open class WearModule {
|
||||||
@Singleton
|
@Singleton
|
||||||
fun provideAAPSLogger(l: L): AAPSLogger = AAPSLoggerProduction(l)
|
fun provideAAPSLogger(l: L): AAPSLogger = AAPSLoggerProduction(l)
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
internal fun provideSchedulers(): AapsSchedulers = DefaultAapsSchedulers()
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
interface AppBindings {
|
interface AppBindings {
|
||||||
|
|
||||||
|
|
|
@ -3,14 +3,15 @@ package info.nightscout.androidaps.di
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.android.ContributesAndroidInjector
|
import dagger.android.ContributesAndroidInjector
|
||||||
import info.nightscout.androidaps.complications.*
|
import info.nightscout.androidaps.complications.*
|
||||||
import info.nightscout.androidaps.data.ListenerService
|
import info.nightscout.androidaps.data.DataLayerListenerService
|
||||||
|
import info.nightscout.androidaps.interaction.actions.BackgroundActionActivity
|
||||||
import info.nightscout.androidaps.watchfaces.*
|
import info.nightscout.androidaps.watchfaces.*
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
abstract class WearServicesModule {
|
abstract class WearServicesModule {
|
||||||
|
|
||||||
@ContributesAndroidInjector abstract fun contributesListenerService(): ListenerService
|
@ContributesAndroidInjector abstract fun contributesDataLayerListenerService(): DataLayerListenerService
|
||||||
|
|
||||||
@ContributesAndroidInjector abstract fun contributesBaseComplicationProviderService(): BaseComplicationProviderService
|
@ContributesAndroidInjector abstract fun contributesBaseComplicationProviderService(): BaseComplicationProviderService
|
||||||
@ContributesAndroidInjector abstract fun contributesBrCobIobComplication(): BrCobIobComplication
|
@ContributesAndroidInjector abstract fun contributesBrCobIobComplication(): BrCobIobComplication
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package info.nightscout.androidaps.interaction.actions;
|
package info.nightscout.androidaps.interaction.actions;
|
||||||
|
|
||||||
|
import static info.nightscout.shared.weardata.WearConstants.KEY_ACTION_DATA;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
@ -19,7 +21,10 @@ import androidx.core.view.MotionEventCompat;
|
||||||
import androidx.core.view.ViewConfigurationCompat;
|
import androidx.core.view.ViewConfigurationCompat;
|
||||||
|
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.data.ListenerService;
|
import info.nightscout.androidaps.data.DataLayerListenerService;
|
||||||
|
import info.nightscout.androidaps.events.EventWearToMobileChange;
|
||||||
|
import info.nightscout.androidaps.events.EventWearToMobileConfirm;
|
||||||
|
import info.nightscout.shared.weardata.ActionData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by adrian on 09/02/17.
|
* Created by adrian on 09/02/17.
|
||||||
|
@ -29,6 +34,7 @@ public class AcceptActivity extends ViewSelectorActivity {
|
||||||
|
|
||||||
String message = "";
|
String message = "";
|
||||||
String actionstring = "";
|
String actionstring = "";
|
||||||
|
String actionKey = "";
|
||||||
private DismissThread dismissThread;
|
private DismissThread dismissThread;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -41,8 +47,9 @@ public class AcceptActivity extends ViewSelectorActivity {
|
||||||
Bundle extras = getIntent().getExtras();
|
Bundle extras = getIntent().getExtras();
|
||||||
message = extras.getString("message", "");
|
message = extras.getString("message", "");
|
||||||
actionstring = extras.getString("actionstring", "");
|
actionstring = extras.getString("actionstring", "");
|
||||||
|
actionKey = extras.getString(KEY_ACTION_DATA, "");
|
||||||
|
|
||||||
if ("".equals(message) || "".equals(actionstring)) {
|
if (message.isEmpty() || (actionstring.isEmpty() && actionKey.isEmpty())) {
|
||||||
finish();
|
finish();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -60,6 +67,7 @@ public class AcceptActivity extends ViewSelectorActivity {
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
private class MyGridViewPagerAdapter extends GridPagerAdapter {
|
private class MyGridViewPagerAdapter extends GridPagerAdapter {
|
||||||
@Override
|
@Override
|
||||||
public int getColumnCount(int arg0) {
|
public int getColumnCount(int arg0) {
|
||||||
|
@ -74,15 +82,14 @@ public class AcceptActivity extends ViewSelectorActivity {
|
||||||
@Override
|
@Override
|
||||||
public Object instantiateItem(ViewGroup container, int row, int col) {
|
public Object instantiateItem(ViewGroup container, int row, int col) {
|
||||||
|
|
||||||
|
final View view;
|
||||||
if (col == 0) {
|
if (col == 0) {
|
||||||
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_confirm_text, container, false);
|
view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_confirm_text, container, false);
|
||||||
final TextView textView = view.findViewById(R.id.message);
|
final TextView textView = view.findViewById(R.id.message);
|
||||||
final View scrollView = view.findViewById(R.id.message_scroll);
|
final View scrollView = view.findViewById(R.id.message_scroll);
|
||||||
textView.setText(message);
|
textView.setText(message);
|
||||||
container.addView(view);
|
container.addView(view);
|
||||||
scrollView.setOnGenericMotionListener(new View.OnGenericMotionListener() {
|
scrollView.setOnGenericMotionListener((v, ev) -> {
|
||||||
@Override
|
|
||||||
public boolean onGenericMotion(View v, MotionEvent ev) {
|
|
||||||
if (ev.getAction() == MotionEvent.ACTION_SCROLL &&
|
if (ev.getAction() == MotionEvent.ACTION_SCROLL &&
|
||||||
ev.isFromSource(InputDeviceCompat.SOURCE_ROTARY_ENCODER)
|
ev.isFromSource(InputDeviceCompat.SOURCE_ROTARY_ENCODER)
|
||||||
) {
|
) {
|
||||||
|
@ -95,27 +102,33 @@ public class AcceptActivity extends ViewSelectorActivity {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
scrollView.requestFocus();
|
scrollView.requestFocus();
|
||||||
return view;
|
|
||||||
} else {
|
} else {
|
||||||
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_send_item, container, false);
|
view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_send_item, container, false);
|
||||||
final ImageView confirmbutton = view.findViewById(R.id.confirmbutton);
|
final ImageView confirmButton = view.findViewById(R.id.confirmbutton);
|
||||||
confirmbutton.setOnClickListener((View v) -> {
|
confirmButton.setOnClickListener((View v) -> {
|
||||||
ListenerService.confirmAction(AcceptActivity.this, actionstring);
|
if (!actionstring.isEmpty())
|
||||||
|
DataLayerListenerService.Companion.confirmAction(AcceptActivity.this, actionstring);
|
||||||
|
else {
|
||||||
|
ActionData actionData = ActionData.Companion.deserialize(actionKey);
|
||||||
|
if (actionData instanceof ActionData.ConfirmAction)
|
||||||
|
rxBus.send(new EventWearToMobileConfirm(actionData));
|
||||||
|
if (actionData instanceof ActionData.ChangeAction)
|
||||||
|
rxBus.send(new EventWearToMobileChange(actionData));
|
||||||
|
}
|
||||||
finishAffinity();
|
finishAffinity();
|
||||||
});
|
});
|
||||||
container.addView(view);
|
container.addView(view);
|
||||||
return view;
|
|
||||||
}
|
}
|
||||||
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void destroyItem(ViewGroup container, int row, int col, Object view) {
|
public void destroyItem(ViewGroup container, int row, int col, Object view) {
|
||||||
// Handle this to get the data before the view is destroyed?
|
// Handle this to get the data before the view is destroyed?
|
||||||
// Object should still be kept by this, just setup for reinit?
|
// Object should still be kept by this, just setup for re-init?
|
||||||
container.removeView((View) view);
|
container.removeView((View) view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,28 +1,26 @@
|
||||||
package info.nightscout.androidaps.interaction.actions
|
package info.nightscout.androidaps.interaction.actions
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import info.nightscout.androidaps.data.ListenerService
|
import dagger.android.DaggerActivity
|
||||||
|
import info.nightscout.androidaps.data.DataLayerListenerService
|
||||||
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
|
import info.nightscout.shared.logging.LTag
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
const val TAG = "QuickWizard"
|
class BackgroundActionActivity : DaggerActivity() {
|
||||||
|
|
||||||
class BackgroundActionActivity : Activity() {
|
@Inject lateinit var aapsLogger: AAPSLogger
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
val actionString = intent.extras?.getString("actionString")
|
intent.extras?.getString("actionString")?.let { actionString ->
|
||||||
Log.i(TAG, "QuickWizardActivity.onCreate: actionString=$actionString")
|
aapsLogger.info(LTag.WEAR, "QuickWizardActivity.onCreate: actionString=$actionString")
|
||||||
if (actionString != null) {
|
DataLayerListenerService.initiateAction(this, actionString)
|
||||||
ListenerService.initiateAction(this, actionString)
|
intent.extras?.getString("message")?.let { message ->
|
||||||
val message = intent.extras?.getString("message")
|
|
||||||
if (message != null) {
|
|
||||||
Toast.makeText(this, message, Toast.LENGTH_LONG).show()
|
Toast.makeText(this, message, Toast.LENGTH_LONG).show()
|
||||||
}
|
}
|
||||||
} else {
|
} ?: aapsLogger.error(LTag.WEAR, "BackgroundActionActivity.onCreate extras 'actionString' required")
|
||||||
Log.e(TAG, "BackgroundActionActivity.onCreate extras 'actionString' required")
|
|
||||||
}
|
|
||||||
finishAffinity()
|
finishAffinity()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package info.nightscout.androidaps.interaction.actions;
|
package info.nightscout.androidaps.interaction.actions;
|
||||||
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
import android.support.wearable.view.GridPagerAdapter;
|
import android.support.wearable.view.GridPagerAdapter;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
@ -12,21 +10,21 @@ import android.widget.ImageView;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
|
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.data.ListenerService;
|
import info.nightscout.androidaps.events.EventWearToMobileAction;
|
||||||
import info.nightscout.androidaps.interaction.utils.PlusMinusEditText;
|
import info.nightscout.androidaps.interaction.utils.PlusMinusEditText;
|
||||||
import info.nightscout.shared.SafeParse;
|
import info.nightscout.shared.SafeParse;
|
||||||
|
import info.nightscout.shared.weardata.ActionData;
|
||||||
|
|
||||||
public class BolusActivity extends ViewSelectorActivity {
|
public class BolusActivity extends ViewSelectorActivity {
|
||||||
|
|
||||||
PlusMinusEditText editInsulin;
|
PlusMinusEditText editInsulin;
|
||||||
float maxBolus;
|
double maxBolus;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setAdapter(new MyGridViewPagerAdapter());
|
setAdapter(new MyGridViewPagerAdapter());
|
||||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
|
maxBolus = sp.getDouble(getString(R.string.key_treatmentssafety_maxbolus), 3.0);
|
||||||
maxBolus = sp.getFloat(getString(R.string.key_treatmentssafety_maxbolus), 3f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -35,6 +33,7 @@ public class BolusActivity extends ViewSelectorActivity {
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
private class MyGridViewPagerAdapter extends GridPagerAdapter {
|
private class MyGridViewPagerAdapter extends GridPagerAdapter {
|
||||||
@Override
|
@Override
|
||||||
public int getColumnCount(int arg0) {
|
public int getColumnCount(int arg0) {
|
||||||
|
@ -49,30 +48,29 @@ public class BolusActivity extends ViewSelectorActivity {
|
||||||
@Override
|
@Override
|
||||||
public Object instantiateItem(ViewGroup container, int row, int col) {
|
public Object instantiateItem(ViewGroup container, int row, int col) {
|
||||||
|
|
||||||
|
final View view;
|
||||||
if (col == 0) {
|
if (col == 0) {
|
||||||
final View view = getInflatedPlusMinusView(container);
|
view = getInflatedPlusMinusView(container);
|
||||||
double def = 0;
|
double def = 0;
|
||||||
if (editInsulin != null) {
|
if (editInsulin != null) {
|
||||||
def = SafeParse.stringToDouble(editInsulin.editText.getText().toString());
|
def = SafeParse.stringToDouble(editInsulin.editText.getText().toString());
|
||||||
}
|
}
|
||||||
editInsulin = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, def, 0d, (double)maxBolus, 0.1d, new DecimalFormat("#0.0"),false);
|
editInsulin = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, def, 0d, maxBolus, 0.1d, new DecimalFormat("#0.0"), false);
|
||||||
setLabelToPlusMinusView(view, getString(R.string.action_insulin));
|
setLabelToPlusMinusView(view, getString(R.string.action_insulin));
|
||||||
container.addView(view);
|
container.addView(view);
|
||||||
view.requestFocus();
|
view.requestFocus();
|
||||||
return view;
|
|
||||||
} else {
|
} else {
|
||||||
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_send_item, container, false);
|
view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_send_item, container, false);
|
||||||
final ImageView confirmbutton = view.findViewById(R.id.confirmbutton);
|
final ImageView confirmButton = view.findViewById(R.id.confirmbutton);
|
||||||
confirmbutton.setOnClickListener((View v) -> {
|
confirmButton.setOnClickListener((View v) -> {
|
||||||
String actionstring = "bolus " + SafeParse.stringToDouble(editInsulin.editText.getText().toString())
|
ActionData.Bolus bolus = new ActionData.Bolus(SafeParse.stringToDouble(editInsulin.editText.getText().toString()), 0);
|
||||||
+ " 0"; // Zero carbs
|
rxBus.send(new EventWearToMobileAction(bolus));
|
||||||
ListenerService.initiateAction(BolusActivity.this, actionstring);
|
showToast(BolusActivity.this, R.string.action_bolus_confirmation);
|
||||||
confirmAction(BolusActivity.this, R.string.action_bolus_confirmation);
|
|
||||||
finishAffinity();
|
finishAffinity();
|
||||||
});
|
});
|
||||||
container.addView(view);
|
container.addView(view);
|
||||||
return view;
|
|
||||||
}
|
}
|
||||||
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -10,9 +10,11 @@ import android.widget.ImageView;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
|
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.data.ListenerService;
|
import info.nightscout.androidaps.data.DataLayerListenerService;
|
||||||
|
import info.nightscout.androidaps.events.EventWearToMobileAction;
|
||||||
import info.nightscout.androidaps.interaction.utils.PlusMinusEditText;
|
import info.nightscout.androidaps.interaction.utils.PlusMinusEditText;
|
||||||
import info.nightscout.shared.SafeParse;
|
import info.nightscout.shared.SafeParse;
|
||||||
|
import info.nightscout.shared.weardata.ActionData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by adrian on 09/02/17.
|
* Created by adrian on 09/02/17.
|
||||||
|
@ -88,15 +90,14 @@ public class CPPActivity extends ViewSelectorActivity {
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_send_item, container, false);
|
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_send_item, container, false);
|
||||||
final ImageView confirmbutton = view.findViewById(R.id.confirmbutton);
|
final ImageView confirmButton = view.findViewById(R.id.confirmbutton);
|
||||||
confirmbutton.setOnClickListener((View v) -> {
|
confirmButton.setOnClickListener((View v) -> {
|
||||||
//check if it can happen that the fagment is never created that hold data?
|
//check if it can happen that the fragment is never created that hold data?
|
||||||
// (you have to swipe past them anyways - but still)
|
// (you have to swipe past them anyways - but still)
|
||||||
|
ActionData.ProfileSwitch ps =
|
||||||
String actionstring = "cppset " + SafeParse.stringToInt(editTimeshift.editText.getText().toString())
|
new ActionData.ProfileSwitch(SafeParse.stringToInt(editTimeshift.editText.getText().toString()), SafeParse.stringToInt(editPercentage.editText.getText().toString()));
|
||||||
+ " " + SafeParse.stringToInt(editPercentage.editText.getText().toString());
|
rxBus.send(new EventWearToMobileAction(ps));
|
||||||
ListenerService.initiateAction(CPPActivity.this, actionstring);
|
showToast(CPPActivity.this, R.string.action_cpp_confirmation);
|
||||||
confirmAction(CPPActivity.this, R.string.action_cpp_confirmation);
|
|
||||||
finishAffinity();
|
finishAffinity();
|
||||||
});
|
});
|
||||||
container.addView(view);
|
container.addView(view);
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package info.nightscout.androidaps.interaction.actions;
|
package info.nightscout.androidaps.interaction.actions;
|
||||||
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
import android.support.wearable.view.GridPagerAdapter;
|
import android.support.wearable.view.GridPagerAdapter;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
@ -12,7 +10,7 @@ import android.widget.ImageView;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
|
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.data.ListenerService;
|
import info.nightscout.androidaps.data.DataLayerListenerService;
|
||||||
import info.nightscout.androidaps.interaction.utils.PlusMinusEditText;
|
import info.nightscout.androidaps.interaction.utils.PlusMinusEditText;
|
||||||
import info.nightscout.shared.SafeParse;
|
import info.nightscout.shared.SafeParse;
|
||||||
|
|
||||||
|
@ -25,7 +23,6 @@ public class CarbActivity extends ViewSelectorActivity {
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setAdapter(new MyGridViewPagerAdapter());
|
setAdapter(new MyGridViewPagerAdapter());
|
||||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
|
|
||||||
maxCarbs = sp.getInt(getString(R.string.key_treatmentssafety_maxcarbs), 48);
|
maxCarbs = sp.getInt(getString(R.string.key_treatmentssafety_maxcarbs), 48);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,8 +63,8 @@ public class CarbActivity extends ViewSelectorActivity {
|
||||||
confirmbutton.setOnClickListener((View v) -> {
|
confirmbutton.setOnClickListener((View v) -> {
|
||||||
// With start time 0 and duration 0
|
// With start time 0 and duration 0
|
||||||
String actionstring = "ecarbs " + SafeParse.stringToInt(editCarbs.editText.getText().toString()) + " 0 0";
|
String actionstring = "ecarbs " + SafeParse.stringToInt(editCarbs.editText.getText().toString()) + " 0 0";
|
||||||
ListenerService.initiateAction(CarbActivity.this, actionstring);
|
DataLayerListenerService.Companion.initiateAction(CarbActivity.this, actionstring);
|
||||||
confirmAction(CarbActivity.this, R.string.action_ecarb_confirmation);
|
showToast(CarbActivity.this, R.string.action_ecarb_confirmation);
|
||||||
finishAffinity();
|
finishAffinity();
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package info.nightscout.androidaps.interaction.actions;
|
package info.nightscout.androidaps.interaction.actions;
|
||||||
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
import android.support.wearable.view.GridPagerAdapter;
|
import android.support.wearable.view.GridPagerAdapter;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
@ -12,7 +10,7 @@ import android.widget.ImageView;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
|
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.data.ListenerService;
|
import info.nightscout.androidaps.data.DataLayerListenerService;
|
||||||
import info.nightscout.androidaps.interaction.utils.PlusMinusEditText;
|
import info.nightscout.androidaps.interaction.utils.PlusMinusEditText;
|
||||||
import info.nightscout.shared.SafeParse;
|
import info.nightscout.shared.SafeParse;
|
||||||
|
|
||||||
|
@ -31,7 +29,6 @@ public class ECarbActivity extends ViewSelectorActivity {
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setAdapter(new MyGridViewPagerAdapter());
|
setAdapter(new MyGridViewPagerAdapter());
|
||||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
|
|
||||||
maxCarbs = sp.getInt(getString(R.string.key_treatmentssafety_maxcarbs), 48);
|
maxCarbs = sp.getInt(getString(R.string.key_treatmentssafety_maxcarbs), 48);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,14 +89,14 @@ public class ECarbActivity extends ViewSelectorActivity {
|
||||||
final ImageView confirmbutton = view.findViewById(R.id.confirmbutton);
|
final ImageView confirmbutton = view.findViewById(R.id.confirmbutton);
|
||||||
confirmbutton.setOnClickListener((View v) -> {
|
confirmbutton.setOnClickListener((View v) -> {
|
||||||
|
|
||||||
//check if it can happen that the fagment is never created that hold data?
|
//check if it can happen that the fragment is never created that hold data?
|
||||||
// (you have to swipe past them anyways - but still)
|
// (you have to swipe past them anyways - but still)
|
||||||
|
|
||||||
String actionstring = "ecarbs " + SafeParse.stringToInt(editCarbs.editText.getText().toString())
|
String actionstring = "ecarbs " + SafeParse.stringToInt(editCarbs.editText.getText().toString())
|
||||||
+ " " + SafeParse.stringToInt(editStartTime.editText.getText().toString())
|
+ " " + SafeParse.stringToInt(editStartTime.editText.getText().toString())
|
||||||
+ " " + SafeParse.stringToInt(editDuration.editText.getText().toString());
|
+ " " + SafeParse.stringToInt(editDuration.editText.getText().toString());
|
||||||
ListenerService.initiateAction(ECarbActivity.this, actionstring);
|
DataLayerListenerService.Companion.initiateAction(ECarbActivity.this, actionstring);
|
||||||
confirmAction(ECarbActivity.this, R.string.action_ecarb_confirmation);
|
showToast(ECarbActivity.this, R.string.action_ecarb_confirmation);
|
||||||
finishAffinity();
|
finishAffinity();
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,7 +10,7 @@ import android.widget.ImageView;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
|
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.data.ListenerService;
|
import info.nightscout.androidaps.data.DataLayerListenerService;
|
||||||
import info.nightscout.androidaps.interaction.utils.PlusMinusEditText;
|
import info.nightscout.androidaps.interaction.utils.PlusMinusEditText;
|
||||||
import info.nightscout.shared.SafeParse;
|
import info.nightscout.shared.SafeParse;
|
||||||
|
|
||||||
|
@ -68,8 +68,8 @@ public class FillActivity extends ViewSelectorActivity {
|
||||||
// (you have to swipe past them anyways - but still)
|
// (you have to swipe past them anyways - but still)
|
||||||
|
|
||||||
String actionstring = "fill " + SafeParse.stringToDouble(editInsulin.editText.getText().toString());
|
String actionstring = "fill " + SafeParse.stringToDouble(editInsulin.editText.getText().toString());
|
||||||
ListenerService.initiateAction(FillActivity.this, actionstring);
|
DataLayerListenerService.Companion.initiateAction(FillActivity.this, actionstring);
|
||||||
confirmAction(FillActivity.this, R.string.action_fill_confirmation);
|
showToast(FillActivity.this, R.string.action_fill_confirmation);
|
||||||
finishAffinity();
|
finishAffinity();
|
||||||
});
|
});
|
||||||
container.addView(view);
|
container.addView(view);
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package info.nightscout.androidaps.interaction.actions;
|
package info.nightscout.androidaps.interaction.actions;
|
||||||
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
import android.support.wearable.view.GridPagerAdapter;
|
import android.support.wearable.view.GridPagerAdapter;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
@ -12,7 +10,7 @@ import android.widget.ImageView;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
|
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.data.ListenerService;
|
import info.nightscout.androidaps.data.DataLayerListenerService;
|
||||||
import info.nightscout.androidaps.interaction.utils.PlusMinusEditText;
|
import info.nightscout.androidaps.interaction.utils.PlusMinusEditText;
|
||||||
import info.nightscout.shared.SafeParse;
|
import info.nightscout.shared.SafeParse;
|
||||||
|
|
||||||
|
@ -34,7 +32,6 @@ public class TempTargetActivity extends ViewSelectorActivity {
|
||||||
|
|
||||||
setAdapter(new MyGridViewPagerAdapter());
|
setAdapter(new MyGridViewPagerAdapter());
|
||||||
|
|
||||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
|
|
||||||
isMGDL = sp.getBoolean("units_mgdl", true);
|
isMGDL = sp.getBoolean("units_mgdl", true);
|
||||||
isSingleTarget = sp.getBoolean("singletarget", true);
|
isSingleTarget = sp.getBoolean("singletarget", true);
|
||||||
}
|
}
|
||||||
|
@ -126,8 +123,8 @@ public class TempTargetActivity extends ViewSelectorActivity {
|
||||||
+ " " + SafeParse.stringToDouble(lowRange.editText.getText().toString())
|
+ " " + SafeParse.stringToDouble(lowRange.editText.getText().toString())
|
||||||
+ " " + (isSingleTarget ? SafeParse.stringToDouble(lowRange.editText.getText().toString()) : SafeParse.stringToDouble(highRange.editText.getText().toString()));
|
+ " " + (isSingleTarget ? SafeParse.stringToDouble(lowRange.editText.getText().toString()) : SafeParse.stringToDouble(highRange.editText.getText().toString()));
|
||||||
|
|
||||||
ListenerService.initiateAction(TempTargetActivity.this, actionstring);
|
DataLayerListenerService.Companion.initiateAction(TempTargetActivity.this, actionstring);
|
||||||
confirmAction(TempTargetActivity.this, R.string.action_tempt_confirmation);
|
showToast(TempTargetActivity.this, R.string.action_tempt_confirmation);
|
||||||
finishAffinity();
|
finishAffinity();
|
||||||
});
|
});
|
||||||
container.addView(view);
|
container.addView(view);
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package info.nightscout.androidaps.interaction.actions;
|
package info.nightscout.androidaps.interaction.actions;
|
||||||
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
import android.support.wearable.view.GridPagerAdapter;
|
import android.support.wearable.view.GridPagerAdapter;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
@ -12,9 +10,11 @@ import android.widget.ImageView;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
|
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.data.ListenerService;
|
import info.nightscout.androidaps.data.DataLayerListenerService;
|
||||||
|
import info.nightscout.androidaps.events.EventWearToMobileAction;
|
||||||
import info.nightscout.androidaps.interaction.utils.PlusMinusEditText;
|
import info.nightscout.androidaps.interaction.utils.PlusMinusEditText;
|
||||||
import info.nightscout.shared.SafeParse;
|
import info.nightscout.shared.SafeParse;
|
||||||
|
import info.nightscout.shared.weardata.ActionData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by adrian on 09/02/17.
|
* Created by adrian on 09/02/17.
|
||||||
|
@ -25,15 +25,14 @@ public class TreatmentActivity extends ViewSelectorActivity {
|
||||||
PlusMinusEditText editCarbs;
|
PlusMinusEditText editCarbs;
|
||||||
PlusMinusEditText editInsulin;
|
PlusMinusEditText editInsulin;
|
||||||
int maxCarbs;
|
int maxCarbs;
|
||||||
float maxBolus;
|
double maxBolus;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setAdapter(new MyGridViewPagerAdapter());
|
setAdapter(new MyGridViewPagerAdapter());
|
||||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
|
|
||||||
maxCarbs = sp.getInt(getString(R.string.key_treatmentssafety_maxcarbs), 48);
|
maxCarbs = sp.getInt(getString(R.string.key_treatmentssafety_maxcarbs), 48);
|
||||||
maxBolus = sp.getFloat(getString(R.string.key_treatmentssafety_maxbolus), 3f);
|
maxBolus = sp.getDouble(getString(R.string.key_treatmentssafety_maxbolus), 3.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -83,12 +82,11 @@ public class TreatmentActivity extends ViewSelectorActivity {
|
||||||
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_send_item, container, false);
|
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_send_item, container, false);
|
||||||
final ImageView confirmbutton = view.findViewById(R.id.confirmbutton);
|
final ImageView confirmbutton = view.findViewById(R.id.confirmbutton);
|
||||||
confirmbutton.setOnClickListener((View v) -> {
|
confirmbutton.setOnClickListener((View v) -> {
|
||||||
//check if it can happen that the fagment is never created that hold data?
|
//check if it can happen that the fragment is never created that hold data?
|
||||||
// (you have to swipe past them anyways - but still)
|
// (you have to swipe past them anyways - but still)
|
||||||
String actionstring = "bolus " + SafeParse.stringToDouble(editInsulin.editText.getText().toString())
|
ActionData.Bolus bolus = new ActionData.Bolus(SafeParse.stringToDouble(editInsulin.editText.getText().toString()), SafeParse.stringToInt(editCarbs.editText.getText().toString()));
|
||||||
+ " " + SafeParse.stringToInt(editCarbs.editText.getText().toString());
|
rxBus.send(new EventWearToMobileAction(bolus));
|
||||||
ListenerService.initiateAction(TreatmentActivity.this, actionstring);
|
showToast(TreatmentActivity.this, R.string.action_treatment_confirmation);
|
||||||
confirmAction(TreatmentActivity.this, R.string.action_treatment_confirmation);
|
|
||||||
finishAffinity();
|
finishAffinity();
|
||||||
});
|
});
|
||||||
container.addView(view);
|
container.addView(view);
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
package info.nightscout.androidaps.interaction.actions;
|
package info.nightscout.androidaps.interaction.actions;
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
import android.support.wearable.view.DotsPageIndicator;
|
import android.support.wearable.view.DotsPageIndicator;
|
||||||
import android.support.wearable.view.GridPagerAdapter;
|
import android.support.wearable.view.GridPagerAdapter;
|
||||||
import android.support.wearable.view.GridViewPager;
|
import android.support.wearable.view.GridViewPager;
|
||||||
|
@ -16,13 +13,21 @@ import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.wear.widget.CurvedTextView;
|
import androidx.wear.widget.CurvedTextView;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import dagger.android.DaggerActivity;
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||||
|
import info.nightscout.shared.sharedPreferences.SP;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by adrian on 13/02/17.
|
* Created by adrian on 13/02/17.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class ViewSelectorActivity extends Activity {
|
public class ViewSelectorActivity extends DaggerActivity {
|
||||||
|
|
||||||
|
@Inject SP sp;
|
||||||
|
@Inject RxBus rxBus;
|
||||||
|
|
||||||
private GridViewPager pager;
|
private GridViewPager pager;
|
||||||
|
|
||||||
|
@ -81,9 +86,7 @@ public class ViewSelectorActivity extends Activity {
|
||||||
}
|
}
|
||||||
|
|
||||||
View getInflatedPlusMinusView(ViewGroup container) {
|
View getInflatedPlusMinusView(ViewGroup container) {
|
||||||
SharedPreferences sharedPrefs = PreferenceManager
|
int design = sp.getInt("input_design", 1);
|
||||||
.getDefaultSharedPreferences(this);
|
|
||||||
int design = Integer.parseInt(sharedPrefs.getString("input_design", "1"));
|
|
||||||
|
|
||||||
if (design == 2) {
|
if (design == 2) {
|
||||||
return LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_editplusminus_item_quickrighty, container, false);
|
return LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_editplusminus_item_quickrighty, container, false);
|
||||||
|
@ -102,7 +105,7 @@ public class ViewSelectorActivity extends Activity {
|
||||||
textView.setText(labelText);
|
textView.setText(labelText);
|
||||||
}
|
}
|
||||||
|
|
||||||
void confirmAction(Context context, int text) {
|
void showToast(Context context, int text) {
|
||||||
Toast.makeText(context, getString(text), Toast.LENGTH_LONG).show();
|
Toast.makeText(context, getString(text), Toast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package info.nightscout.androidaps.interaction.actions;
|
package info.nightscout.androidaps.interaction.actions;
|
||||||
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
import android.support.wearable.view.GridPagerAdapter;
|
import android.support.wearable.view.GridPagerAdapter;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
@ -12,7 +10,7 @@ import android.widget.ImageView;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
|
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.data.ListenerService;
|
import info.nightscout.androidaps.data.DataLayerListenerService;
|
||||||
import info.nightscout.androidaps.interaction.utils.PlusMinusEditText;
|
import info.nightscout.androidaps.interaction.utils.PlusMinusEditText;
|
||||||
import info.nightscout.shared.SafeParse;
|
import info.nightscout.shared.SafeParse;
|
||||||
|
|
||||||
|
@ -33,7 +31,6 @@ public class WizardActivity extends ViewSelectorActivity {
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setAdapter(new MyGridViewPagerAdapter());
|
setAdapter(new MyGridViewPagerAdapter());
|
||||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
|
|
||||||
hasPercentage = sp.getBoolean("wizardpercentage", false);
|
hasPercentage = sp.getBoolean("wizardpercentage", false);
|
||||||
percentage = sp.getInt(getString(R.string.key_boluswizard_percentage), 100);
|
percentage = sp.getInt(getString(R.string.key_boluswizard_percentage), 100);
|
||||||
maxCarbs = sp.getInt(getString(R.string.key_treatmentssafety_maxcarbs), 48);
|
maxCarbs = sp.getInt(getString(R.string.key_treatmentssafety_maxcarbs), 48);
|
||||||
|
@ -93,8 +90,8 @@ public class WizardActivity extends ViewSelectorActivity {
|
||||||
|
|
||||||
String actionstring = "wizard2 " + SafeParse.stringToInt(editCarbs.editText.getText().toString())
|
String actionstring = "wizard2 " + SafeParse.stringToInt(editCarbs.editText.getText().toString())
|
||||||
+ " " + percentage;
|
+ " " + percentage;
|
||||||
ListenerService.initiateAction(WizardActivity.this, actionstring);
|
DataLayerListenerService.Companion.initiateAction(WizardActivity.this, actionstring);
|
||||||
confirmAction(WizardActivity.this, R.string.action_wizard_confirmation);
|
showToast(WizardActivity.this, R.string.action_wizard_confirmation);
|
||||||
finishAffinity();
|
finishAffinity();
|
||||||
});
|
});
|
||||||
container.addView(view);
|
container.addView(view);
|
||||||
|
|
|
@ -7,7 +7,7 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.data.ListenerService;
|
import info.nightscout.androidaps.data.DataLayerListenerService;
|
||||||
import info.nightscout.androidaps.interaction.actions.FillActivity;
|
import info.nightscout.androidaps.interaction.actions.FillActivity;
|
||||||
import info.nightscout.androidaps.interaction.utils.MenuListActivity;
|
import info.nightscout.androidaps.interaction.utils.MenuListActivity;
|
||||||
|
|
||||||
|
@ -37,11 +37,11 @@ public class FillMenuActivity extends MenuListActivity {
|
||||||
@Override
|
@Override
|
||||||
protected void doAction(String action) {
|
protected void doAction(String action) {
|
||||||
if (getString(R.string.action_preset_1).equals(action)) {
|
if (getString(R.string.action_preset_1).equals(action)) {
|
||||||
ListenerService.initiateAction(this, "fillpreset 1");
|
DataLayerListenerService.Companion.initiateAction(this, "fillpreset 1");
|
||||||
} else if (getString(R.string.action_preset_2).equals(action)) {
|
} else if (getString(R.string.action_preset_2).equals(action)) {
|
||||||
ListenerService.initiateAction(this, "fillpreset 2");
|
DataLayerListenerService.Companion.initiateAction(this, "fillpreset 2");
|
||||||
} else if (getString(R.string.action_preset_3).equals(action)) {
|
} else if (getString(R.string.action_preset_3).equals(action)) {
|
||||||
ListenerService.initiateAction(this, "fillpreset 3");
|
DataLayerListenerService.Companion.initiateAction(this, "fillpreset 3");
|
||||||
} else if (getString(R.string.action_free_amount).equals(action)) {
|
} else if (getString(R.string.action_free_amount).equals(action)) {
|
||||||
Intent intent = new Intent(this, FillActivity.class);
|
Intent intent = new Intent(this, FillActivity.class);
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
|
|
@ -9,11 +9,11 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.data.ListenerService;
|
import info.nightscout.androidaps.data.DataLayerListenerService;
|
||||||
import info.nightscout.androidaps.interaction.AAPSPreferences;
|
import info.nightscout.androidaps.interaction.AAPSPreferences;
|
||||||
import info.nightscout.androidaps.interaction.actions.TreatmentActivity;
|
|
||||||
import info.nightscout.androidaps.interaction.actions.ECarbActivity;
|
import info.nightscout.androidaps.interaction.actions.ECarbActivity;
|
||||||
import info.nightscout.androidaps.interaction.actions.TempTargetActivity;
|
import info.nightscout.androidaps.interaction.actions.TempTargetActivity;
|
||||||
|
import info.nightscout.androidaps.interaction.actions.TreatmentActivity;
|
||||||
import info.nightscout.androidaps.interaction.actions.WizardActivity;
|
import info.nightscout.androidaps.interaction.actions.WizardActivity;
|
||||||
import info.nightscout.androidaps.interaction.utils.MenuListActivity;
|
import info.nightscout.androidaps.interaction.utils.MenuListActivity;
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ public class MainMenuActivity extends MenuListActivity {
|
||||||
sp = PreferenceManager.getDefaultSharedPreferences(this);
|
sp = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
setTitle(R.string.label_actions_activity);
|
setTitle(R.string.label_actions_activity);
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
ListenerService.requestData(this);
|
DataLayerListenerService.Companion.requestData(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -68,7 +68,7 @@ public class MainMenuActivity extends MenuListActivity {
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
this.startActivity(intent);
|
this.startActivity(intent);
|
||||||
} else if (getString(R.string.menu_resync).equals(action)) {
|
} else if (getString(R.string.menu_resync).equals(action)) {
|
||||||
ListenerService.requestData(this);
|
DataLayerListenerService.Companion.requestData(this);
|
||||||
} else if (getString(R.string.menu_tempt).equals(action)) {
|
} else if (getString(R.string.menu_tempt).equals(action)) {
|
||||||
intent = new Intent(this, TempTargetActivity.class);
|
intent = new Intent(this, TempTargetActivity.class);
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
|
|
@ -6,7 +6,7 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.data.ListenerService;
|
import info.nightscout.androidaps.data.DataLayerListenerService;
|
||||||
import info.nightscout.androidaps.interaction.utils.MenuListActivity;
|
import info.nightscout.androidaps.interaction.utils.MenuListActivity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,13 +35,13 @@ public class StatusMenuActivity extends MenuListActivity {
|
||||||
@Override
|
@Override
|
||||||
protected void doAction(String action) {
|
protected void doAction(String action) {
|
||||||
if (getString(R.string.status_pump).equals(action)) {
|
if (getString(R.string.status_pump).equals(action)) {
|
||||||
ListenerService.initiateAction(this, "status pump");
|
DataLayerListenerService.Companion.initiateAction(this, "status pump");
|
||||||
} else if (getString(R.string.status_loop).equals(action)) {
|
} else if (getString(R.string.status_loop).equals(action)) {
|
||||||
ListenerService.initiateAction(this, "status loop");
|
DataLayerListenerService.Companion.initiateAction(this, "status loop");
|
||||||
} else if (getString(R.string.status_cpp).equals(action)) {
|
} else if (getString(R.string.status_cpp).equals(action)) {
|
||||||
ListenerService.initiateAction(this, "opencpp");
|
DataLayerListenerService.Companion.initiateAction(this, "opencpp");
|
||||||
} else if (getString(R.string.status_tdd).equals(action)) {
|
} else if (getString(R.string.status_tdd).equals(action)) {
|
||||||
ListenerService.initiateAction(this, "tddstats");
|
DataLayerListenerService.Companion.initiateAction(this, "tddstats");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.data.BasalWatchData;
|
import info.nightscout.androidaps.data.BasalWatchData;
|
||||||
import info.nightscout.androidaps.data.BgWatchData;
|
import info.nightscout.androidaps.data.BgWatchData;
|
||||||
import info.nightscout.androidaps.data.BolusWatchData;
|
import info.nightscout.androidaps.data.BolusWatchData;
|
||||||
import info.nightscout.androidaps.data.ListenerService;
|
import info.nightscout.androidaps.data.DataLayerListenerService;
|
||||||
import info.nightscout.androidaps.data.TempWatchData;
|
import info.nightscout.androidaps.data.TempWatchData;
|
||||||
import info.nightscout.androidaps.interaction.menus.MainMenuActivity;
|
import info.nightscout.androidaps.interaction.menus.MainMenuActivity;
|
||||||
import lecho.lib.hellocharts.view.LineChartView;
|
import lecho.lib.hellocharts.view.LineChartView;
|
||||||
|
@ -158,7 +158,7 @@ public class BIGChart extends WatchFace implements SharedPreferences.OnSharedPre
|
||||||
mRelativeLayout.getMeasuredHeight());
|
mRelativeLayout.getMeasuredHeight());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
ListenerService.requestData(this);
|
DataLayerListenerService.Companion.requestData(this);
|
||||||
wakeLock.acquire(50);
|
wakeLock.acquire(50);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -636,7 +636,7 @@ public class BIGChart extends WatchFace implements SharedPreferences.OnSharedPre
|
||||||
public void missedReadingAlert() {
|
public void missedReadingAlert() {
|
||||||
int minutes_since = (int) Math.floor(timeSince() / (1000 * 60));
|
int minutes_since = (int) Math.floor(timeSince() / (1000 * 60));
|
||||||
if (minutes_since >= 16 && ((minutes_since - 16) % 5) == 0) {
|
if (minutes_since >= 16 && ((minutes_since - 16) % 5) == 0) {
|
||||||
ListenerService.requestData(this); // attempt endTime recover missing data
|
DataLayerListenerService.Companion.requestData(this); // attempt endTime recover missing data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -690,7 +690,7 @@ public class BIGChart extends WatchFace implements SharedPreferences.OnSharedPre
|
||||||
chart.setViewportCalculationEnabled(true);
|
chart.setViewportCalculationEnabled(true);
|
||||||
chart.setMaximumViewport(chart.getMaximumViewport());
|
chart.setMaximumViewport(chart.getMaximumViewport());
|
||||||
} else {
|
} else {
|
||||||
ListenerService.requestData(this);
|
DataLayerListenerService.Companion.requestData(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ import javax.inject.Inject;
|
||||||
|
|
||||||
import dagger.android.AndroidInjection;
|
import dagger.android.AndroidInjection;
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.data.ListenerService;
|
import info.nightscout.androidaps.data.DataLayerListenerService;
|
||||||
import info.nightscout.androidaps.data.RawDisplayData;
|
import info.nightscout.androidaps.data.RawDisplayData;
|
||||||
import info.nightscout.androidaps.interaction.utils.Persistence;
|
import info.nightscout.androidaps.interaction.utils.Persistence;
|
||||||
import info.nightscout.androidaps.interaction.utils.WearUtil;
|
import info.nightscout.androidaps.interaction.utils.WearUtil;
|
||||||
|
@ -678,7 +678,7 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||||
setupBatteryReceiver();
|
setupBatteryReceiver();
|
||||||
if ("delta_granularity".equals(key)) {
|
if ("delta_granularity".equals(key)) {
|
||||||
ListenerService.requestData(this);
|
DataLayerListenerService.Companion.requestData(this);
|
||||||
}
|
}
|
||||||
if (layoutSet) {
|
if (layoutSet) {
|
||||||
setDataFields();
|
setDataFields();
|
||||||
|
@ -695,7 +695,7 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
public void missedReadingAlert() {
|
public void missedReadingAlert() {
|
||||||
int minutes_since = (int) Math.floor(timeSince() / (1000 * 60));
|
int minutes_since = (int) Math.floor(timeSince() / (1000 * 60));
|
||||||
if (rawData.datetime == 0 || minutes_since >= 16 && ((minutes_since - 16) % 5) == 0) {
|
if (rawData.datetime == 0 || minutes_since >= 16 && ((minutes_since - 16) % 5) == 0) {
|
||||||
ListenerService.requestData(this); // Attempt endTime recover missing data
|
DataLayerListenerService.Companion.requestData(this); // Attempt endTime recover missing data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -728,7 +728,7 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
setupCharts();
|
setupCharts();
|
||||||
}
|
}
|
||||||
rawData.updateStatusFromMessage(intent, wakeLock);
|
rawData.updateStatusFromMessage(intent, wakeLock);
|
||||||
rawData.updateBasalsFromMessage(intent, wakeLock);
|
rawData.updateBasalsFromMessage(intent);
|
||||||
|
|
||||||
if (isSimpleUi()) {
|
if (isSimpleUi()) {
|
||||||
if (needUpdate()) {
|
if (needUpdate()) {
|
||||||
|
|
|
@ -43,7 +43,7 @@ import java.util.ArrayList;
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.data.BasalWatchData;
|
import info.nightscout.androidaps.data.BasalWatchData;
|
||||||
import info.nightscout.androidaps.data.BgWatchData;
|
import info.nightscout.androidaps.data.BgWatchData;
|
||||||
import info.nightscout.androidaps.data.ListenerService;
|
import info.nightscout.androidaps.data.DataLayerListenerService;
|
||||||
import info.nightscout.androidaps.data.TempWatchData;
|
import info.nightscout.androidaps.data.TempWatchData;
|
||||||
import info.nightscout.androidaps.interaction.menus.MainMenuActivity;
|
import info.nightscout.androidaps.interaction.menus.MainMenuActivity;
|
||||||
|
|
||||||
|
@ -137,7 +137,7 @@ public class NOChart extends WatchFace implements SharedPreferences.OnSharedPref
|
||||||
mRelativeLayout.getMeasuredHeight());
|
mRelativeLayout.getMeasuredHeight());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
ListenerService.requestData(this);
|
DataLayerListenerService.Companion.requestData(this);
|
||||||
wakeLock.acquire(50);
|
wakeLock.acquire(50);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -518,7 +518,7 @@ public class NOChart extends WatchFace implements SharedPreferences.OnSharedPref
|
||||||
public void missedReadingAlert() {
|
public void missedReadingAlert() {
|
||||||
int minutes_since = (int) Math.floor(timeSince()/(1000*60));
|
int minutes_since = (int) Math.floor(timeSince()/(1000*60));
|
||||||
if(minutes_since >= 16 && ((minutes_since - 16) % 5) == 0) {
|
if(minutes_since >= 16 && ((minutes_since - 16) % 5) == 0) {
|
||||||
ListenerService.requestData(this); // attempt endTime recover missing data
|
DataLayerListenerService.Companion.requestData(this); // attempt endTime recover missing data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?><!--
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
Copyright 2015 Google Inc. All rights reserved.
|
<!-- Copyright (C) 2021 The Android Open Source Project
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
You may obtain a copy of the License at
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
Unless required by applicable law or agreed to in writing, software
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -11,8 +14,12 @@
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<resources>
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
<string-array name="android_wear_capabilities">
|
<string-array
|
||||||
<item>phone_app_sync_bgs</item>
|
name="android_wear_capabilities"
|
||||||
|
translatable="false"
|
||||||
|
tools:ignore="UnusedResources">
|
||||||
|
<!-- declaring the provided capabilities -->
|
||||||
|
<item>androidaps_wear</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
</resources>
|
</resources>
|
|
@ -220,7 +220,7 @@ public class RawDisplayDataBasalsTest extends TestBase {
|
||||||
RawDisplayData newRaw = new RawDisplayData(getWearUtil());
|
RawDisplayData newRaw = new RawDisplayData(getWearUtil());
|
||||||
|
|
||||||
// WHEN
|
// WHEN
|
||||||
newRaw.updateBasalsFromMessage(intent, null);
|
newRaw.updateBasalsFromMessage(intent);
|
||||||
|
|
||||||
// THEN
|
// THEN
|
||||||
assertBasalsOk(newRaw);
|
assertBasalsOk(newRaw);
|
||||||
|
@ -233,7 +233,7 @@ public class RawDisplayDataBasalsTest extends TestBase {
|
||||||
RawDisplayData newRaw = new RawDisplayData(getWearUtil());
|
RawDisplayData newRaw = new RawDisplayData(getWearUtil());
|
||||||
|
|
||||||
// WHEN
|
// WHEN
|
||||||
newRaw.updateBasalsFromMessage(intent, null);
|
newRaw.updateBasalsFromMessage(intent);
|
||||||
|
|
||||||
// THEN
|
// THEN
|
||||||
assertBasalsEmpty(newRaw);
|
assertBasalsEmpty(newRaw);
|
||||||
|
|
Loading…
Reference in a new issue