Wear: migrate to RxBus comm and data classes
This commit is contained in:
parent
2dba081176
commit
2ebaffa4ad
99 changed files with 3716 additions and 6509 deletions
|
@ -167,7 +167,7 @@
|
||||||
</provider>
|
</provider>
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".plugins.general.wear.wearintegration.WatchUpdaterService"
|
android:name=".plugins.general.wear.wearintegration.DataLayerListenerServiceMobile"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="com.google.android.gms.wearable.CHANNEL_EVENT" />
|
<action android:name="com.google.android.gms.wearable.CHANNEL_EVENT" />
|
||||||
|
@ -185,23 +185,7 @@
|
||||||
|
|
||||||
<data
|
<data
|
||||||
android:host="*"
|
android:host="*"
|
||||||
android:pathPrefix="@string/path_pong"
|
android:pathPrefix="@string/path_rx_bridge"
|
||||||
android:scheme="wear" />
|
|
||||||
<data
|
|
||||||
android:host="*"
|
|
||||||
android:pathPrefix="@string/path_resend_data_request"
|
|
||||||
android:scheme="wear" />
|
|
||||||
<data
|
|
||||||
android:host="*"
|
|
||||||
android:pathPrefix="/@path_cancel_bolus_on_watch"
|
|
||||||
android:scheme="wear" />
|
|
||||||
<data
|
|
||||||
android:host="*"
|
|
||||||
android:pathPrefix="@string/path_confirm_action"
|
|
||||||
android:scheme="wear" />
|
|
||||||
<data
|
|
||||||
android:host="*"
|
|
||||||
android:pathPrefix="@string/path_initiate_action_on_phone"
|
|
||||||
android:scheme="wear" />
|
android:scheme="wear" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</service>
|
</service>
|
||||||
|
|
|
@ -5,7 +5,7 @@ import dagger.android.ContributesAndroidInjector
|
||||||
import info.nightscout.androidaps.plugins.general.nsclient.services.NSClientService
|
import info.nightscout.androidaps.plugins.general.nsclient.services.NSClientService
|
||||||
import info.nightscout.androidaps.plugins.general.overview.notifications.DismissNotificationService
|
import info.nightscout.androidaps.plugins.general.overview.notifications.DismissNotificationService
|
||||||
import info.nightscout.androidaps.plugins.general.persistentNotification.DummyService
|
import info.nightscout.androidaps.plugins.general.persistentNotification.DummyService
|
||||||
import info.nightscout.androidaps.plugins.general.wear.wearintegration.WatchUpdaterService
|
import info.nightscout.androidaps.plugins.general.wear.wearintegration.DataLayerListenerServiceMobile
|
||||||
import info.nightscout.androidaps.services.AlarmSoundService
|
import info.nightscout.androidaps.services.AlarmSoundService
|
||||||
import info.nightscout.androidaps.services.LocationService
|
import info.nightscout.androidaps.services.LocationService
|
||||||
|
|
||||||
|
@ -18,5 +18,5 @@ abstract class ServicesModule {
|
||||||
@ContributesAndroidInjector abstract fun contributesDummyService(): DummyService
|
@ContributesAndroidInjector abstract fun contributesDummyService(): DummyService
|
||||||
@ContributesAndroidInjector abstract fun contributesLocationService(): LocationService
|
@ContributesAndroidInjector abstract fun contributesLocationService(): LocationService
|
||||||
@ContributesAndroidInjector abstract fun contributesNSClientService(): NSClientService
|
@ContributesAndroidInjector abstract fun contributesNSClientService(): NSClientService
|
||||||
@ContributesAndroidInjector abstract fun contributesWatchUpdaterService(): WatchUpdaterService
|
@ContributesAndroidInjector abstract fun contributesWatchUpdaterService(): DataLayerListenerServiceMobile
|
||||||
}
|
}
|
|
@ -1,3 +0,0 @@
|
||||||
package info.nightscout.androidaps.events
|
|
||||||
|
|
||||||
class EventBolusRequested(var amount: Double) : Event()
|
|
|
@ -27,6 +27,7 @@ import info.nightscout.androidaps.database.entities.ValueWithUnit
|
||||||
import info.nightscout.androidaps.database.transactions.InsertAndCancelCurrentOfflineEventTransaction
|
import info.nightscout.androidaps.database.transactions.InsertAndCancelCurrentOfflineEventTransaction
|
||||||
import info.nightscout.androidaps.database.transactions.InsertTherapyEventAnnouncementTransaction
|
import info.nightscout.androidaps.database.transactions.InsertTherapyEventAnnouncementTransaction
|
||||||
import info.nightscout.androidaps.events.EventAcceptOpenLoopChange
|
import info.nightscout.androidaps.events.EventAcceptOpenLoopChange
|
||||||
|
import info.nightscout.androidaps.events.EventMobileToWear
|
||||||
import info.nightscout.androidaps.events.EventTempTargetChange
|
import info.nightscout.androidaps.events.EventTempTargetChange
|
||||||
import info.nightscout.androidaps.extensions.buildDeviceStatus
|
import info.nightscout.androidaps.extensions.buildDeviceStatus
|
||||||
import info.nightscout.androidaps.extensions.convertedToAbsolute
|
import info.nightscout.androidaps.extensions.convertedToAbsolute
|
||||||
|
@ -44,8 +45,6 @@ import info.nightscout.androidaps.plugins.configBuilder.RunningConfiguration
|
||||||
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification
|
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification
|
||||||
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
|
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
|
||||||
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
|
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
|
||||||
import info.nightscout.androidaps.plugins.general.wear.events.EventWearConfirmAction
|
|
||||||
import info.nightscout.androidaps.plugins.general.wear.events.EventWearInitiateAction
|
|
||||||
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin
|
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin
|
||||||
import info.nightscout.androidaps.queue.Callback
|
import info.nightscout.androidaps.queue.Callback
|
||||||
import info.nightscout.androidaps.receivers.ReceiverStatusStore
|
import info.nightscout.androidaps.receivers.ReceiverStatusStore
|
||||||
|
@ -58,6 +57,7 @@ import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
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
|
||||||
|
import info.nightscout.shared.weardata.EventData
|
||||||
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 javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -349,7 +349,7 @@ class LoopPlugin @Inject constructor(
|
||||||
//only send to wear if Native notifications are turned off
|
//only send to wear if Native notifications are turned off
|
||||||
if (!sp.getBoolean(R.string.key_raise_notifications_as_android_notifications, true)) {
|
if (!sp.getBoolean(R.string.key_raise_notifications_as_android_notifications, true)) {
|
||||||
// Send to Wear
|
// Send to Wear
|
||||||
rxBus.send(EventWearInitiateAction("changeRequest"))
|
sendToWear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -454,14 +454,28 @@ class LoopPlugin @Inject constructor(
|
||||||
rxBus.send(EventNewOpenLoopNotification())
|
rxBus.send(EventNewOpenLoopNotification())
|
||||||
|
|
||||||
// Send to Wear
|
// Send to Wear
|
||||||
rxBus.send(EventWearInitiateAction("changeRequest"))
|
sendToWear()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun dismissSuggestion() {
|
private fun dismissSuggestion() {
|
||||||
// dismiss notifications
|
// dismiss notifications
|
||||||
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)
|
||||||
rxBus.send(EventWearConfirmAction("cancelChangeRequest"))
|
rxBus.send(EventMobileToWear(EventData.CancelNotification(dateUtil.now())))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sendToWear() {
|
||||||
|
lastRun?.let {
|
||||||
|
rxBus.send(
|
||||||
|
EventMobileToWear(
|
||||||
|
EventData.OpenLoopRequest(
|
||||||
|
rh.gs(R.string.openloop_newsuggestion),
|
||||||
|
it.constraintsProcessed.toString(),
|
||||||
|
EventData.OpenLoopRequestConfirmed(dateUtil.now())
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun acceptChangeRequest() {
|
override fun acceptChangeRequest() {
|
||||||
|
|
|
@ -54,7 +54,6 @@ import info.nightscout.androidaps.plugins.general.overview.activities.QuickWizar
|
||||||
import info.nightscout.androidaps.plugins.general.overview.events.*
|
import info.nightscout.androidaps.plugins.general.overview.events.*
|
||||||
import info.nightscout.androidaps.plugins.general.overview.graphData.GraphData
|
import info.nightscout.androidaps.plugins.general.overview.graphData.GraphData
|
||||||
import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationStore
|
import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationStore
|
||||||
import info.nightscout.androidaps.plugins.general.wear.events.EventWearInitiateAction
|
|
||||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider
|
||||||
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
|
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.eros.OmnipodErosPumpPlugin
|
import info.nightscout.androidaps.plugins.pump.omnipod.eros.OmnipodErosPumpPlugin
|
||||||
|
@ -76,6 +75,7 @@ import info.nightscout.androidaps.utils.ui.UIRunnable
|
||||||
import info.nightscout.androidaps.utils.wizard.QuickWizard
|
import info.nightscout.androidaps.utils.wizard.QuickWizard
|
||||||
import info.nightscout.shared.logging.AAPSLogger
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
import info.nightscout.shared.sharedPreferences.SP
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
|
import info.nightscout.shared.weardata.EventData
|
||||||
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.util.*
|
import java.util.*
|
||||||
|
@ -408,7 +408,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
||||||
?: "".toSpanned(), {
|
?: "".toSpanned(), {
|
||||||
uel.log(Action.ACCEPTS_TEMP_BASAL, Sources.Overview)
|
uel.log(Action.ACCEPTS_TEMP_BASAL, Sources.Overview)
|
||||||
(context?.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager?)?.cancel(Constants.notificationID)
|
(context?.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager?)?.cancel(Constants.notificationID)
|
||||||
rxBus.send(EventWearInitiateAction("cancelChangeRequest"))
|
rxBus.send(EventMobileToWear(EventData.CancelNotification(dateUtil.now())))
|
||||||
Thread { loop.acceptChangeRequest() }.run()
|
Thread { loop.acceptChangeRequest() }.run()
|
||||||
binding.buttonsLayout.acceptTempButton.visibility = View.GONE
|
binding.buttonsLayout.acceptTempButton.visibility = View.GONE
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,841 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.wear
|
|
||||||
|
|
||||||
import android.app.NotificationManager
|
|
||||||
import android.content.Context
|
|
||||||
import dagger.android.HasAndroidInjector
|
|
||||||
import info.nightscout.androidaps.Constants
|
|
||||||
import info.nightscout.androidaps.R
|
|
||||||
import info.nightscout.androidaps.dana.DanaPump
|
|
||||||
import info.nightscout.androidaps.danaRKorean.DanaRKoreanPlugin
|
|
||||||
import info.nightscout.androidaps.danaRv2.DanaRv2Plugin
|
|
||||||
import info.nightscout.androidaps.danar.DanaRPlugin
|
|
||||||
import info.nightscout.androidaps.danars.DanaRSPlugin
|
|
||||||
import info.nightscout.androidaps.data.DetailedBolusInfo
|
|
||||||
import info.nightscout.androidaps.database.AppRepository
|
|
||||||
import info.nightscout.androidaps.database.ValueWrapper
|
|
||||||
import info.nightscout.androidaps.database.entities.TemporaryTarget
|
|
||||||
import info.nightscout.androidaps.database.entities.TotalDailyDose
|
|
||||||
import info.nightscout.androidaps.database.entities.UserEntry.Action
|
|
||||||
import info.nightscout.androidaps.database.entities.UserEntry.Sources
|
|
||||||
import info.nightscout.androidaps.database.entities.ValueWithUnit
|
|
||||||
import info.nightscout.androidaps.database.interfaces.end
|
|
||||||
import info.nightscout.androidaps.database.transactions.CancelCurrentTemporaryTargetIfAnyTransaction
|
|
||||||
import info.nightscout.androidaps.database.transactions.InsertAndCancelCurrentTemporaryTargetTransaction
|
|
||||||
import info.nightscout.androidaps.extensions.total
|
|
||||||
import info.nightscout.androidaps.extensions.valueToUnits
|
|
||||||
import info.nightscout.androidaps.interfaces.*
|
|
||||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
|
||||||
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification
|
|
||||||
import info.nightscout.androidaps.plugins.general.wear.events.EventWearConfirmAction
|
|
||||||
import info.nightscout.androidaps.plugins.general.wear.events.EventWearInitiateAction
|
|
||||||
import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin
|
|
||||||
import info.nightscout.androidaps.queue.Callback
|
|
||||||
import info.nightscout.androidaps.utils.*
|
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
|
||||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
|
||||||
import info.nightscout.androidaps.utils.wizard.BolusWizard
|
|
||||||
import info.nightscout.androidaps.utils.wizard.QuickWizard
|
|
||||||
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.kotlin.plusAssign
|
|
||||||
import java.text.DateFormat
|
|
||||||
import java.text.SimpleDateFormat
|
|
||||||
import java.util.*
|
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
import javax.inject.Inject
|
|
||||||
import javax.inject.Singleton
|
|
||||||
import kotlin.math.abs
|
|
||||||
import kotlin.math.min
|
|
||||||
|
|
||||||
@Suppress("SpellCheckingInspection")
|
|
||||||
@Singleton
|
|
||||||
class ActionStringHandler @Inject constructor(
|
|
||||||
private val sp: SP,
|
|
||||||
private val rxBus: RxBus,
|
|
||||||
private val aapsLogger: AAPSLogger,
|
|
||||||
private val aapsSchedulers: AapsSchedulers,
|
|
||||||
private val rh: ResourceHelper,
|
|
||||||
private val injector: HasAndroidInjector,
|
|
||||||
private val context: Context,
|
|
||||||
private val constraintChecker: ConstraintChecker,
|
|
||||||
private val profileFunction: ProfileFunction,
|
|
||||||
private val loop: Loop,
|
|
||||||
private val wearPlugin: WearPlugin,
|
|
||||||
private val fabricPrivacy: FabricPrivacy,
|
|
||||||
private val commandQueue: CommandQueue,
|
|
||||||
private val activePlugin: ActivePlugin,
|
|
||||||
private val iobCobCalculator: IobCobCalculator,
|
|
||||||
private val localInsightPlugin: LocalInsightPlugin,
|
|
||||||
private val quickWizard: QuickWizard,
|
|
||||||
private val danaRPlugin: DanaRPlugin,
|
|
||||||
private val danaRKoreanPlugin: DanaRKoreanPlugin,
|
|
||||||
private val danaRv2Plugin: DanaRv2Plugin,
|
|
||||||
private val danaRSPlugin: DanaRSPlugin,
|
|
||||||
private val danaPump: DanaPump,
|
|
||||||
private val dateUtil: DateUtil,
|
|
||||||
private val config: Config,
|
|
||||||
private val repository: AppRepository,
|
|
||||||
private val uel: UserEntryLogger,
|
|
||||||
private val defaultValueHelper: DefaultValueHelper
|
|
||||||
) {
|
|
||||||
|
|
||||||
private val timeout = 65 * 1000
|
|
||||||
private var lastSentTimestamp: Long = 0
|
|
||||||
private var lastConfirmActionString: String? = null
|
|
||||||
private var lastBolusWizard: BolusWizard? = null
|
|
||||||
|
|
||||||
private val disposable = CompositeDisposable()
|
|
||||||
|
|
||||||
fun setup() {
|
|
||||||
disposable += rxBus
|
|
||||||
.toObservable(EventWearInitiateAction::class.java)
|
|
||||||
.observeOn(aapsSchedulers.main)
|
|
||||||
.subscribe({ handleInitiateActionOnPhone(it.action) }, fabricPrivacy::logException)
|
|
||||||
|
|
||||||
disposable += rxBus
|
|
||||||
.toObservable(EventWearConfirmAction::class.java)
|
|
||||||
.observeOn(aapsSchedulers.main)
|
|
||||||
.subscribe({ handleConfirmation(it.action) }, fabricPrivacy::logException)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun tearDown() {
|
|
||||||
disposable.clear()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Synchronized
|
|
||||||
private fun handleInitiateActionOnPhone(actionString: String) {
|
|
||||||
//TODO: i18n
|
|
||||||
aapsLogger.debug(LTag.WEAR, "handleInitiateActionOnPhone actionString=$actionString")
|
|
||||||
if (!sp.getBoolean(R.string.key_wear_control, false)) return
|
|
||||||
lastBolusWizard = null
|
|
||||||
var rTitle = rh.gs(R.string.confirm).uppercase()
|
|
||||||
var rMessage = ""
|
|
||||||
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
|
|
||||||
val act = actionString.split("\\s+".toRegex()).toTypedArray()
|
|
||||||
when (act[0]) {
|
|
||||||
ACTION_FILL_PRESET -> { ///////////////////////////////////// PRIME/FILL
|
|
||||||
val amount: Double = when {
|
|
||||||
"1" == act[1] -> sp.getDouble("fill_button1", 0.3)
|
|
||||||
"2" == act[1] -> sp.getDouble("fill_button2", 0.0)
|
|
||||||
"3" == act[1] -> sp.getDouble("fill_button3", 0.0)
|
|
||||||
else -> return
|
|
||||||
}
|
|
||||||
val insulinAfterConstraints = constraintChecker.applyBolusConstraints(Constraint(amount)).value()
|
|
||||||
rMessage += rh.gs(R.string.primefill) + ": " + insulinAfterConstraints + "U"
|
|
||||||
if (insulinAfterConstraints - amount != 0.0) rMessage += "\n" + rh.gs(R.string.constraintapllied)
|
|
||||||
rAction += "fill $insulinAfterConstraints"
|
|
||||||
}
|
|
||||||
|
|
||||||
ACTION_FILL -> {
|
|
||||||
val amount = SafeParse.stringToDouble(act[1])
|
|
||||||
val insulinAfterConstraints = constraintChecker.applyBolusConstraints(Constraint(amount)).value()
|
|
||||||
rMessage += rh.gs(R.string.primefill) + ": " + insulinAfterConstraints + "U"
|
|
||||||
if (insulinAfterConstraints - amount != 0.0) rMessage += "\n" + rh.gs(R.string.constraintapllied)
|
|
||||||
rAction += "fill $insulinAfterConstraints"
|
|
||||||
}
|
|
||||||
|
|
||||||
ACTION_TEMPORARY_TARGET -> {
|
|
||||||
aapsLogger.info(LTag.WEAR, "temptarget received: $act")
|
|
||||||
if ("cancel" == act[1]) {
|
|
||||||
rMessage += rh.gs(R.string.wear_action_tempt_cancel_message)
|
|
||||||
rAction = "temptarget true 0 0 0"
|
|
||||||
} else if ("preset" == act[1]) {
|
|
||||||
val presetIsMGDL = profileFunction.getUnits() == GlucoseUnit.MGDL
|
|
||||||
val preset = act[2]
|
|
||||||
when (preset) {
|
|
||||||
"activity" -> {
|
|
||||||
val activityTTDuration = defaultValueHelper.determineActivityTTDuration()
|
|
||||||
val activityTT = defaultValueHelper.determineActivityTT()
|
|
||||||
val reason = rh.gs(R.string.activity)
|
|
||||||
rMessage += rh.gs(R.string.wear_action_tempt_preset_message, reason, activityTT, activityTTDuration)
|
|
||||||
rAction = "temptarget $presetIsMGDL $activityTTDuration $activityTT $activityTT"
|
|
||||||
}
|
|
||||||
|
|
||||||
"hypo" -> {
|
|
||||||
val hypoTTDuration = defaultValueHelper.determineHypoTTDuration()
|
|
||||||
val hypoTT = defaultValueHelper.determineHypoTT()
|
|
||||||
val reason = rh.gs(R.string.hypo)
|
|
||||||
rMessage += rh.gs(R.string.wear_action_tempt_preset_message, reason, hypoTT, hypoTTDuration)
|
|
||||||
rAction = "temptarget $presetIsMGDL $hypoTTDuration $hypoTT $hypoTT"
|
|
||||||
}
|
|
||||||
|
|
||||||
"eating" -> {
|
|
||||||
val eatingSoonTTDuration = defaultValueHelper.determineEatingSoonTTDuration()
|
|
||||||
val eatingSoonTT = defaultValueHelper.determineEatingSoonTT()
|
|
||||||
val reason = rh.gs(R.string.eatingsoon)
|
|
||||||
rMessage += rh.gs(R.string.wear_action_tempt_preset_message, reason, eatingSoonTT, eatingSoonTTDuration)
|
|
||||||
rAction = "temptarget $presetIsMGDL $eatingSoonTTDuration $eatingSoonTT $eatingSoonTT"
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> {
|
|
||||||
sendError(rh.gs(R.string.wear_action_tempt_preset_error, preset))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
val isMGDL = java.lang.Boolean.parseBoolean(act[1])
|
|
||||||
if (profileFunction.getUnits() == GlucoseUnit.MGDL != isMGDL) {
|
|
||||||
sendError(rh.gs(R.string.wear_action_tempt_unit_error))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
val duration = SafeParse.stringToInt(act[2])
|
|
||||||
if (duration == 0) {
|
|
||||||
rMessage += rh.gs(R.string.wear_action_tempt_zero_message)
|
|
||||||
rAction = "temptarget true 0 0 0"
|
|
||||||
} else {
|
|
||||||
var low = SafeParse.stringToDouble(act[3])
|
|
||||||
var high = SafeParse.stringToDouble(act[4])
|
|
||||||
if (!isMGDL) {
|
|
||||||
low *= Constants.MMOLL_TO_MGDL
|
|
||||||
high *= Constants.MMOLL_TO_MGDL
|
|
||||||
}
|
|
||||||
if (low < HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[0] || low > HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[1]) {
|
|
||||||
sendError(rh.gs(R.string.wear_action_tempt_min_bg_error))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (high < HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[0] || high > HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[1]) {
|
|
||||||
sendError(rh.gs(R.string.wear_action_tempt_max_bg_error))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
rMessage += if (act[3] === act[4]) rh.gs(R.string.wear_action_tempt_manual_message, act[3], act[2])
|
|
||||||
else rh.gs(R.string.wear_action_tempt_manual_range_message, act[3], act[4], act[2])
|
|
||||||
rAction = actionString
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ACTION_STATUS -> {
|
|
||||||
rTitle = "STATUS"
|
|
||||||
rAction = "statusmessage"
|
|
||||||
if ("pump" == act[1]) {
|
|
||||||
rTitle += " PUMP"
|
|
||||||
rMessage = pumpStatus
|
|
||||||
} else if ("loop" == act[1]) {
|
|
||||||
rTitle += " LOOP"
|
|
||||||
rMessage = "TARGETS:\n$targetsStatus"
|
|
||||||
rMessage += "\n\n" + loopStatus
|
|
||||||
rMessage += "\n\nOAPS RESULT:\n$oAPSResultStatus"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ACTION_WIZARD -> {
|
|
||||||
sendError("Update APP on Watch!")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ACTION_WIZARD2 -> {
|
|
||||||
val pump = activePlugin.activePump
|
|
||||||
if (!pump.isInitialized() || pump.isSuspended() || loop.isDisconnected) {
|
|
||||||
sendError(rh.gs(R.string.wizard_pump_not_available))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
val carbsBeforeConstraints = SafeParse.stringToInt(act[1])
|
|
||||||
val carbsAfterConstraints = constraintChecker.applyCarbsConstraints(Constraint(carbsBeforeConstraints)).value()
|
|
||||||
if (carbsAfterConstraints - carbsBeforeConstraints != 0) {
|
|
||||||
sendError(rh.gs(R.string.wizard_carbs_constraint))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
val useBG = sp.getBoolean(R.string.key_wearwizard_bg, true)
|
|
||||||
val useTT = sp.getBoolean(R.string.key_wearwizard_tt, false)
|
|
||||||
val useBolusIOB = sp.getBoolean(R.string.key_wearwizard_bolusiob, true)
|
|
||||||
val useBasalIOB = sp.getBoolean(R.string.key_wearwizard_basaliob, true)
|
|
||||||
val useCOB = sp.getBoolean(R.string.key_wearwizard_cob, true)
|
|
||||||
val useTrend = sp.getBoolean(R.string.key_wearwizard_trend, false)
|
|
||||||
val percentage = act[2].toInt()
|
|
||||||
val profile = profileFunction.getProfile()
|
|
||||||
val profileName = profileFunction.getProfileName()
|
|
||||||
if (profile == null) {
|
|
||||||
sendError(rh.gs(R.string.wizard_no_active_profile))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
val bgReading = iobCobCalculator.ads.actualBg()
|
|
||||||
if (bgReading == null) {
|
|
||||||
sendError(rh.gs(R.string.wizard_no_actual_bg))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
val cobInfo = iobCobCalculator.getCobInfo(false, "Wizard wear")
|
|
||||||
if (cobInfo.displayCob == null) {
|
|
||||||
sendError(rh.gs(R.string.wizard_no_cob))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
val dbRecord = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet()
|
|
||||||
val tempTarget = if (dbRecord is ValueWrapper.Existing) dbRecord.value else null
|
|
||||||
|
|
||||||
val bolusWizard = BolusWizard(injector).doCalc(
|
|
||||||
profile, profileName, tempTarget,
|
|
||||||
carbsAfterConstraints, cobInfo.displayCob!!, bgReading.valueToUnits(profileFunction.getUnits()),
|
|
||||||
0.0, percentage, useBG, useCOB, useBolusIOB, useBasalIOB, false, useTT, useTrend, false
|
|
||||||
)
|
|
||||||
val insulinAfterConstraints = bolusWizard.insulinAfterConstraints
|
|
||||||
val minStep = pump.pumpDescription.pumpType.determineCorrectBolusStepSize(insulinAfterConstraints)
|
|
||||||
if (abs(insulinAfterConstraints - bolusWizard.calculatedTotalInsulin) >= minStep) {
|
|
||||||
sendError(rh.gs(R.string.wizard_constraint_bolus_size, bolusWizard.calculatedTotalInsulin))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (bolusWizard.calculatedTotalInsulin <= 0 && bolusWizard.carbs <= 0) {
|
|
||||||
rAction = "info"
|
|
||||||
rTitle = rh.gs(R.string.info)
|
|
||||||
} else {
|
|
||||||
rAction = actionString
|
|
||||||
}
|
|
||||||
rMessage += rh.gs(R.string.wizard_result, bolusWizard.calculatedTotalInsulin, bolusWizard.carbs)
|
|
||||||
rMessage += "\n_____________"
|
|
||||||
rMessage += "\n" + bolusWizard.explainShort()
|
|
||||||
lastBolusWizard = bolusWizard
|
|
||||||
}
|
|
||||||
|
|
||||||
ACTION_QUICK_WIZARD -> {
|
|
||||||
val guid = act[1]
|
|
||||||
val actualBg = iobCobCalculator.ads.actualBg()
|
|
||||||
val profile = profileFunction.getProfile()
|
|
||||||
val profileName = profileFunction.getProfileName()
|
|
||||||
val quickWizardEntry = quickWizard.get(guid)
|
|
||||||
//Log.i("QuickWizard", "handleInitiate: quick_wizard " + quickWizardEntry?.buttonText() + " c " + quickWizardEntry?.carbs())
|
|
||||||
if (quickWizardEntry == null) {
|
|
||||||
sendError(rh.gs(R.string.quick_wizard_not_available))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (actualBg == null) {
|
|
||||||
sendError(rh.gs(R.string.wizard_no_actual_bg))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (profile == null) {
|
|
||||||
sendError(rh.gs(R.string.wizard_no_active_profile))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
val cobInfo = iobCobCalculator.getCobInfo(false, "QuickWizard wear")
|
|
||||||
if (cobInfo.displayCob == null) {
|
|
||||||
sendError(rh.gs(R.string.wizard_no_cob))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
val pump = activePlugin.activePump
|
|
||||||
if (!pump.isInitialized() || pump.isSuspended() || loop.isDisconnected) {
|
|
||||||
sendError(rh.gs(R.string.wizard_pump_not_available))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val wizard = quickWizardEntry.doCalc(profile, profileName, actualBg, true)
|
|
||||||
|
|
||||||
val carbsAfterConstraints = constraintChecker.applyCarbsConstraints(Constraint(quickWizardEntry.carbs())).value()
|
|
||||||
if (carbsAfterConstraints != quickWizardEntry.carbs()) {
|
|
||||||
sendError(rh.gs(R.string.wizard_carbs_constraint))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
val insulinAfterConstraints = wizard.insulinAfterConstraints
|
|
||||||
val minStep = pump.pumpDescription.pumpType.determineCorrectBolusStepSize(insulinAfterConstraints)
|
|
||||||
if (abs(insulinAfterConstraints - wizard.calculatedTotalInsulin) >= minStep) {
|
|
||||||
sendError(rh.gs(R.string.wizard_constraint_bolus_size, wizard.calculatedTotalInsulin))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
rMessage = rh.gs(R.string.quick_wizard_message, quickWizardEntry.buttonText(), wizard.calculatedTotalInsulin, quickWizardEntry.carbs())
|
|
||||||
rAction = "bolus $insulinAfterConstraints $carbsAfterConstraints"
|
|
||||||
//Log.i("QuickWizard", "handleInitiate: quick_wizard action=$rAction")
|
|
||||||
|
|
||||||
rMessage += "\n_____________"
|
|
||||||
rMessage += "\n" + wizard.explainShort()
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ACTION_OPEN_CPP -> {
|
|
||||||
val activeProfileSwitch = repository.getEffectiveProfileSwitchActiveAt(dateUtil.now()).blockingGet()
|
|
||||||
if (activeProfileSwitch is ValueWrapper.Existing) { // read CPP values
|
|
||||||
rTitle = "opencpp"
|
|
||||||
rMessage = "opencpp"
|
|
||||||
rAction = "opencpp" + " " + activeProfileSwitch.value.originalPercentage + " " + activeProfileSwitch.value.originalTimeshift
|
|
||||||
} else {
|
|
||||||
sendError("No active profile switch!")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ACTION_TDD_STATS -> {
|
|
||||||
val activePump = activePlugin.activePump
|
|
||||||
// check if DB up to date
|
|
||||||
val dummies: MutableList<TotalDailyDose> = LinkedList()
|
|
||||||
val historyList = getTDDList(dummies)
|
|
||||||
if (isOldData(historyList)) {
|
|
||||||
rTitle = "TDD"
|
|
||||||
rAction = "statusmessage"
|
|
||||||
rMessage = "OLD DATA - "
|
|
||||||
//if pump is not busy: try to fetch data
|
|
||||||
if (activePump.isBusy()) {
|
|
||||||
rMessage += rh.gs(R.string.pumpbusy)
|
|
||||||
} else {
|
|
||||||
rMessage += "trying to fetch data from pump."
|
|
||||||
commandQueue.loadTDDs(object : Callback() {
|
|
||||||
override fun run() {
|
|
||||||
val dummies1: MutableList<TotalDailyDose> = LinkedList()
|
|
||||||
val historyList1 = getTDDList(dummies1)
|
|
||||||
if (isOldData(historyList1)) {
|
|
||||||
sendStatusMessage("TDD: Still old data! Cannot load from pump.\n" + generateTDDMessage(historyList1, dummies1))
|
|
||||||
} else {
|
|
||||||
sendStatusMessage(generateTDDMessage(historyList1, dummies1))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} else { // if up to date: prepare, send (check if CPP is activated -> add CPP stats)
|
|
||||||
rTitle = "TDD"
|
|
||||||
rAction = "statusmessage"
|
|
||||||
rMessage = generateTDDMessage(historyList, dummies)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ACTION_E_CARBS -> {
|
|
||||||
val carbs = SafeParse.stringToInt(act[1])
|
|
||||||
val starttime = SafeParse.stringToInt(act[2])
|
|
||||||
val duration = SafeParse.stringToInt(act[3])
|
|
||||||
val starttimestamp = System.currentTimeMillis() + starttime * 60 * 1000
|
|
||||||
val carbsAfterConstraints = constraintChecker.applyCarbsConstraints(Constraint(carbs)).value()
|
|
||||||
rMessage += rh.gs(R.string.carbs) + ": " + carbsAfterConstraints + "g"
|
|
||||||
rMessage += "\n" + rh.gs(R.string.time) + ": " + dateUtil.timeString(starttimestamp)
|
|
||||||
rMessage += "\n" + rh.gs(R.string.duration) + ": " + duration + "h"
|
|
||||||
if (carbsAfterConstraints - carbs != 0) {
|
|
||||||
rMessage += "\n" + rh.gs(R.string.constraintapllied)
|
|
||||||
}
|
|
||||||
if (carbsAfterConstraints <= 0) {
|
|
||||||
sendError("Carbs = 0! No action taken!")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
rAction += "ecarbs $carbsAfterConstraints $starttimestamp $duration"
|
|
||||||
}
|
|
||||||
|
|
||||||
ACTION_CHANGE_REQUEST -> {
|
|
||||||
rTitle = rh.gs(R.string.openloop_newsuggestion)
|
|
||||||
rAction = "changeRequest"
|
|
||||||
loop.lastRun?.let {
|
|
||||||
rMessage += it.constraintsProcessed
|
|
||||||
wearPlugin.requestChangeConfirmation(rTitle, rMessage, rAction)
|
|
||||||
lastSentTimestamp = System.currentTimeMillis()
|
|
||||||
lastConfirmActionString = rAction
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ACTION_CANCEL_CHANGE_REQUEST -> {
|
|
||||||
rAction = "cancelChangeRequest"
|
|
||||||
wearPlugin.requestNotificationCancel(rAction)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> {
|
|
||||||
sendError(rh.gs(R.string.wear_unknown_action_string) + " " + act[0])
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// send result
|
|
||||||
wearPlugin.requestActionConfirmation(rTitle, rMessage, rAction)
|
|
||||||
lastSentTimestamp = System.currentTimeMillis()
|
|
||||||
lastConfirmActionString = rAction
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun generateTDDMessage(historyList: MutableList<TotalDailyDose>, dummies: MutableList<TotalDailyDose>): String {
|
|
||||||
val profile = profileFunction.getProfile() ?: return "No profile loaded :("
|
|
||||||
if (historyList.isEmpty()) {
|
|
||||||
return "No history data!"
|
|
||||||
}
|
|
||||||
val df: DateFormat = SimpleDateFormat("dd.MM.", Locale.getDefault())
|
|
||||||
var message = ""
|
|
||||||
val refTDD = profile.baseBasalSum() * 2
|
|
||||||
val pump = activePlugin.activePump
|
|
||||||
if (df.format(Date(historyList[0].timestamp)) == df.format(Date())) {
|
|
||||||
val tdd = historyList[0].total
|
|
||||||
historyList.removeAt(0)
|
|
||||||
message += "Today: " + DecimalFormatter.to2Decimal(tdd) + "U " + (DecimalFormatter.to0Decimal(100 * tdd / refTDD) + "%") + "\n"
|
|
||||||
message += "\n"
|
|
||||||
} else if (pump is DanaRPlugin) {
|
|
||||||
val tdd = danaPump.dailyTotalUnits
|
|
||||||
message += "Today: " + DecimalFormatter.to2Decimal(tdd) + "U " + (DecimalFormatter.to0Decimal(100 * tdd / refTDD) + "%") + "\n"
|
|
||||||
message += "\n"
|
|
||||||
}
|
|
||||||
var weighted03 = 0.0
|
|
||||||
var weighted05 = 0.0
|
|
||||||
var weighted07 = 0.0
|
|
||||||
historyList.reverse()
|
|
||||||
for ((i, record) in historyList.withIndex()) {
|
|
||||||
val tdd = record.total
|
|
||||||
if (i == 0) {
|
|
||||||
weighted03 = tdd
|
|
||||||
weighted05 = tdd
|
|
||||||
weighted07 = tdd
|
|
||||||
} else {
|
|
||||||
weighted07 = weighted07 * 0.3 + tdd * 0.7
|
|
||||||
weighted05 = weighted05 * 0.5 + tdd * 0.5
|
|
||||||
weighted03 = weighted03 * 0.7 + tdd * 0.3
|
|
||||||
}
|
|
||||||
}
|
|
||||||
message += "weighted:\n"
|
|
||||||
message += "0.3: " + DecimalFormatter.to2Decimal(weighted03) + "U " + (DecimalFormatter.to0Decimal(100 * weighted03 / refTDD) + "%") + "\n"
|
|
||||||
message += "0.5: " + DecimalFormatter.to2Decimal(weighted05) + "U " + (DecimalFormatter.to0Decimal(100 * weighted05 / refTDD) + "%") + "\n"
|
|
||||||
message += "0.7: " + DecimalFormatter.to2Decimal(weighted07) + "U " + (DecimalFormatter.to0Decimal(100 * weighted07 / refTDD) + "%") + "\n"
|
|
||||||
message += "\n"
|
|
||||||
historyList.reverse()
|
|
||||||
//add TDDs:
|
|
||||||
for (record in historyList) {
|
|
||||||
val tdd = record.total
|
|
||||||
message += df.format(Date(record.timestamp)) + " " + DecimalFormatter.to2Decimal(tdd) + "U " + (DecimalFormatter.to0Decimal(100 * tdd / refTDD) + "%") + (if (dummies.contains(record)) "x" else "") + "\n"
|
|
||||||
}
|
|
||||||
return message
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun isOldData(historyList: List<TotalDailyDose>): Boolean {
|
|
||||||
val activePump = activePlugin.activePump
|
|
||||||
val startsYesterday = activePump === danaRPlugin || activePump === danaRSPlugin || activePump === danaRv2Plugin || activePump === danaRKoreanPlugin || activePump === localInsightPlugin
|
|
||||||
val df: DateFormat = SimpleDateFormat("dd.MM.", Locale.getDefault())
|
|
||||||
return historyList.size < 3 || df.format(Date(historyList[0].timestamp)) != df.format(Date(System.currentTimeMillis() - if (startsYesterday) 1000 * 60 * 60 * 24 else 0))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getTDDList(returnDummies: MutableList<TotalDailyDose>): MutableList<TotalDailyDose> {
|
|
||||||
var historyList = repository.getLastTotalDailyDoses(10, false).blockingGet().toMutableList()
|
|
||||||
//var historyList = databaseHelper.getTDDs().toMutableList()
|
|
||||||
historyList = historyList.subList(0, min(10, historyList.size))
|
|
||||||
//fill single gaps - only needed for Dana*R data
|
|
||||||
val dummies: MutableList<TotalDailyDose> = returnDummies
|
|
||||||
val df: DateFormat = SimpleDateFormat("dd.MM.", Locale.getDefault())
|
|
||||||
for (i in 0 until historyList.size - 1) {
|
|
||||||
val elem1 = historyList[i]
|
|
||||||
val elem2 = historyList[i + 1]
|
|
||||||
if (df.format(Date(elem1.timestamp)) != df.format(Date(elem2.timestamp + 25 * 60 * 60 * 1000))) {
|
|
||||||
val dummy = TotalDailyDose(timestamp = elem1.timestamp - T.hours(24).msecs(), bolusAmount = elem1.bolusAmount / 2, basalAmount = elem1.basalAmount / 2)
|
|
||||||
dummies.add(dummy)
|
|
||||||
elem1.basalAmount /= 2.0
|
|
||||||
elem1.bolusAmount /= 2.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
historyList.addAll(dummies)
|
|
||||||
historyList.sortWith { lhs, rhs -> (rhs.timestamp - lhs.timestamp).toInt() }
|
|
||||||
return historyList
|
|
||||||
}
|
|
||||||
|
|
||||||
private val pumpStatus: String
|
|
||||||
get() = activePlugin.activePump.shortStatus(false)
|
|
||||||
|
|
||||||
// decide if enabled/disabled closed/open; what Plugin as APS?
|
|
||||||
private val loopStatus: String
|
|
||||||
get() {
|
|
||||||
var ret = ""
|
|
||||||
// decide if enabled/disabled closed/open; what Plugin as APS?
|
|
||||||
if ((loop as PluginBase).isEnabled()) {
|
|
||||||
ret += if (constraintChecker.isClosedLoopAllowed().value()) {
|
|
||||||
"CLOSED LOOP\n"
|
|
||||||
} else {
|
|
||||||
"OPEN LOOP\n"
|
|
||||||
}
|
|
||||||
val aps = activePlugin.activeAPS
|
|
||||||
ret += "APS: " + (aps as PluginBase).name
|
|
||||||
val lastRun = loop.lastRun
|
|
||||||
if (lastRun != null) {
|
|
||||||
ret += "\nLast Run: " + dateUtil.timeString(lastRun.lastAPSRun)
|
|
||||||
if (lastRun.lastTBREnact != 0L) ret += "\nLast Enact: " + dateUtil.timeString(lastRun.lastTBREnact)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ret += "LOOP DISABLED\n"
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
//Check for Temp-Target:
|
|
||||||
private val targetsStatus: String
|
|
||||||
get() {
|
|
||||||
var ret = ""
|
|
||||||
if (!config.APS) {
|
|
||||||
return "Targets only apply in APS mode!"
|
|
||||||
}
|
|
||||||
val profile = profileFunction.getProfile() ?: return "No profile set :("
|
|
||||||
//Check for Temp-Target:
|
|
||||||
val tempTarget = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet()
|
|
||||||
if (tempTarget is ValueWrapper.Existing) {
|
|
||||||
ret += "Temp Target: " + Profile.toTargetRangeString(tempTarget.value.lowTarget, tempTarget.value.lowTarget, GlucoseUnit.MGDL, profileFunction.getUnits())
|
|
||||||
ret += "\nuntil: " + dateUtil.timeString(tempTarget.value.end)
|
|
||||||
ret += "\n\n"
|
|
||||||
}
|
|
||||||
ret += "DEFAULT RANGE: "
|
|
||||||
ret += Profile.fromMgdlToUnits(profile.getTargetLowMgdl(), profileFunction.getUnits()).toString() + " - " + Profile.fromMgdlToUnits(profile.getTargetHighMgdl(), profileFunction.getUnits())
|
|
||||||
ret += " target: " + Profile.fromMgdlToUnits(profile.getTargetMgdl(), profileFunction.getUnits())
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
private val oAPSResultStatus: String
|
|
||||||
get() {
|
|
||||||
var ret = ""
|
|
||||||
if (!config.APS)
|
|
||||||
return "Only apply in APS mode!"
|
|
||||||
val usedAPS = activePlugin.activeAPS
|
|
||||||
val result = usedAPS.lastAPSResult ?: return "Last result not available!"
|
|
||||||
ret += if (!result.isChangeRequested) {
|
|
||||||
rh.gs(R.string.nochangerequested) + "\n"
|
|
||||||
} else if (result.rate == 0.0 && result.duration == 0) {
|
|
||||||
rh.gs(R.string.canceltemp) + "\n"
|
|
||||||
} else {
|
|
||||||
rh.gs(R.string.rate) + ": " + DecimalFormatter.to2Decimal(result.rate) + " U/h " +
|
|
||||||
"(" + DecimalFormatter.to2Decimal(result.rate / activePlugin.activePump.baseBasalRate * 100) + "%)\n" +
|
|
||||||
rh.gs(R.string.duration) + ": " + DecimalFormatter.to0Decimal(result.duration.toDouble()) + " min\n"
|
|
||||||
}
|
|
||||||
ret += "\n" + rh.gs(R.string.reason) + ": " + result.reason
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
@Synchronized
|
|
||||||
fun handleConfirmation(actionString: String) {
|
|
||||||
if (!sp.getBoolean(R.string.key_wear_control, false)) return
|
|
||||||
//Guard from old or duplicate confirmations
|
|
||||||
if (lastConfirmActionString == null) return
|
|
||||||
if (lastConfirmActionString != actionString) return
|
|
||||||
if (System.currentTimeMillis() - lastSentTimestamp > timeout) return
|
|
||||||
lastConfirmActionString = null
|
|
||||||
// do the parsing, check constraints and enact!
|
|
||||||
val act = actionString.split("\\s+".toRegex()).toTypedArray()
|
|
||||||
when (act[0]) {
|
|
||||||
ACTION_FILL -> {
|
|
||||||
val amount = SafeParse.stringToDouble(act[1])
|
|
||||||
val insulinAfterConstraints = constraintChecker.applyBolusConstraints(Constraint(amount)).value()
|
|
||||||
if (amount - insulinAfterConstraints != 0.0) {
|
|
||||||
ToastUtils.showToastInUiThread(context, "aborting: previously applied constraint changed")
|
|
||||||
sendError("aborting: previously applied constraint changed")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
doFillBolus(amount)
|
|
||||||
}
|
|
||||||
|
|
||||||
ACTION_TEMPORARY_TARGET -> {
|
|
||||||
val duration = SafeParse.stringToInt(act[2])
|
|
||||||
val low = SafeParse.stringToDouble(act[3])
|
|
||||||
val high = SafeParse.stringToDouble(act[4])
|
|
||||||
generateTempTarget(duration, low, high)
|
|
||||||
}
|
|
||||||
|
|
||||||
ACTION_WIZARD2 -> {
|
|
||||||
if (lastBolusWizard != null) { //use last calculation as confirmed string matches
|
|
||||||
doBolus(lastBolusWizard!!.calculatedTotalInsulin, lastBolusWizard!!.carbs, null, 0)
|
|
||||||
lastBolusWizard = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ACTION_BOLUS -> {
|
|
||||||
val insulin = SafeParse.stringToDouble(act[1])
|
|
||||||
val carbs = SafeParse.stringToInt(act[2])
|
|
||||||
doBolus(insulin, carbs, null, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
ACTION_CPP_SET -> {
|
|
||||||
val timeshift = SafeParse.stringToInt(act[1])
|
|
||||||
val percentage = SafeParse.stringToInt(act[2])
|
|
||||||
setCPP(timeshift, percentage)
|
|
||||||
}
|
|
||||||
|
|
||||||
ACTION_E_CARBS -> {
|
|
||||||
val carbs = SafeParse.stringToInt(act[1])
|
|
||||||
val starttime = SafeParse.stringToLong(act[2])
|
|
||||||
val duration = SafeParse.stringToInt(act[3])
|
|
||||||
doECarbs(carbs, starttime, duration)
|
|
||||||
}
|
|
||||||
|
|
||||||
ACTION_DISMISS_OVERVIEW_NOTIF -> {
|
|
||||||
rxBus.send(EventDismissNotification(SafeParse.stringToInt(act[1])))
|
|
||||||
}
|
|
||||||
|
|
||||||
ACTION_CHANGE_REQUEST -> {
|
|
||||||
loop.acceptChangeRequest()
|
|
||||||
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
|
||||||
notificationManager.cancel(Constants.notificationID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lastBolusWizard = null
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setCPP(timeshift: Int, percentage: Int) {
|
|
||||||
var msg = ""
|
|
||||||
//check for validity
|
|
||||||
if (percentage < Constants.CPP_MIN_PERCENTAGE || percentage > Constants.CPP_MAX_PERCENTAGE) {
|
|
||||||
msg += rh.gs(R.string.valueoutofrange, "Profile-Percentage") + "\n"
|
|
||||||
}
|
|
||||||
if (timeshift < 0 || timeshift > 23) {
|
|
||||||
msg += rh.gs(R.string.valueoutofrange, "Profile-Timeshift") + "\n"
|
|
||||||
}
|
|
||||||
val profile = profileFunction.getProfile()
|
|
||||||
if (profile == null) {
|
|
||||||
msg += rh.gs(R.string.notloadedplugins) + "\n"
|
|
||||||
}
|
|
||||||
if ("" != msg) {
|
|
||||||
msg += rh.gs(R.string.valuesnotstored)
|
|
||||||
val rTitle = "STATUS"
|
|
||||||
val rAction = "statusmessage"
|
|
||||||
wearPlugin.requestActionConfirmation(rTitle, msg, rAction)
|
|
||||||
lastSentTimestamp = System.currentTimeMillis()
|
|
||||||
lastConfirmActionString = rAction
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//send profile to pump
|
|
||||||
uel.log(Action.PROFILE_SWITCH, Sources.Wear,
|
|
||||||
ValueWithUnit.Percent(percentage),
|
|
||||||
ValueWithUnit.Hour(timeshift).takeIf { timeshift != 0 })
|
|
||||||
profileFunction.createProfileSwitch(0, percentage, timeshift)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun generateTempTarget(duration: Int, low: Double, high: Double) {
|
|
||||||
if (duration != 0) {
|
|
||||||
disposable += repository.runTransactionForResult(
|
|
||||||
InsertAndCancelCurrentTemporaryTargetTransaction(
|
|
||||||
timestamp = System.currentTimeMillis(),
|
|
||||||
duration = TimeUnit.MINUTES.toMillis(duration.toLong()),
|
|
||||||
reason = TemporaryTarget.Reason.WEAR,
|
|
||||||
lowTarget = Profile.toMgdl(low, profileFunction.getUnits()),
|
|
||||||
highTarget = Profile.toMgdl(high, profileFunction.getUnits())
|
|
||||||
)
|
|
||||||
).subscribe({ result ->
|
|
||||||
result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted temp target $it") }
|
|
||||||
result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated temp target $it") }
|
|
||||||
}, {
|
|
||||||
aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
|
|
||||||
})
|
|
||||||
uel.log(
|
|
||||||
Action.TT, Sources.Wear,
|
|
||||||
ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.WEAR),
|
|
||||||
ValueWithUnit.fromGlucoseUnit(low, profileFunction.getUnits().asText),
|
|
||||||
ValueWithUnit.fromGlucoseUnit(high, profileFunction.getUnits().asText).takeIf { low != high },
|
|
||||||
ValueWithUnit.Minute(duration)
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
disposable += repository.runTransactionForResult(CancelCurrentTemporaryTargetIfAnyTransaction(System.currentTimeMillis()))
|
|
||||||
.subscribe({ result ->
|
|
||||||
result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated temp target $it") }
|
|
||||||
}, {
|
|
||||||
aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
|
|
||||||
})
|
|
||||||
uel.log(
|
|
||||||
Action.CANCEL_TT, Sources.Wear,
|
|
||||||
ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.WEAR)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun doFillBolus(amount: Double) {
|
|
||||||
val detailedBolusInfo = DetailedBolusInfo()
|
|
||||||
detailedBolusInfo.insulin = amount
|
|
||||||
detailedBolusInfo.bolusType = DetailedBolusInfo.BolusType.PRIMING
|
|
||||||
uel.log(Action.PRIME_BOLUS, Sources.Wear,
|
|
||||||
ValueWithUnit.Insulin(amount).takeIf { amount != 0.0 })
|
|
||||||
commandQueue.bolus(detailedBolusInfo, object : Callback() {
|
|
||||||
override fun run() {
|
|
||||||
if (!result.success) {
|
|
||||||
sendError(
|
|
||||||
rh.gs(R.string.treatmentdeliveryerror) +
|
|
||||||
"\n" +
|
|
||||||
result.comment
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun doECarbs(carbs: Int, time: Long, duration: Int) {
|
|
||||||
uel.log(if (duration == 0) Action.CARBS else Action.EXTENDED_CARBS, Sources.Wear,
|
|
||||||
ValueWithUnit.Timestamp(time),
|
|
||||||
ValueWithUnit.Gram(carbs),
|
|
||||||
ValueWithUnit.Hour(duration).takeIf { duration != 0 })
|
|
||||||
doBolus(0.0, carbs, time, duration)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun doBolus(amount: Double, carbs: Int, carbsTime: Long?, carbsDuration: Int) {
|
|
||||||
val detailedBolusInfo = DetailedBolusInfo()
|
|
||||||
detailedBolusInfo.insulin = amount
|
|
||||||
detailedBolusInfo.carbs = carbs.toDouble()
|
|
||||||
detailedBolusInfo.bolusType = DetailedBolusInfo.BolusType.NORMAL
|
|
||||||
detailedBolusInfo.carbsTimestamp = carbsTime
|
|
||||||
detailedBolusInfo.carbsDuration = T.hours(carbsDuration.toLong()).msecs()
|
|
||||||
if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) {
|
|
||||||
val action = when {
|
|
||||||
amount.equals(0.0) -> Action.CARBS
|
|
||||||
carbs.equals(0) -> Action.BOLUS
|
|
||||||
carbsDuration > 0 -> Action.EXTENDED_CARBS
|
|
||||||
else -> Action.TREATMENT
|
|
||||||
}
|
|
||||||
uel.log(action, Sources.Wear,
|
|
||||||
ValueWithUnit.Insulin(amount).takeIf { amount != 0.0 },
|
|
||||||
ValueWithUnit.Gram(carbs).takeIf { carbs != 0 },
|
|
||||||
ValueWithUnit.Hour(carbsDuration).takeIf { carbsDuration != 0 })
|
|
||||||
commandQueue.bolus(detailedBolusInfo, object : Callback() {
|
|
||||||
override fun run() {
|
|
||||||
if (!result.success) {
|
|
||||||
sendError(
|
|
||||||
rh.gs(R.string.treatmentdeliveryerror) +
|
|
||||||
"\n" +
|
|
||||||
result.comment
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Synchronized private fun sendError(errorMessage: String) {
|
|
||||||
wearPlugin.requestActionConfirmation("ERROR", errorMessage, "error")
|
|
||||||
lastSentTimestamp = System.currentTimeMillis()
|
|
||||||
lastConfirmActionString = null
|
|
||||||
lastBolusWizard = null
|
|
||||||
}
|
|
||||||
|
|
||||||
@Synchronized
|
|
||||||
private fun sendStatusMessage(message: String) {
|
|
||||||
wearPlugin.requestActionConfirmation("TDD", message, "statusmessage")
|
|
||||||
lastSentTimestamp = System.currentTimeMillis()
|
|
||||||
lastConfirmActionString = null
|
|
||||||
lastBolusWizard = null
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -6,10 +6,13 @@ 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.events.EventMobileToWear
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientUpdateGUI
|
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientUpdateGUI
|
||||||
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
|
import info.nightscout.shared.weardata.EventData
|
||||||
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 javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -20,6 +23,7 @@ class WearFragment : DaggerFragment() {
|
||||||
@Inject lateinit var rxBus: RxBus
|
@Inject lateinit var rxBus: RxBus
|
||||||
@Inject lateinit var aapsSchedulers: AapsSchedulers
|
@Inject lateinit var aapsSchedulers: AapsSchedulers
|
||||||
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
||||||
|
@Inject lateinit var dateUtil: DateUtil
|
||||||
|
|
||||||
private var _binding: WearFragmentBinding? = null
|
private var _binding: WearFragmentBinding? = null
|
||||||
|
|
||||||
|
@ -37,8 +41,8 @@ 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 { rxBus.send(EventData.ActionResendData("WearFragment")) }
|
||||||
binding.openSettings.setOnClickListener { wearPlugin.openSettings() }
|
binding.openSettings.setOnClickListener { rxBus.send(EventMobileToWear(EventData.OpenSettings(dateUtil.now()))) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
|
|
|
@ -2,24 +2,26 @@ package info.nightscout.androidaps.plugins.general.wear
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
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.EventAutosensCalculationFinished
|
||||||
|
import info.nightscout.androidaps.events.EventMobileToWear
|
||||||
|
import info.nightscout.androidaps.events.EventPreferenceChange
|
||||||
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.androidaps.plugins.aps.events.EventOpenAPSUpdateGui
|
|
||||||
import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopUpdateGui
|
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
|
||||||
import info.nightscout.androidaps.plugins.general.wear.wearintegration.WatchUpdaterService
|
import info.nightscout.androidaps.plugins.general.wear.wearintegration.DataHandlerMobile
|
||||||
|
import info.nightscout.androidaps.plugins.general.wear.wearintegration.DataLayerListenerServiceMobile
|
||||||
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.logging.AAPSLogger
|
||||||
import info.nightscout.shared.sharedPreferences.SP
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
|
import info.nightscout.shared.weardata.EventData
|
||||||
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 javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -32,10 +34,10 @@ class WearPlugin @Inject constructor(
|
||||||
rh: ResourceHelper,
|
rh: ResourceHelper,
|
||||||
private val aapsSchedulers: AapsSchedulers,
|
private val aapsSchedulers: AapsSchedulers,
|
||||||
private val sp: SP,
|
private val sp: SP,
|
||||||
private val ctx: Context,
|
|
||||||
private val fabricPrivacy: FabricPrivacy,
|
private val fabricPrivacy: FabricPrivacy,
|
||||||
private val rxBus: RxBus,
|
private val rxBus: RxBus,
|
||||||
private val actionStringHandler: Lazy<ActionStringHandler>
|
private val context: Context,
|
||||||
|
private val dataHandlerMobile: DataHandlerMobile
|
||||||
|
|
||||||
) : PluginBase(
|
) : PluginBase(
|
||||||
PluginDescription()
|
PluginDescription()
|
||||||
|
@ -55,136 +57,43 @@ class WearPlugin @Inject constructor(
|
||||||
|
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
super.onStart()
|
super.onStart()
|
||||||
disposable += rxBus
|
context.startService(Intent(context, DataLayerListenerServiceMobile::class.java))
|
||||||
.toObservable(EventOpenAPSUpdateGui::class.java)
|
|
||||||
.observeOn(aapsSchedulers.io)
|
|
||||||
.subscribe({ sendDataToWatch(status = true, basals = true, bgValue = false) }, fabricPrivacy::logException)
|
|
||||||
|
|
||||||
disposable += rxBus
|
|
||||||
.toObservable(EventExtendedBolusChange::class.java)
|
|
||||||
.observeOn(aapsSchedulers.io)
|
|
||||||
.subscribe({ sendDataToWatch(status = true, basals = true, bgValue = false) }, fabricPrivacy::logException)
|
|
||||||
disposable += rxBus
|
|
||||||
.toObservable(EventTempBasalChange::class.java)
|
|
||||||
.observeOn(aapsSchedulers.io)
|
|
||||||
.subscribe({ sendDataToWatch(status = true, basals = true, bgValue = false) }, fabricPrivacy::logException)
|
|
||||||
disposable += rxBus
|
|
||||||
.toObservable(EventTreatmentChange::class.java)
|
|
||||||
.observeOn(aapsSchedulers.io)
|
|
||||||
.subscribe({ sendDataToWatch(status = true, basals = true, bgValue = false) }, fabricPrivacy::logException)
|
|
||||||
disposable += rxBus
|
|
||||||
.toObservable(EventEffectiveProfileSwitchChanged::class.java)
|
|
||||||
.observeOn(aapsSchedulers.io)
|
|
||||||
.subscribe({ sendDataToWatch(status = false, basals = true, bgValue = false) }, fabricPrivacy::logException)
|
|
||||||
disposable += rxBus
|
|
||||||
.toObservable(EventAutosensCalculationFinished::class.java)
|
|
||||||
.observeOn(aapsSchedulers.io)
|
|
||||||
.subscribe({ sendDataToWatch(status = true, basals = true, bgValue = true) }, fabricPrivacy::logException)
|
|
||||||
disposable += rxBus
|
|
||||||
.toObservable(EventPreferenceChange::class.java)
|
|
||||||
.observeOn(aapsSchedulers.io)
|
|
||||||
.subscribe({
|
|
||||||
// possibly new high or low mark
|
|
||||||
resendDataToWatch()
|
|
||||||
// status may be formatted differently
|
|
||||||
sendDataToWatch(status = true, basals = false, bgValue = false)
|
|
||||||
}, fabricPrivacy::logException)
|
|
||||||
disposable += rxBus
|
|
||||||
.toObservable(EventLoopUpdateGui::class.java)
|
|
||||||
.observeOn(aapsSchedulers.io)
|
|
||||||
.subscribe({
|
|
||||||
sendDataToWatch(status = true, basals = false, bgValue = false)
|
|
||||||
}, fabricPrivacy::logException)
|
|
||||||
disposable += rxBus
|
|
||||||
.toObservable(EventBolusRequested::class.java)
|
|
||||||
.observeOn(aapsSchedulers.io)
|
|
||||||
.subscribe({ event: EventBolusRequested ->
|
|
||||||
val status = rh.gs(R.string.bolusrequested, event.amount)
|
|
||||||
val intent = Intent(ctx, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_BOLUS_PROGRESS)
|
|
||||||
intent.putExtra("progresspercent", 0)
|
|
||||||
intent.putExtra("progressstatus", status)
|
|
||||||
ctx.startService(intent)
|
|
||||||
}, fabricPrivacy::logException)
|
|
||||||
disposable += rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventDismissBolusProgressIfRunning::class.java)
|
.toObservable(EventDismissBolusProgressIfRunning::class.java)
|
||||||
.observeOn(aapsSchedulers.io)
|
.observeOn(aapsSchedulers.io)
|
||||||
.subscribe({ event: EventDismissBolusProgressIfRunning ->
|
.subscribe({ event: EventDismissBolusProgressIfRunning ->
|
||||||
if (event.result == null) return@subscribe
|
event.result?.let {
|
||||||
val status: String = if (event.result!!.success) {
|
val status =
|
||||||
rh.gs(R.string.success)
|
if (it.success) rh.gs(R.string.success)
|
||||||
} else {
|
else rh.gs(R.string.nosuccess)
|
||||||
rh.gs(R.string.nosuccess)
|
if (isEnabled()) rxBus.send(EventMobileToWear(EventData.BolusProgress(percent = 100, status = status)))
|
||||||
}
|
}
|
||||||
val intent = Intent(ctx, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_BOLUS_PROGRESS)
|
|
||||||
intent.putExtra("progresspercent", 100)
|
|
||||||
intent.putExtra("progressstatus", status)
|
|
||||||
ctx.startService(intent)
|
|
||||||
}, fabricPrivacy::logException)
|
}, fabricPrivacy::logException)
|
||||||
disposable += 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_BOLUS_PROGRESS)
|
if (isEnabled()) rxBus.send(EventMobileToWear(EventData.BolusProgress(percent = event.percent, status = event.status)))
|
||||||
intent.putExtra("progresspercent", event.percent)
|
|
||||||
intent.putExtra("progressstatus", event.status)
|
|
||||||
ctx.startService(intent)
|
|
||||||
}
|
}
|
||||||
}, fabricPrivacy::logException)
|
}, fabricPrivacy::logException)
|
||||||
actionStringHandler.get().setup()
|
disposable += rxBus
|
||||||
|
.toObservable(EventPreferenceChange::class.java)
|
||||||
|
.observeOn(aapsSchedulers.io)
|
||||||
|
.subscribe({ dataHandlerMobile.resendData("EventPreferenceChange") }, fabricPrivacy::logException)
|
||||||
|
disposable += rxBus
|
||||||
|
.toObservable(EventAutosensCalculationFinished::class.java)
|
||||||
|
.observeOn(aapsSchedulers.io)
|
||||||
|
.subscribe({ dataHandlerMobile.resendData("EventAutosensCalculationFinished") }, fabricPrivacy::logException)
|
||||||
|
disposable += rxBus
|
||||||
|
.toObservable(EventLoopUpdateGui::class.java)
|
||||||
|
.observeOn(aapsSchedulers.io)
|
||||||
|
.subscribe({ dataHandlerMobile.resendData("EventLoopUpdateGui") }, fabricPrivacy::logException)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStop() {
|
override fun onStop() {
|
||||||
disposable.clear()
|
disposable.clear()
|
||||||
super.onStop()
|
super.onStop()
|
||||||
actionStringHandler.get().tearDown()
|
context.stopService(Intent(context, DataLayerListenerServiceMobile::class.java))
|
||||||
}
|
|
||||||
|
|
||||||
private fun sendDataToWatch(status: Boolean, basals: Boolean, bgValue: Boolean) {
|
|
||||||
// only start service when this plugin is enabled
|
|
||||||
if (isEnabled()) {
|
|
||||||
if (bgValue) ctx.startService(Intent(ctx, WatchUpdaterService::class.java))
|
|
||||||
if (basals) 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() {
|
|
||||||
ctx.startService(Intent(ctx, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_RESEND))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun openSettings() {
|
|
||||||
ctx.startService(Intent(ctx, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_OPEN_SETTINGS))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun requestNotificationCancel(actionString: String?) {
|
|
||||||
ctx.startService(
|
|
||||||
Intent(ctx, WatchUpdaterService::class.java)
|
|
||||||
.setAction(WatchUpdaterService.ACTION_CANCEL_NOTIFICATION)
|
|
||||||
.also {
|
|
||||||
it.putExtra("actionstring", actionString)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fun requestActionConfirmation(title: String, message: String, actionString: String) {
|
|
||||||
ctx.startService(
|
|
||||||
Intent(ctx, WatchUpdaterService::class.java)
|
|
||||||
.setAction(WatchUpdaterService.ACTION_SEND_ACTION_CONFIRMATION_REQUEST)
|
|
||||||
.also {
|
|
||||||
it.putExtra("title", title)
|
|
||||||
it.putExtra("message", message)
|
|
||||||
it.putExtra("actionstring", actionString)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fun requestChangeConfirmation(title: String, message: String, actionString: String) {
|
|
||||||
ctx.startService(
|
|
||||||
Intent(ctx, WatchUpdaterService::class.java)
|
|
||||||
.setAction(WatchUpdaterService.ACTION_SEND_CHANGE_CONFIRMATION_REQUEST)
|
|
||||||
.also {
|
|
||||||
it.putExtra("title", title)
|
|
||||||
it.putExtra("message", message)
|
|
||||||
it.putExtra("actionstring", actionString)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.wear.events
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.events.Event
|
|
||||||
|
|
||||||
class EventWearConfirmAction(val action: String) : Event()
|
|
|
@ -1,5 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.wear.events
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.events.Event
|
|
||||||
|
|
||||||
class EventWearInitiateAction(val action: String) : Event()
|
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,200 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.wear.wearintegration
|
||||||
|
|
||||||
|
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.R
|
||||||
|
import info.nightscout.androidaps.database.AppRepository
|
||||||
|
import info.nightscout.androidaps.events.EventMobileToWear
|
||||||
|
import info.nightscout.androidaps.interfaces.ActivePlugin
|
||||||
|
import info.nightscout.androidaps.interfaces.Config
|
||||||
|
import info.nightscout.androidaps.interfaces.IobCobCalculator
|
||||||
|
import info.nightscout.androidaps.interfaces.Loop
|
||||||
|
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||||
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
|
import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus
|
||||||
|
import info.nightscout.androidaps.plugins.general.wear.WearPlugin
|
||||||
|
import info.nightscout.androidaps.plugins.general.wear.events.EventWearUpdateGui
|
||||||
|
import info.nightscout.androidaps.receivers.ReceiverStatusStore
|
||||||
|
import info.nightscout.androidaps.utils.DefaultValueHelper
|
||||||
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
|
import info.nightscout.androidaps.utils.wizard.QuickWizard
|
||||||
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
|
import info.nightscout.shared.logging.LTag
|
||||||
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
|
import info.nightscout.shared.weardata.EventData
|
||||||
|
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 DataLayerListenerServiceMobile : 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 activePlugin: ActivePlugin
|
||||||
|
@Inject lateinit var rxBus: RxBus
|
||||||
|
@Inject lateinit var aapsSchedulers: AapsSchedulers
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
private val rxPath get() = getString(R.string.path_rx_bridge)
|
||||||
|
|
||||||
|
override fun onCreate() {
|
||||||
|
AndroidInjection.inject(this)
|
||||||
|
super.onCreate()
|
||||||
|
aapsLogger.debug(LTag.WEAR, "onCreate")
|
||||||
|
handler.post { updateTranscriptionCapability() }
|
||||||
|
disposable += rxBus
|
||||||
|
.toObservable(EventMobileToWear::class.java)
|
||||||
|
.observeOn(aapsSchedulers.io)
|
||||||
|
.subscribe { sendMessage(rxPath, it.payload.serialize()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
|
||||||
|
@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)
|
||||||
|
|
||||||
|
if (wearPlugin.isEnabled()) {
|
||||||
|
when (messageEvent.path) {
|
||||||
|
rxPath -> {
|
||||||
|
aapsLogger.debug(LTag.WEAR, "onMessageReceived: ${String(messageEvent.data)}")
|
||||||
|
val command = EventData.deserialize(String(messageEvent.data))
|
||||||
|
rxBus.send(command.also { it.sourceNodeId = 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")
|
||||||
|
rxBus.send(EventMobileToWear(EventData.ActionPing(System.currentTimeMillis())))
|
||||||
|
rxBus.send(EventData.ActionResendData("WatchUpdaterService"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find a nearby node or pick one arbitrarily
|
||||||
|
private fun pickBestNodeId(nodes: Set<Node>): Node? =
|
||||||
|
nodes.firstOrNull { it.isNearby } ?: nodes.firstOrNull()
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
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: String?) {
|
||||||
|
aapsLogger.debug(LTag.WEAR, "sendMessage: $path $data")
|
||||||
|
transcriptionNodeId?.also { nodeId ->
|
||||||
|
messageClient
|
||||||
|
.sendMessage(nodeId, path, data?.toByteArray() ?: byteArrayOf()).apply {
|
||||||
|
addOnSuccessListener { }
|
||||||
|
addOnFailureListener {
|
||||||
|
aapsLogger.debug(LTag.WEAR, "sendMessage: $path failure")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
const val WEAR_CAPABILITY = "androidaps_wear"
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,633 +0,0 @@
|
||||||
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,778 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.wear.wearintegration;
|
|
||||||
|
|
||||||
/*
|
|
||||||
public class WatchUpdaterService1 extends WearableListenerService implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
|
|
||||||
@Inject public GlucoseStatusProvider glucoseStatusProvider;
|
|
||||||
@Inject public AAPSLogger aapsLogger;
|
|
||||||
@Inject public WearPlugin wearPlugin;
|
|
||||||
@Inject public ResourceHelper rh;
|
|
||||||
@Inject public SP sp;
|
|
||||||
@Inject public RxBus rxBus;
|
|
||||||
@Inject public ProfileFunction profileFunction;
|
|
||||||
@Inject public DefaultValueHelper defaultValueHelper;
|
|
||||||
@Inject public NSDeviceStatus nsDeviceStatus;
|
|
||||||
@Inject public ActivePlugin activePlugin;
|
|
||||||
@Inject public Loop loop;
|
|
||||||
@Inject public IobCobCalculator iobCobCalculator;
|
|
||||||
@Inject public AppRepository repository;
|
|
||||||
@Inject ReceiverStatusStore receiverStatusStore;
|
|
||||||
@Inject Config config;
|
|
||||||
@Inject public TrendCalculator trendCalculator;
|
|
||||||
@Inject public QuickWizard quickWizard;
|
|
||||||
|
|
||||||
public static final String ACTION_RESEND = WatchUpdaterService.class.getName().concat(".Resend");
|
|
||||||
public static final String ACTION_OPEN_SETTINGS = WatchUpdaterService.class.getName().concat(".OpenSettings");
|
|
||||||
public static final String ACTION_SEND_STATUS = WatchUpdaterService.class.getName().concat(".SendStatus");
|
|
||||||
public static final String ACTION_SEND_BASALS = WatchUpdaterService.class.getName().concat(".SendBasals");
|
|
||||||
public static final String ACTION_SEND_BOLUSPROGRESS = WatchUpdaterService.class.getName().concat(".BolusProgress");
|
|
||||||
public static final String ACTION_SEND_ACTIONCONFIRMATIONREQUEST = WatchUpdaterService.class.getName().concat(".ActionConfirmationRequest");
|
|
||||||
public static final String ACTION_SEND_CHANGECONFIRMATIONREQUEST = WatchUpdaterService.class.getName().concat(".ChangeConfirmationRequest");
|
|
||||||
public static final String ACTION_CANCEL_NOTIFICATION = WatchUpdaterService.class.getName().concat(".CancelNotification");
|
|
||||||
|
|
||||||
private GoogleApiClient googleApiClient;
|
|
||||||
|
|
||||||
String TAG = "WatchUpdateService";
|
|
||||||
|
|
||||||
private static boolean lastLoopStatus;
|
|
||||||
|
|
||||||
private Handler handler;
|
|
||||||
|
|
||||||
// Phone
|
|
||||||
private static final String CAPABILITY_PHONE_APP = "phone_app_sync_bgs";
|
|
||||||
private static final String MESSAGE_PATH_PHONE = "/phone_message_path";
|
|
||||||
// Wear
|
|
||||||
private static final String CAPABILITY_WEAR_APP = "wear_app_sync_bgs";
|
|
||||||
private static final String MESSAGE_PATH_WEAR = "/wear_message_path";
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate() {
|
|
||||||
AndroidInjection.inject(this);
|
|
||||||
if (wearIntegration()) {
|
|
||||||
googleApiConnect();
|
|
||||||
}
|
|
||||||
if (handler == null) {
|
|
||||||
HandlerThread handlerThread = new HandlerThread(this.getClass().getSimpleName() + "Handler");
|
|
||||||
handlerThread.start();
|
|
||||||
handler = new Handler(handlerThread.getLooper());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean wearIntegration() {
|
|
||||||
return wearPlugin.isEnabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void googleApiConnect() {
|
|
||||||
if (googleApiClient != null && (googleApiClient.isConnected() || googleApiClient.isConnecting())) {
|
|
||||||
googleApiClient.disconnect();
|
|
||||||
}
|
|
||||||
googleApiClient = new GoogleApiClient.Builder(this).addConnectionCallbacks(this)
|
|
||||||
.addOnConnectionFailedListener(this).addApi(Wearable.API).build();
|
|
||||||
Wearable.MessageApi.addListener(googleApiClient, this);
|
|
||||||
if (googleApiClient.isConnected()) {
|
|
||||||
aapsLogger.debug(LTag.WEAR, "API client is connected");
|
|
||||||
} else {
|
|
||||||
// Log.d("WatchUpdater", logPrefix + "API client is not connected and is trying to connect");
|
|
||||||
googleApiClient.connect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
|
||||||
String action = intent != null ? intent.getAction() : null;
|
|
||||||
|
|
||||||
// Log.d(TAG, "onStartCommand: " + action);
|
|
||||||
|
|
||||||
if (wearIntegration()) {
|
|
||||||
handler.post(() -> {
|
|
||||||
if (googleApiClient != null && googleApiClient.isConnected()) {
|
|
||||||
if (ACTION_RESEND.equals(action)) {
|
|
||||||
resendData();
|
|
||||||
} else if (ACTION_OPEN_SETTINGS.equals(action)) {
|
|
||||||
sendNotification();
|
|
||||||
} else if (ACTION_SEND_STATUS.equals(action)) {
|
|
||||||
sendStatus();
|
|
||||||
} else if (ACTION_SEND_BASALS.equals(action)) {
|
|
||||||
sendBasals();
|
|
||||||
} else if (ACTION_SEND_BOLUSPROGRESS.equals(action)) {
|
|
||||||
sendBolusProgress(intent.getIntExtra("progresspercent", 0), intent.hasExtra("progressstatus") ? intent.getStringExtra("progressstatus") : "");
|
|
||||||
} else if (ACTION_SEND_ACTIONCONFIRMATIONREQUEST.equals(action)) {
|
|
||||||
String title = intent.getStringExtra("title");
|
|
||||||
String message = intent.getStringExtra("message");
|
|
||||||
String actionstring = intent.getStringExtra("actionstring");
|
|
||||||
sendActionConfirmationRequest(title, message, actionstring);
|
|
||||||
} else if (ACTION_SEND_CHANGECONFIRMATIONREQUEST.equals(action)) {
|
|
||||||
String title = intent.getStringExtra("title");
|
|
||||||
String message = intent.getStringExtra("message");
|
|
||||||
String actionstring = intent.getStringExtra("actionstring");
|
|
||||||
sendChangeConfirmationRequest(title, message, actionstring);
|
|
||||||
} else if (ACTION_CANCEL_NOTIFICATION.equals(action)) {
|
|
||||||
String actionstring = intent.getStringExtra("actionstring");
|
|
||||||
sendCancelNotificationRequest(actionstring);
|
|
||||||
} else {
|
|
||||||
sendData();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (googleApiClient != null) googleApiClient.connect();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return START_STICKY;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void updateWearSyncBgsCapability(CapabilityInfo capabilityInfo) {
|
|
||||||
Log.d("WatchUpdaterService", "CabilityInfo: " + capabilityInfo);
|
|
||||||
Set<Node> connectedNodes = capabilityInfo.getNodes();
|
|
||||||
String mWearNodeId = pickBestNodeId(connectedNodes);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private String pickBestNodeId(Set<Node> nodes) {
|
|
||||||
String bestNodeId = null;
|
|
||||||
// Find a nearby node or pick one arbitrarily
|
|
||||||
for (Node node : nodes) {
|
|
||||||
if (node.isNearby()) {
|
|
||||||
return node.getId();
|
|
||||||
}
|
|
||||||
bestNodeId = node.getId();
|
|
||||||
}
|
|
||||||
return bestNodeId;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onConnected(Bundle connectionHint) {
|
|
||||||
CapabilityApi.CapabilityListener capabilityListener = capabilityInfo -> {
|
|
||||||
updateWearSyncBgsCapability(capabilityInfo);
|
|
||||||
// Log.d(TAG, logPrefix + "onConnected onCapabilityChanged mWearNodeID:" + mWearNodeId);
|
|
||||||
// new CheckWearableConnected().execute();
|
|
||||||
};
|
|
||||||
|
|
||||||
Wearable.CapabilityApi.addCapabilityListener(googleApiClient, capabilityListener, CAPABILITY_WEAR_APP);
|
|
||||||
sendData();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPeerConnected(com.google.android.gms.wearable.Node peer) {// KS
|
|
||||||
super.onPeerConnected(peer);
|
|
||||||
String id = peer.getId();
|
|
||||||
String name = peer.getDisplayName();
|
|
||||||
Log.d(TAG, "onPeerConnected peer name & ID: " + name + "|" + id);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPeerDisconnected(com.google.android.gms.wearable.Node peer) {// KS
|
|
||||||
super.onPeerDisconnected(peer);
|
|
||||||
String id = peer.getId();
|
|
||||||
String name = peer.getDisplayName();
|
|
||||||
Log.d(TAG, "onPeerDisconnected peer name & ID: " + name + "|" + id);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onMessageReceived(MessageEvent event) {
|
|
||||||
|
|
||||||
// Log.d(TAG, "onMessageRecieved: " + event);
|
|
||||||
|
|
||||||
if (wearIntegration()) {
|
|
||||||
if (event != null && event.getPath().equals(WearUris.WEARABLE_RESEND_PATH)) {
|
|
||||||
resendData();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event != null && event.getPath().equals(WearUris.WEARABLE_CANCELBOLUS_PATH)) {
|
|
||||||
cancelBolus();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event != null && event.getPath().equals(WearUris.WEARABLE_INITIATE_ACTIONSTRING_PATH)) {
|
|
||||||
String actionstring = new String(event.getData());
|
|
||||||
aapsLogger.debug(LTag.WEAR, "Wear: " + actionstring);
|
|
||||||
rxBus.send(new EventWearInitiateAction(actionstring));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event != null && event.getPath().equals(WearUris.WEARABLE_CONFIRM_ACTIONSTRING_PATH)) {
|
|
||||||
String actionstring = new String(event.getData());
|
|
||||||
aapsLogger.debug(LTag.WEAR, "Wear Confirm: " + actionstring);
|
|
||||||
rxBus.send(new EventWearConfirmAction(actionstring));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void cancelBolus() {
|
|
||||||
activePlugin.getActivePump().stopBolusDelivering();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendData() {
|
|
||||||
|
|
||||||
GlucoseValue lastBG = iobCobCalculator.getAds().lastBg();
|
|
||||||
// Log.d(TAG, "LastBg=" + lastBG);
|
|
||||||
if (lastBG != null) {
|
|
||||||
GlucoseStatus glucoseStatus = glucoseStatusProvider.getGlucoseStatusData();
|
|
||||||
|
|
||||||
if (googleApiClient != null && !googleApiClient.isConnected() && !googleApiClient.isConnecting()) {
|
|
||||||
googleApiConnect();
|
|
||||||
}
|
|
||||||
if (wearIntegration()) {
|
|
||||||
|
|
||||||
final DataMap dataMap = dataMapSingleBG(lastBG, glucoseStatus);
|
|
||||||
|
|
||||||
(new SendToDataLayerThread(WearUris.WEARABLE_DATA_PATH, googleApiClient)).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, dataMap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private DataMap dataMapSingleBG(GlucoseValue lastBG, GlucoseStatus glucoseStatus) {
|
|
||||||
GlucoseUnit units = profileFunction.getUnits();
|
|
||||||
double convert2MGDL = 1.0;
|
|
||||||
if (units.equals(GlucoseUnit.MMOL))
|
|
||||||
convert2MGDL = Constants.MMOLL_TO_MGDL;
|
|
||||||
double lowLine = defaultValueHelper.determineLowLine() * convert2MGDL;
|
|
||||||
double highLine = defaultValueHelper.determineHighLine() * convert2MGDL;
|
|
||||||
|
|
||||||
long sgvLevel = 0L;
|
|
||||||
if (lastBG.getValue() > highLine) {
|
|
||||||
sgvLevel = 1;
|
|
||||||
} else if (lastBG.getValue() < lowLine) {
|
|
||||||
sgvLevel = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
DataMap dataMap = new DataMap();
|
|
||||||
dataMap.putString("sgvString", GlucoseValueExtensionKt.valueToUnitsString(lastBG, units));
|
|
||||||
dataMap.putString("glucoseUnits", units.getAsText());
|
|
||||||
dataMap.putLong("timestamp", lastBG.getTimestamp());
|
|
||||||
if (glucoseStatus == null) {
|
|
||||||
dataMap.putString("slopeArrow", "");
|
|
||||||
dataMap.putString("delta", "--");
|
|
||||||
dataMap.putString("avgDelta", "--");
|
|
||||||
} else {
|
|
||||||
dataMap.putString("slopeArrow", trendCalculator.getTrendArrow(lastBG).getSymbol());
|
|
||||||
dataMap.putString("delta", deltastring(glucoseStatus.getDelta(), glucoseStatus.getDelta() * Constants.MGDL_TO_MMOLL, units));
|
|
||||||
dataMap.putString("avgDelta", deltastring(glucoseStatus.getShortAvgDelta(), glucoseStatus.getShortAvgDelta() * Constants.MGDL_TO_MMOLL, units));
|
|
||||||
}
|
|
||||||
dataMap.putLong("sgvLevel", sgvLevel);
|
|
||||||
dataMap.putDouble("sgvDouble", lastBG.getValue());
|
|
||||||
dataMap.putDouble("high", highLine);
|
|
||||||
dataMap.putDouble("low", lowLine);
|
|
||||||
return dataMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String deltastring(double deltaMGDL, double deltaMMOL, GlucoseUnit units) {
|
|
||||||
String deltastring = "";
|
|
||||||
if (deltaMGDL >= 0) {
|
|
||||||
deltastring += "+";
|
|
||||||
} else {
|
|
||||||
deltastring += "-";
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean detailed = sp.getBoolean(R.string.key_wear_detailed_delta, false);
|
|
||||||
if (units.equals(GlucoseUnit.MGDL)) {
|
|
||||||
if (detailed) {
|
|
||||||
deltastring += DecimalFormatter.INSTANCE.to1Decimal(Math.abs(deltaMGDL));
|
|
||||||
} else {
|
|
||||||
deltastring += DecimalFormatter.INSTANCE.to0Decimal(Math.abs(deltaMGDL));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (detailed) {
|
|
||||||
deltastring += DecimalFormatter.INSTANCE.to2Decimal(Math.abs(deltaMMOL));
|
|
||||||
} else {
|
|
||||||
deltastring += DecimalFormatter.INSTANCE.to1Decimal(Math.abs(deltaMMOL));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return deltastring;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void resendData() {
|
|
||||||
if (googleApiClient != null && !googleApiClient.isConnected() && !googleApiClient.isConnecting()) {
|
|
||||||
googleApiConnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
sendPreferences();
|
|
||||||
sendQuickWizard();
|
|
||||||
|
|
||||||
long startTime = System.currentTimeMillis() - (long) (60000 * 60 * 5.5);
|
|
||||||
GlucoseValue last_bg = iobCobCalculator.getAds().lastBg();
|
|
||||||
|
|
||||||
if (last_bg == null) return;
|
|
||||||
|
|
||||||
List<GlucoseValue> graph_bgs = repository.compatGetBgReadingsDataFromTime(startTime, true).blockingGet();
|
|
||||||
GlucoseStatus glucoseStatus = glucoseStatusProvider.getGlucoseStatusData(true);
|
|
||||||
|
|
||||||
if (!graph_bgs.isEmpty()) {
|
|
||||||
DataMap entries = dataMapSingleBG(last_bg, glucoseStatus);
|
|
||||||
final ArrayList<DataMap> dataMaps = new ArrayList<>(graph_bgs.size());
|
|
||||||
for (GlucoseValue bg : graph_bgs) {
|
|
||||||
DataMap dataMap = dataMapSingleBG(bg, glucoseStatus);
|
|
||||||
dataMaps.add(dataMap);
|
|
||||||
}
|
|
||||||
entries.putDataMapArrayList("entries", dataMaps);
|
|
||||||
(new SendToDataLayerThread(WearUris.WEARABLE_DATA_PATH, googleApiClient)).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, entries);
|
|
||||||
}
|
|
||||||
sendBasals();
|
|
||||||
sendStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendBasals() {
|
|
||||||
if (googleApiClient != null && !googleApiClient.isConnected() && !googleApiClient.isConnecting()) {
|
|
||||||
googleApiConnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
long now = System.currentTimeMillis();
|
|
||||||
final long startTimeWindow = now - (long) (60000 * 60 * 5.5);
|
|
||||||
|
|
||||||
|
|
||||||
ArrayList<DataMap> basals = new ArrayList<>();
|
|
||||||
ArrayList<DataMap> temps = new ArrayList<>();
|
|
||||||
ArrayList<DataMap> boluses = new ArrayList<>();
|
|
||||||
ArrayList<DataMap> predictions = new ArrayList<>();
|
|
||||||
|
|
||||||
|
|
||||||
Profile profile = profileFunction.getProfile();
|
|
||||||
|
|
||||||
if (profile == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
long beginBasalSegmentTime = startTimeWindow;
|
|
||||||
long runningTime = startTimeWindow;
|
|
||||||
|
|
||||||
double beginBasalValue = profile.getBasal(beginBasalSegmentTime);
|
|
||||||
double endBasalValue = beginBasalValue;
|
|
||||||
|
|
||||||
TemporaryBasal tb1 = iobCobCalculator.getTempBasalIncludingConvertedExtended(runningTime);
|
|
||||||
TemporaryBasal tb2;
|
|
||||||
double tb_before = beginBasalValue;
|
|
||||||
double tb_amount = beginBasalValue;
|
|
||||||
long tb_start = runningTime;
|
|
||||||
|
|
||||||
if (tb1 != null) {
|
|
||||||
Profile profileTB = profileFunction.getProfile(runningTime);
|
|
||||||
if (profileTB != null) {
|
|
||||||
tb_amount = TemporaryBasalExtensionKt.convertedToAbsolute(tb1, runningTime, profileTB);
|
|
||||||
tb_start = runningTime;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
for (; runningTime < now; runningTime += 5 * 60 * 1000) {
|
|
||||||
Profile profileTB = profileFunction.getProfile(runningTime);
|
|
||||||
if (profileTB == null)
|
|
||||||
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(tempDatamap(tb_start, tb_before, runningTime, endBasalValue, tb_amount));
|
|
||||||
tb1 = null;
|
|
||||||
|
|
||||||
} else if (tb1 == null && tb2 != null) {
|
|
||||||
//temp begins
|
|
||||||
tb1 = tb2;
|
|
||||||
tb_start = runningTime;
|
|
||||||
tb_before = endBasalValue;
|
|
||||||
tb_amount = TemporaryBasalExtensionKt.convertedToAbsolute(tb1, runningTime, profileTB);
|
|
||||||
|
|
||||||
} else if (tb1 != null && tb2 != null) {
|
|
||||||
double currentAmount = TemporaryBasalExtensionKt.convertedToAbsolute(tb2, runningTime, profileTB);
|
|
||||||
if (currentAmount != tb_amount) {
|
|
||||||
temps.add(tempDatamap(tb_start, tb_before, runningTime, currentAmount, tb_amount));
|
|
||||||
tb_start = runningTime;
|
|
||||||
tb_before = tb_amount;
|
|
||||||
tb_amount = currentAmount;
|
|
||||||
tb1 = tb2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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(tempDatamap(tb_start, tb_before, now - 60 * 1000, endBasalValue, tb_amount));
|
|
||||||
} else {
|
|
||||||
//express currently running temp by painting it a bit into the future
|
|
||||||
Profile profileNow = profileFunction.getProfile(now);
|
|
||||||
double currentAmount = TemporaryBasalExtensionKt.convertedToAbsolute(tb2, now, profileNow);
|
|
||||||
if (currentAmount != tb_amount) {
|
|
||||||
temps.add(tempDatamap(tb_start, tb_before, now, tb_amount, tb_amount));
|
|
||||||
temps.add(tempDatamap(now, tb_amount, runningTime + 5 * 60 * 1000, currentAmount, currentAmount));
|
|
||||||
} else {
|
|
||||||
temps.add(tempDatamap(tb_start, tb_before, runningTime + 5 * 60 * 1000, tb_amount, tb_amount));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
tb2 = iobCobCalculator.getTempBasalIncludingConvertedExtended(now); //use "now" to express current situation
|
|
||||||
if (tb2 != null) {
|
|
||||||
//onset at the end
|
|
||||||
Profile profileTB = profileFunction.getProfile(runningTime);
|
|
||||||
double currentAmount = TemporaryBasalExtensionKt.convertedToAbsolute(tb2, runningTime, profileTB);
|
|
||||||
temps.add(tempDatamap(now - 60 * 1000, endBasalValue, runningTime + 5 * 60 * 1000, currentAmount, currentAmount));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
repository.getBolusesIncludingInvalidFromTime(startTimeWindow, true).blockingGet()
|
|
||||||
.stream()
|
|
||||||
.filter(bolus -> bolus.getType() != Bolus.Type.PRIMING)
|
|
||||||
.forEach(bolus -> boluses.add(treatmentMap(bolus.getTimestamp(), bolus.getAmount(), 0, bolus.getType() == Bolus.Type.SMB, bolus.isValid())));
|
|
||||||
repository.getCarbsDataFromTimeExpanded(startTimeWindow, true).blockingGet()
|
|
||||||
.forEach(carb -> boluses.add(treatmentMap(carb.getTimestamp(), 0, carb.getAmount(), false, carb.isValid())));
|
|
||||||
|
|
||||||
final LoopPlugin.LastRun finalLastRun = loop.getLastRun();
|
|
||||||
if (sp.getBoolean("wear_predictions", true) && finalLastRun != null && finalLastRun.getRequest().getHasPredictions() && finalLastRun.getConstraintsProcessed() != null) {
|
|
||||||
List<GlucoseValueDataPoint> predArray =
|
|
||||||
finalLastRun.getConstraintsProcessed().getPredictions()
|
|
||||||
.stream().map(bg -> new GlucoseValueDataPoint(bg, defaultValueHelper, profileFunction, rh))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
if (!predArray.isEmpty()) {
|
|
||||||
for (GlucoseValueDataPoint bg : predArray) {
|
|
||||||
if (bg.getData().getValue() < 40) continue;
|
|
||||||
predictions.add(predictionMap(bg.getData().getTimestamp(),
|
|
||||||
bg.getData().getValue(), bg.color(null)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
DataMap dm = new DataMap();
|
|
||||||
dm.putDataMapArrayList("basals", basals);
|
|
||||||
dm.putDataMapArrayList("temps", temps);
|
|
||||||
dm.putDataMapArrayList("boluses", boluses);
|
|
||||||
dm.putDataMapArrayList("predictions", predictions);
|
|
||||||
(new SendToDataLayerThread(WearUris.BASAL_DATA_PATH, googleApiClient)).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, dm);
|
|
||||||
}
|
|
||||||
|
|
||||||
private DataMap tempDatamap(long startTime, double startBasal, long to, double toBasal, double amount) {
|
|
||||||
DataMap dm = new DataMap();
|
|
||||||
dm.putLong("starttime", startTime);
|
|
||||||
dm.putDouble("startBasal", startBasal);
|
|
||||||
dm.putLong("endtime", to);
|
|
||||||
dm.putDouble("endbasal", toBasal);
|
|
||||||
dm.putDouble("amount", amount);
|
|
||||||
return dm;
|
|
||||||
}
|
|
||||||
|
|
||||||
private DataMap basalMap(long startTime, long endTime, double amount) {
|
|
||||||
DataMap dm = new DataMap();
|
|
||||||
dm.putLong("starttime", startTime);
|
|
||||||
dm.putLong("endtime", endTime);
|
|
||||||
dm.putDouble("amount", amount);
|
|
||||||
return dm;
|
|
||||||
}
|
|
||||||
|
|
||||||
private DataMap treatmentMap(long date, double bolus, double carbs, boolean isSMB, boolean isValid) {
|
|
||||||
DataMap dm = new DataMap();
|
|
||||||
dm.putLong("date", date);
|
|
||||||
dm.putDouble("bolus", bolus);
|
|
||||||
dm.putDouble("carbs", carbs);
|
|
||||||
dm.putBoolean("isSMB", isSMB);
|
|
||||||
dm.putBoolean("isValid", isValid);
|
|
||||||
return dm;
|
|
||||||
}
|
|
||||||
|
|
||||||
private DataMap predictionMap(long timestamp, double sgv, int color) {
|
|
||||||
DataMap dm = new DataMap();
|
|
||||||
dm.putLong("timestamp", timestamp);
|
|
||||||
dm.putDouble("sgv", sgv);
|
|
||||||
dm.putInt("color", color);
|
|
||||||
return dm;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void sendNotification() {
|
|
||||||
if (googleApiClient != null && googleApiClient.isConnected()) {
|
|
||||||
PutDataMapRequest dataMapRequest = PutDataMapRequest.create(WearUris.OPEN_SETTINGS_PATH);
|
|
||||||
//unique content
|
|
||||||
dataMapRequest.getDataMap().putLong("timestamp", System.currentTimeMillis());
|
|
||||||
dataMapRequest.getDataMap().putString("openSettings", "openSettings");
|
|
||||||
PutDataRequest putDataRequest = dataMapRequest.asPutDataRequest();
|
|
||||||
Wearable.DataApi.putDataItem(googleApiClient, putDataRequest);
|
|
||||||
} else {
|
|
||||||
Log.e("OpenSettings", "No connection to wearable available!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendBolusProgress(int progresspercent, String status) {
|
|
||||||
if (googleApiClient != null && googleApiClient.isConnected()) {
|
|
||||||
PutDataMapRequest dataMapRequest = PutDataMapRequest.create(WearUris.BOLUS_PROGRESS_PATH);
|
|
||||||
//unique content
|
|
||||||
dataMapRequest.getDataMap().putLong("timestamp", System.currentTimeMillis());
|
|
||||||
dataMapRequest.getDataMap().putString("bolusProgress", "bolusProgress");
|
|
||||||
dataMapRequest.getDataMap().putString("progressstatus", status);
|
|
||||||
dataMapRequest.getDataMap().putInt("progresspercent", progresspercent);
|
|
||||||
PutDataRequest putDataRequest = dataMapRequest.asPutDataRequest();
|
|
||||||
Wearable.DataApi.putDataItem(googleApiClient, putDataRequest);
|
|
||||||
} else {
|
|
||||||
Log.e("BolusProgress", "No connection to wearable available!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendActionConfirmationRequest(String title, String message, String actionstring) {
|
|
||||||
if (googleApiClient != null && googleApiClient.isConnected()) {
|
|
||||||
PutDataMapRequest dataMapRequest = PutDataMapRequest.create(WearUris.ACTION_CONFIRMATION_REQUEST_PATH);
|
|
||||||
//unique content
|
|
||||||
dataMapRequest.getDataMap().putLong("timestamp", System.currentTimeMillis());
|
|
||||||
dataMapRequest.getDataMap().putString("actionConfirmationRequest", "actionConfirmationRequest");
|
|
||||||
dataMapRequest.getDataMap().putString("title", title);
|
|
||||||
dataMapRequest.getDataMap().putString("message", message);
|
|
||||||
dataMapRequest.getDataMap().putString("actionstring", actionstring);
|
|
||||||
|
|
||||||
aapsLogger.debug(LTag.WEAR, "Requesting confirmation from wear: " + actionstring);
|
|
||||||
|
|
||||||
PutDataRequest putDataRequest = dataMapRequest.asPutDataRequest();
|
|
||||||
Wearable.DataApi.putDataItem(googleApiClient, putDataRequest);
|
|
||||||
} else {
|
|
||||||
Log.e("confirmationRequest", "No connection to wearable available!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendChangeConfirmationRequest(String title, String message, String actionstring) {
|
|
||||||
if (googleApiClient != null && googleApiClient.isConnected()) {
|
|
||||||
PutDataMapRequest dataMapRequest = PutDataMapRequest.create(WearUris.ACTION_CHANGECONFIRMATION_REQUEST_PATH);
|
|
||||||
//unique content
|
|
||||||
dataMapRequest.getDataMap().putLong("timestamp", System.currentTimeMillis());
|
|
||||||
dataMapRequest.getDataMap().putString("changeConfirmationRequest", "changeConfirmationRequest");
|
|
||||||
dataMapRequest.getDataMap().putString("title", title);
|
|
||||||
dataMapRequest.getDataMap().putString("message", message);
|
|
||||||
dataMapRequest.getDataMap().putString("actionstring", actionstring);
|
|
||||||
|
|
||||||
aapsLogger.debug(LTag.WEAR, "Requesting confirmation from wear: " + actionstring);
|
|
||||||
|
|
||||||
PutDataRequest putDataRequest = dataMapRequest.asPutDataRequest();
|
|
||||||
Wearable.DataApi.putDataItem(googleApiClient, putDataRequest);
|
|
||||||
} else {
|
|
||||||
Log.e("changeConfirmRequest", "No connection to wearable available!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendCancelNotificationRequest(String actionstring) {
|
|
||||||
if (googleApiClient != null && googleApiClient.isConnected()) {
|
|
||||||
PutDataMapRequest dataMapRequest = PutDataMapRequest.create(WearUris.ACTION_CANCELNOTIFICATION_REQUEST_PATH);
|
|
||||||
//unique content
|
|
||||||
dataMapRequest.getDataMap().putLong("timestamp", System.currentTimeMillis());
|
|
||||||
dataMapRequest.getDataMap().putString("cancelNotificationRequest", "cancelNotificationRequest");
|
|
||||||
dataMapRequest.getDataMap().putString("actionstring", actionstring);
|
|
||||||
|
|
||||||
aapsLogger.debug(LTag.WEAR, "Canceling notification on wear: " + actionstring);
|
|
||||||
|
|
||||||
PutDataRequest putDataRequest = dataMapRequest.asPutDataRequest();
|
|
||||||
Wearable.DataApi.putDataItem(googleApiClient, putDataRequest);
|
|
||||||
} else {
|
|
||||||
Log.e("cancelNotificationReq", "No connection to wearable available!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendStatus() {
|
|
||||||
|
|
||||||
if (googleApiClient != null && googleApiClient.isConnected()) {
|
|
||||||
Profile profile = profileFunction.getProfile();
|
|
||||||
String status = rh.gs(R.string.noprofile);
|
|
||||||
String iobSum, iobDetail, cobString, currentBasal, bgiString;
|
|
||||||
iobSum = iobDetail = cobString = currentBasal = bgiString = "";
|
|
||||||
if (profile != null) {
|
|
||||||
IobTotal bolusIob = iobCobCalculator.calculateIobFromBolus().round();
|
|
||||||
IobTotal basalIob = iobCobCalculator.calculateIobFromTempBasalsIncludingConvertedExtended().round();
|
|
||||||
|
|
||||||
iobSum = DecimalFormatter.INSTANCE.to2Decimal(bolusIob.getIob() + basalIob.getBasaliob());
|
|
||||||
iobDetail =
|
|
||||||
"(" + DecimalFormatter.INSTANCE.to2Decimal(bolusIob.getIob()) + "|" + DecimalFormatter.INSTANCE.to2Decimal(basalIob.getBasaliob()) + ")";
|
|
||||||
cobString = iobCobCalculator.getCobInfo(false, "WatcherUpdaterService").generateCOBString();
|
|
||||||
currentBasal = generateBasalString();
|
|
||||||
|
|
||||||
//bgi
|
|
||||||
double bgi =
|
|
||||||
-(bolusIob.getActivity() + basalIob.getActivity()) * 5 * Profile.Companion.fromMgdlToUnits(profile.getIsfMgdl(), profileFunction.getUnits());
|
|
||||||
bgiString = "" + ((bgi >= 0) ? "+" : "") + DecimalFormatter.INSTANCE.to1Decimal(bgi);
|
|
||||||
|
|
||||||
status = generateStatusString(profile, currentBasal, iobSum, iobDetail, bgiString);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//batteries
|
|
||||||
int phoneBattery = receiverStatusStore.getBatteryLevel();
|
|
||||||
String rigBattery = nsDeviceStatus.getUploaderStatus().trim();
|
|
||||||
|
|
||||||
|
|
||||||
long openApsStatus;
|
|
||||||
//OpenAPS status
|
|
||||||
if (config.getAPS()) {
|
|
||||||
//we are AndroidAPS
|
|
||||||
openApsStatus = loop.getLastRun() != null && loop.getLastRun().getLastTBREnact() != 0 ? loop.getLastRun().getLastTBREnact() : -1;
|
|
||||||
} else {
|
|
||||||
//NSClient or remote
|
|
||||||
openApsStatus = nsDeviceStatus.getOpenApsTimestamp();
|
|
||||||
}
|
|
||||||
|
|
||||||
PutDataMapRequest dataMapRequest = PutDataMapRequest.create(WearUris.NEW_STATUS_PATH);
|
|
||||||
//unique content
|
|
||||||
dataMapRequest.getDataMap().putString("externalStatusString", status);
|
|
||||||
dataMapRequest.getDataMap().putString("iobSum", iobSum);
|
|
||||||
dataMapRequest.getDataMap().putString("iobDetail", iobDetail);
|
|
||||||
dataMapRequest.getDataMap().putBoolean("detailedIob", sp.getBoolean(R.string.key_wear_detailediob, false));
|
|
||||||
dataMapRequest.getDataMap().putString("cob", cobString);
|
|
||||||
dataMapRequest.getDataMap().putString("currentBasal", currentBasal);
|
|
||||||
dataMapRequest.getDataMap().putString("battery", "" + phoneBattery);
|
|
||||||
dataMapRequest.getDataMap().putString("rigBattery", rigBattery);
|
|
||||||
dataMapRequest.getDataMap().putLong("openApsStatus", openApsStatus);
|
|
||||||
dataMapRequest.getDataMap().putString("bgi", bgiString);
|
|
||||||
dataMapRequest.getDataMap().putBoolean("showBgi", sp.getBoolean(R.string.key_wear_showbgi, false));
|
|
||||||
dataMapRequest.getDataMap().putInt("batteryLevel", (phoneBattery >= 30) ? 1 : 0);
|
|
||||||
PutDataRequest putDataRequest = dataMapRequest.asPutDataRequest();
|
|
||||||
Wearable.DataApi.putDataItem(googleApiClient, putDataRequest);
|
|
||||||
} else {
|
|
||||||
Log.e("SendStatus", "No connection to wearable available!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendPreferences() {
|
|
||||||
if (googleApiClient != null && googleApiClient.isConnected()) {
|
|
||||||
|
|
||||||
GlucoseUnit units = profileFunction.getUnits();
|
|
||||||
boolean wearcontrol = sp.getBoolean(R.string.key_wear_control, false);
|
|
||||||
boolean mgdl = units.equals(GlucoseUnit.MGDL);
|
|
||||||
int percentage = sp.getInt(R.string.key_boluswizard_percentage, 100);
|
|
||||||
int maxCarbs = sp.getInt(R.string.key_treatmentssafety_maxcarbs, 48);
|
|
||||||
double maxBolus = sp.getDouble(R.string.key_treatmentssafety_maxbolus, 3.0);
|
|
||||||
PutDataMapRequest dataMapRequest = PutDataMapRequest.create(WearUris.NEW_PREFERENCES_PATH);
|
|
||||||
//unique content
|
|
||||||
dataMapRequest.getDataMap().putLong("timestamp", System.currentTimeMillis());
|
|
||||||
dataMapRequest.getDataMap().putBoolean(rh.gs(R.string.key_wear_control), wearcontrol);
|
|
||||||
dataMapRequest.getDataMap().putBoolean(rh.gs(R.string.key_units_mgdl), mgdl);
|
|
||||||
dataMapRequest.getDataMap().putInt(rh.gs(R.string.key_boluswizard_percentage), percentage);
|
|
||||||
dataMapRequest.getDataMap().putInt(rh.gs(R.string.key_treatmentssafety_maxcarbs), maxCarbs);
|
|
||||||
dataMapRequest.getDataMap().putDouble(rh.gs(R.string.key_treatmentssafety_maxbolus), maxBolus);
|
|
||||||
PutDataRequest putDataRequest = dataMapRequest.asPutDataRequest();
|
|
||||||
Wearable.DataApi.putDataItem(googleApiClient, putDataRequest);
|
|
||||||
} else {
|
|
||||||
Log.e("SendPreferences", "No connection to wearable available!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendQuickWizard() {
|
|
||||||
if (googleApiClient != null && googleApiClient.isConnected()) {
|
|
||||||
int size = quickWizard.size();
|
|
||||||
ArrayList<DataMap> entities = new ArrayList<>();
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
QuickWizardEntry q = quickWizard.get(i);
|
|
||||||
if (q.forDevice(QuickWizardEntry.DEVICE_WATCH)) {
|
|
||||||
entities.add(quickMap(q));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PutDataMapRequest dataMapRequest = PutDataMapRequest.create(WearUris.QUICK_WIZARD_PATH);
|
|
||||||
|
|
||||||
DataMap dm = dataMapRequest.getDataMap();
|
|
||||||
dm.putLong("timestamp", System.currentTimeMillis());
|
|
||||||
dm.putDataMapArrayList("quick_wizard", entities);
|
|
||||||
|
|
||||||
PutDataRequest putDataRequest = dataMapRequest.asPutDataRequest();
|
|
||||||
Log.i(TAG, "sendQuickWizard: " + putDataRequest);
|
|
||||||
Wearable.DataApi.putDataItem(googleApiClient, putDataRequest);
|
|
||||||
} else {
|
|
||||||
Log.e("sendQuickWizard", "No connection to wearable available!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private DataMap quickMap(QuickWizardEntry q) {
|
|
||||||
DataMap dm = new DataMap();
|
|
||||||
dm.putString("guid", q.guid());
|
|
||||||
dm.putString("button_text", q.buttonText());
|
|
||||||
dm.putInt("carbs", q.carbs());
|
|
||||||
dm.putInt("from", q.validFrom());
|
|
||||||
dm.putInt("to", q.validTo());
|
|
||||||
return dm;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
private String generateStatusString(Profile profile, String currentBasal, String iobSum, String iobDetail, String bgiString) {
|
|
||||||
|
|
||||||
String status = "";
|
|
||||||
|
|
||||||
if (profile == null) {
|
|
||||||
status = rh.gs(R.string.noprofile);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!((PluginBase) loop).isEnabled()) {
|
|
||||||
status += rh.gs(R.string.disabledloop) + "\n";
|
|
||||||
lastLoopStatus = false;
|
|
||||||
} else {
|
|
||||||
lastLoopStatus = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
String iobString;
|
|
||||||
if (sp.getBoolean(R.string.key_wear_detailediob, false)) {
|
|
||||||
iobString = iobSum + " " + iobDetail;
|
|
||||||
} else {
|
|
||||||
iobString = iobSum + "U";
|
|
||||||
}
|
|
||||||
|
|
||||||
status += currentBasal + " " + iobString;
|
|
||||||
|
|
||||||
//add BGI if shown, otherwise return
|
|
||||||
if (sp.getBoolean(R.string.key_wear_showbgi, false)) {
|
|
||||||
status += " " + bgiString;
|
|
||||||
}
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
private String generateBasalString() {
|
|
||||||
|
|
||||||
String basalStringResult;
|
|
||||||
|
|
||||||
Profile profile = profileFunction.getProfile();
|
|
||||||
if (profile == null)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
TemporaryBasal activeTemp = iobCobCalculator.getTempBasalIncludingConvertedExtended(System.currentTimeMillis());
|
|
||||||
if (activeTemp != null) {
|
|
||||||
basalStringResult = TemporaryBasalExtensionKt.toStringShort(activeTemp);
|
|
||||||
} else {
|
|
||||||
basalStringResult = DecimalFormatter.INSTANCE.to2Decimal(profile.getBasal()) + "U/h";
|
|
||||||
}
|
|
||||||
return basalStringResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroy() {
|
|
||||||
if (googleApiClient != null && googleApiClient.isConnected()) {
|
|
||||||
googleApiClient.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onConnectionSuspended(int cause) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean shouldReportLoopStatus(boolean enabled) {
|
|
||||||
return (lastLoopStatus != enabled);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
|
@ -19,12 +19,10 @@ import info.nightscout.androidaps.database.entities.EffectiveProfileSwitch
|
||||||
import info.nightscout.androidaps.database.entities.ProfileSwitch
|
import info.nightscout.androidaps.database.entities.ProfileSwitch
|
||||||
import info.nightscout.androidaps.database.interfaces.end
|
import info.nightscout.androidaps.database.interfaces.end
|
||||||
import info.nightscout.androidaps.dialogs.BolusProgressDialog
|
import info.nightscout.androidaps.dialogs.BolusProgressDialog
|
||||||
import info.nightscout.androidaps.events.EventBolusRequested
|
import info.nightscout.androidaps.events.EventMobileToWear
|
||||||
import info.nightscout.androidaps.events.EventProfileSwitchChanged
|
import info.nightscout.androidaps.events.EventProfileSwitchChanged
|
||||||
import info.nightscout.androidaps.extensions.getCustomizedName
|
import info.nightscout.androidaps.extensions.getCustomizedName
|
||||||
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.configBuilder.ConstraintChecker
|
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||||
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissBolusProgressIfRunning
|
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissBolusProgressIfRunning
|
||||||
|
@ -40,7 +38,10 @@ import info.nightscout.androidaps.utils.HtmlHelper
|
||||||
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
|
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
|
||||||
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 info.nightscout.shared.weardata.EventData
|
||||||
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 io.reactivex.rxjava3.kotlin.subscribeBy
|
import io.reactivex.rxjava3.kotlin.subscribeBy
|
||||||
|
@ -297,7 +298,7 @@ class CommandQueueImplementation @Inject constructor(
|
||||||
// not when the Bolus command is starting. The command closes the dialog upon completion).
|
// not when the Bolus command is starting. The command closes the dialog upon completion).
|
||||||
showBolusProgressDialog(detailedBolusInfo)
|
showBolusProgressDialog(detailedBolusInfo)
|
||||||
// Notify Wear about upcoming bolus
|
// Notify Wear about upcoming bolus
|
||||||
rxBus.send(EventBolusRequested(detailedBolusInfo.insulin))
|
rxBus.send(EventMobileToWear(EventData.BolusProgress(percent = 0, status = rh.gs(R.string.bolusrequested, detailedBolusInfo.insulin))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
notifyAboutNewCommand()
|
notifyAboutNewCommand()
|
||||||
|
|
|
@ -65,10 +65,14 @@ class BolusWizard @Inject constructor(
|
||||||
|
|
||||||
private val disposable = CompositeDisposable()
|
private val disposable = CompositeDisposable()
|
||||||
|
|
||||||
|
var timeStamp : Long
|
||||||
|
|
||||||
init {
|
init {
|
||||||
injector.androidInjector().inject(this)
|
injector.androidInjector().inject(this)
|
||||||
|
timeStamp = dateUtil.now()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Intermediate
|
// Intermediate
|
||||||
var sens = 0.0
|
var sens = 0.0
|
||||||
private set
|
private set
|
||||||
|
@ -236,7 +240,7 @@ class BolusWizard @Inject constructor(
|
||||||
// Total
|
// Total
|
||||||
calculatedTotalInsulin = insulinFromBG + insulinFromTrend + insulinFromCarbs + insulinFromBolusIOB + insulinFromBasalIOB + insulinFromCorrection + insulinFromSuperBolus + insulinFromCOB
|
calculatedTotalInsulin = insulinFromBG + insulinFromTrend + insulinFromCarbs + insulinFromBolusIOB + insulinFromBasalIOB + insulinFromCorrection + insulinFromSuperBolus + insulinFromCOB
|
||||||
|
|
||||||
var percentage = if (usePercentage) totalPercentage else percentageCorrection.toDouble()
|
val percentage = if (usePercentage) totalPercentage else percentageCorrection.toDouble()
|
||||||
|
|
||||||
// Percentage adjustment
|
// Percentage adjustment
|
||||||
totalBeforePercentageAdjustment = calculatedTotalInsulin
|
totalBeforePercentageAdjustment = calculatedTotalInsulin
|
||||||
|
|
|
@ -9,6 +9,7 @@ import org.json.JSONObject
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
class QuickWizard @Inject constructor(
|
class QuickWizard @Inject constructor(
|
||||||
|
@ -55,6 +56,11 @@ class QuickWizard @Inject constructor(
|
||||||
operator fun get(position: Int): QuickWizardEntry =
|
operator fun get(position: Int): QuickWizardEntry =
|
||||||
QuickWizardEntry(injector).from(storage.get(position) as JSONObject, position)
|
QuickWizardEntry(injector).from(storage.get(position) as JSONObject, position)
|
||||||
|
|
||||||
|
fun list(): ArrayList<QuickWizardEntry> =
|
||||||
|
ArrayList<QuickWizardEntry>().also {
|
||||||
|
for (i in 0 until size()) it.add(get(i))
|
||||||
|
}
|
||||||
|
|
||||||
fun get(guid: String): QuickWizardEntry? {
|
fun get(guid: String): QuickWizardEntry? {
|
||||||
for (i in 0 until storage.length()) {
|
for (i in 0 until storage.length()) {
|
||||||
val entry = QuickWizardEntry(injector).from(storage.get(i) as JSONObject, i)
|
val entry = QuickWizardEntry(injector).from(storage.get(i) as JSONObject, i)
|
||||||
|
|
|
@ -1212,4 +1212,5 @@
|
||||||
<string name="show_hide_records">Hide loop records</string>
|
<string name="show_hide_records">Hide loop records</string>
|
||||||
<string name="widget_description">AndroidAPS widget</string>
|
<string name="widget_description">AndroidAPS widget</string>
|
||||||
<string name="configure">Configure opacity</string>
|
<string name="configure">Configure opacity</string>
|
||||||
|
<string name="loop_status">Loop status</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -4,9 +4,9 @@ import android.content.Context
|
||||||
import android.os.PowerManager
|
import android.os.PowerManager
|
||||||
import dagger.android.AndroidInjector
|
import dagger.android.AndroidInjector
|
||||||
import dagger.android.HasAndroidInjector
|
import dagger.android.HasAndroidInjector
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
import info.nightscout.androidaps.TestBaseWithProfile
|
import info.nightscout.androidaps.TestBaseWithProfile
|
||||||
import info.nightscout.androidaps.TestPumpPlugin
|
import info.nightscout.androidaps.TestPumpPlugin
|
||||||
import info.nightscout.androidaps.core.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.database.AppRepository
|
import info.nightscout.androidaps.database.AppRepository
|
||||||
|
@ -138,6 +138,7 @@ class CommandQueueImplementationTest : TestBaseWithProfile() {
|
||||||
`when`(constraintChecker.applyBasalPercentConstraints(anyObject(), anyObject())).thenReturn(percentageConstraint)
|
`when`(constraintChecker.applyBasalPercentConstraints(anyObject(), anyObject())).thenReturn(percentageConstraint)
|
||||||
`when`(rh.gs(R.string.connectiontimedout)).thenReturn("Connection timed out")
|
`when`(rh.gs(R.string.connectiontimedout)).thenReturn("Connection timed out")
|
||||||
`when`(rh.gs(R.string.formatinsulinunits)).thenReturn("%1\$.2f U")
|
`when`(rh.gs(R.string.formatinsulinunits)).thenReturn("%1\$.2f U")
|
||||||
|
`when`(rh.gs(R.string.bolusrequested)).thenReturn("Going to deliver %1\$.2f U")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -48,6 +48,7 @@ class BolusWizardTest : TestBase() {
|
||||||
it.activePlugin = activePlugin
|
it.activePlugin = activePlugin
|
||||||
it.commandQueue = commandQueue
|
it.commandQueue = commandQueue
|
||||||
it.loop = loop
|
it.loop = loop
|
||||||
|
it.dateUtil = dateUtil
|
||||||
it.iobCobCalculator = iobCobCalculator
|
it.iobCobCalculator = iobCobCalculator
|
||||||
it.glucoseStatusProvider = GlucoseStatusProvider(aapsLogger = aapsLogger, iobCobCalculator = iobCobCalculator, dateUtil = dateUtil)
|
it.glucoseStatusProvider = GlucoseStatusProvider(aapsLogger = aapsLogger, iobCobCalculator = iobCobCalculator, dateUtil = dateUtil)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
package info.nightscout.androidaps.events
|
||||||
|
|
||||||
|
import info.nightscout.shared.weardata.EventData
|
||||||
|
|
||||||
|
class EventMobileToWear(val payload: EventData) : Event()
|
|
@ -0,0 +1,5 @@
|
||||||
|
package info.nightscout.androidaps.events
|
||||||
|
|
||||||
|
import info.nightscout.shared.weardata.EventData
|
||||||
|
|
||||||
|
class EventWearToMobile(val payload: EventData) : Event()
|
|
@ -1,7 +0,0 @@
|
||||||
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()
|
|
|
@ -1,7 +0,0 @@
|
||||||
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()
|
|
|
@ -1,7 +0,0 @@
|
||||||
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()
|
|
|
@ -1,33 +0,0 @@
|
||||||
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,237 @@
|
||||||
|
package info.nightscout.shared.weardata
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.events.Event
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
sealed class EventData : Event() {
|
||||||
|
|
||||||
|
var sourceNodeId = ""
|
||||||
|
|
||||||
|
fun serialize() = Json.encodeToString(serializer(), this)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
fun deserialize(json: String) = Json.decodeFromString(serializer(), json)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mobile <- Wear
|
||||||
|
@Serializable
|
||||||
|
data class ActionPong(val timeStamp: Long) : EventData()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Error(val timeStamp: Long) : EventData() // ignored
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class CancelBolus(val timeStamp: Long) : EventData()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ActionResendData(val from: String) : EventData()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ActionPumpStatus(val timeStamp: Long) : EventData()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ActionLoopStatus(val timeStamp: Long) : EventData()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ActionTddStatus(val timeStamp: Long) : EventData()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ActionECarbsPreCheck(val carbs: Int, val carbsTimeShift: Int, val duration: Int) : EventData()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ActionBolusPreCheck(val insulin: Double, val carbs: Int) : EventData()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ActionFillPreCheck(val insulin: Double) : EventData()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ActionFillPresetPreCheck(val button: Int) : EventData()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ActionProfileSwitchSendInitialData(val timeStamp: Long) : EventData()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ActionProfileSwitchPreCheck(val timeShift: Int, val percentage: Int) : EventData()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ActionWizardPreCheck(val carbs: Int, val percentage: Int) : EventData()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ActionQuickWizardPreCheck(val guid: String) : EventData()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ActionTempTargetPreCheck(
|
||||||
|
val command: TempTargetCommand,
|
||||||
|
val isMgdl: Boolean = true, val duration: Int = 0, val low: Double = 0.0, val high: Double = 0.0 // manual
|
||||||
|
) : EventData() {
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
enum class TempTargetCommand {
|
||||||
|
|
||||||
|
PRESET_ACTIVITY, PRESET_HYPO, PRESET_EATING, CANCEL, MANUAL
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mobile <- Wear return
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ActionWizardConfirmed(val timeStamp: Long) : EventData()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ActionTempTargetConfirmed(val isMgdl: Boolean = true, val duration: Int = 0, val low: Double = 0.0, val high: Double = 0.0) : EventData()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ActionBolusConfirmed(val insulin: Double, val carbs: Int) : EventData()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ActionECarbsConfirmed(val carbs: Int, val carbsTime: Long, val duration: Int) : EventData()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ActionFillConfirmed(val insulin: Double) : EventData()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ActionProfileSwitchConfirmed(val timeShift: Int, val percentage: Int) : EventData()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class OpenLoopRequestConfirmed(val timeStamp: Long) : EventData()
|
||||||
|
|
||||||
|
// Mobile -> Wear
|
||||||
|
@Serializable
|
||||||
|
data class CancelNotification(val timeStamp: Long) : EventData()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ActionPing(val timeStamp: Long) : EventData()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class OpenSettings(val timeStamp: Long) : EventData()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class BolusProgress(val percent: Int, val status: String) : EventData()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class SingleBg @JvmOverloads constructor(
|
||||||
|
var timeStamp: Long,
|
||||||
|
val sgvString: String = "---",
|
||||||
|
val glucoseUnits: String = "-",
|
||||||
|
val slopeArrow: String = "--",
|
||||||
|
val delta: String = "--",
|
||||||
|
val avgDelta: String = "--",
|
||||||
|
val sgvLevel: Long = 0,
|
||||||
|
val sgv: Double,
|
||||||
|
val high: Double, // highLine
|
||||||
|
val low: Double, // lowLine
|
||||||
|
val color: Int = 0
|
||||||
|
) : EventData(), Comparable<SingleBg> {
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean =
|
||||||
|
when {
|
||||||
|
other !is SingleBg -> false
|
||||||
|
color != other.color -> false
|
||||||
|
else -> timeStamp == other.timeStamp
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return Objects.hash(timeStamp, color)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun compareTo(other: SingleBg): Int {
|
||||||
|
// reverse order endTime get latest first
|
||||||
|
if (this.timeStamp < other.timeStamp) return 1
|
||||||
|
return if (this.timeStamp > other.timeStamp) -1 else 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class GraphData(
|
||||||
|
val entries: ArrayList<SingleBg>
|
||||||
|
) : EventData()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class TreatmentData(
|
||||||
|
val temps: ArrayList<TempBasal>,
|
||||||
|
val basals: ArrayList<Basal>,
|
||||||
|
val boluses: ArrayList<Treatment>,
|
||||||
|
val predictions: ArrayList<SingleBg>
|
||||||
|
) : EventData() {
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class TempBasal(
|
||||||
|
val startTime: Long,
|
||||||
|
val startBasal: Double,
|
||||||
|
val endTime: Long,
|
||||||
|
val endBasal: Double,
|
||||||
|
val amount: Double
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Basal(
|
||||||
|
val startTime: Long,
|
||||||
|
val endTime: Long,
|
||||||
|
val amount: Double
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Treatment(
|
||||||
|
val date: Long,
|
||||||
|
val bolus: Double,
|
||||||
|
val carbs: Double,
|
||||||
|
val isSMB: Boolean,
|
||||||
|
val isValid: Boolean,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Status(
|
||||||
|
val externalStatus: String,
|
||||||
|
val iobSum: String,
|
||||||
|
val iobDetail: String,
|
||||||
|
val detailedIob: Boolean,
|
||||||
|
val cob: String,
|
||||||
|
val currentBasal: String,
|
||||||
|
val battery: String,
|
||||||
|
val rigBattery: String,
|
||||||
|
val openApsStatus: Long,
|
||||||
|
val bgi: String,
|
||||||
|
val showBgi: Boolean,
|
||||||
|
val batteryLevel: Int
|
||||||
|
) : EventData()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Preferences(
|
||||||
|
val timeStamp: Long,
|
||||||
|
val wearControl: Boolean,
|
||||||
|
val unitsMgdl: Boolean,
|
||||||
|
val bolusPercentage: Int,
|
||||||
|
val maxCarbs: Int,
|
||||||
|
val maxBolus: Double
|
||||||
|
) : EventData()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class QuickWizard(
|
||||||
|
val entries: ArrayList<QuickWizardEntry>
|
||||||
|
) : EventData() {
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class QuickWizardEntry(
|
||||||
|
val guid: String,
|
||||||
|
val buttonText: String,
|
||||||
|
val carbs: Int,
|
||||||
|
val validFrom: Int,
|
||||||
|
val validTo: Int
|
||||||
|
) : EventData()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ActionProfileSwitchOpenActivity(val timeShift: Int, val percentage: Int) : EventData()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class OpenLoopRequest(val title: String, val message: String, val returnCommand: EventData?) : EventData()
|
||||||
|
|
||||||
|
@Serializable // returnCommand is sent back to Mobile after confirmation
|
||||||
|
data class ConfirmAction(val title: String, val message: String, val returnCommand: EventData?) : EventData()
|
||||||
|
}
|
|
@ -1,61 +0,0 @@
|
||||||
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,19 +1,4 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="path_ping" translatable="false">/ping</string>
|
<string name="path_rx_bridge" translatable="false">/rx_bridge</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>
|
</resources>
|
|
@ -241,7 +241,7 @@
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<service android:name=".data.DataLayerListenerService"
|
<service android:name=".comm.DataLayerListenerServiceWear"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="com.google.android.gms.wearable.CAPABILITY_CHANGED" />
|
<action android:name="com.google.android.gms.wearable.CAPABILITY_CHANGED" />
|
||||||
|
@ -252,42 +252,6 @@
|
||||||
|
|
||||||
<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>
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
@ -299,15 +263,7 @@
|
||||||
|
|
||||||
<data
|
<data
|
||||||
android:host="*"
|
android:host="*"
|
||||||
android:pathPrefix="@string/path_ping"
|
android:pathPrefix="@string/path_rx_bridge"
|
||||||
android:scheme="wear" />
|
|
||||||
<data
|
|
||||||
android:host="*"
|
|
||||||
android:pathPrefix="@string/path_open_wear_setting"
|
|
||||||
android:scheme="wear" />
|
|
||||||
<data
|
|
||||||
android:host="*"
|
|
||||||
android:pathPrefix="@string/path_action_confirmation"
|
|
||||||
android:scheme="wear" />
|
android:scheme="wear" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</service>
|
</service>
|
||||||
|
@ -466,7 +422,7 @@
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".complications.UploaderBattery"
|
android:name=".complications.UploaderBatteryComplication"
|
||||||
android:icon="@drawable/ic_battery_charging_wireless_50"
|
android:icon="@drawable/ic_battery_charging_wireless_50"
|
||||||
android:label="Uploader/Phone Battery"
|
android:label="Uploader/Phone Battery"
|
||||||
android:permission="com.google.android.wearable.permission.BIND_COMPLICATION_PROVIDER">
|
android:permission="com.google.android.wearable.permission.BIND_COMPLICATION_PROVIDER">
|
||||||
|
|
|
@ -7,7 +7,11 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import dagger.android.AndroidInjector
|
import dagger.android.AndroidInjector
|
||||||
import dagger.android.DaggerApplication
|
import dagger.android.DaggerApplication
|
||||||
|
import info.nightscout.androidaps.comm.DataHandlerWear
|
||||||
|
import info.nightscout.androidaps.comm.DataLayerListenerServiceWear
|
||||||
import info.nightscout.androidaps.di.DaggerWearComponent
|
import info.nightscout.androidaps.di.DaggerWearComponent
|
||||||
|
import info.nightscout.androidaps.events.EventWearPreferenceChange
|
||||||
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
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 javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -15,11 +19,15 @@ import javax.inject.Inject
|
||||||
class Aaps : DaggerApplication(), OnSharedPreferenceChangeListener {
|
class Aaps : DaggerApplication(), OnSharedPreferenceChangeListener {
|
||||||
|
|
||||||
@Inject lateinit var aapsLogger: AAPSLogger
|
@Inject lateinit var aapsLogger: AAPSLogger
|
||||||
|
@Inject lateinit var rxBus: RxBus
|
||||||
|
@Inject lateinit var dataHandlerWear: DataHandlerWear // instantiate only
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
aapsLogger.debug(LTag.WEAR, "onCreate")
|
aapsLogger.debug(LTag.WEAR, "onCreate")
|
||||||
PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this)
|
PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this)
|
||||||
|
startService(Intent(this, DataLayerListenerServiceWear::class.java))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun applicationInjector(): AndroidInjector<out DaggerApplication> =
|
override fun applicationInjector(): AndroidInjector<out DaggerApplication> =
|
||||||
|
@ -30,6 +38,7 @@ class Aaps : DaggerApplication(), OnSharedPreferenceChangeListener {
|
||||||
|
|
||||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) {
|
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) {
|
||||||
// we trigger update on Complications
|
// we trigger update on Complications
|
||||||
LocalBroadcastManager.getInstance(this).sendBroadcast(Intent(Intent.ACTION_SEND))
|
LocalBroadcastManager.getInstance(this).sendBroadcast(Intent(DataLayerListenerServiceWear.INTENT_NEW_DATA))
|
||||||
|
rxBus.send(EventWearPreferenceChange(key))
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,301 @@
|
||||||
|
package info.nightscout.androidaps.comm
|
||||||
|
|
||||||
|
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.SystemClock
|
||||||
|
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.wearable.WearableListenerService
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.events.EventWearToMobile
|
||||||
|
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.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.logging.AAPSLogger
|
||||||
|
import info.nightscout.shared.logging.LTag
|
||||||
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
|
import info.nightscout.shared.weardata.EventData
|
||||||
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
|
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class DataHandlerWear @Inject constructor(
|
||||||
|
private val context: Context,
|
||||||
|
private val rxBus: RxBus,
|
||||||
|
private val aapsSchedulers: AapsSchedulers,
|
||||||
|
private val sp: SP,
|
||||||
|
private val aapsLogger: AAPSLogger,
|
||||||
|
private val persistence: Persistence
|
||||||
|
) {
|
||||||
|
|
||||||
|
private val disposable = CompositeDisposable()
|
||||||
|
|
||||||
|
init {
|
||||||
|
setupBus()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupBus() {
|
||||||
|
disposable += rxBus
|
||||||
|
.toObservable(EventData.ActionPing::class.java)
|
||||||
|
.observeOn(aapsSchedulers.io)
|
||||||
|
.subscribe {
|
||||||
|
aapsLogger.debug(LTag.WEAR, "Ping received from ${it.sourceNodeId}")
|
||||||
|
rxBus.send(EventWearToMobile(EventData.ActionPong(System.currentTimeMillis())))
|
||||||
|
}
|
||||||
|
disposable += rxBus
|
||||||
|
.toObservable(EventData.ConfirmAction::class.java)
|
||||||
|
.observeOn(aapsSchedulers.io)
|
||||||
|
.subscribe {
|
||||||
|
aapsLogger.debug(LTag.WEAR, "ConfirmAction received from ${it.sourceNodeId}")
|
||||||
|
context.startActivity(Intent(context, AcceptActivity::class.java).apply {
|
||||||
|
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
putExtras(
|
||||||
|
Bundle().also { bundle ->
|
||||||
|
bundle.putString("title", it.title)
|
||||||
|
bundle.putString("message", it.message)
|
||||||
|
bundle.putString(DataLayerListenerServiceWear.KEY_ACTION_DATA, it.returnCommand?.serialize())
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
disposable += rxBus
|
||||||
|
.toObservable(EventData.CancelNotification::class.java)
|
||||||
|
.observeOn(aapsSchedulers.io)
|
||||||
|
.subscribe {
|
||||||
|
aapsLogger.debug(LTag.WEAR, "ActionCancelNotification received from ${it.sourceNodeId}")
|
||||||
|
(context.getSystemService(WearableListenerService.NOTIFICATION_SERVICE) as NotificationManager).cancel(DataLayerListenerServiceWear.CHANGE_NOTIF_ID)
|
||||||
|
}
|
||||||
|
disposable += rxBus
|
||||||
|
.toObservable(EventData.OpenLoopRequest::class.java)
|
||||||
|
.observeOn(aapsSchedulers.io)
|
||||||
|
.subscribe {
|
||||||
|
aapsLogger.debug(LTag.WEAR, "OpenLoopRequest received from ${it.sourceNodeId}")
|
||||||
|
handleOpenLoopRequest(it)
|
||||||
|
}
|
||||||
|
disposable += rxBus
|
||||||
|
.toObservable(EventData.OpenSettings::class.java)
|
||||||
|
.observeOn(aapsSchedulers.io)
|
||||||
|
.subscribe {
|
||||||
|
aapsLogger.debug(LTag.WEAR, "ActionOpenSettings received from ${it.sourceNodeId}")
|
||||||
|
context.startActivity(Intent(context, AAPSPreferences::class.java).apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) })
|
||||||
|
}
|
||||||
|
disposable += rxBus
|
||||||
|
.toObservable(EventData.ActionProfileSwitchOpenActivity::class.java)
|
||||||
|
.observeOn(aapsSchedulers.io)
|
||||||
|
.subscribe { event ->
|
||||||
|
aapsLogger.debug(LTag.WEAR, "ActionProfileSwitchOpenActivity received from ${event.sourceNodeId}")
|
||||||
|
context.startActivity(Intent(context, CPPActivity::class.java).apply {
|
||||||
|
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
putExtras(Bundle().also { bundle ->
|
||||||
|
bundle.putInt("percentage", event.percentage)
|
||||||
|
bundle.putInt("timeshift", event.timeShift)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
disposable += rxBus
|
||||||
|
.toObservable(EventData.BolusProgress::class.java)
|
||||||
|
.observeOn(aapsSchedulers.io)
|
||||||
|
.subscribe {
|
||||||
|
aapsLogger.debug(LTag.WEAR, "Bolus progress received from ${it.sourceNodeId}")
|
||||||
|
handleBolusProgress(it)
|
||||||
|
rxBus.send(EventWearToMobile(EventData.ActionPong(System.currentTimeMillis())))
|
||||||
|
}
|
||||||
|
disposable += rxBus
|
||||||
|
.toObservable(EventData.Status::class.java)
|
||||||
|
.observeOn(aapsSchedulers.io)
|
||||||
|
.subscribe {
|
||||||
|
aapsLogger.debug(LTag.WEAR, "Status received from ${it.sourceNodeId}")
|
||||||
|
persistence.store(it)
|
||||||
|
LocalBroadcastManager.getInstance(context).sendBroadcast(
|
||||||
|
Intent(DataLayerListenerServiceWear.INTENT_NEW_DATA).apply {
|
||||||
|
putExtra(DataLayerListenerServiceWear.KEY_STATUS_DATA, it.serialize())
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
disposable += rxBus
|
||||||
|
.toObservable(EventData.SingleBg::class.java)
|
||||||
|
.observeOn(aapsSchedulers.io)
|
||||||
|
.subscribe {
|
||||||
|
aapsLogger.debug(LTag.WEAR, "SingleBg received from ${it.sourceNodeId}")
|
||||||
|
persistence.store(it)
|
||||||
|
LocalBroadcastManager.getInstance(context).sendBroadcast(
|
||||||
|
Intent(DataLayerListenerServiceWear.INTENT_NEW_DATA).apply {
|
||||||
|
putExtra(DataLayerListenerServiceWear.KEY_SINGLE_BG_DATA, it.serialize())
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
disposable += rxBus
|
||||||
|
.toObservable(EventData.GraphData::class.java)
|
||||||
|
.observeOn(aapsSchedulers.io)
|
||||||
|
.subscribe {
|
||||||
|
aapsLogger.debug(LTag.WEAR, "GraphData received from ${it.sourceNodeId}")
|
||||||
|
persistence.store(it)
|
||||||
|
LocalBroadcastManager.getInstance(context).sendBroadcast(
|
||||||
|
Intent(DataLayerListenerServiceWear.INTENT_NEW_DATA).apply {
|
||||||
|
putExtra(DataLayerListenerServiceWear.KEY_GRAPH_DATA, it.serialize())
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
disposable += rxBus
|
||||||
|
.toObservable(EventData.TreatmentData::class.java)
|
||||||
|
.observeOn(aapsSchedulers.io)
|
||||||
|
.subscribe {
|
||||||
|
aapsLogger.debug(LTag.WEAR, "TreatmentData received from ${it.sourceNodeId}")
|
||||||
|
persistence.store(it)
|
||||||
|
LocalBroadcastManager.getInstance(context).sendBroadcast(
|
||||||
|
Intent(DataLayerListenerServiceWear.INTENT_NEW_DATA).apply {
|
||||||
|
putExtra(DataLayerListenerServiceWear.KEY_TREATMENTS_DATA, it.serialize())
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
disposable += rxBus
|
||||||
|
.toObservable(EventData.Preferences::class.java)
|
||||||
|
.observeOn(aapsSchedulers.io)
|
||||||
|
.subscribe {
|
||||||
|
aapsLogger.debug(LTag.WEAR, "Preferences received from ${it.sourceNodeId}")
|
||||||
|
if (it.wearControl != sp.getBoolean(R.string.key_wear_control, false)) {
|
||||||
|
sp.putBoolean(R.string.key_wear_control, it.wearControl)
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
TileService.getUpdater(context).requestUpdate(ActionsTileService::class.java)
|
||||||
|
TileService.getUpdater(context).requestUpdate(TempTargetTileService::class.java)
|
||||||
|
TileService.getUpdater(context).requestUpdate(QuickWizardTileService::class.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sp.putBoolean(R.string.key_units_mgdl, it.unitsMgdl)
|
||||||
|
sp.putInt(R.string.key_boluswizard_percentage, it.bolusPercentage)
|
||||||
|
sp.putInt(R.string.key_treatmentssafety_maxcarbs, it.maxCarbs)
|
||||||
|
sp.putDouble(R.string.key_treatmentssafety_maxbolus, it.maxBolus)
|
||||||
|
}
|
||||||
|
disposable += rxBus
|
||||||
|
.toObservable(EventData.QuickWizard::class.java)
|
||||||
|
.observeOn(aapsSchedulers.io)
|
||||||
|
.subscribe {
|
||||||
|
aapsLogger.debug(LTag.WEAR, "QuickWizard received from ${it.sourceNodeId}")
|
||||||
|
val serialized = it.serialize()
|
||||||
|
if (serialized != sp.getString(R.string.key_quick_wizard_data, "")) {
|
||||||
|
sp.putString(R.string.key_quick_wizard_data, serialized)
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
|
||||||
|
TileService.getUpdater(context).requestUpdate(QuickWizardTileService::class.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleBolusProgress(bolusProgress: EventData.BolusProgress) {
|
||||||
|
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(context, DataLayerListenerServiceWear::class.java)
|
||||||
|
cancelIntent.action = DataLayerListenerServiceWear.INTENT_CANCEL_BOLUS
|
||||||
|
val cancelPendingIntent = PendingIntent.getService(context, 0, cancelIntent, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT)
|
||||||
|
val notificationBuilder: NotificationCompat.Builder =
|
||||||
|
NotificationCompat.Builder(context, if (vibrate) DataLayerListenerServiceWear.AAPS_NOTIFY_CHANNEL_ID_BOLUS_PROGRESS else DataLayerListenerServiceWear.AAPS_NOTIFY_CHANNEL_ID_BOLUS_PROGRESS_SILENT)
|
||||||
|
.setSmallIcon(R.drawable.ic_icon)
|
||||||
|
.setContentTitle(context.getString(R.string.bolus_progress))
|
||||||
|
.setContentText("${bolusProgress.percent}% - ${bolusProgress.status}")
|
||||||
|
.setSubText(context.getString(R.string.press_to_cancel))
|
||||||
|
.setContentIntent(cancelPendingIntent)
|
||||||
|
.setPriority(NotificationCompat.PRIORITY_MAX)
|
||||||
|
.setVibrate(vibratePattern)
|
||||||
|
.addAction(R.drawable.ic_cancel, context.getString(R.string.cancel_bolus), cancelPendingIntent)
|
||||||
|
val notificationManager = NotificationManagerCompat.from(context)
|
||||||
|
notificationManager.notify(DataLayerListenerServiceWear.BOLUS_PROGRESS_NOTIF_ID, notificationBuilder.build())
|
||||||
|
notificationManager.cancel(DataLayerListenerServiceWear.CONFIRM_NOTIF_ID) // multiple watch setup
|
||||||
|
if (bolusProgress.percent == 100) {
|
||||||
|
scheduleDismissBolusProgress(5)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@TargetApi(value = 26) private fun createBolusProgressChannels() {
|
||||||
|
createNotificationChannel(
|
||||||
|
longArrayOf(0, 50, 1000),
|
||||||
|
DataLayerListenerServiceWear.AAPS_NOTIFY_CHANNEL_ID_BOLUS_PROGRESS,
|
||||||
|
context.getString(R.string.bolus_progress_channel_name),
|
||||||
|
context.getString(R.string.bolus_progress_channel_description)
|
||||||
|
)
|
||||||
|
createNotificationChannel(
|
||||||
|
longArrayOf(0, 1, 1000),
|
||||||
|
DataLayerListenerServiceWear.AAPS_NOTIFY_CHANNEL_ID_BOLUS_PROGRESS_SILENT,
|
||||||
|
context.getString(R.string.bolus_progress_silent_channel_name),
|
||||||
|
context.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
|
||||||
|
context.getSystemService(NotificationManager::class.java)
|
||||||
|
.createNotificationChannel(channel)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleOpenLoopRequest(command: EventData.OpenLoopRequest) {
|
||||||
|
// 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(DataLayerListenerServiceWear.AAPS_NOTIFY_CHANNEL_ID_OPEN_LOOP, 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 = context.getSystemService(NotificationManager::class.java)
|
||||||
|
notificationManager.createNotificationChannel(channel)
|
||||||
|
}
|
||||||
|
var builder = NotificationCompat.Builder(context, DataLayerListenerServiceWear.AAPS_NOTIFY_CHANNEL_ID_OPEN_LOOP)
|
||||||
|
builder = builder.setSmallIcon(R.drawable.notif_icon)
|
||||||
|
.setContentTitle(command.title)
|
||||||
|
.setContentText(command.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(context, AcceptActivity::class.java).apply {
|
||||||
|
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
putExtras(Bundle().also { bundle ->
|
||||||
|
bundle.putString("title", command.title)
|
||||||
|
bundle.putString("message", command.message)
|
||||||
|
bundle.putString(DataLayerListenerServiceWear.KEY_ACTION_DATA, command.returnCommand?.serialize())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
val resultPendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT)
|
||||||
|
builder = builder.setContentIntent(resultPendingIntent)
|
||||||
|
val mNotificationManager = context.getSystemService(WearableListenerService.NOTIFICATION_SERVICE) as NotificationManager
|
||||||
|
// mId allows you to update the notification later on.
|
||||||
|
mNotificationManager.notify(DataLayerListenerServiceWear.CHANGE_NOTIF_ID, builder.build())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("SameParameterValue")
|
||||||
|
private fun scheduleDismissBolusProgress(seconds: Int) {
|
||||||
|
Thread {
|
||||||
|
SystemClock.sleep(seconds * 1000L)
|
||||||
|
NotificationManagerCompat.from(context).cancel(DataLayerListenerServiceWear.BOLUS_PROGRESS_NOTIF_ID)
|
||||||
|
}.start()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,210 @@
|
||||||
|
package info.nightscout.androidaps.comm
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.HandlerThread
|
||||||
|
import androidx.core.app.NotificationManagerCompat
|
||||||
|
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.EventWearToMobile
|
||||||
|
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.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.weardata.EventData
|
||||||
|
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 DataLayerListenerServiceWear : 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
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
private val rxPath get() = getString(R.string.path_rx_bridge)
|
||||||
|
|
||||||
|
override fun onCreate() {
|
||||||
|
AndroidInjection.inject(this)
|
||||||
|
super.onCreate()
|
||||||
|
handler.post { updateTranscriptionCapability() }
|
||||||
|
disposable += rxBus
|
||||||
|
.toObservable(EventWearToMobile::class.java)
|
||||||
|
.observeOn(aapsSchedulers.io)
|
||||||
|
.subscribe {
|
||||||
|
sendMessage(rxPath, it.payload.serialize())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
@Suppress("ControlFlowWithEmptyBody", "UNUSED_EXPRESSION")
|
||||||
|
when (path) {
|
||||||
|
}
|
||||||
|
} catch (exception: Exception) {
|
||||||
|
aapsLogger.error(LTag.WEAR, "onDataChanged failed", exception)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.onDataChanged(dataEvents)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMessageReceived(messageEvent: MessageEvent) {
|
||||||
|
super.onMessageReceived(messageEvent)
|
||||||
|
|
||||||
|
when (messageEvent.path) {
|
||||||
|
rxPath -> {
|
||||||
|
aapsLogger.debug(LTag.WEAR, "onMessageReceived: ${String(messageEvent.data)}")
|
||||||
|
val command = EventData.deserialize(String(messageEvent.data))
|
||||||
|
rxBus.send(command.also { it.sourceNodeId = messageEvent.sourceNodeId })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
|
when (intent?.action) {
|
||||||
|
|
||||||
|
INTENT_CANCEL_BOLUS -> {
|
||||||
|
//dismiss notification
|
||||||
|
NotificationManagerCompat.from(this).cancel(BOLUS_PROGRESS_NOTIF_ID)
|
||||||
|
//send cancel-request to phone.
|
||||||
|
rxBus.send(EventWearToMobile(EventData.CancelBolus(System.currentTimeMillis())))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
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
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
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: String?) {
|
||||||
|
aapsLogger.debug(LTag.WEAR, "sendMessage: $path $data")
|
||||||
|
transcriptionNodeId?.also { nodeId ->
|
||||||
|
messageClient
|
||||||
|
.sendMessage(nodeId, path, data?.toByteArray() ?: byteArrayOf()).apply {
|
||||||
|
addOnSuccessListener { }
|
||||||
|
addOnFailureListener {
|
||||||
|
aapsLogger.debug(LTag.WEAR, "sendMessage: $path failure")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
const val PHONE_CAPABILITY = "androidaps_mobile"
|
||||||
|
|
||||||
|
// Accepted intents
|
||||||
|
val INTENT_CANCEL_BOLUS = DataLayerListenerServiceWear::class.java.name + ".CancelBolus"
|
||||||
|
val INTENT_NEW_DATA = DataLayerListenerServiceWear::class.java.name + ".NewData"
|
||||||
|
|
||||||
|
//data keys
|
||||||
|
const val KEY_ACTION_DATA = "actionData"
|
||||||
|
const val KEY_ACTION = "action"
|
||||||
|
const val KEY_MESSAGE = "message"
|
||||||
|
const val KEY_SINGLE_BG_DATA = "single_bg_data"
|
||||||
|
const val KEY_TREATMENTS_DATA = "treatments_data"
|
||||||
|
const val KEY_GRAPH_DATA = "graph_data"
|
||||||
|
const val KEY_STATUS_DATA = "status_data"
|
||||||
|
|
||||||
|
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_OPEN_LOOP = "AndroidAPS-OpenLoop"
|
||||||
|
const val AAPS_NOTIFY_CHANNEL_ID_BOLUS_PROGRESS = "bolus progress vibration"
|
||||||
|
const val AAPS_NOTIFY_CHANNEL_ID_BOLUS_PROGRESS_SILENT = "bolus progress silent"
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,15 +22,18 @@ 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.DataLayerListenerService;
|
import info.nightscout.androidaps.comm.DataLayerListenerServiceWear;
|
||||||
import info.nightscout.androidaps.data.RawDisplayData;
|
import info.nightscout.androidaps.data.RawDisplayData;
|
||||||
|
import info.nightscout.androidaps.events.EventWearToMobile;
|
||||||
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;
|
||||||
import info.nightscout.androidaps.interaction.utils.Inevitable;
|
import info.nightscout.androidaps.interaction.utils.Inevitable;
|
||||||
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;
|
||||||
|
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||||
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.weardata.EventData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for all complications
|
* Base class for all complications
|
||||||
|
@ -44,6 +47,7 @@ public abstract class BaseComplicationProviderService extends ComplicationProvid
|
||||||
@Inject DisplayFormat displayFormat;
|
@Inject DisplayFormat displayFormat;
|
||||||
@Inject Persistence persistence;
|
@Inject Persistence persistence;
|
||||||
@Inject AAPSLogger aapsLogger;
|
@Inject AAPSLogger aapsLogger;
|
||||||
|
@Inject RxBus rxBus;
|
||||||
|
|
||||||
// Not derived from DaggerService, do injection here
|
// Not derived from DaggerService, do injection here
|
||||||
@Override
|
@Override
|
||||||
|
@ -199,13 +203,13 @@ public abstract class BaseComplicationProviderService extends ComplicationProvid
|
||||||
persistence.putBoolean("complication_" + complicationId + "_since", usesSinceField());
|
persistence.putBoolean("complication_" + complicationId + "_since", usesSinceField());
|
||||||
persistence.addToSet(KEY_COMPLICATIONS, "complication_" + complicationId);
|
persistence.addToSet(KEY_COMPLICATIONS, "complication_" + complicationId);
|
||||||
|
|
||||||
IntentFilter messageFilter = new IntentFilter(Intent.ACTION_SEND);
|
IntentFilter messageFilter = new IntentFilter(DataLayerListenerServiceWear.Companion.getINTENT_NEW_DATA());
|
||||||
|
|
||||||
messageReceiver = new MessageReceiver();
|
messageReceiver = new MessageReceiver();
|
||||||
localBroadcastManager = LocalBroadcastManager.getInstance(this);
|
localBroadcastManager = LocalBroadcastManager.getInstance(this);
|
||||||
localBroadcastManager.registerReceiver(messageReceiver, messageFilter);
|
localBroadcastManager.registerReceiver(messageReceiver, messageFilter);
|
||||||
|
|
||||||
DataLayerListenerService.Companion.requestData(this);
|
rxBus.send(new EventWearToMobile(new EventData.ActionResendData("BaseComplicationProviderService")));
|
||||||
checkIfUpdateNeeded();
|
checkIfUpdateNeeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,12 +236,13 @@ public abstract class BaseComplicationProviderService extends ComplicationProvid
|
||||||
ComplicationTapBroadcastReceiver.getTapActionIntent(
|
ComplicationTapBroadcastReceiver.getTapActionIntent(
|
||||||
getApplicationContext(), thisProvider, complicationId, getComplicationAction());
|
getApplicationContext(), thisProvider, complicationId, getComplicationAction());
|
||||||
|
|
||||||
final RawDisplayData raw = new RawDisplayData(wearUtil);
|
final RawDisplayData raw = new RawDisplayData();
|
||||||
raw.updateForComplicationsFromPersistence(persistence);
|
raw.updateForComplicationsFromPersistence(persistence);
|
||||||
aapsLogger.warn(LTag.WEAR, "Complication data: " + raw.toDebugString());
|
aapsLogger.warn(LTag.WEAR, "Complication data: " + raw.toDebugString());
|
||||||
|
|
||||||
// store what is currently rendered in 'SGV since' field, to detect if it was changed and need update
|
// store what is currently rendered in 'SGV since' field, to detect if it was changed and need update
|
||||||
persistence.putString(KEY_LAST_SHOWN_SINCE_VALUE, displayFormat.shortTimeSince(raw.datetime));
|
persistence.putString(KEY_LAST_SHOWN_SINCE_VALUE,
|
||||||
|
displayFormat.shortTimeSince(raw.getSingleBg().getTimeStamp()));
|
||||||
|
|
||||||
// by each render we clear stale flag to ensure it is re-rendered at next refresh detection round
|
// by each render we clear stale flag to ensure it is re-rendered at next refresh detection round
|
||||||
persistence.putBoolean(KEY_STALE_REPORTED, false);
|
persistence.putBoolean(KEY_STALE_REPORTED, false);
|
||||||
|
@ -249,11 +254,11 @@ public abstract class BaseComplicationProviderService extends ComplicationProvid
|
||||||
final PendingIntent infoToast = ComplicationTapBroadcastReceiver.getTapWarningSinceIntent(
|
final PendingIntent infoToast = ComplicationTapBroadcastReceiver.getTapWarningSinceIntent(
|
||||||
getApplicationContext(), thisProvider, complicationId, ComplicationAction.WARNING_SYNC, persistence.whenDataUpdated());
|
getApplicationContext(), thisProvider, complicationId, ComplicationAction.WARNING_SYNC, persistence.whenDataUpdated());
|
||||||
complicationData = buildNoSyncComplicationData(dataType, raw, complicationPendingIntent, infoToast, persistence.whenDataUpdated());
|
complicationData = buildNoSyncComplicationData(dataType, raw, complicationPendingIntent, infoToast, persistence.whenDataUpdated());
|
||||||
} else if (wearUtil.msSince(raw.datetime) > Constants.STALE_MS) {
|
} else if (wearUtil.msSince(raw.getSingleBg().getTimeStamp()) > Constants.STALE_MS) {
|
||||||
// data arriving from phone AAPS, but it is outdated (uploader/NS/xDrip/Sensor error)
|
// data arriving from phone AAPS, but it is outdated (uploader/NS/xDrip/Sensor error)
|
||||||
final PendingIntent infoToast = ComplicationTapBroadcastReceiver.getTapWarningSinceIntent(
|
final PendingIntent infoToast = ComplicationTapBroadcastReceiver.getTapWarningSinceIntent(
|
||||||
getApplicationContext(), thisProvider, complicationId, ComplicationAction.WARNING_OLD, raw.datetime);
|
getApplicationContext(), thisProvider, complicationId, ComplicationAction.WARNING_OLD, raw.getSingleBg().getTimeStamp());
|
||||||
complicationData = buildOutdatedComplicationData(dataType, raw, complicationPendingIntent, infoToast, raw.datetime);
|
complicationData = buildOutdatedComplicationData(dataType, raw, complicationPendingIntent, infoToast, raw.getSingleBg().getTimeStamp());
|
||||||
} else {
|
} else {
|
||||||
// data is up-to-date, we can render standard complication
|
// data is up-to-date, we can render standard complication
|
||||||
complicationData = buildComplicationData(dataType, raw, complicationPendingIntent);
|
complicationData = buildComplicationData(dataType, raw, complicationPendingIntent);
|
||||||
|
@ -310,13 +315,13 @@ public abstract class BaseComplicationProviderService extends ComplicationProvid
|
||||||
* is up-to-date or need to be changed (a minute or more elapsed)
|
* is up-to-date or need to be changed (a minute or more elapsed)
|
||||||
*/
|
*/
|
||||||
private void requestUpdateIfSinceChanged() {
|
private void requestUpdateIfSinceChanged() {
|
||||||
final RawDisplayData raw = new RawDisplayData(wearUtil);
|
final RawDisplayData raw = new RawDisplayData();
|
||||||
raw.updateForComplicationsFromPersistence(persistence);
|
raw.updateForComplicationsFromPersistence(persistence);
|
||||||
|
|
||||||
final String lastSince = persistence.getString(KEY_LAST_SHOWN_SINCE_VALUE, "-");
|
final String lastSince = persistence.getString(KEY_LAST_SHOWN_SINCE_VALUE, "-");
|
||||||
final String calcSince = displayFormat.shortTimeSince(raw.datetime);
|
final String calcSince = displayFormat.shortTimeSince(raw.getSingleBg().getTimeStamp());
|
||||||
final boolean isStale = (wearUtil.msSince(persistence.whenDataUpdated()) > Constants.STALE_MS)
|
final boolean isStale = (wearUtil.msSince(persistence.whenDataUpdated()) > Constants.STALE_MS)
|
||||||
|| (wearUtil.msSince(raw.datetime) > Constants.STALE_MS);
|
|| (wearUtil.msSince(raw.getSingleBg().getTimeStamp()) > Constants.STALE_MS);
|
||||||
|
|
||||||
final boolean staleWasRefreshed = persistence.getBoolean(KEY_STALE_REPORTED, false);
|
final boolean staleWasRefreshed = persistence.getBoolean(KEY_STALE_REPORTED, false);
|
||||||
final boolean sinceWasChanged = !lastSince.equals(calcSince);
|
final boolean sinceWasChanged = !lastSince.equals(calcSince);
|
||||||
|
|
|
@ -3,7 +3,6 @@ package info.nightscout.androidaps.complications;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.support.wearable.complications.ComplicationData;
|
import android.support.wearable.complications.ComplicationData;
|
||||||
import android.support.wearable.complications.ComplicationText;
|
import android.support.wearable.complications.ComplicationText;
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
@ -32,11 +31,11 @@ public class BrCobIobComplication extends BaseComplicationProviderService {
|
||||||
ComplicationData complicationData = null;
|
ComplicationData complicationData = null;
|
||||||
|
|
||||||
if (dataType == ComplicationData.TYPE_SHORT_TEXT) {
|
if (dataType == ComplicationData.TYPE_SHORT_TEXT) {
|
||||||
final String cob = new SmallestDoubleString(raw.sCOB2, SmallestDoubleString.Units.USE).minimise(displayFormat.MIN_FIELD_LEN_COB);
|
final String cob = new SmallestDoubleString(raw.getStatus().getCob(), SmallestDoubleString.Units.USE).minimise(displayFormat.MIN_FIELD_LEN_COB);
|
||||||
final String iob = new SmallestDoubleString(raw.sIOB1, SmallestDoubleString.Units.USE).minimise(Math.max(displayFormat.MIN_FIELD_LEN_IOB, (displayFormat.MAX_FIELD_LEN_SHORT - 1) - cob.length()));
|
final String iob = new SmallestDoubleString(raw.getStatus().getIobSum(), SmallestDoubleString.Units.USE).minimise(Math.max(displayFormat.MIN_FIELD_LEN_IOB, (displayFormat.MAX_FIELD_LEN_SHORT - 1) - cob.length()));
|
||||||
|
|
||||||
final ComplicationData.Builder builder = new ComplicationData.Builder(ComplicationData.TYPE_SHORT_TEXT)
|
final ComplicationData.Builder builder = new ComplicationData.Builder(ComplicationData.TYPE_SHORT_TEXT)
|
||||||
.setShortText(ComplicationText.plainText(displayFormat.basalRateSymbol() + raw.sBasalRate))
|
.setShortText(ComplicationText.plainText(displayFormat.basalRateSymbol() + raw.getStatus().getCurrentBasal()))
|
||||||
.setShortTitle(ComplicationText.plainText(cob + " " + iob))
|
.setShortTitle(ComplicationText.plainText(cob + " " + iob))
|
||||||
.setTapAction(complicationPendingIntent);
|
.setTapAction(complicationPendingIntent);
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ public class CobIconComplication extends BaseComplicationProviderService {
|
||||||
|
|
||||||
if (dataType == ComplicationData.TYPE_SHORT_TEXT) {
|
if (dataType == ComplicationData.TYPE_SHORT_TEXT) {
|
||||||
final ComplicationData.Builder builder = new ComplicationData.Builder(ComplicationData.TYPE_SHORT_TEXT)
|
final ComplicationData.Builder builder = new ComplicationData.Builder(ComplicationData.TYPE_SHORT_TEXT)
|
||||||
.setShortText(ComplicationText.plainText(raw.sCOB2))
|
.setShortText(ComplicationText.plainText(raw.getStatus().getCob()))
|
||||||
.setIcon(
|
.setIcon(
|
||||||
Icon.createWithResource(
|
Icon.createWithResource(
|
||||||
this, R.drawable.ic_carbs))
|
this, R.drawable.ic_carbs))
|
||||||
|
|
|
@ -18,8 +18,8 @@ public class CobIobComplication extends BaseComplicationProviderService {
|
||||||
ComplicationData complicationData = null;
|
ComplicationData complicationData = null;
|
||||||
|
|
||||||
if (dataType == ComplicationData.TYPE_SHORT_TEXT) {
|
if (dataType == ComplicationData.TYPE_SHORT_TEXT) {
|
||||||
final String cob = raw.sCOB2;
|
final String cob = raw.getStatus().getCob();
|
||||||
final String iob = new SmallestDoubleString(raw.sIOB1, SmallestDoubleString.Units.USE).minimise(displayFormat.MAX_FIELD_LEN_SHORT);
|
final String iob = new SmallestDoubleString(raw.getStatus().getIobSum(), SmallestDoubleString.Units.USE).minimise(displayFormat.MAX_FIELD_LEN_SHORT);
|
||||||
|
|
||||||
final ComplicationData.Builder builder = new ComplicationData.Builder(ComplicationData.TYPE_SHORT_TEXT)
|
final ComplicationData.Builder builder = new ComplicationData.Builder(ComplicationData.TYPE_SHORT_TEXT)
|
||||||
.setShortText(ComplicationText.plainText(cob))
|
.setShortText(ComplicationText.plainText(cob))
|
||||||
|
|
|
@ -20,7 +20,7 @@ public class IobIconComplication extends BaseComplicationProviderService {
|
||||||
ComplicationData complicationData = null;
|
ComplicationData complicationData = null;
|
||||||
|
|
||||||
if (dataType == ComplicationData.TYPE_SHORT_TEXT) {
|
if (dataType == ComplicationData.TYPE_SHORT_TEXT) {
|
||||||
final String iob = new SmallestDoubleString(raw.sIOB1, SmallestDoubleString.Units.USE).minimise(displayFormat.MAX_FIELD_LEN_SHORT);
|
final String iob = new SmallestDoubleString(raw.getStatus().getIobSum(), SmallestDoubleString.Units.USE).minimise(displayFormat.MAX_FIELD_LEN_SHORT);
|
||||||
|
|
||||||
final ComplicationData.Builder builder = new ComplicationData.Builder(ComplicationData.TYPE_SHORT_TEXT)
|
final ComplicationData.Builder builder = new ComplicationData.Builder(ComplicationData.TYPE_SHORT_TEXT)
|
||||||
.setShortText(ComplicationText.plainText(iob))
|
.setShortText(ComplicationText.plainText(iob))
|
||||||
|
|
|
@ -32,7 +32,8 @@ public class SgvComplication extends BaseComplicationProviderService {
|
||||||
switch (dataType) {
|
switch (dataType) {
|
||||||
case ComplicationData.TYPE_SHORT_TEXT:
|
case ComplicationData.TYPE_SHORT_TEXT:
|
||||||
final ComplicationData.Builder builder = new ComplicationData.Builder(ComplicationData.TYPE_SHORT_TEXT)
|
final ComplicationData.Builder builder = new ComplicationData.Builder(ComplicationData.TYPE_SHORT_TEXT)
|
||||||
.setShortText(ComplicationText.plainText(raw.sSgv + raw.sDirection + "\uFE0E"))
|
.setShortText(ComplicationText.plainText(raw.getSingleBg().getSgvString() + raw.getSingleBg().getSlopeArrow() +
|
||||||
|
"\uFE0E"))
|
||||||
.setShortTitle(ComplicationText.plainText(displayFormat.shortTrend(raw)))
|
.setShortTitle(ComplicationText.plainText(displayFormat.shortTrend(raw)))
|
||||||
.setTapAction(complicationPendingIntent);
|
.setTapAction(complicationPendingIntent);
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ import info.nightscout.shared.logging.LTag;
|
||||||
/*
|
/*
|
||||||
* Created by dlvoy on 2019-11-12
|
* Created by dlvoy on 2019-11-12
|
||||||
*/
|
*/
|
||||||
public class UploaderBattery extends BaseComplicationProviderService {
|
public class UploaderBatteryComplication extends BaseComplicationProviderService {
|
||||||
|
|
||||||
public ComplicationData buildComplicationData(int dataType, RawDisplayData raw, PendingIntent complicationPendingIntent) {
|
public ComplicationData buildComplicationData(int dataType, RawDisplayData raw, PendingIntent complicationPendingIntent) {
|
||||||
|
|
||||||
|
@ -25,9 +25,9 @@ public class UploaderBattery extends BaseComplicationProviderService {
|
||||||
int level = 0;
|
int level = 0;
|
||||||
String levelStr = "???";
|
String levelStr = "???";
|
||||||
|
|
||||||
if (raw.sUploaderBattery.matches("^[0-9]+$")) {
|
if (raw.getStatus().getBattery().matches("^[0-9]+$")) {
|
||||||
try {
|
try {
|
||||||
level = Integer.parseInt(raw.sUploaderBattery);
|
level = Integer.parseInt(raw.getStatus().getBattery());
|
||||||
level = Math.max(Math.min(level, 100), 0);
|
level = Math.max(Math.min(level, 100), 0);
|
||||||
levelStr = level + "%";
|
levelStr = level + "%";
|
||||||
int iconNo = (int) Math.floor(level / 10.0);
|
int iconNo = (int) Math.floor(level / 10.0);
|
||||||
|
@ -112,7 +112,7 @@ public class UploaderBattery extends BaseComplicationProviderService {
|
||||||
|
|
||||||
|
|
||||||
} catch (NumberFormatException ex) {
|
} catch (NumberFormatException ex) {
|
||||||
aapsLogger.error(LTag.WEAR, "Cannot parse battery level of: " + raw.sUploaderBattery);
|
aapsLogger.error(LTag.WEAR, "Cannot parse battery level of: " + raw.getStatus().getBattery());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,7 +147,7 @@ public class UploaderBattery extends BaseComplicationProviderService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getProviderCanonicalName() {
|
public String getProviderCanonicalName() {
|
||||||
return UploaderBattery.class.getCanonicalName();
|
return UploaderBatteryComplication.class.getCanonicalName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
|
@ -1,11 +0,0 @@
|
||||||
package info.nightscout.androidaps.data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by adrian on 18/11/16.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class BasalWatchData {
|
|
||||||
public long startTime;
|
|
||||||
public long endTime;
|
|
||||||
public double amount;
|
|
||||||
}
|
|
|
@ -1,49 +0,0 @@
|
||||||
package info.nightscout.androidaps.data;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by emmablack on 1/7/15.
|
|
||||||
*/
|
|
||||||
public class BgWatchData implements Comparable<BgWatchData>{
|
|
||||||
public double sgv;
|
|
||||||
public double high;
|
|
||||||
public double low;
|
|
||||||
public long timestamp;
|
|
||||||
public int color;
|
|
||||||
|
|
||||||
public BgWatchData(double aSgv, double aHigh, double aLow, long aTimestamp, int aColor) {
|
|
||||||
this.sgv = aSgv;
|
|
||||||
this.high = aHigh;
|
|
||||||
this.low = aLow;
|
|
||||||
this.timestamp = aTimestamp;
|
|
||||||
this.color = aColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BgWatchData(){
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object that){
|
|
||||||
if(! (that instanceof BgWatchData)){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (this.color != ((BgWatchData) that).color)
|
|
||||||
return false;
|
|
||||||
return this.timestamp == ((BgWatchData) that).timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(timestamp, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(BgWatchData that) {
|
|
||||||
// reverse order endTime get latest first
|
|
||||||
if(this.timestamp < that.timestamp) return 1;
|
|
||||||
if(this.timestamp > that.timestamp) return -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
package info.nightscout.androidaps.data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by adrian on 17/11/16.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class BolusWatchData {
|
|
||||||
public long date;
|
|
||||||
public double bolus;
|
|
||||||
public double carbs;
|
|
||||||
public boolean isSMB;
|
|
||||||
public boolean isValid;
|
|
||||||
}
|
|
|
@ -1,552 +0,0 @@
|
||||||
/*
|
|
||||||
* 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,281 +0,0 @@
|
||||||
package info.nightscout.androidaps.data;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.PowerManager;
|
|
||||||
|
|
||||||
import com.google.android.gms.wearable.DataMap;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Iterator;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.interaction.utils.Constants;
|
|
||||||
import info.nightscout.androidaps.interaction.utils.Persistence;
|
|
||||||
import info.nightscout.androidaps.interaction.utils.WearUtil;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds bunch of data model variables and lists that arrive from phone app and are due to be
|
|
||||||
* displayed on watchface and complications. Keeping them together makes code cleaner and allows
|
|
||||||
* passing it to complications via persistence layer.
|
|
||||||
*
|
|
||||||
* Created by dlvoy on 2019-11-12
|
|
||||||
*/
|
|
||||||
public class RawDisplayData {
|
|
||||||
|
|
||||||
private final WearUtil wearUtil;
|
|
||||||
|
|
||||||
public RawDisplayData(WearUtil wearUtil) {
|
|
||||||
this.wearUtil = wearUtil;
|
|
||||||
}
|
|
||||||
|
|
||||||
static final String DATA_PERSISTENCE_KEY = "raw_data";
|
|
||||||
static final String BASALS_PERSISTENCE_KEY = "raw_basals";
|
|
||||||
static final String STATUS_PERSISTENCE_KEY = "raw_status";
|
|
||||||
|
|
||||||
// data bundle
|
|
||||||
public long sgvLevel = 0;
|
|
||||||
public long datetime;
|
|
||||||
public String sSgv = "---";
|
|
||||||
public String sDirection = "--";
|
|
||||||
public String sDelta = "--";
|
|
||||||
public String sAvgDelta = "--";
|
|
||||||
public String sUnits = "-";
|
|
||||||
|
|
||||||
// status bundle
|
|
||||||
public String sBasalRate = "-.--U/h";
|
|
||||||
public String sUploaderBattery = "--";
|
|
||||||
public String sRigBattery = "--";
|
|
||||||
public boolean detailedIOB = false;
|
|
||||||
public String sIOB1 = "IOB";
|
|
||||||
public String sIOB2 = "-.--";
|
|
||||||
public String sCOB1 = "Carb";
|
|
||||||
public String sCOB2= "--g";
|
|
||||||
public String sBgi = "--";
|
|
||||||
public boolean showBGI = false;
|
|
||||||
public String externalStatusString = "no status";
|
|
||||||
public int batteryLevel = 1;
|
|
||||||
public long openApsStatus = -1;
|
|
||||||
|
|
||||||
// basals bundle
|
|
||||||
public ArrayList<BgWatchData> bgDataList = new ArrayList<>();
|
|
||||||
public ArrayList<TempWatchData> tempWatchDataList = new ArrayList<>();
|
|
||||||
public ArrayList<BasalWatchData> basalWatchDataList = new ArrayList<>();
|
|
||||||
public ArrayList<BolusWatchData> bolusWatchDataList = new ArrayList<>();
|
|
||||||
public ArrayList<BgWatchData> predictionList = new ArrayList<>();
|
|
||||||
|
|
||||||
public String toDebugString() {
|
|
||||||
return "DisplayRawData{" +
|
|
||||||
"sgvLevel=" + sgvLevel +
|
|
||||||
", datetime=" + datetime +
|
|
||||||
", sSgv='" + sSgv + '\'' +
|
|
||||||
", sDirection='" + sDirection + '\'' +
|
|
||||||
", sDelta='" + sDelta + '\'' +
|
|
||||||
", sAvgDelta='" + sAvgDelta + '\'' +
|
|
||||||
", sUnits='" + sUnits + '\'' +
|
|
||||||
", sBasalRate='" + sBasalRate + '\'' +
|
|
||||||
", sUploaderBattery='" + sUploaderBattery + '\'' +
|
|
||||||
", sRigBattery='" + sRigBattery + '\'' +
|
|
||||||
", detailedIOB=" + detailedIOB +
|
|
||||||
", sIOB1='" + sIOB1 + '\'' +
|
|
||||||
", sIOB2='" + sIOB2 + '\'' +
|
|
||||||
", sCOB1='" + sCOB1 + '\'' +
|
|
||||||
", sCOB2='" + sCOB2 + '\'' +
|
|
||||||
", sBgi='" + sBgi + '\'' +
|
|
||||||
", showBGI=" + showBGI +
|
|
||||||
", externalStatusString='" + externalStatusString + '\'' +
|
|
||||||
", batteryLevel=" + batteryLevel +
|
|
||||||
", openApsStatus=" + openApsStatus +
|
|
||||||
", bgDataList size=" + bgDataList.size() +
|
|
||||||
", tempWatchDataList size=" + tempWatchDataList.size() +
|
|
||||||
", basalWatchDataList size=" + basalWatchDataList.size() +
|
|
||||||
", bolusWatchDataLis size=" + bolusWatchDataList.size() +
|
|
||||||
", predictionList size=" + predictionList.size() +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateFromPersistence(Persistence persistence) {
|
|
||||||
|
|
||||||
DataMap dataMapData = persistence.getDataMap(DATA_PERSISTENCE_KEY);
|
|
||||||
if (dataMapData != null) {
|
|
||||||
updateData(dataMapData);
|
|
||||||
}
|
|
||||||
DataMap dataMapStatus = persistence.getDataMap(STATUS_PERSISTENCE_KEY);
|
|
||||||
if (dataMapStatus != null) {
|
|
||||||
updateStatus(dataMapStatus);
|
|
||||||
}
|
|
||||||
DataMap dataMapBasals = persistence.getDataMap(BASALS_PERSISTENCE_KEY);
|
|
||||||
if (dataMapBasals != null) {
|
|
||||||
updateBasals(dataMapBasals);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Since complications do not need Basals, we skip them for performance
|
|
||||||
*/
|
|
||||||
public void updateForComplicationsFromPersistence(Persistence persistence) {
|
|
||||||
|
|
||||||
DataMap dataMapData = persistence.getDataMap(DATA_PERSISTENCE_KEY);
|
|
||||||
if (dataMapData != null) {
|
|
||||||
updateData(dataMapData);
|
|
||||||
}
|
|
||||||
DataMap dataMapStatus = persistence.getDataMap(STATUS_PERSISTENCE_KEY);
|
|
||||||
if (dataMapStatus != null) {
|
|
||||||
updateStatus(dataMapStatus);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public DataMap updateDataFromMessage(Intent intent, PowerManager.WakeLock wakeLock) {
|
|
||||||
Bundle bundle = intent.getBundleExtra("data");
|
|
||||||
if (bundle != null) {
|
|
||||||
DataMap dataMap = wearUtil.bundleToDataMap(bundle);
|
|
||||||
updateData(dataMap);
|
|
||||||
return dataMap;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateData(DataMap dataMap) {
|
|
||||||
PowerManager.WakeLock wl = wearUtil.getWakeLock("readingPrefs", 50);
|
|
||||||
sgvLevel = dataMap.getLong("sgvLevel");
|
|
||||||
datetime = dataMap.getLong("timestamp");
|
|
||||||
sSgv = dataMap.getString("sgvString");
|
|
||||||
sDirection = dataMap.getString("slopeArrow");
|
|
||||||
sDelta = dataMap.getString("delta");
|
|
||||||
sAvgDelta = dataMap.getString("avgDelta");
|
|
||||||
sUnits = dataMap.getString("glucoseUnits");
|
|
||||||
wearUtil.releaseWakeLock(wl);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DataMap updateStatusFromMessage(Intent intent, PowerManager.WakeLock wakeLock) {
|
|
||||||
Bundle bundle = intent.getBundleExtra("status");
|
|
||||||
if (bundle != null) {
|
|
||||||
DataMap dataMap = wearUtil.bundleToDataMap(bundle);
|
|
||||||
updateStatus(dataMap);
|
|
||||||
return dataMap;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateStatus(DataMap dataMap) {
|
|
||||||
PowerManager.WakeLock wl = wearUtil.getWakeLock("readingPrefs", 50);
|
|
||||||
sBasalRate = dataMap.getString("currentBasal");
|
|
||||||
sUploaderBattery = dataMap.getString("battery");
|
|
||||||
sRigBattery = dataMap.getString("rigBattery");
|
|
||||||
detailedIOB = dataMap.getBoolean("detailedIob");
|
|
||||||
sIOB1 = dataMap.getString("iobSum") + "U";
|
|
||||||
sIOB2 = dataMap.getString("iobDetail");
|
|
||||||
sCOB1 = "Carb";
|
|
||||||
sCOB2 = dataMap.getString("cob");
|
|
||||||
sBgi = dataMap.getString("bgi");
|
|
||||||
showBGI = dataMap.getBoolean("showBgi");
|
|
||||||
externalStatusString = dataMap.getString("externalStatusString");
|
|
||||||
batteryLevel = dataMap.getInt("batteryLevel");
|
|
||||||
openApsStatus = dataMap.getLong("openApsStatus");
|
|
||||||
wearUtil.releaseWakeLock(wl);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DataMap updateBasalsFromMessage(Intent intent) {
|
|
||||||
Bundle bundle = intent.getBundleExtra("basals");
|
|
||||||
if (bundle != null) {
|
|
||||||
DataMap dataMap = wearUtil.bundleToDataMap(bundle);
|
|
||||||
updateBasals(dataMap);
|
|
||||||
return dataMap;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateBasals(DataMap dataMap) {
|
|
||||||
PowerManager.WakeLock wl = wearUtil.getWakeLock("readingPrefs", 500);
|
|
||||||
loadBasalsAndTemps(dataMap);
|
|
||||||
wearUtil.releaseWakeLock(wl);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadBasalsAndTemps(DataMap dataMap) {
|
|
||||||
ArrayList<DataMap> temps = dataMap.getDataMapArrayList("temps");
|
|
||||||
if (temps != null) {
|
|
||||||
tempWatchDataList = new ArrayList<>();
|
|
||||||
for (DataMap temp : temps) {
|
|
||||||
TempWatchData twd = new TempWatchData();
|
|
||||||
twd.startTime = temp.getLong("starttime");
|
|
||||||
twd.startBasal = temp.getDouble("startBasal");
|
|
||||||
twd.endTime = temp.getLong("endtime");
|
|
||||||
twd.endBasal = temp.getDouble("endbasal");
|
|
||||||
twd.amount = temp.getDouble("amount");
|
|
||||||
tempWatchDataList.add(twd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ArrayList<DataMap> basals = dataMap.getDataMapArrayList("basals");
|
|
||||||
if (basals != null) {
|
|
||||||
basalWatchDataList = new ArrayList<>();
|
|
||||||
for (DataMap basal : basals) {
|
|
||||||
BasalWatchData bwd = new BasalWatchData();
|
|
||||||
bwd.startTime = basal.getLong("starttime");
|
|
||||||
bwd.endTime = basal.getLong("endtime");
|
|
||||||
bwd.amount = basal.getDouble("amount");
|
|
||||||
basalWatchDataList.add(bwd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ArrayList<DataMap> boluses = dataMap.getDataMapArrayList("boluses");
|
|
||||||
if (boluses != null) {
|
|
||||||
bolusWatchDataList = new ArrayList<>();
|
|
||||||
for (DataMap bolus : boluses) {
|
|
||||||
BolusWatchData bwd = new BolusWatchData();
|
|
||||||
bwd.date = bolus.getLong("date");
|
|
||||||
bwd.bolus = bolus.getDouble("bolus");
|
|
||||||
bwd.carbs = bolus.getDouble("carbs");
|
|
||||||
bwd.isSMB = bolus.getBoolean("isSMB");
|
|
||||||
bwd.isValid = bolus.getBoolean("isValid");
|
|
||||||
bolusWatchDataList.add(bwd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ArrayList<DataMap> predictions = dataMap.getDataMapArrayList("predictions");
|
|
||||||
if (boluses != null) {
|
|
||||||
predictionList = new ArrayList<>();
|
|
||||||
for (DataMap prediction : predictions) {
|
|
||||||
BgWatchData bwd = new BgWatchData();
|
|
||||||
bwd.timestamp = prediction.getLong("timestamp");
|
|
||||||
bwd.sgv = prediction.getDouble("sgv");
|
|
||||||
bwd.color = prediction.getInt("color");
|
|
||||||
predictionList.add(bwd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addToWatchSet(DataMap dataMap) {
|
|
||||||
ArrayList<DataMap> entries = dataMap.getDataMapArrayList("entries");
|
|
||||||
if (entries != null) {
|
|
||||||
bgDataList = new ArrayList<>();
|
|
||||||
for (DataMap entry : entries) {
|
|
||||||
double sgv = entry.getDouble("sgvDouble");
|
|
||||||
double high = entry.getDouble("high");
|
|
||||||
double low = entry.getDouble("low");
|
|
||||||
long timestamp = entry.getLong("timestamp");
|
|
||||||
int color = entry.getInt("color", 0);
|
|
||||||
bgDataList.add(new BgWatchData(sgv, high, low, timestamp, color));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
double sgv = dataMap.getDouble("sgvDouble");
|
|
||||||
double high = dataMap.getDouble("high");
|
|
||||||
double low = dataMap.getDouble("low");
|
|
||||||
long timestamp = dataMap.getLong("timestamp");
|
|
||||||
int color = dataMap.getInt("color", 0);
|
|
||||||
|
|
||||||
final int size = bgDataList.size();
|
|
||||||
if (size > 0) {
|
|
||||||
if (bgDataList.get(size - 1).timestamp == timestamp)
|
|
||||||
return; // Ignore duplicates.
|
|
||||||
}
|
|
||||||
|
|
||||||
bgDataList.add(new BgWatchData(sgv, high, low, timestamp, color));
|
|
||||||
}
|
|
||||||
|
|
||||||
// We use iterator instead for-loop because we iterate and remove on the go
|
|
||||||
Iterator itr = bgDataList.iterator();
|
|
||||||
while (itr.hasNext()) {
|
|
||||||
BgWatchData entry = (BgWatchData)itr.next();
|
|
||||||
if (entry.timestamp < (wearUtil.timestamp() - (Constants.HOUR_IN_MS * 5))) {
|
|
||||||
itr.remove(); //Get rid of anything more than 5 hours old
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
package info.nightscout.androidaps.data
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import info.nightscout.androidaps.comm.DataLayerListenerServiceWear
|
||||||
|
import info.nightscout.androidaps.interaction.utils.Persistence
|
||||||
|
import info.nightscout.shared.weardata.EventData
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds bunch of data model variables and lists that arrive from phone app and are due to be
|
||||||
|
* displayed on watchface and complications. Keeping them together makes code cleaner and allows
|
||||||
|
* passing it to complications via persistence layer.
|
||||||
|
*
|
||||||
|
* Created by dlvoy on 2019-11-12
|
||||||
|
*/
|
||||||
|
class RawDisplayData {
|
||||||
|
|
||||||
|
// bg data bundle
|
||||||
|
var singleBg = EventData.SingleBg(
|
||||||
|
timeStamp = 0,
|
||||||
|
sgv = 0.0,
|
||||||
|
high = 0.0,
|
||||||
|
low = 0.0,
|
||||||
|
color = 0
|
||||||
|
)
|
||||||
|
|
||||||
|
// status bundle
|
||||||
|
var status = EventData.Status(
|
||||||
|
externalStatus = "no status",
|
||||||
|
iobSum = "IOB",
|
||||||
|
iobDetail = "-.--",
|
||||||
|
detailedIob = false,
|
||||||
|
cob = "--g",
|
||||||
|
currentBasal = "-.--U/h",
|
||||||
|
battery = "--",
|
||||||
|
rigBattery = "--",
|
||||||
|
openApsStatus = -1,
|
||||||
|
bgi = "--",
|
||||||
|
showBgi = false,
|
||||||
|
batteryLevel = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
// basals bundle
|
||||||
|
var graphData = EventData.GraphData(
|
||||||
|
entries = ArrayList<EventData.SingleBg>()
|
||||||
|
)
|
||||||
|
|
||||||
|
var treatmentData = EventData.TreatmentData(
|
||||||
|
temps = ArrayList<EventData.TreatmentData.TempBasal>(),
|
||||||
|
basals = ArrayList<EventData.TreatmentData.Basal>(),
|
||||||
|
boluses = ArrayList<EventData.TreatmentData.Treatment>(),
|
||||||
|
predictions = ArrayList<EventData.SingleBg>()
|
||||||
|
)
|
||||||
|
|
||||||
|
fun toDebugString(): String =
|
||||||
|
"DisplayRawData{singleBg=$singleBg, status=$status, graphData=$graphData, treatmentData=$treatmentData}"
|
||||||
|
|
||||||
|
fun updateFromPersistence(persistence: Persistence) {
|
||||||
|
persistence.readSingleBg()?.let { singleBg = it }
|
||||||
|
persistence.readGraphData()?.let { graphData = it }
|
||||||
|
persistence.readStatus()?.let { status = it }
|
||||||
|
persistence.readTreatments()?.let { treatmentData = it }
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Since complications do not need Basals, we skip them for performance
|
||||||
|
*/
|
||||||
|
fun updateForComplicationsFromPersistence(persistence: Persistence) {
|
||||||
|
persistence.readSingleBg()?.let { singleBg = it }
|
||||||
|
persistence.readGraphData()?.let { graphData = it }
|
||||||
|
persistence.readStatus()?.let { status = it }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateFromMessage(intent: Intent) {
|
||||||
|
intent.getStringExtra(DataLayerListenerServiceWear.KEY_SINGLE_BG_DATA)?.let{
|
||||||
|
singleBg = EventData.deserialize(it) as EventData.SingleBg
|
||||||
|
}
|
||||||
|
intent.getStringExtra(DataLayerListenerServiceWear.KEY_STATUS_DATA)?.let{
|
||||||
|
status = EventData.deserialize(it) as EventData.Status
|
||||||
|
}
|
||||||
|
intent.getStringExtra(DataLayerListenerServiceWear.KEY_TREATMENTS_DATA)?.let{
|
||||||
|
treatmentData = EventData.deserialize(it) as EventData.TreatmentData
|
||||||
|
}
|
||||||
|
intent.getStringExtra(DataLayerListenerServiceWear.KEY_GRAPH_DATA)?.let{
|
||||||
|
graphData = EventData.deserialize(it) as EventData.GraphData
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
const val BG_DATA_PERSISTENCE_KEY = "raw_data"
|
||||||
|
const val GRAPH_DATA_PERSISTENCE_KEY = "raw_data"
|
||||||
|
const val BASALS_PERSISTENCE_KEY = "raw_basals"
|
||||||
|
const val STATUS_PERSISTENCE_KEY = "raw_status"
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,13 +0,0 @@
|
||||||
package info.nightscout.androidaps.data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by adrian on 17/11/16.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class TempWatchData {
|
|
||||||
public long startTime;
|
|
||||||
public double startBasal;
|
|
||||||
public long endTime;
|
|
||||||
public double endBasal;
|
|
||||||
public double amount;
|
|
||||||
}
|
|
|
@ -3,6 +3,10 @@ package info.nightscout.androidaps.di
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.android.ContributesAndroidInjector
|
import dagger.android.ContributesAndroidInjector
|
||||||
import info.nightscout.androidaps.interaction.actions.*
|
import info.nightscout.androidaps.interaction.actions.*
|
||||||
|
import info.nightscout.androidaps.interaction.menus.FillMenuActivity
|
||||||
|
import info.nightscout.androidaps.interaction.menus.MainMenuActivity
|
||||||
|
import info.nightscout.androidaps.interaction.menus.StatusMenuActivity
|
||||||
|
import info.nightscout.androidaps.interaction.utils.MenuListActivity
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
|
@ -20,4 +24,9 @@ abstract class WearActivitiesModule {
|
||||||
@ContributesAndroidInjector abstract fun contributesTempTargetActivity(): TempTargetActivity
|
@ContributesAndroidInjector abstract fun contributesTempTargetActivity(): TempTargetActivity
|
||||||
@ContributesAndroidInjector abstract fun contributesTreatmentActivity(): TreatmentActivity
|
@ContributesAndroidInjector abstract fun contributesTreatmentActivity(): TreatmentActivity
|
||||||
@ContributesAndroidInjector abstract fun contributesWizardActivity(): WizardActivity
|
@ContributesAndroidInjector abstract fun contributesWizardActivity(): WizardActivity
|
||||||
|
|
||||||
|
@ContributesAndroidInjector abstract fun contributesMenuListActivity(): MenuListActivity
|
||||||
|
@ContributesAndroidInjector abstract fun contributesFillMenuActivity(): FillMenuActivity
|
||||||
|
@ContributesAndroidInjector abstract fun contributesMainMenuActivity(): MainMenuActivity
|
||||||
|
@ContributesAndroidInjector abstract fun contributesStatusMenuActivity(): StatusMenuActivity
|
||||||
}
|
}
|
|
@ -2,16 +2,18 @@ package info.nightscout.androidaps.di
|
||||||
|
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.android.ContributesAndroidInjector
|
import dagger.android.ContributesAndroidInjector
|
||||||
|
import info.nightscout.androidaps.comm.DataLayerListenerServiceWear
|
||||||
import info.nightscout.androidaps.complications.*
|
import info.nightscout.androidaps.complications.*
|
||||||
import info.nightscout.androidaps.data.DataLayerListenerService
|
import info.nightscout.androidaps.tile.QuickWizardTileService
|
||||||
import info.nightscout.androidaps.interaction.actions.BackgroundActionActivity
|
import info.nightscout.androidaps.tile.TempTargetTileService
|
||||||
|
import info.nightscout.androidaps.tile.TileBase
|
||||||
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 contributesDataLayerListenerService(): DataLayerListenerService
|
@ContributesAndroidInjector abstract fun contributesDataLayerListenerService(): DataLayerListenerServiceWear
|
||||||
|
|
||||||
@ContributesAndroidInjector abstract fun contributesBaseComplicationProviderService(): BaseComplicationProviderService
|
@ContributesAndroidInjector abstract fun contributesBaseComplicationProviderService(): BaseComplicationProviderService
|
||||||
@ContributesAndroidInjector abstract fun contributesBrCobIobComplication(): BrCobIobComplication
|
@ContributesAndroidInjector abstract fun contributesBrCobIobComplication(): BrCobIobComplication
|
||||||
|
@ -24,7 +26,7 @@ abstract class WearServicesModule {
|
||||||
@ContributesAndroidInjector abstract fun contributesLongStatusComplication(): LongStatusComplication
|
@ContributesAndroidInjector abstract fun contributesLongStatusComplication(): LongStatusComplication
|
||||||
@ContributesAndroidInjector abstract fun contributesLongStatusFlippedComplication(): LongStatusFlippedComplication
|
@ContributesAndroidInjector abstract fun contributesLongStatusFlippedComplication(): LongStatusFlippedComplication
|
||||||
@ContributesAndroidInjector abstract fun contributesSgvComplication(): SgvComplication
|
@ContributesAndroidInjector abstract fun contributesSgvComplication(): SgvComplication
|
||||||
@ContributesAndroidInjector abstract fun contributesUploaderBattery(): UploaderBattery
|
@ContributesAndroidInjector abstract fun contributesUploaderBatteryComplication(): UploaderBatteryComplication
|
||||||
@ContributesAndroidInjector abstract fun contributesWallpaperComplication(): WallpaperComplication
|
@ContributesAndroidInjector abstract fun contributesWallpaperComplication(): WallpaperComplication
|
||||||
|
|
||||||
@ContributesAndroidInjector abstract fun contributesBaseWatchFace(): BaseWatchFace
|
@ContributesAndroidInjector abstract fun contributesBaseWatchFace(): BaseWatchFace
|
||||||
|
@ -34,4 +36,12 @@ abstract class WearServicesModule {
|
||||||
@ContributesAndroidInjector abstract fun contributesSteampunk(): Steampunk
|
@ContributesAndroidInjector abstract fun contributesSteampunk(): Steampunk
|
||||||
@ContributesAndroidInjector abstract fun contributesDigitalStyle(): DigitalStyle
|
@ContributesAndroidInjector abstract fun contributesDigitalStyle(): DigitalStyle
|
||||||
@ContributesAndroidInjector abstract fun contributesCockpit(): Cockpit
|
@ContributesAndroidInjector abstract fun contributesCockpit(): Cockpit
|
||||||
|
|
||||||
|
@ContributesAndroidInjector abstract fun contributesBIGChart(): BIGChart
|
||||||
|
@ContributesAndroidInjector abstract fun contributesNOChart(): NOChart
|
||||||
|
@ContributesAndroidInjector abstract fun contributesCircleWatchface(): CircleWatchface
|
||||||
|
|
||||||
|
@ContributesAndroidInjector abstract fun contributesTileBase(): TileBase
|
||||||
|
@ContributesAndroidInjector abstract fun contributesQuickWizardTileService(): QuickWizardTileService
|
||||||
|
@ContributesAndroidInjector abstract fun contributesTempTargetTileService(): TempTargetTileService
|
||||||
}
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package info.nightscout.androidaps.events
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
class EventWearPreferenceChange : Event {
|
||||||
|
|
||||||
|
var changedKey: String? = null
|
||||||
|
private set
|
||||||
|
|
||||||
|
constructor(key: String) {
|
||||||
|
changedKey = key
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(context: Context, resourceID: Int) {
|
||||||
|
changedKey = context.getString(resourceID)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isChanged(context: Context, id: Int): Boolean {
|
||||||
|
return changedKey == context.getString(id)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
package info.nightscout.androidaps.interaction.actions;
|
package info.nightscout.androidaps.interaction.actions;
|
||||||
|
|
||||||
import static info.nightscout.shared.weardata.WearConstants.KEY_ACTION_DATA;
|
import static info.nightscout.androidaps.comm.DataLayerListenerServiceWear.KEY_ACTION_DATA;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
@ -21,10 +21,8 @@ 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.DataLayerListenerService;
|
import info.nightscout.androidaps.events.EventWearToMobile;
|
||||||
import info.nightscout.androidaps.events.EventWearToMobileChange;
|
import info.nightscout.shared.weardata.EventData;
|
||||||
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.
|
||||||
|
@ -33,7 +31,6 @@ import info.nightscout.shared.weardata.ActionData;
|
||||||
public class AcceptActivity extends ViewSelectorActivity {
|
public class AcceptActivity extends ViewSelectorActivity {
|
||||||
|
|
||||||
String message = "";
|
String message = "";
|
||||||
String actionstring = "";
|
|
||||||
String actionKey = "";
|
String actionKey = "";
|
||||||
private DismissThread dismissThread;
|
private DismissThread dismissThread;
|
||||||
|
|
||||||
|
@ -46,10 +43,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", "");
|
|
||||||
actionKey = extras.getString(KEY_ACTION_DATA, "");
|
actionKey = extras.getString(KEY_ACTION_DATA, "");
|
||||||
|
|
||||||
if (message.isEmpty() || (actionstring.isEmpty() && actionKey.isEmpty())) {
|
if (message.isEmpty() || actionKey.isEmpty()) {
|
||||||
finish();
|
finish();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -109,15 +105,9 @@ public class AcceptActivity extends ViewSelectorActivity {
|
||||||
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) -> {
|
||||||
if (!actionstring.isEmpty())
|
EventData returnCommand = EventData.Companion.deserialize(actionKey);
|
||||||
DataLayerListenerService.Companion.confirmAction(AcceptActivity.this, actionstring);
|
rxBus.send(new EventWearToMobile(returnCommand));
|
||||||
else {
|
rxBus.send(new EventData.CancelNotification(System.currentTimeMillis()));
|
||||||
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);
|
||||||
|
|
|
@ -3,21 +3,25 @@ package info.nightscout.androidaps.interaction.actions
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import dagger.android.DaggerActivity
|
import dagger.android.DaggerActivity
|
||||||
import info.nightscout.androidaps.data.DataLayerListenerService
|
import info.nightscout.androidaps.comm.DataLayerListenerServiceWear
|
||||||
|
import info.nightscout.androidaps.events.EventWearToMobile
|
||||||
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
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.weardata.EventData
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class BackgroundActionActivity : DaggerActivity() {
|
class BackgroundActionActivity : DaggerActivity() {
|
||||||
|
|
||||||
@Inject lateinit var aapsLogger: AAPSLogger
|
@Inject lateinit var aapsLogger: AAPSLogger
|
||||||
|
@Inject lateinit var rxBus: RxBus
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
intent.extras?.getString("actionString")?.let { actionString ->
|
intent.extras?.getString(DataLayerListenerServiceWear.KEY_ACTION)?.let { action ->
|
||||||
aapsLogger.info(LTag.WEAR, "QuickWizardActivity.onCreate: actionString=$actionString")
|
aapsLogger.info(LTag.WEAR, "QuickWizardActivity.onCreate: action=$action")
|
||||||
DataLayerListenerService.initiateAction(this, actionString)
|
rxBus.send(EventWearToMobile(EventData.deserialize(action)))
|
||||||
intent.extras?.getString("message")?.let { message ->
|
intent.extras?.getString(DataLayerListenerServiceWear.KEY_MESSAGE)?.let { message ->
|
||||||
Toast.makeText(this, message, Toast.LENGTH_LONG).show()
|
Toast.makeText(this, message, Toast.LENGTH_LONG).show()
|
||||||
}
|
}
|
||||||
} ?: aapsLogger.error(LTag.WEAR, "BackgroundActionActivity.onCreate extras 'actionString' required")
|
} ?: aapsLogger.error(LTag.WEAR, "BackgroundActionActivity.onCreate extras 'actionString' required")
|
||||||
|
|
|
@ -10,10 +10,10 @@ 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.events.EventWearToMobileAction;
|
import info.nightscout.androidaps.events.EventWearToMobile;
|
||||||
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;
|
import info.nightscout.shared.weardata.EventData;
|
||||||
|
|
||||||
public class BolusActivity extends ViewSelectorActivity {
|
public class BolusActivity extends ViewSelectorActivity {
|
||||||
|
|
||||||
|
@ -63,8 +63,7 @@ public class BolusActivity extends ViewSelectorActivity {
|
||||||
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) -> {
|
||||||
ActionData.Bolus bolus = new ActionData.Bolus(SafeParse.stringToDouble(editInsulin.editText.getText().toString()), 0);
|
rxBus.send(new EventWearToMobile(new EventData.ActionBolusPreCheck(SafeParse.stringToDouble(editInsulin.editText.getText().toString()), 0)));
|
||||||
rxBus.send(new EventWearToMobileAction(bolus));
|
|
||||||
showToast(BolusActivity.this, R.string.action_bolus_confirmation);
|
showToast(BolusActivity.this, R.string.action_bolus_confirmation);
|
||||||
finishAffinity();
|
finishAffinity();
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,11 +10,10 @@ 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.DataLayerListenerService;
|
import info.nightscout.androidaps.events.EventWearToMobile;
|
||||||
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;
|
import info.nightscout.shared.weardata.EventData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by adrian on 09/02/17.
|
* Created by adrian on 09/02/17.
|
||||||
|
@ -52,6 +51,7 @@ public class CPPActivity 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) {
|
||||||
|
@ -94,9 +94,9 @@ public class CPPActivity extends ViewSelectorActivity {
|
||||||
confirmButton.setOnClickListener((View v) -> {
|
confirmButton.setOnClickListener((View v) -> {
|
||||||
//check if it can happen that the fragment 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 =
|
EventData.ActionProfileSwitchPreCheck ps =
|
||||||
new ActionData.ProfileSwitch(SafeParse.stringToInt(editTimeshift.editText.getText().toString()), SafeParse.stringToInt(editPercentage.editText.getText().toString()));
|
new EventData.ActionProfileSwitchPreCheck(SafeParse.stringToInt(editTimeshift.editText.getText().toString()), SafeParse.stringToInt(editPercentage.editText.getText().toString()));
|
||||||
rxBus.send(new EventWearToMobileAction(ps));
|
rxBus.send(new EventWearToMobile(ps));
|
||||||
showToast(CPPActivity.this, R.string.action_cpp_confirmation);
|
showToast(CPPActivity.this, R.string.action_cpp_confirmation);
|
||||||
finishAffinity();
|
finishAffinity();
|
||||||
});
|
});
|
||||||
|
@ -108,7 +108,7 @@ public class CPPActivity extends ViewSelectorActivity {
|
||||||
@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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,9 +10,10 @@ 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.DataLayerListenerService;
|
import info.nightscout.androidaps.events.EventWearToMobile;
|
||||||
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.EventData;
|
||||||
|
|
||||||
public class CarbActivity extends ViewSelectorActivity {
|
public class CarbActivity extends ViewSelectorActivity {
|
||||||
|
|
||||||
|
@ -32,6 +33,7 @@ public class CarbActivity 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) {
|
||||||
|
@ -46,37 +48,42 @@ public class CarbActivity 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 (editCarbs != null) {
|
if (editCarbs != null) {
|
||||||
def = SafeParse.stringToDouble(editCarbs.editText.getText().toString());
|
def = SafeParse.stringToDouble(editCarbs.editText.getText().toString());
|
||||||
}
|
}
|
||||||
editCarbs = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, def, 0d, (double)maxCarbs, 1d, new DecimalFormat("0"), true);
|
editCarbs = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, def, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), true);
|
||||||
setLabelToPlusMinusView(view, getString(R.string.action_carbs));
|
setLabelToPlusMinusView(view, getString(R.string.action_carbs));
|
||||||
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) -> {
|
||||||
// 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";
|
EventData.ActionECarbsPreCheck bolus =
|
||||||
DataLayerListenerService.Companion.initiateAction(CarbActivity.this, actionstring);
|
new EventData.ActionECarbsPreCheck(
|
||||||
|
SafeParse.stringToInt(editCarbs.editText.getText().toString()),
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
rxBus.send(new EventWearToMobile(bolus));
|
||||||
showToast(CarbActivity.this, R.string.action_ecarb_confirmation);
|
showToast(CarbActivity.this, R.string.action_ecarb_confirmation);
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,9 +10,10 @@ 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.DataLayerListenerService;
|
import info.nightscout.androidaps.events.EventWearToMobile;
|
||||||
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.EventData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by adrian on 04/08/18.
|
* Created by adrian on 04/08/18.
|
||||||
|
@ -38,6 +39,7 @@ public class ECarbActivity 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) {
|
||||||
|
@ -86,16 +88,19 @@ public class ECarbActivity 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 fragment 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())
|
EventData.ActionECarbsPreCheck bolus =
|
||||||
+ " " + SafeParse.stringToInt(editStartTime.editText.getText().toString())
|
new EventData.ActionECarbsPreCheck(
|
||||||
+ " " + SafeParse.stringToInt(editDuration.editText.getText().toString());
|
SafeParse.stringToInt(editCarbs.editText.getText().toString()),
|
||||||
DataLayerListenerService.Companion.initiateAction(ECarbActivity.this, actionstring);
|
SafeParse.stringToInt(editStartTime.editText.getText().toString()),
|
||||||
|
SafeParse.stringToInt(editDuration.editText.getText().toString())
|
||||||
|
);
|
||||||
|
rxBus.send(new EventWearToMobile(bolus));
|
||||||
showToast(ECarbActivity.this, R.string.action_ecarb_confirmation);
|
showToast(ECarbActivity.this, R.string.action_ecarb_confirmation);
|
||||||
finishAffinity();
|
finishAffinity();
|
||||||
|
|
||||||
|
@ -108,7 +113,7 @@ public class ECarbActivity extends ViewSelectorActivity {
|
||||||
@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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,9 +10,10 @@ 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.DataLayerListenerService;
|
import info.nightscout.androidaps.events.EventWearToMobile;
|
||||||
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.EventData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by adrian on 09/02/17.
|
* Created by adrian on 09/02/17.
|
||||||
|
@ -34,6 +35,7 @@ public class FillActivity 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) {
|
||||||
|
@ -67,8 +69,7 @@ public class FillActivity extends ViewSelectorActivity {
|
||||||
//check if it can happen that the fagment is never created that hold data?
|
//check if it can happen that the fagment 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 = "fill " + SafeParse.stringToDouble(editInsulin.editText.getText().toString());
|
rxBus.send(new EventWearToMobile(new EventData.ActionFillPreCheck(SafeParse.stringToDouble(editInsulin.editText.getText().toString()))));
|
||||||
DataLayerListenerService.Companion.initiateAction(FillActivity.this, actionstring);
|
|
||||||
showToast(FillActivity.this, R.string.action_fill_confirmation);
|
showToast(FillActivity.this, R.string.action_fill_confirmation);
|
||||||
finishAffinity();
|
finishAffinity();
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,9 +10,10 @@ 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.DataLayerListenerService;
|
import info.nightscout.androidaps.events.EventWearToMobile;
|
||||||
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.EventData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by adrian on 09/02/17.
|
* Created by adrian on 09/02/17.
|
||||||
|
@ -42,6 +43,7 @@ public class TempTargetActivity 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) {
|
||||||
|
@ -112,18 +114,20 @@ public class TempTargetActivity 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)
|
||||||
|
|
||||||
String actionstring = "temptarget"
|
EventData.ActionTempTargetPreCheck action = new EventData.ActionTempTargetPreCheck(
|
||||||
+ " " + isMGDL
|
EventData.ActionTempTargetPreCheck.TempTargetCommand.MANUAL,
|
||||||
+ " " + SafeParse.stringToInt(time.editText.getText().toString())
|
isMGDL,
|
||||||
+ " " + SafeParse.stringToDouble(lowRange.editText.getText().toString())
|
SafeParse.stringToInt(time.editText.getText().toString()),
|
||||||
+ " " + (isSingleTarget ? SafeParse.stringToDouble(lowRange.editText.getText().toString()) : SafeParse.stringToDouble(highRange.editText.getText().toString()));
|
SafeParse.stringToDouble(lowRange.editText.getText().toString()),
|
||||||
|
(isSingleTarget ?
|
||||||
DataLayerListenerService.Companion.initiateAction(TempTargetActivity.this, actionstring);
|
SafeParse.stringToDouble(lowRange.editText.getText().toString()) : SafeParse.stringToDouble(highRange.editText.getText().toString()))
|
||||||
|
);
|
||||||
|
rxBus.send(new EventWearToMobile(action));
|
||||||
showToast(TempTargetActivity.this, R.string.action_tempt_confirmation);
|
showToast(TempTargetActivity.this, R.string.action_tempt_confirmation);
|
||||||
finishAffinity();
|
finishAffinity();
|
||||||
});
|
});
|
||||||
|
@ -135,7 +139,7 @@ public class TempTargetActivity extends ViewSelectorActivity {
|
||||||
@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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,11 +10,10 @@ 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.DataLayerListenerService;
|
import info.nightscout.androidaps.events.EventWearToMobile;
|
||||||
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;
|
import info.nightscout.shared.weardata.EventData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by adrian on 09/02/17.
|
* Created by adrian on 09/02/17.
|
||||||
|
@ -42,6 +41,7 @@ public class TreatmentActivity extends ViewSelectorActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
private class MyGridViewPagerAdapter extends GridPagerAdapter {
|
private class MyGridViewPagerAdapter extends GridPagerAdapter {
|
||||||
@Override
|
@Override
|
||||||
public int getColumnCount(int arg0) {
|
public int getColumnCount(int arg0) {
|
||||||
|
@ -80,12 +80,12 @@ public class TreatmentActivity 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 fragment 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.Bolus bolus = new ActionData.Bolus(SafeParse.stringToDouble(editInsulin.editText.getText().toString()), SafeParse.stringToInt(editCarbs.editText.getText().toString()));
|
EventData.ActionBolusPreCheck bolus = new EventData.ActionBolusPreCheck(SafeParse.stringToDouble(editInsulin.editText.getText().toString()), SafeParse.stringToInt(editCarbs.editText.getText().toString()));
|
||||||
rxBus.send(new EventWearToMobileAction(bolus));
|
rxBus.send(new EventWearToMobile(bolus));
|
||||||
showToast(TreatmentActivity.this, R.string.action_treatment_confirmation);
|
showToast(TreatmentActivity.this, R.string.action_treatment_confirmation);
|
||||||
finishAffinity();
|
finishAffinity();
|
||||||
});
|
});
|
||||||
|
@ -97,7 +97,7 @@ public class TreatmentActivity extends ViewSelectorActivity {
|
||||||
@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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,9 +10,10 @@ 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.DataLayerListenerService;
|
import info.nightscout.androidaps.events.EventWearToMobile;
|
||||||
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.EventData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by adrian on 09/02/17.
|
* Created by adrian on 09/02/17.
|
||||||
|
@ -42,6 +43,7 @@ public class WizardActivity 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) {
|
||||||
|
@ -82,15 +84,17 @@ public class WizardActivity 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) -> {
|
||||||
if (editPercentage != null) {
|
if (editPercentage != null) {
|
||||||
percentage = SafeParse.stringToInt(editPercentage.editText.getText().toString());
|
percentage = SafeParse.stringToInt(editPercentage.editText.getText().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
String actionstring = "wizard2 " + SafeParse.stringToInt(editCarbs.editText.getText().toString())
|
EventData.ActionWizardPreCheck action = new EventData.ActionWizardPreCheck(
|
||||||
+ " " + percentage;
|
SafeParse.stringToInt(editCarbs.editText.getText().toString()),
|
||||||
DataLayerListenerService.Companion.initiateAction(WizardActivity.this, actionstring);
|
percentage
|
||||||
|
);
|
||||||
|
rxBus.send(new EventWearToMobile(action));
|
||||||
showToast(WizardActivity.this, R.string.action_wizard_confirmation);
|
showToast(WizardActivity.this, R.string.action_wizard_confirmation);
|
||||||
finishAffinity();
|
finishAffinity();
|
||||||
});
|
});
|
||||||
|
@ -102,7 +106,7 @@ public class WizardActivity extends ViewSelectorActivity {
|
||||||
@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,51 +0,0 @@
|
||||||
package info.nightscout.androidaps.interaction.menus;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.os.Bundle;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.R;
|
|
||||||
import info.nightscout.androidaps.data.DataLayerListenerService;
|
|
||||||
import info.nightscout.androidaps.interaction.actions.FillActivity;
|
|
||||||
import info.nightscout.androidaps.interaction.utils.MenuListActivity;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by adrian on 09/02/17.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class FillMenuActivity extends MenuListActivity {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
setTitle(R.string.menu_prime_fill);
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected List<MenuItem> getElements() {
|
|
||||||
List<MenuItem> menuItems = new ArrayList<>();
|
|
||||||
menuItems.add(new MenuItem(R.drawable.ic_canula, getString(R.string.action_preset_1)));
|
|
||||||
menuItems.add(new MenuItem(R.drawable.ic_canula, getString(R.string.action_preset_2)));
|
|
||||||
menuItems.add(new MenuItem(R.drawable.ic_canula, getString(R.string.action_preset_3)));
|
|
||||||
menuItems.add(new MenuItem(R.drawable.ic_canula, getString(R.string.action_free_amount)));
|
|
||||||
|
|
||||||
return menuItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doAction(String action) {
|
|
||||||
if (getString(R.string.action_preset_1).equals(action)) {
|
|
||||||
DataLayerListenerService.Companion.initiateAction(this, "fillpreset 1");
|
|
||||||
} else if (getString(R.string.action_preset_2).equals(action)) {
|
|
||||||
DataLayerListenerService.Companion.initiateAction(this, "fillpreset 2");
|
|
||||||
} else if (getString(R.string.action_preset_3).equals(action)) {
|
|
||||||
DataLayerListenerService.Companion.initiateAction(this, "fillpreset 3");
|
|
||||||
} else if (getString(R.string.action_free_amount).equals(action)) {
|
|
||||||
Intent intent = new Intent(this, FillActivity.class);
|
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
||||||
this.startActivity(intent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
package info.nightscout.androidaps.interaction.menus
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.events.EventWearToMobile
|
||||||
|
import info.nightscout.androidaps.interaction.actions.FillActivity
|
||||||
|
import info.nightscout.androidaps.interaction.utils.MenuListActivity
|
||||||
|
import info.nightscout.shared.weardata.EventData
|
||||||
|
|
||||||
|
class FillMenuActivity : MenuListActivity() {
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
setTitle(R.string.menu_prime_fill)
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getElements(): List<MenuItem> =
|
||||||
|
ArrayList<MenuItem>().apply {
|
||||||
|
add(MenuItem(R.drawable.ic_canula, getString(R.string.action_preset_1)))
|
||||||
|
add(MenuItem(R.drawable.ic_canula, getString(R.string.action_preset_2)))
|
||||||
|
add(MenuItem(R.drawable.ic_canula, getString(R.string.action_preset_3)))
|
||||||
|
add(MenuItem(R.drawable.ic_canula, getString(R.string.action_free_amount)))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun doAction(action: String) {
|
||||||
|
when (action) {
|
||||||
|
getString(R.string.action_preset_1) -> rxBus.send(EventWearToMobile(EventData.ActionFillPresetPreCheck(1)))
|
||||||
|
getString(R.string.action_preset_2) -> rxBus.send(EventWearToMobile(EventData.ActionFillPresetPreCheck(2)))
|
||||||
|
getString(R.string.action_preset_3) -> rxBus.send(EventWearToMobile(EventData.ActionFillPresetPreCheck(3)))
|
||||||
|
getString(R.string.action_free_amount) -> startActivity(Intent(this, FillActivity::class.java).apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,98 +0,0 @@
|
||||||
package info.nightscout.androidaps.interaction.menus;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.R;
|
|
||||||
import info.nightscout.androidaps.data.DataLayerListenerService;
|
|
||||||
import info.nightscout.androidaps.interaction.AAPSPreferences;
|
|
||||||
import info.nightscout.androidaps.interaction.actions.ECarbActivity;
|
|
||||||
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.utils.MenuListActivity;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by adrian on 09/02/17.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class MainMenuActivity extends MenuListActivity {
|
|
||||||
|
|
||||||
SharedPreferences sp;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
sp = PreferenceManager.getDefaultSharedPreferences(this);
|
|
||||||
setTitle(R.string.label_actions_activity);
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
DataLayerListenerService.Companion.requestData(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected List<MenuItem> getElements() {
|
|
||||||
|
|
||||||
List<MenuItem> menuItems = new ArrayList<>();
|
|
||||||
if (!sp.getBoolean("wearcontrol", false)) {
|
|
||||||
menuItems.add(new MenuItem(R.drawable.ic_settings, getString(R.string.menu_settings)));
|
|
||||||
menuItems.add(new MenuItem(R.drawable.ic_sync, getString(R.string.menu_resync)));
|
|
||||||
|
|
||||||
return menuItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean showPrimeFill = sp.getBoolean("primefill", false);
|
|
||||||
boolean showWizard = sp.getBoolean("showWizard", true);
|
|
||||||
|
|
||||||
if (showWizard) menuItems.add(new MenuItem(R.drawable.ic_calculator, getString(R.string.menu_wizard)));
|
|
||||||
menuItems.add(new MenuItem(R.drawable.ic_e_carbs, getString(R.string.menu_ecarb)));
|
|
||||||
menuItems.add(new MenuItem(R.drawable.ic_treatment, getString(R.string.menu_treatment)));
|
|
||||||
menuItems.add(new MenuItem(R.drawable.ic_temptarget, getString(R.string.menu_tempt)));
|
|
||||||
menuItems.add(new MenuItem(R.drawable.ic_settings, getString(R.string.menu_settings)));
|
|
||||||
menuItems.add(new MenuItem(R.drawable.ic_status, getString(R.string.menu_status)));
|
|
||||||
if (showPrimeFill) menuItems.add(new MenuItem(R.drawable.ic_canula, getString(R.string.menu_prime_fill)));
|
|
||||||
|
|
||||||
return menuItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doAction(String action) {
|
|
||||||
|
|
||||||
Intent intent;
|
|
||||||
|
|
||||||
if (getString(R.string.menu_settings).equals(action)) {
|
|
||||||
intent = new Intent(this, AAPSPreferences.class);
|
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
||||||
this.startActivity(intent);
|
|
||||||
} else if (getString(R.string.menu_resync).equals(action)) {
|
|
||||||
DataLayerListenerService.Companion.requestData(this);
|
|
||||||
} else if (getString(R.string.menu_tempt).equals(action)) {
|
|
||||||
intent = new Intent(this, TempTargetActivity.class);
|
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
||||||
this.startActivity(intent);
|
|
||||||
} else if (getString(R.string.menu_treatment).equals(action)) {
|
|
||||||
intent = new Intent(this, TreatmentActivity.class);
|
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
||||||
this.startActivity(intent);
|
|
||||||
} else if (getString(R.string.menu_wizard).equals(action)) {
|
|
||||||
intent = new Intent(this, WizardActivity.class);
|
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
||||||
this.startActivity(intent);
|
|
||||||
} else if (getString(R.string.menu_status).equals(action)) {
|
|
||||||
intent = new Intent(this, StatusMenuActivity.class);
|
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
||||||
this.startActivity(intent);
|
|
||||||
} else if (getString(R.string.menu_prime_fill).equals(action)) {
|
|
||||||
intent = new Intent(this, FillMenuActivity.class);
|
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
||||||
this.startActivity(intent);
|
|
||||||
} else if (getString(R.string.menu_ecarb).equals(action)) {
|
|
||||||
intent = new Intent(this, ECarbActivity.class);
|
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
||||||
this.startActivity(intent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
package info.nightscout.androidaps.interaction.menus
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.events.EventWearToMobile
|
||||||
|
import info.nightscout.androidaps.interaction.AAPSPreferences
|
||||||
|
import info.nightscout.androidaps.interaction.actions.ECarbActivity
|
||||||
|
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.utils.MenuListActivity
|
||||||
|
import info.nightscout.shared.weardata.EventData
|
||||||
|
import info.nightscout.shared.weardata.EventData.ActionResendData
|
||||||
|
|
||||||
|
class MainMenuActivity : MenuListActivity() {
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
setTitle(R.string.label_actions_activity)
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
rxBus.send(EventWearToMobile(ActionResendData("MainMenuListActivity")))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getElements(): List<MenuItem> =
|
||||||
|
ArrayList<MenuItem>().apply {
|
||||||
|
if (!sp.getBoolean(R.string.key_wear_control, false)) {
|
||||||
|
add(MenuItem(R.drawable.ic_settings, getString(R.string.menu_settings)))
|
||||||
|
add(MenuItem(R.drawable.ic_sync, getString(R.string.menu_resync)))
|
||||||
|
} else {
|
||||||
|
if (sp.getBoolean(R.string.key_show_wizard, true))
|
||||||
|
add(MenuItem(R.drawable.ic_calculator, getString(R.string.menu_wizard)))
|
||||||
|
add(MenuItem(R.drawable.ic_e_carbs, getString(R.string.menu_ecarb)))
|
||||||
|
add(MenuItem(R.drawable.ic_treatment, getString(R.string.menu_treatment)))
|
||||||
|
add(MenuItem(R.drawable.ic_temptarget, getString(R.string.menu_tempt)))
|
||||||
|
add(MenuItem(R.drawable.ic_status, getString(R.string.status_cpp)))
|
||||||
|
add(MenuItem(R.drawable.ic_settings, getString(R.string.menu_settings)))
|
||||||
|
add(MenuItem(R.drawable.ic_status, getString(R.string.menu_status)))
|
||||||
|
if (sp.getBoolean(R.string.key_prime_fill, false))
|
||||||
|
add(MenuItem(R.drawable.ic_canula, getString(R.string.menu_prime_fill)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun doAction(action: String) {
|
||||||
|
when (action) {
|
||||||
|
getString(R.string.menu_settings) -> startActivity(Intent(this, AAPSPreferences::class.java).apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) })
|
||||||
|
getString(R.string.menu_resync) -> rxBus.send(EventWearToMobile(ActionResendData("Re-Sync")))
|
||||||
|
getString(R.string.status_cpp) -> rxBus.send(EventWearToMobile(EventData.ActionProfileSwitchSendInitialData(System.currentTimeMillis())))
|
||||||
|
getString(R.string.menu_tempt) -> startActivity(Intent(this, TempTargetActivity::class.java).apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) })
|
||||||
|
getString(R.string.menu_treatment) -> startActivity(Intent(this, TreatmentActivity::class.java).apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) })
|
||||||
|
getString(R.string.menu_wizard) -> startActivity(Intent(this, WizardActivity::class.java).apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) })
|
||||||
|
getString(R.string.menu_status) -> startActivity(Intent(this, StatusMenuActivity::class.java).apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) })
|
||||||
|
getString(R.string.menu_prime_fill) -> startActivity(Intent(this, FillMenuActivity::class.java).apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) })
|
||||||
|
getString(R.string.menu_ecarb) -> startActivity(Intent(this, ECarbActivity::class.java).apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,47 +0,0 @@
|
||||||
package info.nightscout.androidaps.interaction.menus;
|
|
||||||
|
|
||||||
import android.os.Bundle;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.R;
|
|
||||||
import info.nightscout.androidaps.data.DataLayerListenerService;
|
|
||||||
import info.nightscout.androidaps.interaction.utils.MenuListActivity;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by adrian on 09/02/17.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class StatusMenuActivity extends MenuListActivity {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
setTitle(R.string.menu_status);
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected List<MenuItem> getElements() {
|
|
||||||
List<MenuItem> menuitems = new ArrayList<>();
|
|
||||||
menuitems.add(new MenuItem(R.drawable.ic_status, getString(R.string.status_pump)));
|
|
||||||
menuitems.add(new MenuItem(R.drawable.ic_loop_closed, getString(R.string.status_loop)));
|
|
||||||
menuitems.add(new MenuItem(R.drawable.ic_status, getString(R.string.status_cpp)));
|
|
||||||
menuitems.add(new MenuItem(R.drawable.ic_tdd, getString(R.string.status_tdd)));
|
|
||||||
|
|
||||||
return menuitems;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doAction(String action) {
|
|
||||||
if (getString(R.string.status_pump).equals(action)) {
|
|
||||||
DataLayerListenerService.Companion.initiateAction(this, "status pump");
|
|
||||||
} else if (getString(R.string.status_loop).equals(action)) {
|
|
||||||
DataLayerListenerService.Companion.initiateAction(this, "status loop");
|
|
||||||
} else if (getString(R.string.status_cpp).equals(action)) {
|
|
||||||
DataLayerListenerService.Companion.initiateAction(this, "opencpp");
|
|
||||||
} else if (getString(R.string.status_tdd).equals(action)) {
|
|
||||||
DataLayerListenerService.Companion.initiateAction(this, "tddstats");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
package info.nightscout.androidaps.interaction.menus
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.events.EventWearToMobile
|
||||||
|
import info.nightscout.androidaps.interaction.utils.MenuListActivity
|
||||||
|
import info.nightscout.shared.weardata.EventData.ActionLoopStatus
|
||||||
|
import info.nightscout.shared.weardata.EventData.ActionPumpStatus
|
||||||
|
import info.nightscout.shared.weardata.EventData.ActionTddStatus
|
||||||
|
|
||||||
|
class StatusMenuActivity : MenuListActivity() {
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
setTitle(R.string.menu_status)
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getElements(): List<MenuItem> =
|
||||||
|
ArrayList<MenuItem>().apply {
|
||||||
|
add(MenuItem(R.drawable.ic_status, getString(R.string.status_pump)))
|
||||||
|
add(MenuItem(R.drawable.ic_loop_closed, getString(R.string.status_loop)))
|
||||||
|
add(MenuItem(R.drawable.ic_tdd, getString(R.string.status_tdd)))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun doAction(action: String) {
|
||||||
|
when (action) {
|
||||||
|
getString(R.string.status_pump) -> rxBus.send(EventWearToMobile(ActionPumpStatus(System.currentTimeMillis())))
|
||||||
|
getString(R.string.status_loop) -> rxBus.send(EventWearToMobile(ActionLoopStatus(System.currentTimeMillis())))
|
||||||
|
getString(R.string.status_tdd) -> rxBus.send(EventWearToMobile(ActionTddStatus(System.currentTimeMillis())))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -65,27 +65,27 @@ public class DisplayFormat {
|
||||||
|
|
||||||
public String shortTrend(final RawDisplayData raw) {
|
public String shortTrend(final RawDisplayData raw) {
|
||||||
String minutes = "--";
|
String minutes = "--";
|
||||||
if (raw.datetime > 0) {
|
if (raw.getSingleBg().getTimeStamp() > 0) {
|
||||||
minutes = shortTimeSince(raw.datetime);
|
minutes = shortTimeSince(raw.getSingleBg().getTimeStamp());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (minutes.length() + raw.sDelta.length() + deltaSymbol().length() + 1 <= MAX_FIELD_LEN_SHORT) {
|
if (minutes.length() + raw.getSingleBg().getDelta().length() + deltaSymbol().length() + 1 <= MAX_FIELD_LEN_SHORT) {
|
||||||
return minutes + " " + deltaSymbol() + raw.sDelta;
|
return minutes + " " + deltaSymbol() + raw.getSingleBg().getDelta();
|
||||||
}
|
}
|
||||||
|
|
||||||
// that only optimizes obvious things like 0 before . or at end, + at beginning
|
// that only optimizes obvious things like 0 before . or at end, + at beginning
|
||||||
String delta = (new SmallestDoubleString(raw.sDelta)).minimise(MAX_FIELD_LEN_SHORT -1);
|
String delta = (new SmallestDoubleString(raw.getSingleBg().getDelta())).minimise(MAX_FIELD_LEN_SHORT -1);
|
||||||
if (minutes.length() + delta.length() + deltaSymbol().length() + 1 <= MAX_FIELD_LEN_SHORT) {
|
if (minutes.length() + delta.length() + deltaSymbol().length() + 1 <= MAX_FIELD_LEN_SHORT) {
|
||||||
return minutes + " " + deltaSymbol() + delta;
|
return minutes + " " + deltaSymbol() + delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
String shortDelta = (new SmallestDoubleString(raw.sDelta)).minimise(MAX_FIELD_LEN_SHORT -(1+minutes.length()));
|
String shortDelta = (new SmallestDoubleString(raw.getSingleBg().getDelta())).minimise(MAX_FIELD_LEN_SHORT -(1+minutes.length()));
|
||||||
|
|
||||||
return minutes + " " + shortDelta;
|
return minutes + " " + shortDelta;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String longGlucoseLine(final RawDisplayData raw) {
|
public String longGlucoseLine(final RawDisplayData raw) {
|
||||||
return raw.sSgv + raw.sDirection + " " + deltaSymbol() + (new SmallestDoubleString(raw.sDelta)).minimise(8) + " (" + shortTimeSince(raw.datetime) + ")";
|
return raw.getSingleBg().getSgvString() + raw.getSingleBg().getSlopeArrow() + " " + deltaSymbol() + (new SmallestDoubleString(raw.getSingleBg().getDelta())).minimise(8) + " (" + shortTimeSince(raw.getSingleBg().getTimeStamp()) + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
public String longDetailsLine(final RawDisplayData raw) {
|
public String longDetailsLine(final RawDisplayData raw) {
|
||||||
|
@ -95,40 +95,41 @@ public class DisplayFormat {
|
||||||
final int SEP_SHORT_LEN = SEP_SHORT.length();
|
final int SEP_SHORT_LEN = SEP_SHORT.length();
|
||||||
final String SEP_MIN = " ";
|
final String SEP_MIN = " ";
|
||||||
|
|
||||||
String line = raw.sCOB2 + SEP_LONG + raw.sIOB1 + SEP_LONG + basalRateSymbol()+raw.sBasalRate;
|
String line =
|
||||||
|
raw.getStatus().getCob() + SEP_LONG + raw.getStatus().getIobSum() + SEP_LONG + basalRateSymbol()+raw.getStatus().getCurrentBasal();
|
||||||
if (line.length() <= MAX_FIELD_LEN_LONG) {
|
if (line.length() <= MAX_FIELD_LEN_LONG) {
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
line = raw.sCOB2 + SEP_SHORT + raw.sIOB1 + SEP_SHORT + raw.sBasalRate;
|
line = raw.getStatus().getCob() + SEP_SHORT + raw.getStatus().getIobSum() + SEP_SHORT + raw.getStatus().getCurrentBasal();
|
||||||
if (line.length() <= MAX_FIELD_LEN_LONG) {
|
if (line.length() <= MAX_FIELD_LEN_LONG) {
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
|
||||||
int remainingMax = MAX_FIELD_LEN_LONG - (raw.sCOB2.length() + raw.sBasalRate.length() + SEP_SHORT_LEN*2);
|
int remainingMax = MAX_FIELD_LEN_LONG - (raw.getStatus().getCob().length() + raw.getStatus().getCurrentBasal().length() + SEP_SHORT_LEN*2);
|
||||||
final String smallestIoB = new SmallestDoubleString(raw.sIOB1, SmallestDoubleString.Units.USE).minimise(Math.max(MIN_FIELD_LEN_IOB, remainingMax));
|
final String smallestIoB = new SmallestDoubleString(raw.getStatus().getIobSum(), SmallestDoubleString.Units.USE).minimise(Math.max(MIN_FIELD_LEN_IOB, remainingMax));
|
||||||
line = raw.sCOB2 + SEP_SHORT + smallestIoB + SEP_SHORT + raw.sBasalRate;
|
line = raw.getStatus().getCob() + SEP_SHORT + smallestIoB + SEP_SHORT + raw.getStatus().getCurrentBasal();
|
||||||
if (line.length() <= MAX_FIELD_LEN_LONG) {
|
if (line.length() <= MAX_FIELD_LEN_LONG) {
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
|
||||||
remainingMax = MAX_FIELD_LEN_LONG - (smallestIoB.length() + raw.sBasalRate.length() + SEP_SHORT_LEN*2);
|
remainingMax = MAX_FIELD_LEN_LONG - (smallestIoB.length() + raw.getStatus().getCurrentBasal().length() + SEP_SHORT_LEN*2);
|
||||||
final String simplifiedCob = new SmallestDoubleString(raw.sCOB2, SmallestDoubleString.Units.USE).minimise(Math.max(MIN_FIELD_LEN_COB, remainingMax));
|
final String simplifiedCob = new SmallestDoubleString(raw.getStatus().getCob(), SmallestDoubleString.Units.USE).minimise(Math.max(MIN_FIELD_LEN_COB, remainingMax));
|
||||||
|
|
||||||
line = simplifiedCob + SEP_SHORT + smallestIoB + SEP_SHORT + raw.sBasalRate;
|
line = simplifiedCob + SEP_SHORT + smallestIoB + SEP_SHORT + raw.getStatus().getCurrentBasal();
|
||||||
if (line.length() <= MAX_FIELD_LEN_LONG) {
|
if (line.length() <= MAX_FIELD_LEN_LONG) {
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
|
||||||
line = simplifiedCob + SEP_MIN + smallestIoB + SEP_MIN + raw.sBasalRate;
|
line = simplifiedCob + SEP_MIN + smallestIoB + SEP_MIN + raw.getStatus().getCurrentBasal();
|
||||||
|
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Pair<String, String> detailedIob(RawDisplayData raw) {
|
public Pair<String, String> detailedIob(RawDisplayData raw) {
|
||||||
final String iob1 = new SmallestDoubleString(raw.sIOB1, SmallestDoubleString.Units.USE).minimise(MAX_FIELD_LEN_SHORT);
|
final String iob1 = new SmallestDoubleString(raw.getStatus().getIobSum(), SmallestDoubleString.Units.USE).minimise(MAX_FIELD_LEN_SHORT);
|
||||||
String iob2 = "";
|
String iob2 = "";
|
||||||
if (raw.sIOB2.contains("|")) {
|
if (raw.getStatus().getIobDetail().contains("|")) {
|
||||||
String[] iobs = raw.sIOB2.replace("(", "").replace(")", "").split("\\|");
|
String[] iobs = raw.getStatus().getIobDetail().replace("(", "").replace(")", "").split("\\|");
|
||||||
|
|
||||||
String iobBolus = new SmallestDoubleString(iobs[0]).minimise(MIN_FIELD_LEN_IOB);
|
String iobBolus = new SmallestDoubleString(iobs[0]).minimise(MIN_FIELD_LEN_IOB);
|
||||||
if (iobBolus.trim().length() == 0) {
|
if (iobBolus.trim().length() == 0) {
|
||||||
|
@ -144,7 +145,7 @@ public class DisplayFormat {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Pair<String, String> detailedCob(final RawDisplayData raw) {
|
public Pair<String, String> detailedCob(final RawDisplayData raw) {
|
||||||
SmallestDoubleString cobMini = new SmallestDoubleString(raw.sCOB2, SmallestDoubleString.Units.USE);
|
SmallestDoubleString cobMini = new SmallestDoubleString(raw.getStatus().getCob(), SmallestDoubleString.Units.USE);
|
||||||
|
|
||||||
String cob2 = "";
|
String cob2 = "";
|
||||||
if (cobMini.getExtra().length() > 0) {
|
if (cobMini.getExtra().length() > 0) {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package info.nightscout.androidaps.interaction.utils;
|
package info.nightscout.androidaps.interaction.utils;
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
@ -9,6 +8,7 @@ import android.widget.ImageView;
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
import androidx.wear.widget.CurvedTextView;
|
import androidx.wear.widget.CurvedTextView;
|
||||||
import androidx.wear.widget.WearableLinearLayoutManager;
|
import androidx.wear.widget.WearableLinearLayoutManager;
|
||||||
|
@ -16,13 +16,22 @@ import androidx.wear.widget.WearableRecyclerView;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
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 08/02/17.
|
* Created by adrian on 08/02/17.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public abstract class MenuListActivity extends Activity {
|
public abstract class MenuListActivity extends DaggerActivity {
|
||||||
|
|
||||||
|
@Inject public RxBus rxBus;
|
||||||
|
@Inject public SP sp;
|
||||||
|
|
||||||
List<MenuItem> elements;
|
List<MenuItem> elements;
|
||||||
|
|
||||||
protected abstract List<MenuItem> getElements();
|
protected abstract List<MenuItem> getElements();
|
||||||
|
@ -96,7 +105,7 @@ public abstract class MenuListActivity extends Activity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@NonNull @Override
|
||||||
public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
|
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
|
||||||
|
|
||||||
|
|
|
@ -3,22 +3,20 @@ package info.nightscout.androidaps.interaction.utils;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.util.Base64;
|
import android.util.Base64;
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.google.android.gms.wearable.DataMap;
|
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import info.nightscout.androidaps.Aaps;
|
|
||||||
import info.nightscout.androidaps.complications.BaseComplicationProviderService;
|
import info.nightscout.androidaps.complications.BaseComplicationProviderService;
|
||||||
|
import info.nightscout.androidaps.data.RawDisplayData;
|
||||||
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.weardata.EventData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by dlvoy on 2019-11-12
|
* Created by dlvoy on 2019-11-12
|
||||||
|
@ -26,7 +24,6 @@ import info.nightscout.shared.logging.LTag;
|
||||||
@Singleton
|
@Singleton
|
||||||
public class Persistence {
|
public class Persistence {
|
||||||
|
|
||||||
private final Context context;
|
|
||||||
private final AAPSLogger aapsLogger;
|
private final AAPSLogger aapsLogger;
|
||||||
private final WearUtil wearUtil;
|
private final WearUtil wearUtil;
|
||||||
private final SharedPreferences preferences;
|
private final SharedPreferences preferences;
|
||||||
|
@ -35,7 +32,6 @@ public class Persistence {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public Persistence(Context context, AAPSLogger aapsLogger, WearUtil wearUtil) {
|
public Persistence(Context context, AAPSLogger aapsLogger, WearUtil wearUtil) {
|
||||||
this.context = context;
|
|
||||||
this.aapsLogger = aapsLogger;
|
this.aapsLogger = aapsLogger;
|
||||||
this.wearUtil = wearUtil;
|
this.wearUtil = wearUtil;
|
||||||
preferences = context.getSharedPreferences(COMPLICATION_PROVIDER_PREFERENCES_FILE_KEY, 0);
|
preferences = context.getSharedPreferences(COMPLICATION_PROVIDER_PREFERENCES_FILE_KEY, 0);
|
||||||
|
@ -51,24 +47,6 @@ public class Persistence {
|
||||||
return Base64.encodeToString(input, flags);
|
return Base64.encodeToString(input, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public DataMap getDataMap(String key) {
|
|
||||||
if (preferences.contains(key)) {
|
|
||||||
final String rawB64Data = preferences.getString(key, null);
|
|
||||||
byte[] rawData = base64decode(rawB64Data, Base64.DEFAULT);
|
|
||||||
try {
|
|
||||||
return DataMap.fromByteArray(rawData);
|
|
||||||
} catch (IllegalArgumentException ex) {
|
|
||||||
// Should never happen, and if it happen - we ignore and fallback to null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void putDataMap(String key, DataMap dataMap) {
|
|
||||||
preferences.edit().putString(key, base64encodeToString(dataMap.toByteArray(), Base64.DEFAULT)).apply();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getString(String key, String defaultValue) {
|
public String getString(String key, String defaultValue) {
|
||||||
return preferences.getString(key, defaultValue);
|
return preferences.getString(key, defaultValue);
|
||||||
}
|
}
|
||||||
|
@ -109,11 +87,67 @@ public class Persistence {
|
||||||
putString(key, joinSet(set, "|"));
|
putString(key, joinSet(set, "|"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void storeDataMap(String key, DataMap dataMap) {
|
public void store(EventData.SingleBg singleBg) {
|
||||||
putDataMap(key, dataMap);
|
putString(RawDisplayData.BG_DATA_PERSISTENCE_KEY, singleBg.serialize());
|
||||||
markDataUpdated();
|
markDataUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public EventData.SingleBg readSingleBg() {
|
||||||
|
try {
|
||||||
|
String s = getString(RawDisplayData.BG_DATA_PERSISTENCE_KEY, null);
|
||||||
|
if (s != null) {
|
||||||
|
return (EventData.SingleBg) EventData.Companion.deserialize(s);
|
||||||
|
}
|
||||||
|
} catch (Exception ignored) {}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public EventData.Status readStatus() {
|
||||||
|
try {
|
||||||
|
String s = getString(RawDisplayData.STATUS_PERSISTENCE_KEY, null);
|
||||||
|
if (s != null) {
|
||||||
|
return (EventData.Status) EventData.Companion.deserialize(s);
|
||||||
|
}
|
||||||
|
} catch (Exception ignored) {}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public EventData.TreatmentData readTreatments() {
|
||||||
|
try {
|
||||||
|
String s = getString(RawDisplayData.BASALS_PERSISTENCE_KEY, null);
|
||||||
|
if (s != null) {
|
||||||
|
return (EventData.TreatmentData) EventData.Companion.deserialize(s);
|
||||||
|
}
|
||||||
|
} catch (Exception ignored) {}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public EventData.GraphData readGraphData() {
|
||||||
|
try {
|
||||||
|
String s = getString(RawDisplayData.BG_DATA_PERSISTENCE_KEY, null);
|
||||||
|
if (s != null) {
|
||||||
|
return (EventData.GraphData) EventData.Companion.deserialize(s);
|
||||||
|
}
|
||||||
|
} catch (Exception ignored) {}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void store(EventData.GraphData graphData) {
|
||||||
|
putString(RawDisplayData.GRAPH_DATA_PERSISTENCE_KEY, graphData.serialize());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void store(EventData.TreatmentData treatmentData) {
|
||||||
|
putString(RawDisplayData.BASALS_PERSISTENCE_KEY, treatmentData.serialize());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void store(EventData.Status status) {
|
||||||
|
putString(RawDisplayData.STATUS_PERSISTENCE_KEY, status.serialize());
|
||||||
|
}
|
||||||
|
|
||||||
public String joinSet(Set<String> set, String separator) {
|
public String joinSet(Set<String> set, String separator) {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
|
@ -2,93 +2,64 @@ package info.nightscout.androidaps.tile
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.util.Base64
|
|
||||||
import android.util.Log
|
|
||||||
import androidx.preference.PreferenceManager
|
|
||||||
import com.google.android.gms.wearable.DataMap
|
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
import info.nightscout.androidaps.interaction.actions.BackgroundActionActivity
|
import info.nightscout.androidaps.interaction.actions.BackgroundActionActivity
|
||||||
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
|
import info.nightscout.shared.logging.LTag
|
||||||
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
|
import info.nightscout.shared.weardata.EventData
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
object QuickWizardSource : TileSource {
|
object QuickWizardSource : TileSource {
|
||||||
|
|
||||||
override fun getSelectedActions(context: Context): List<Action> {
|
override fun getSelectedActions(context: Context, sp: SP, aapsLogger: AAPSLogger): List<Action> {
|
||||||
val quickList = mutableListOf<Action>()
|
val quickList = mutableListOf<Action>()
|
||||||
val quickMap = getDataMap(context)
|
val quickMap = getQuickWizardData(sp)
|
||||||
val sfm = secondsFromMidnight()
|
val sfm = secondsFromMidnight()
|
||||||
|
|
||||||
for (quick in quickMap) {
|
for (quick in quickMap.entries) {
|
||||||
val validFrom = quick.getInt("from", 0)
|
val isActive = sfm in quick.validFrom..quick.validTo
|
||||||
val validTo = quick.getInt("to", 0)
|
if (isActive && quick.guid.isNotEmpty()) {
|
||||||
val isActive = sfm in validFrom..validTo
|
|
||||||
val guid = quick.getString("guid", "")
|
|
||||||
if (isActive && guid != "") {
|
|
||||||
quickList.add(
|
quickList.add(
|
||||||
Action(
|
Action(
|
||||||
buttonText = quick.getString("button_text", "?"),
|
buttonText = quick.buttonText,
|
||||||
buttonTextSub = "${quick.getInt("carbs", 0)} g",
|
buttonTextSub = "${quick.carbs} g",
|
||||||
iconRes = R.drawable.ic_quick_wizard,
|
iconRes = R.drawable.ic_quick_wizard,
|
||||||
activityClass = BackgroundActionActivity::class.java.name,
|
activityClass = BackgroundActionActivity::class.java.name,
|
||||||
actionString = "quick_wizard $guid",
|
action = EventData.ActionQuickWizardPreCheck(quick.guid),
|
||||||
message = context.resources.getString(R.string.action_quick_wizard_confirmation),
|
message = context.resources.getString(R.string.action_quick_wizard_confirmation)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
Log.i(TAG, "getSelectedActions: active " + quick.getString("button_text", "?") + " guid=" + guid)
|
aapsLogger.info(LTag.WEAR, """getSelectedActions: active ${quick.buttonText} guid=${quick.guid}""")
|
||||||
} else {
|
} else {
|
||||||
Log.i(TAG, "getSelectedActions: not active " + quick.getString("button_text", "?") + " guid=" + guid)
|
aapsLogger.info(LTag.WEAR, """getSelectedActions: not active ${quick.buttonText} guid=${quick.guid}""")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return quickList
|
return quickList
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getValidFor(context: Context): Long? {
|
override fun getValidFor(sp: SP): Long? {
|
||||||
val quickMap = getDataMap(context)
|
val quickMap = getQuickWizardData(sp)
|
||||||
if (quickMap.size == 0) {
|
if (quickMap.entries.size == 0) return null
|
||||||
return null
|
|
||||||
}
|
|
||||||
val sfm = secondsFromMidnight()
|
val sfm = secondsFromMidnight()
|
||||||
var validTill = 24 * 60 * 60
|
var validTill = 24 * 60 * 60
|
||||||
|
|
||||||
for (quick in quickMap) {
|
for (quick in quickMap.entries) {
|
||||||
val validFrom = quick.getInt("from", 0)
|
val isActive = sfm in quick.validFrom..quick.validTo
|
||||||
val validTo = quick.getInt("to", 0)
|
if (quick.guid.isNotEmpty()) {
|
||||||
val isActive = sfm in validFrom..validTo
|
if (isActive && validTill > quick.validTo) validTill = quick.validTo
|
||||||
val guid = quick.getString("guid", "")
|
if (quick.validFrom in (sfm + 1) until validTill) validTill = quick.validFrom
|
||||||
Log.i(TAG, "valid: " + validFrom + "-" + validTo)
|
|
||||||
if (guid != "") {
|
|
||||||
if (isActive && validTill > validTo) {
|
|
||||||
validTill = validTo
|
|
||||||
}
|
|
||||||
if (validFrom > sfm && validTill > validFrom) {
|
|
||||||
validTill = validFrom
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val validWithin = 60
|
val validWithin = 60
|
||||||
val delta = (validTill - sfm + validWithin) * 1000L
|
//aapsLogger.info(LTag.WEAR, "getValidTill: sfm$sfm till$validTill d=$delta")
|
||||||
Log.i(TAG, "getValidTill: sfm" + sfm + " till" + validTill + " d=" + delta)
|
return (validTill - sfm + validWithin) * 1000L
|
||||||
return delta
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getDataMap(context: Context): ArrayList<DataMap> {
|
private fun getQuickWizardData(sp: SP): EventData.QuickWizard =
|
||||||
val sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context)
|
EventData.deserialize(sp.getString(R.string.key_quick_wizard_data, EventData.QuickWizard(arrayListOf()).serialize())) as EventData.QuickWizard
|
||||||
val key = context.resources.getString(R.string.key_quick_wizard_data_map)
|
|
||||||
if (sharedPrefs.contains(key)) {
|
|
||||||
val rawB64Data: String? = sharedPrefs.getString(key, null)
|
|
||||||
val rawData: ByteArray = Base64.decode(rawB64Data, Base64.DEFAULT)
|
|
||||||
try {
|
|
||||||
val map = DataMap.fromByteArray(rawData)
|
|
||||||
return map.getDataMapArrayList("quick_wizard")
|
|
||||||
|
|
||||||
} catch (ex: IllegalArgumentException) {
|
|
||||||
Log.e(TAG, "getSelectedActions: IllegalArgumentException ", ex)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return arrayListOf()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun secondsFromMidnight(): Int {
|
private fun secondsFromMidnight(): Int {
|
||||||
val c = Calendar.getInstance()
|
val c = Calendar.getInstance()
|
||||||
|
@ -101,8 +72,5 @@ object QuickWizardSource : TileSource {
|
||||||
return (passed / 1000).toInt()
|
return (passed / 1000).toInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getResourceReferences(resources: Resources): List<Int> {
|
override fun getResourceReferences(resources: Resources): List<Int> = listOf(R.drawable.ic_quick_wizard)
|
||||||
return listOf(R.drawable.ic_quick_wizard)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,9 @@ import android.content.SharedPreferences
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
|
import info.nightscout.shared.weardata.EventData
|
||||||
|
|
||||||
class StaticAction(
|
class StaticAction(
|
||||||
val settingName: String,
|
val settingName: String,
|
||||||
|
@ -12,9 +15,9 @@ class StaticAction(
|
||||||
buttonTextSub: String? = null,
|
buttonTextSub: String? = null,
|
||||||
activityClass: String,
|
activityClass: String,
|
||||||
@DrawableRes iconRes: Int,
|
@DrawableRes iconRes: Int,
|
||||||
actionString: String? = null,
|
action: EventData? = null,
|
||||||
message: String? = null,
|
message: String? = null,
|
||||||
) : Action(buttonText, buttonTextSub, activityClass, iconRes, actionString, message)
|
) : Action(buttonText, buttonTextSub, activityClass, iconRes, action, message)
|
||||||
|
|
||||||
abstract class StaticTileSource : TileSource {
|
abstract class StaticTileSource : TileSource {
|
||||||
|
|
||||||
|
@ -23,7 +26,7 @@ abstract class StaticTileSource : TileSource {
|
||||||
abstract val preferencePrefix: String
|
abstract val preferencePrefix: String
|
||||||
abstract fun getDefaultConfig(): Map<String, String>
|
abstract fun getDefaultConfig(): Map<String, String>
|
||||||
|
|
||||||
override fun getSelectedActions(context: Context): List<Action> {
|
override fun getSelectedActions(context: Context, sp: SP, aapsLogger: AAPSLogger): List<Action> {
|
||||||
val sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context)
|
val sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
setDefaultSettings(sharedPrefs)
|
setDefaultSettings(sharedPrefs)
|
||||||
|
|
||||||
|
@ -40,7 +43,7 @@ abstract class StaticTileSource : TileSource {
|
||||||
return actionList
|
return actionList
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getValidFor(context: Context): Long? = null
|
override fun getValidFor(sp: SP): Long? = null
|
||||||
|
|
||||||
private fun getActionFromPreference(resources: Resources, sharedPrefs: SharedPreferences, index: Int): Action? {
|
private fun getActionFromPreference(resources: Resources, sharedPrefs: SharedPreferences, index: Int): Action? {
|
||||||
val actionPref = sharedPrefs.getString(preferencePrefix + index, "none")
|
val actionPref = sharedPrefs.getString(preferencePrefix + index, "none")
|
||||||
|
|
|
@ -4,6 +4,7 @@ import android.content.res.Resources
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
import info.nightscout.androidaps.interaction.actions.BackgroundActionActivity
|
import info.nightscout.androidaps.interaction.actions.BackgroundActionActivity
|
||||||
import info.nightscout.androidaps.interaction.actions.TempTargetActivity
|
import info.nightscout.androidaps.interaction.actions.TempTargetActivity
|
||||||
|
import info.nightscout.shared.weardata.EventData
|
||||||
|
|
||||||
object TempTargetSource : StaticTileSource() {
|
object TempTargetSource : StaticTileSource() {
|
||||||
|
|
||||||
|
@ -19,7 +20,8 @@ object TempTargetSource : StaticTileSource() {
|
||||||
activityClass = BackgroundActionActivity::class.java.name,
|
activityClass = BackgroundActionActivity::class.java.name,
|
||||||
message = message,
|
message = message,
|
||||||
// actionString = "temptarget false 90 8.0 8.0",
|
// actionString = "temptarget false 90 8.0 8.0",
|
||||||
actionString = "temptarget preset activity",
|
// actionString = "temptarget preset activity",
|
||||||
|
action = EventData.ActionTempTargetPreCheck(EventData.ActionTempTargetPreCheck.TempTargetCommand.PRESET_ACTIVITY)
|
||||||
),
|
),
|
||||||
StaticAction(
|
StaticAction(
|
||||||
settingName = "eating_soon",
|
settingName = "eating_soon",
|
||||||
|
@ -28,7 +30,8 @@ object TempTargetSource : StaticTileSource() {
|
||||||
activityClass = BackgroundActionActivity::class.java.name,
|
activityClass = BackgroundActionActivity::class.java.name,
|
||||||
message = message,
|
message = message,
|
||||||
// actionString = "temptarget false 45 4.5 4.5",
|
// actionString = "temptarget false 45 4.5 4.5",
|
||||||
actionString = "temptarget preset eating",
|
// actionString = "temptarget preset eating",
|
||||||
|
action = EventData.ActionTempTargetPreCheck(EventData.ActionTempTargetPreCheck.TempTargetCommand.PRESET_EATING)
|
||||||
),
|
),
|
||||||
StaticAction(
|
StaticAction(
|
||||||
settingName = "hypo",
|
settingName = "hypo",
|
||||||
|
@ -37,13 +40,15 @@ object TempTargetSource : StaticTileSource() {
|
||||||
activityClass = BackgroundActionActivity::class.java.name,
|
activityClass = BackgroundActionActivity::class.java.name,
|
||||||
message = message,
|
message = message,
|
||||||
// actionString = "temptarget false 45 7.0 7.0",
|
// actionString = "temptarget false 45 7.0 7.0",
|
||||||
actionString = "temptarget preset hypo",
|
// actionString = "temptarget preset hypo",
|
||||||
|
action = EventData.ActionTempTargetPreCheck(EventData.ActionTempTargetPreCheck.TempTargetCommand.PRESET_HYPO)
|
||||||
),
|
),
|
||||||
StaticAction(
|
StaticAction(
|
||||||
settingName = "manual",
|
settingName = "manual",
|
||||||
buttonText = resources.getString(R.string.temp_target_manual),
|
buttonText = resources.getString(R.string.temp_target_manual),
|
||||||
iconRes = R.drawable.ic_target_manual,
|
iconRes = R.drawable.ic_target_manual,
|
||||||
activityClass = TempTargetActivity::class.java.name,
|
activityClass = TempTargetActivity::class.java.name,
|
||||||
|
action = null
|
||||||
),
|
),
|
||||||
StaticAction(
|
StaticAction(
|
||||||
settingName = "cancel",
|
settingName = "cancel",
|
||||||
|
@ -51,7 +56,8 @@ object TempTargetSource : StaticTileSource() {
|
||||||
iconRes = R.drawable.ic_target_cancel,
|
iconRes = R.drawable.ic_target_cancel,
|
||||||
activityClass = BackgroundActionActivity::class.java.name,
|
activityClass = BackgroundActionActivity::class.java.name,
|
||||||
message = message,
|
message = message,
|
||||||
actionString = "temptarget cancel",
|
//actionString = "temptarget cancel",
|
||||||
|
action = EventData.ActionTempTargetPreCheck(EventData.ActionTempTargetPreCheck.TempTargetCommand.CANCEL)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,11 +5,10 @@ import android.os.Build
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.preference.PreferenceManager
|
|
||||||
import androidx.wear.tiles.ActionBuilders
|
import androidx.wear.tiles.ActionBuilders
|
||||||
import androidx.wear.tiles.ColorBuilders.argb
|
import androidx.wear.tiles.ColorBuilders.argb
|
||||||
import androidx.wear.tiles.DeviceParametersBuilders.SCREEN_SHAPE_ROUND
|
|
||||||
import androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters
|
import androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters
|
||||||
|
import androidx.wear.tiles.DeviceParametersBuilders.SCREEN_SHAPE_ROUND
|
||||||
import androidx.wear.tiles.DimensionBuilders.SpProp
|
import androidx.wear.tiles.DimensionBuilders.SpProp
|
||||||
import androidx.wear.tiles.DimensionBuilders.dp
|
import androidx.wear.tiles.DimensionBuilders.dp
|
||||||
import androidx.wear.tiles.DimensionBuilders.sp
|
import androidx.wear.tiles.DimensionBuilders.sp
|
||||||
|
@ -29,11 +28,17 @@ import androidx.wear.tiles.TileService
|
||||||
import androidx.wear.tiles.TimelineBuilders.Timeline
|
import androidx.wear.tiles.TimelineBuilders.Timeline
|
||||||
import androidx.wear.tiles.TimelineBuilders.TimelineEntry
|
import androidx.wear.tiles.TimelineBuilders.TimelineEntry
|
||||||
import com.google.common.util.concurrent.ListenableFuture
|
import com.google.common.util.concurrent.ListenableFuture
|
||||||
|
import dagger.android.AndroidInjection
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.comm.DataLayerListenerServiceWear
|
||||||
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
|
import info.nightscout.shared.weardata.EventData
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.guava.future
|
import kotlinx.coroutines.guava.future
|
||||||
|
import javax.inject.Inject
|
||||||
import kotlin.math.sqrt
|
import kotlin.math.sqrt
|
||||||
|
|
||||||
private const val SPACING_ACTIONS = 3f
|
private const val SPACING_ACTIONS = 3f
|
||||||
|
@ -44,8 +49,8 @@ private const val LARGE_SCREEN_WIDTH_DP = 210
|
||||||
interface TileSource {
|
interface TileSource {
|
||||||
|
|
||||||
fun getResourceReferences(resources: android.content.res.Resources): List<Int>
|
fun getResourceReferences(resources: android.content.res.Resources): List<Int>
|
||||||
fun getSelectedActions(context: Context): List<Action>
|
fun getSelectedActions(context: Context, sp: SP, aapsLogger: AAPSLogger): List<Action>
|
||||||
fun getValidFor(context: Context): Long?
|
fun getValidFor(sp: SP): Long?
|
||||||
}
|
}
|
||||||
|
|
||||||
open class Action(
|
open class Action(
|
||||||
|
@ -53,7 +58,7 @@ open class Action(
|
||||||
val buttonTextSub: String? = null,
|
val buttonTextSub: String? = null,
|
||||||
val activityClass: String,
|
val activityClass: String,
|
||||||
@DrawableRes val iconRes: Int,
|
@DrawableRes val iconRes: Int,
|
||||||
val actionString: String? = null,
|
val action: EventData? = null,
|
||||||
val message: String? = null,
|
val message: String? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -63,12 +68,21 @@ enum class WearControl {
|
||||||
|
|
||||||
abstract class TileBase : TileService() {
|
abstract class TileBase : TileService() {
|
||||||
|
|
||||||
|
@Inject lateinit var sp: SP
|
||||||
|
@Inject lateinit var aapsLogger: AAPSLogger
|
||||||
|
|
||||||
abstract val resourceVersion: String
|
abstract val resourceVersion: String
|
||||||
abstract val source: TileSource
|
abstract val source: TileSource
|
||||||
|
|
||||||
private val serviceJob = Job()
|
private val serviceJob = Job()
|
||||||
private val serviceScope = CoroutineScope(Dispatchers.IO + serviceJob)
|
private val serviceScope = CoroutineScope(Dispatchers.IO + serviceJob)
|
||||||
|
|
||||||
|
// Not derived from DaggerService, do injection here
|
||||||
|
override fun onCreate() {
|
||||||
|
AndroidInjection.inject(this)
|
||||||
|
super.onCreate()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onTileRequest(
|
override fun onTileRequest(
|
||||||
requestParams: RequestBuilders.TileRequest
|
requestParams: RequestBuilders.TileRequest
|
||||||
): ListenableFuture<Tile> = serviceScope.future {
|
): ListenableFuture<Tile> = serviceScope.future {
|
||||||
|
@ -93,11 +107,11 @@ abstract class TileBase : TileService() {
|
||||||
|
|
||||||
private fun getSelectedActions(): List<Action> {
|
private fun getSelectedActions(): List<Action> {
|
||||||
// TODO check why thi scan not be don in scope of the coroutine
|
// TODO check why thi scan not be don in scope of the coroutine
|
||||||
return source.getSelectedActions(this)
|
return source.getSelectedActions(this, sp, aapsLogger)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun validFor(): Long? {
|
private fun validFor(): Long? {
|
||||||
return source.getValidFor(this)
|
return source.getValidFor(sp)
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.N)
|
@RequiresApi(Build.VERSION_CODES.N)
|
||||||
|
@ -172,13 +186,13 @@ abstract class TileBase : TileService() {
|
||||||
val builder = ActionBuilders.AndroidActivity.Builder()
|
val builder = ActionBuilders.AndroidActivity.Builder()
|
||||||
.setClassName(action.activityClass)
|
.setClassName(action.activityClass)
|
||||||
.setPackageName(this.packageName)
|
.setPackageName(this.packageName)
|
||||||
if (action.actionString != null) {
|
if (action.action != null) {
|
||||||
val actionString = ActionBuilders.AndroidStringExtra.Builder().setValue(action.actionString).build()
|
val actionString = ActionBuilders.AndroidStringExtra.Builder().setValue(action.action.serialize()).build()
|
||||||
builder.addKeyToExtraMapping("actionString", actionString)
|
builder.addKeyToExtraMapping(DataLayerListenerServiceWear.KEY_ACTION, actionString)
|
||||||
}
|
}
|
||||||
if (action.message != null) {
|
if (action.message != null) {
|
||||||
val message = ActionBuilders.AndroidStringExtra.Builder().setValue(action.message).build()
|
val message = ActionBuilders.AndroidStringExtra.Builder().setValue(action.message).build()
|
||||||
builder.addKeyToExtraMapping("message", message)
|
builder.addKeyToExtraMapping(DataLayerListenerServiceWear.KEY_MESSAGE, message)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ActionBuilders.LaunchAction.Builder()
|
return ActionBuilders.LaunchAction.Builder()
|
||||||
|
@ -197,12 +211,8 @@ abstract class TileBase : TileService() {
|
||||||
Modifiers.Builder()
|
Modifiers.Builder()
|
||||||
.setBackground(
|
.setBackground(
|
||||||
Background.Builder()
|
Background.Builder()
|
||||||
.setColor(
|
.setColor(argb(ContextCompat.getColor(baseContext, BUTTON_COLOR)))
|
||||||
argb(ContextCompat.getColor(baseContext, BUTTON_COLOR))
|
.setCorner(Corner.Builder().setRadius(dp(circleDiameter / 2)).build())
|
||||||
)
|
|
||||||
.setCorner(
|
|
||||||
Corner.Builder().setRadius(dp(circleDiameter / 2)).build()
|
|
||||||
)
|
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
.setSemantics(
|
.setSemantics(
|
||||||
|
@ -239,9 +249,7 @@ abstract class TileBase : TileService() {
|
||||||
.setFontStyle(
|
.setFontStyle(
|
||||||
FontStyle.Builder()
|
FontStyle.Builder()
|
||||||
.setWeight(FONT_WEIGHT_BOLD)
|
.setWeight(FONT_WEIGHT_BOLD)
|
||||||
.setColor(
|
.setColor(argb(ContextCompat.getColor(baseContext, R.color.white)))
|
||||||
argb(ContextCompat.getColor(baseContext, R.color.white))
|
|
||||||
)
|
|
||||||
.setSize(buttonTextSize(deviceParameters, text))
|
.setSize(buttonTextSize(deviceParameters, text))
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
|
@ -253,9 +261,7 @@ abstract class TileBase : TileService() {
|
||||||
.setText(textSub)
|
.setText(textSub)
|
||||||
.setFontStyle(
|
.setFontStyle(
|
||||||
FontStyle.Builder()
|
FontStyle.Builder()
|
||||||
.setColor(
|
.setColor(argb(ContextCompat.getColor(baseContext, R.color.white)))
|
||||||
argb(ContextCompat.getColor(baseContext, R.color.white))
|
|
||||||
)
|
|
||||||
.setSize(buttonTextSize(deviceParameters, textSub))
|
.setSize(buttonTextSize(deviceParameters, textSub))
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
|
@ -283,11 +289,10 @@ abstract class TileBase : TileService() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getWearControl(): WearControl {
|
private fun getWearControl(): WearControl {
|
||||||
val sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this)
|
if (!sp.contains("wearcontrol")) {
|
||||||
if (!sharedPrefs.contains("wearcontrol")) {
|
|
||||||
return WearControl.NO_DATA
|
return WearControl.NO_DATA
|
||||||
}
|
}
|
||||||
val wearControlPref = sharedPrefs.getBoolean("wearcontrol", false)
|
val wearControlPref = sp.getBoolean("wearcontrol", false)
|
||||||
if (wearControlPref) {
|
if (wearControlPref) {
|
||||||
return WearControl.ENABLED
|
return WearControl.ENABLED
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,29 +1,18 @@
|
||||||
package info.nightscout.androidaps.watchfaces;
|
package info.nightscout.androidaps.watchfaces;
|
||||||
|
|
||||||
import android.content.BroadcastReceiver;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.LinearGradient;
|
|
||||||
import android.graphics.Matrix;
|
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.Point;
|
import android.graphics.Point;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.graphics.Shader;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.os.SystemClock;
|
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
|
||||||
import android.support.wearable.view.WatchViewStub;
|
import android.support.wearable.view.WatchViewStub;
|
||||||
import android.support.wearable.watchface.WatchFaceStyle;
|
import android.support.wearable.watchface.WatchFaceStyle;
|
||||||
import android.text.format.DateFormat;
|
import android.text.format.DateFormat;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.Display;
|
import android.view.Display;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
@ -32,7 +21,8 @@ import android.view.WindowManager;
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.google.android.gms.wearable.DataMap;
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
import com.ustwo.clockwise.common.WatchFaceTime;
|
import com.ustwo.clockwise.common.WatchFaceTime;
|
||||||
import com.ustwo.clockwise.common.WatchMode;
|
import com.ustwo.clockwise.common.WatchMode;
|
||||||
import com.ustwo.clockwise.common.WatchShape;
|
import com.ustwo.clockwise.common.WatchShape;
|
||||||
|
@ -40,25 +30,43 @@ import com.ustwo.clockwise.wearable.WatchFace;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import dagger.android.AndroidInjection;
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.data.BasalWatchData;
|
import info.nightscout.androidaps.events.EventWearToMobile;
|
||||||
import info.nightscout.androidaps.data.BgWatchData;
|
|
||||||
import info.nightscout.androidaps.data.BolusWatchData;
|
|
||||||
import info.nightscout.androidaps.data.DataLayerListenerService;
|
|
||||||
import info.nightscout.androidaps.data.TempWatchData;
|
|
||||||
import info.nightscout.androidaps.interaction.menus.MainMenuActivity;
|
import info.nightscout.androidaps.interaction.menus.MainMenuActivity;
|
||||||
|
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||||
|
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.weardata.EventData;
|
||||||
|
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
||||||
import lecho.lib.hellocharts.view.LineChartView;
|
import lecho.lib.hellocharts.view.LineChartView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by adrianLxM.
|
* Created by adrianLxM.
|
||||||
*/
|
*/
|
||||||
public class BIGChart extends WatchFace implements SharedPreferences.OnSharedPreferenceChangeListener {
|
@SuppressWarnings("deprecation")
|
||||||
public final static IntentFilter INTENT_FILTER;
|
public class BIGChart extends WatchFace {
|
||||||
public static final int SCREENSIZE_SMALL = 280;
|
|
||||||
public TextView mTime, mSgv, mTimestamp, mDelta, mAvgDelta;
|
@Inject RxBus rxBus;
|
||||||
public RelativeLayout mRelativeLayout;
|
@Inject AapsSchedulers aapsSchedulers;
|
||||||
public long sgvLevel = 0;
|
@Inject AAPSLogger aapsLogger;
|
||||||
public int batteryLevel = 1;
|
@Inject SP sp;
|
||||||
|
|
||||||
|
CompositeDisposable disposable = new CompositeDisposable();
|
||||||
|
|
||||||
|
private EventData.SingleBg singleBg;
|
||||||
|
private EventData.Status status;
|
||||||
|
private EventData.TreatmentData treatmentData;
|
||||||
|
private EventData.GraphData graphData;
|
||||||
|
|
||||||
|
private static final int SCREEN_SIZE_SMALL = 280;
|
||||||
|
private TextView mTime, mSgv, mTimestamp, mDelta, mAvgDelta;
|
||||||
|
private RelativeLayout mRelativeLayout;
|
||||||
|
|
||||||
public int ageLevel = 1;
|
public int ageLevel = 1;
|
||||||
public int highColor = Color.YELLOW;
|
public int highColor = Color.YELLOW;
|
||||||
public int lowColor = Color.RED;
|
public int lowColor = Color.RED;
|
||||||
|
@ -73,36 +81,21 @@ public class BIGChart extends WatchFace implements SharedPreferences.OnSharedPre
|
||||||
public boolean layoutSet = false;
|
public boolean layoutSet = false;
|
||||||
public BgGraphBuilder bgGraphBuilder;
|
public BgGraphBuilder bgGraphBuilder;
|
||||||
public LineChartView chart;
|
public LineChartView chart;
|
||||||
public long datetime;
|
public ArrayList<EventData.SingleBg> bgDataList = new ArrayList<>();
|
||||||
public ArrayList<BgWatchData> bgDataList = new ArrayList<>();
|
|
||||||
public ArrayList<TempWatchData> tempWatchDataList = new ArrayList<>();
|
|
||||||
public ArrayList<BasalWatchData> basalWatchDataList = new ArrayList<>();
|
|
||||||
public ArrayList<BolusWatchData> bolusWatchDataList = new ArrayList<>();
|
|
||||||
public ArrayList<BgWatchData> predictionList = new ArrayList<>();
|
|
||||||
|
|
||||||
public PowerManager.WakeLock wakeLock;
|
public PowerManager.WakeLock wakeLock;
|
||||||
public View layoutView;
|
public View layoutView;
|
||||||
private final Point displaySize = new Point();
|
private final Point displaySize = new Point();
|
||||||
private int specW, specH;
|
private int specW, specH;
|
||||||
private int animationAngle = 0;
|
|
||||||
private boolean isAnimated = false;
|
|
||||||
|
|
||||||
private LocalBroadcastManager localBroadcastManager;
|
|
||||||
private MessageReceiver messageReceiver;
|
|
||||||
|
|
||||||
protected SharedPreferences sharedPrefs;
|
|
||||||
private String rawString = "000 | 000 | 000";
|
|
||||||
private String batteryString = "--";
|
|
||||||
private String sgvString = "--";
|
|
||||||
private String externalStatusString = "no status";
|
|
||||||
private String cobString = "";
|
|
||||||
|
|
||||||
private TextView statusView;
|
private TextView statusView;
|
||||||
private long chartTapTime = 0L;
|
private long chartTapTime = 0L;
|
||||||
private long sgvTapTime = 0L;
|
private long sgvTapTime = 0L;
|
||||||
|
|
||||||
|
@SuppressLint("InflateParams")
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
|
AndroidInjection.inject(this);
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE))
|
Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE))
|
||||||
.getDefaultDisplay();
|
.getDefaultDisplay();
|
||||||
|
@ -113,17 +106,71 @@ public class BIGChart extends WatchFace implements SharedPreferences.OnSharedPre
|
||||||
View.MeasureSpec.EXACTLY);
|
View.MeasureSpec.EXACTLY);
|
||||||
specH = View.MeasureSpec.makeMeasureSpec(displaySize.y,
|
specH = View.MeasureSpec.makeMeasureSpec(displaySize.y,
|
||||||
View.MeasureSpec.EXACTLY);
|
View.MeasureSpec.EXACTLY);
|
||||||
sharedPrefs = PreferenceManager
|
|
||||||
.getDefaultSharedPreferences(this);
|
|
||||||
sharedPrefs.registerOnSharedPreferenceChangeListener(this);
|
|
||||||
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||||
DisplayMetrics metrics = getResources().getDisplayMetrics();
|
DisplayMetrics metrics = getResources().getDisplayMetrics();
|
||||||
if(metrics.widthPixels < SCREENSIZE_SMALL || metrics.heightPixels < SCREENSIZE_SMALL){
|
if (metrics.widthPixels < SCREEN_SIZE_SMALL || metrics.heightPixels < SCREEN_SIZE_SMALL) {
|
||||||
layoutView = inflater.inflate(R.layout.activity_bigchart_small, null);
|
layoutView = inflater.inflate(R.layout.activity_bigchart_small, null);
|
||||||
} else {
|
} else {
|
||||||
layoutView = inflater.inflate(R.layout.activity_bigchart, null);
|
layoutView = inflater.inflate(R.layout.activity_bigchart, null);
|
||||||
}
|
}
|
||||||
performViewSetup();
|
performViewSetup();
|
||||||
|
disposable.add(rxBus
|
||||||
|
.toObservable(EventData.SingleBg.class)
|
||||||
|
.observeOn(aapsSchedulers.getMain())
|
||||||
|
.subscribe(event -> {
|
||||||
|
aapsLogger.debug(LTag.WEAR, "SingleBg received");
|
||||||
|
singleBg = event;
|
||||||
|
|
||||||
|
mSgv.setText(singleBg.getSgvString());
|
||||||
|
if (ageLevel() <= 0)
|
||||||
|
mSgv.setPaintFlags(mSgv.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
|
||||||
|
else mSgv.setPaintFlags(mSgv.getPaintFlags() & ~Paint.STRIKE_THRU_TEXT_FLAG);
|
||||||
|
final java.text.DateFormat timeFormat = DateFormat.getTimeFormat(BIGChart.this);
|
||||||
|
mTime.setText(timeFormat.format(System.currentTimeMillis()));
|
||||||
|
mDelta.setText(singleBg.getDelta());
|
||||||
|
mAvgDelta.setText(singleBg.getAvgDelta());
|
||||||
|
})
|
||||||
|
);
|
||||||
|
disposable.add(rxBus
|
||||||
|
.toObservable(EventData.TreatmentData.class)
|
||||||
|
.observeOn(aapsSchedulers.getMain())
|
||||||
|
.subscribe(event -> treatmentData = event)
|
||||||
|
);
|
||||||
|
disposable.add(rxBus
|
||||||
|
.toObservable(EventData.GraphData.class)
|
||||||
|
.observeOn(aapsSchedulers.getMain())
|
||||||
|
.subscribe(event -> graphData = event)
|
||||||
|
);
|
||||||
|
disposable.add(rxBus
|
||||||
|
.toObservable(EventData.Status.class)
|
||||||
|
.observeOn(aapsSchedulers.getMain())
|
||||||
|
.subscribe(event -> {
|
||||||
|
// this event is received as last batch of data
|
||||||
|
aapsLogger.debug(LTag.WEAR, "Status received");
|
||||||
|
status = event;
|
||||||
|
showAgeAndStatus();
|
||||||
|
addToWatchSet();
|
||||||
|
mRelativeLayout.measure(specW, specH);
|
||||||
|
mRelativeLayout.layout(0, 0, mRelativeLayout.getMeasuredWidth(),
|
||||||
|
mRelativeLayout.getMeasuredHeight());
|
||||||
|
invalidate();
|
||||||
|
setColor();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
disposable.add(rxBus
|
||||||
|
.toObservable(EventData.Preferences.class)
|
||||||
|
.observeOn(aapsSchedulers.getMain())
|
||||||
|
.subscribe(event -> {
|
||||||
|
setColor();
|
||||||
|
if (layoutSet) {
|
||||||
|
showAgeAndStatus();
|
||||||
|
mRelativeLayout.measure(specW, specH);
|
||||||
|
mRelativeLayout.layout(0, 0, mRelativeLayout.getMeasuredWidth(),
|
||||||
|
mRelativeLayout.getMeasuredHeight());
|
||||||
|
}
|
||||||
|
invalidate();
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -134,54 +181,46 @@ public class BIGChart extends WatchFace implements SharedPreferences.OnSharedPre
|
||||||
|
|
||||||
public void performViewSetup() {
|
public void performViewSetup() {
|
||||||
final WatchViewStub stub = layoutView.findViewById(R.id.watch_view_stub);
|
final WatchViewStub stub = layoutView.findViewById(R.id.watch_view_stub);
|
||||||
IntentFilter messageFilter = new IntentFilter(Intent.ACTION_SEND);
|
|
||||||
|
|
||||||
messageReceiver = new MessageReceiver();
|
stub.setOnLayoutInflatedListener(stub1 -> {
|
||||||
localBroadcastManager = LocalBroadcastManager.getInstance(this);
|
mTime = stub1.findViewById(R.id.watch_time);
|
||||||
localBroadcastManager.registerReceiver(messageReceiver, messageFilter);
|
mSgv = stub1.findViewById(R.id.sgv);
|
||||||
|
mTimestamp = stub1.findViewById(R.id.timestamp);
|
||||||
stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
|
mDelta = stub1.findViewById(R.id.delta);
|
||||||
@Override
|
mAvgDelta = stub1.findViewById(R.id.avgdelta);
|
||||||
public void onLayoutInflated(WatchViewStub stub) {
|
mRelativeLayout = stub1.findViewById(R.id.main_layout);
|
||||||
mTime = stub.findViewById(R.id.watch_time);
|
chart = stub1.findViewById(R.id.chart);
|
||||||
mSgv = stub.findViewById(R.id.sgv);
|
statusView = stub1.findViewById(R.id.aps_status);
|
||||||
mTimestamp = stub.findViewById(R.id.timestamp);
|
layoutSet = true;
|
||||||
mDelta = stub.findViewById(R.id.delta);
|
showAgeAndStatus();
|
||||||
mAvgDelta = stub.findViewById(R.id.avgdelta);
|
mRelativeLayout.measure(specW, specH);
|
||||||
mRelativeLayout = stub.findViewById(R.id.main_layout);
|
mRelativeLayout.layout(0, 0, mRelativeLayout.getMeasuredWidth(),
|
||||||
chart = stub.findViewById(R.id.chart);
|
mRelativeLayout.getMeasuredHeight());
|
||||||
statusView = stub.findViewById(R.id.aps_status);
|
|
||||||
layoutSet = true;
|
|
||||||
showAgeAndStatus();
|
|
||||||
mRelativeLayout.measure(specW, specH);
|
|
||||||
mRelativeLayout.layout(0, 0, mRelativeLayout.getMeasuredWidth(),
|
|
||||||
mRelativeLayout.getMeasuredHeight());
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
DataLayerListenerService.Companion.requestData(this);
|
rxBus.send(new EventWearToMobile(new EventData.ActionResendData("BIGChart:performViewSetup")));
|
||||||
wakeLock.acquire(50);
|
wakeLock.acquire(50);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onTapCommand(int tapType, int x, int y, long eventTime) {
|
protected void onTapCommand(int tapType, int x, int y, long eventTime) {
|
||||||
|
|
||||||
int extra = mSgv!=null?(mSgv.getRight() - mSgv.getLeft())/2:0;
|
int extra = mSgv != null ? (mSgv.getRight() - mSgv.getLeft()) / 2 : 0;
|
||||||
|
|
||||||
if (tapType == TAP_TYPE_TAP&&
|
if (tapType == TAP_TYPE_TAP &&
|
||||||
x >=chart.getLeft() &&
|
x >= chart.getLeft() &&
|
||||||
x <= chart.getRight()&&
|
x <= chart.getRight() &&
|
||||||
y >= chart.getTop() &&
|
y >= chart.getTop() &&
|
||||||
y <= chart.getBottom()){
|
y <= chart.getBottom()) {
|
||||||
if (eventTime - chartTapTime < 800){
|
if (eventTime - chartTapTime < 800) {
|
||||||
changeChartTimeframe();
|
changeChartTimeframe();
|
||||||
}
|
}
|
||||||
chartTapTime = eventTime;
|
chartTapTime = eventTime;
|
||||||
} else if (tapType == TAP_TYPE_TAP&&
|
} else if (tapType == TAP_TYPE_TAP &&
|
||||||
x + extra >=mSgv.getLeft() &&
|
x + extra >= mSgv.getLeft() &&
|
||||||
x - extra <= mSgv.getRight()&&
|
x - extra <= mSgv.getRight() &&
|
||||||
y >= mSgv.getTop() &&
|
y >= mSgv.getTop() &&
|
||||||
y <= mSgv.getBottom()){
|
y <= mSgv.getBottom()) {
|
||||||
if (eventTime - sgvTapTime < 800){
|
if (eventTime - sgvTapTime < 800) {
|
||||||
Intent intent = new Intent(this, MainMenuActivity.class);
|
Intent intent = new Intent(this, MainMenuActivity.class);
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
|
@ -191,17 +230,17 @@ public class BIGChart extends WatchFace implements SharedPreferences.OnSharedPre
|
||||||
}
|
}
|
||||||
|
|
||||||
private void changeChartTimeframe() {
|
private void changeChartTimeframe() {
|
||||||
int timeframe = Integer.parseInt(sharedPrefs.getString("chart_timeframe", "3"));
|
int timeframe = sp.getInt("chart_timeframe", 3);
|
||||||
timeframe = (timeframe%5) + 1;
|
timeframe = (timeframe % 5) + 1;
|
||||||
sharedPrefs.edit().putString("chart_timeframe", "" + timeframe).apply();
|
sp.putInt("chart_timeframe", timeframe);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void onWatchModeChanged(WatchMode watchMode) {
|
protected void onWatchModeChanged(WatchMode watchMode) {
|
||||||
|
|
||||||
if(lowResMode ^ isLowRes(watchMode)){ //if there was a change in lowResMode
|
if (lowResMode ^ isLowRes(watchMode)) { //if there was a change in lowResMode
|
||||||
lowResMode = isLowRes(watchMode);
|
lowResMode = isLowRes(watchMode);
|
||||||
setColor();
|
setColor();
|
||||||
} else if (! sharedPrefs.getBoolean("dark", true)){
|
} else if (!sp.getBoolean("dark", true)) {
|
||||||
//in bright mode: different colours if active:
|
//in bright mode: different colours if active:
|
||||||
setColor();
|
setColor();
|
||||||
}
|
}
|
||||||
|
@ -213,14 +252,13 @@ public class BIGChart extends WatchFace implements SharedPreferences.OnSharedPre
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected WatchFaceStyle getWatchFaceStyle(){
|
protected WatchFaceStyle getWatchFaceStyle() {
|
||||||
return new WatchFaceStyle.Builder(this).setAcceptsTapEvents(true).build();
|
return new WatchFaceStyle.Builder(this).setAcceptsTapEvents(true).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public int ageLevel() {
|
public int ageLevel() {
|
||||||
if(timeSince() <= (1000 * 60 * 12)) {
|
if (timeSince() <= (1000 * 60 * 12)) {
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -228,40 +266,30 @@ public class BIGChart extends WatchFace implements SharedPreferences.OnSharedPre
|
||||||
}
|
}
|
||||||
|
|
||||||
public double timeSince() {
|
public double timeSince() {
|
||||||
return System.currentTimeMillis() - datetime;
|
return System.currentTimeMillis() - singleBg.getTimeStamp();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String readingAge(boolean shortString) {
|
public String readingAge(boolean shortString) {
|
||||||
if (datetime == 0) { return shortString?"--'":"-- Minute ago"; }
|
if (singleBg == null || singleBg.getTimeStamp() == 0) {
|
||||||
int minutesAgo = (int) Math.floor(timeSince()/(1000*60));
|
return shortString ? "--'" : "-- Minute ago";
|
||||||
if (minutesAgo == 1) {
|
|
||||||
return minutesAgo + (shortString?"'":" Minute ago");
|
|
||||||
}
|
}
|
||||||
return minutesAgo + (shortString?"'":" Minutes ago");
|
int minutesAgo = (int) Math.floor(timeSince() / (1000 * 60));
|
||||||
|
if (minutesAgo == 1) {
|
||||||
|
return minutesAgo + (shortString ? "'" : " Minute ago");
|
||||||
|
}
|
||||||
|
return minutesAgo + (shortString ? "'" : " Minutes ago");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
if(localBroadcastManager != null && messageReceiver != null){
|
disposable.clear();
|
||||||
localBroadcastManager.unregisterReceiver(messageReceiver);}
|
|
||||||
if (sharedPrefs != null){
|
|
||||||
sharedPrefs.unregisterOnSharedPreferenceChangeListener(this);
|
|
||||||
}
|
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
static {
|
|
||||||
INTENT_FILTER = new IntentFilter();
|
|
||||||
INTENT_FILTER.addAction(Intent.ACTION_TIME_TICK);
|
|
||||||
INTENT_FILTER.addAction(Intent.ACTION_TIMEZONE_CHANGED);
|
|
||||||
INTENT_FILTER.addAction(Intent.ACTION_TIME_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDraw(Canvas canvas) {
|
protected void onDraw(Canvas canvas) {
|
||||||
if(layoutSet) {
|
if (layoutSet) {
|
||||||
this.mRelativeLayout.draw(canvas);
|
this.mRelativeLayout.draw(canvas);
|
||||||
Log.d("onDraw", "draw");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,7 +301,7 @@ public class BIGChart extends WatchFace implements SharedPreferences.OnSharedPre
|
||||||
mTime.setText(timeFormat.format(System.currentTimeMillis()));
|
mTime.setText(timeFormat.format(System.currentTimeMillis()));
|
||||||
showAgeAndStatus();
|
showAgeAndStatus();
|
||||||
|
|
||||||
if(ageLevel()<=0) {
|
if (ageLevel() <= 0) {
|
||||||
mSgv.setPaintFlags(mSgv.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
|
mSgv.setPaintFlags(mSgv.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
|
||||||
} else {
|
} else {
|
||||||
mSgv.setPaintFlags(mSgv.getPaintFlags() & ~Paint.STRIKE_THRU_TEXT_FLAG);
|
mSgv.setPaintFlags(mSgv.getPaintFlags() & ~Paint.STRIKE_THRU_TEXT_FLAG);
|
||||||
|
@ -286,173 +314,25 @@ public class BIGChart extends WatchFace implements SharedPreferences.OnSharedPre
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class MessageReceiver extends BroadcastReceiver {
|
|
||||||
@Override
|
|
||||||
public void onReceive(Context context, Intent intent) {
|
|
||||||
Bundle bundle = intent.getBundleExtra("data");
|
|
||||||
if (layoutSet && bundle !=null) {
|
|
||||||
DataMap dataMap = DataMap.fromBundle(bundle);
|
|
||||||
wakeLock.acquire(50);
|
|
||||||
sgvLevel = dataMap.getLong("sgvLevel");
|
|
||||||
batteryLevel = dataMap.getInt("batteryLevel");
|
|
||||||
datetime = dataMap.getLong("timestamp");
|
|
||||||
rawString = dataMap.getString("rawString");
|
|
||||||
sgvString = dataMap.getString("sgvString");
|
|
||||||
batteryString = dataMap.getString("battery");
|
|
||||||
mSgv.setText(dataMap.getString("sgvString"));
|
|
||||||
|
|
||||||
if(ageLevel()<=0) {
|
|
||||||
mSgv.setPaintFlags(mSgv.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
|
|
||||||
} else {
|
|
||||||
mSgv.setPaintFlags(mSgv.getPaintFlags() & ~Paint.STRIKE_THRU_TEXT_FLAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
final java.text.DateFormat timeFormat = DateFormat.getTimeFormat(BIGChart.this);
|
|
||||||
mTime.setText(timeFormat.format(System.currentTimeMillis()));
|
|
||||||
|
|
||||||
showAgeAndStatus();
|
|
||||||
|
|
||||||
String delta = dataMap.getString("delta");
|
|
||||||
|
|
||||||
if (delta.endsWith(" mg/dl")) {
|
|
||||||
mDelta.setText(delta.substring(0, delta.length() - 6));
|
|
||||||
} else if (delta.endsWith(" mmol/l")||delta.endsWith(" mmol")) {
|
|
||||||
mDelta.setText(delta.substring(0, delta.length() - 5));
|
|
||||||
} else {
|
|
||||||
mDelta.setText(delta);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
String avgDelta = dataMap.getString("avgDelta");
|
|
||||||
|
|
||||||
if (delta.endsWith(" mg/dl")) {
|
|
||||||
mAvgDelta.setText(avgDelta.substring(0, avgDelta.length() - 6));
|
|
||||||
} else if (avgDelta.endsWith(" mmol/l")||avgDelta.endsWith(" mmol")) {
|
|
||||||
mAvgDelta.setText(avgDelta.substring(0, avgDelta.length() - 5));
|
|
||||||
} else {
|
|
||||||
mAvgDelta.setText(avgDelta);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chart != null) {
|
|
||||||
addToWatchSet(dataMap);
|
|
||||||
setupCharts();
|
|
||||||
}
|
|
||||||
mRelativeLayout.measure(specW, specH);
|
|
||||||
mRelativeLayout.layout(0, 0, mRelativeLayout.getMeasuredWidth(),
|
|
||||||
mRelativeLayout.getMeasuredHeight());
|
|
||||||
invalidate();
|
|
||||||
setColor();
|
|
||||||
|
|
||||||
//start animation?
|
|
||||||
// dataMap.getDataMapArrayList("entries") == null -> not on "resend data".
|
|
||||||
if (!lowResMode && (sharedPrefs.getBoolean("animation", false) && dataMap.getDataMapArrayList("entries") == null && (sgvString.equals("100") || sgvString.equals("5.5") || sgvString.equals("5,5")))) {
|
|
||||||
startAnimation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//status
|
|
||||||
bundle = intent.getBundleExtra("status");
|
|
||||||
if (layoutSet && bundle != null) {
|
|
||||||
DataMap dataMap = DataMap.fromBundle(bundle);
|
|
||||||
wakeLock.acquire(50);
|
|
||||||
externalStatusString = dataMap.getString("externalStatusString");
|
|
||||||
cobString = dataMap.getString("cob");
|
|
||||||
|
|
||||||
|
|
||||||
showAgeAndStatus();
|
|
||||||
|
|
||||||
mRelativeLayout.measure(specW, specH);
|
|
||||||
mRelativeLayout.layout(0, 0, mRelativeLayout.getMeasuredWidth(),
|
|
||||||
mRelativeLayout.getMeasuredHeight());
|
|
||||||
invalidate();
|
|
||||||
setColor();
|
|
||||||
}
|
|
||||||
//basals and temps
|
|
||||||
bundle = intent.getBundleExtra("basals");
|
|
||||||
if (layoutSet && bundle != null) {
|
|
||||||
DataMap dataMap = DataMap.fromBundle(bundle);
|
|
||||||
wakeLock.acquire(500);
|
|
||||||
|
|
||||||
loadBasalsAndTemps(dataMap);
|
|
||||||
|
|
||||||
mRelativeLayout.measure(specW, specH);
|
|
||||||
mRelativeLayout.layout(0, 0, mRelativeLayout.getMeasuredWidth(),
|
|
||||||
mRelativeLayout.getMeasuredHeight());
|
|
||||||
invalidate();
|
|
||||||
setColor();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadBasalsAndTemps(DataMap dataMap) {
|
|
||||||
ArrayList<DataMap> temps = dataMap.getDataMapArrayList("temps");
|
|
||||||
if (temps != null) {
|
|
||||||
tempWatchDataList = new ArrayList<>();
|
|
||||||
for (DataMap temp : temps) {
|
|
||||||
TempWatchData twd = new TempWatchData();
|
|
||||||
twd.startTime = temp.getLong("starttime");
|
|
||||||
twd.startBasal = temp.getDouble("startBasal");
|
|
||||||
twd.endTime = temp.getLong("endtime");
|
|
||||||
twd.endBasal = temp.getDouble("endbasal");
|
|
||||||
twd.amount = temp.getDouble("amount");
|
|
||||||
tempWatchDataList.add(twd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ArrayList<DataMap> basals = dataMap.getDataMapArrayList("basals");
|
|
||||||
if (basals != null) {
|
|
||||||
basalWatchDataList = new ArrayList<>();
|
|
||||||
for (DataMap basal : basals) {
|
|
||||||
BasalWatchData bwd = new BasalWatchData();
|
|
||||||
bwd.startTime = basal.getLong("starttime");
|
|
||||||
bwd.endTime = basal.getLong("endtime");
|
|
||||||
bwd.amount = basal.getDouble("amount");
|
|
||||||
basalWatchDataList.add(bwd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ArrayList<DataMap> boluses = dataMap.getDataMapArrayList("boluses");
|
|
||||||
if (boluses != null) {
|
|
||||||
bolusWatchDataList = new ArrayList<>();
|
|
||||||
for (DataMap bolus : boluses) {
|
|
||||||
BolusWatchData bwd = new BolusWatchData();
|
|
||||||
bwd.date = bolus.getLong("date");
|
|
||||||
bwd.bolus = bolus.getDouble("bolus");
|
|
||||||
bwd.carbs = bolus.getDouble("carbs");
|
|
||||||
bwd.isSMB = bolus.getBoolean("isSMB");
|
|
||||||
bwd.isValid = bolus.getBoolean("isValid");
|
|
||||||
bolusWatchDataList.add(bwd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ArrayList<DataMap> predictions = dataMap.getDataMapArrayList("predictions");
|
|
||||||
if (boluses != null) {
|
|
||||||
predictionList = new ArrayList<>();
|
|
||||||
for (DataMap prediction : predictions) {
|
|
||||||
BgWatchData bwd = new BgWatchData();
|
|
||||||
bwd.timestamp = prediction.getLong("timestamp");
|
|
||||||
bwd.sgv = prediction.getDouble("sgv");
|
|
||||||
bwd.color = prediction.getInt("color");
|
|
||||||
predictionList.add(bwd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showAgeAndStatus() {
|
private void showAgeAndStatus() {
|
||||||
|
|
||||||
if( mTimestamp != null){
|
if (mTimestamp != null) {
|
||||||
mTimestamp.setText(readingAge(true));
|
mTimestamp.setText(readingAge(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean showStatus = sharedPrefs.getBoolean("showExternalStatus", true);
|
boolean showStatus = sp.getBoolean("showExternalStatus", true);
|
||||||
boolean showAvgDelta = sharedPrefs.getBoolean("showAvgDelta", true);
|
boolean showAvgDelta = sp.getBoolean("showAvgDelta", true);
|
||||||
|
|
||||||
if(showAvgDelta){
|
if (showAvgDelta) {
|
||||||
mAvgDelta.setVisibility(View.VISIBLE);
|
mAvgDelta.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
mAvgDelta.setVisibility(View.GONE);
|
mAvgDelta.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(showStatus){
|
if (showStatus && status != null) {
|
||||||
String status = externalStatusString;
|
String status = this.status.getExternalStatus();
|
||||||
if (sharedPrefs.getBoolean("show_cob", true)) {
|
if (sp.getBoolean("show_cob", true)) {
|
||||||
status = externalStatusString + " " + cobString;
|
status += " " + this.status.getCob();
|
||||||
}
|
}
|
||||||
|
|
||||||
statusView.setText(status);
|
statusView.setText(status);
|
||||||
|
@ -463,9 +343,9 @@ public class BIGChart extends WatchFace implements SharedPreferences.OnSharedPre
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setColor() {
|
public void setColor() {
|
||||||
if(lowResMode){
|
if (lowResMode) {
|
||||||
setColorLowRes();
|
setColorLowRes();
|
||||||
} else if (sharedPrefs.getBoolean("dark", true)) {
|
} else if (sp.getBoolean("dark", true)) {
|
||||||
setColorDark();
|
setColorDark();
|
||||||
} else {
|
} else {
|
||||||
setColorBright();
|
setColorBright();
|
||||||
|
@ -473,66 +353,6 @@ public class BIGChart extends WatchFace implements SharedPreferences.OnSharedPre
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key){
|
|
||||||
setColor();
|
|
||||||
if(layoutSet){
|
|
||||||
showAgeAndStatus();
|
|
||||||
mRelativeLayout.measure(specW, specH);
|
|
||||||
mRelativeLayout.layout(0, 0, mRelativeLayout.getMeasuredWidth(),
|
|
||||||
mRelativeLayout.getMeasuredHeight());
|
|
||||||
}
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void updateRainbow() {
|
|
||||||
animationAngle = (animationAngle + 1) % 360;
|
|
||||||
//Animation matrix:
|
|
||||||
int[] rainbow = {Color.RED, Color.YELLOW, Color.GREEN, Color.BLUE
|
|
||||||
, Color.CYAN};
|
|
||||||
Shader shader = new LinearGradient(0, 0, 0, 20, rainbow,
|
|
||||||
null, Shader.TileMode.MIRROR);
|
|
||||||
Matrix matrix = new Matrix();
|
|
||||||
matrix.setRotate(animationAngle);
|
|
||||||
shader.setLocalMatrix(matrix);
|
|
||||||
mSgv.getPaint().setShader(shader);
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized boolean isAnimated() {
|
|
||||||
return isAnimated;
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized void setIsAnimated(boolean isAnimated) {
|
|
||||||
this.isAnimated = isAnimated;
|
|
||||||
}
|
|
||||||
|
|
||||||
void startAnimation() {
|
|
||||||
Log.d("CircleWatchface", "start startAnimation");
|
|
||||||
|
|
||||||
Thread animator = new Thread() {
|
|
||||||
|
|
||||||
|
|
||||||
public void run() {
|
|
||||||
setIsAnimated(true);
|
|
||||||
for (int i = 0; i <= 8 * 1000 / 40; i++) {
|
|
||||||
updateRainbow();
|
|
||||||
SystemClock.sleep(40);
|
|
||||||
}
|
|
||||||
mSgv.getPaint().setShader(null);
|
|
||||||
setIsAnimated(false);
|
|
||||||
invalidate();
|
|
||||||
setColor();
|
|
||||||
|
|
||||||
System.gc();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
animator.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setColorLowRes() {
|
protected void setColorLowRes() {
|
||||||
mTime.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_mTime));
|
mTime.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_mTime));
|
||||||
statusView.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_statusView));
|
statusView.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_statusView));
|
||||||
|
@ -555,40 +375,41 @@ public class BIGChart extends WatchFace implements SharedPreferences.OnSharedPre
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setColorDark() {
|
protected void setColorDark() {
|
||||||
mTime.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_mTime));
|
if (singleBg != null) {
|
||||||
statusView.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_statusView));
|
mTime.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_mTime));
|
||||||
mRelativeLayout.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_background));
|
statusView.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_statusView));
|
||||||
if (sgvLevel == 1) {
|
mRelativeLayout.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_background));
|
||||||
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor));
|
if (singleBg.getSgvLevel() == 1) {
|
||||||
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor));
|
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor));
|
||||||
mAvgDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor));
|
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor));
|
||||||
} else if (sgvLevel == 0) {
|
mAvgDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor));
|
||||||
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
|
} else if (singleBg.getSgvLevel() == 0) {
|
||||||
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
|
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
|
||||||
mAvgDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
|
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
|
||||||
} else if (sgvLevel == -1) {
|
mAvgDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
|
||||||
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor));
|
} else if (singleBg.getSgvLevel() == -1) {
|
||||||
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor));
|
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor));
|
||||||
mAvgDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor));
|
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor));
|
||||||
}
|
mAvgDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor));
|
||||||
|
}
|
||||||
|
|
||||||
if (ageLevel == 1) {
|
if (ageLevel == 1) {
|
||||||
mTimestamp.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_Timestamp));
|
mTimestamp.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_Timestamp));
|
||||||
} else {
|
} else {
|
||||||
mTimestamp.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_TimestampOld));
|
mTimestamp.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_TimestampOld));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chart != null) {
|
if (chart != null) {
|
||||||
highColor = ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor);
|
highColor = ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor);
|
||||||
lowColor = ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor);
|
lowColor = ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor);
|
||||||
midColor = ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor);
|
midColor = ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor);
|
||||||
gridColour = ContextCompat.getColor(getApplicationContext(), R.color.dark_gridColor);
|
gridColour = ContextCompat.getColor(getApplicationContext(), R.color.dark_gridColor);
|
||||||
basalBackgroundColor = ContextCompat.getColor(getApplicationContext(), R.color.basal_dark);
|
basalBackgroundColor = ContextCompat.getColor(getApplicationContext(), R.color.basal_dark);
|
||||||
basalCenterColor = ContextCompat.getColor(getApplicationContext(), R.color.basal_light);
|
basalCenterColor = ContextCompat.getColor(getApplicationContext(), R.color.basal_light);
|
||||||
pointSize = 2;
|
pointSize = 2;
|
||||||
setupCharts();
|
setupCharts();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -598,15 +419,15 @@ public class BIGChart extends WatchFace implements SharedPreferences.OnSharedPre
|
||||||
mTime.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_bigchart_time));
|
mTime.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_bigchart_time));
|
||||||
statusView.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_bigchart_status));
|
statusView.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_bigchart_status));
|
||||||
mRelativeLayout.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.light_background));
|
mRelativeLayout.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.light_background));
|
||||||
if (sgvLevel == 1) {
|
if (singleBg.getSgvLevel() == 1) {
|
||||||
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_highColor));
|
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_highColor));
|
||||||
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_highColor));
|
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_highColor));
|
||||||
mAvgDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_highColor));
|
mAvgDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_highColor));
|
||||||
} else if (sgvLevel == 0) {
|
} else if (singleBg.getSgvLevel() == 0) {
|
||||||
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_midColor));
|
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_midColor));
|
||||||
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_midColor));
|
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_midColor));
|
||||||
mAvgDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_midColor));
|
mAvgDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_midColor));
|
||||||
} else if (sgvLevel == -1) {
|
} else if (singleBg.getSgvLevel() == -1) {
|
||||||
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_lowColor));
|
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_lowColor));
|
||||||
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_lowColor));
|
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_lowColor));
|
||||||
mAvgDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_lowColor));
|
mAvgDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_lowColor));
|
||||||
|
@ -636,61 +457,36 @@ 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) {
|
||||||
DataLayerListenerService.Companion.requestData(this); // attempt endTime recover missing data
|
// attempt endTime recover missing data
|
||||||
|
rxBus.send(new EventWearToMobile(new EventData.ActionResendData("BIGChart:missedReadingAlert")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addToWatchSet(DataMap dataMap) {
|
public void addToWatchSet() {
|
||||||
|
if (graphData != null) {
|
||||||
ArrayList<DataMap> entries = dataMap.getDataMapArrayList("entries");
|
bgDataList = graphData.getEntries();
|
||||||
if (entries != null) {
|
|
||||||
bgDataList = new ArrayList<BgWatchData>();
|
|
||||||
for (DataMap entry : entries) {
|
|
||||||
double sgv = entry.getDouble("sgvDouble");
|
|
||||||
double high = entry.getDouble("high");
|
|
||||||
double low = entry.getDouble("low");
|
|
||||||
long timestamp = entry.getLong("timestamp");
|
|
||||||
int color = entry.getInt("color", 0);
|
|
||||||
bgDataList.add(new BgWatchData(sgv, high, low, timestamp, color));
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
double sgv = dataMap.getDouble("sgvDouble");
|
|
||||||
double high = dataMap.getDouble("high");
|
|
||||||
double low = dataMap.getDouble("low");
|
|
||||||
long timestamp = dataMap.getLong("timestamp");
|
|
||||||
int color = dataMap.getInt("color", 0);
|
|
||||||
|
|
||||||
final int size = bgDataList.size();
|
final int size = bgDataList.size();
|
||||||
if (size > 0) {
|
if (size > 0 && bgDataList.get(size - 1).getTimeStamp() == singleBg.getTimeStamp())
|
||||||
if (bgDataList.get(size - 1).timestamp == timestamp)
|
return; // Ignore duplicates.
|
||||||
return; // Ignore duplicates.
|
bgDataList.add(singleBg);
|
||||||
}
|
|
||||||
|
|
||||||
bgDataList.add(new BgWatchData(sgv, high, low, timestamp, color));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < bgDataList.size(); i++) {
|
|
||||||
if (bgDataList.get(i).timestamp < (System.currentTimeMillis() - (1000 * 60 * 60 * 5))) {
|
|
||||||
bgDataList.remove(i); //Get rid of anything more than 5 hours old
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setupCharts() {
|
public void setupCharts() {
|
||||||
if(bgDataList.size() > 0) { //Dont crash things just because we dont have values, people dont like crashy things
|
if (bgDataList.size() > 0) {
|
||||||
int timeframe = Integer.parseInt(sharedPrefs.getString("chart_timeframe", "3"));
|
int timeframe = sp.getInt("chart_timeframe", 3);
|
||||||
if (lowResMode) {
|
if (lowResMode) {
|
||||||
bgGraphBuilder = new BgGraphBuilder(getApplicationContext(), bgDataList, predictionList, tempWatchDataList, basalWatchDataList, bolusWatchDataList, pointSize, midColor, gridColour, basalBackgroundColor, basalCenterColor, bolusColor, carbsColor, timeframe);
|
bgGraphBuilder = new BgGraphBuilder(getApplicationContext(), bgDataList, treatmentData.getPredictions(), treatmentData.getTemps(), treatmentData.getBasals(), treatmentData.getBoluses(), pointSize, midColor, gridColour, basalBackgroundColor, basalCenterColor, bolusColor, carbsColor, timeframe);
|
||||||
} else {
|
} else {
|
||||||
bgGraphBuilder = new BgGraphBuilder(getApplicationContext(), bgDataList, predictionList, tempWatchDataList, basalWatchDataList, bolusWatchDataList, pointSize, highColor, lowColor, midColor, gridColour, basalBackgroundColor, basalCenterColor, bolusColor, carbsColor, timeframe);
|
bgGraphBuilder = new BgGraphBuilder(getApplicationContext(), bgDataList, treatmentData.getPredictions(), treatmentData.getTemps(), treatmentData.getBasals(), treatmentData.getBoluses(), pointSize, highColor, lowColor, midColor, gridColour, basalBackgroundColor, basalCenterColor, bolusColor, carbsColor, timeframe);
|
||||||
}
|
}
|
||||||
|
|
||||||
chart.setLineChartData(bgGraphBuilder.lineData());
|
chart.setLineChartData(bgGraphBuilder.lineData());
|
||||||
chart.setViewportCalculationEnabled(true);
|
chart.setViewportCalculationEnabled(true);
|
||||||
chart.setMaximumViewport(chart.getMaximumViewport());
|
chart.setMaximumViewport(chart.getMaximumViewport());
|
||||||
} else {
|
} else {
|
||||||
DataLayerListenerService.Companion.requestData(this);
|
rxBus.send(new EventWearToMobile(new EventData.ActionResendData("BIGChart:setupCharts")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
|
@ -15,7 +14,6 @@ import android.graphics.Typeface;
|
||||||
import android.os.BatteryManager;
|
import android.os.BatteryManager;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.os.Vibrator;
|
import android.os.Vibrator;
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
import android.support.wearable.view.WatchViewStub;
|
import android.support.wearable.view.WatchViewStub;
|
||||||
import android.text.format.DateFormat;
|
import android.text.format.DateFormat;
|
||||||
import android.view.Display;
|
import android.view.Display;
|
||||||
|
@ -28,15 +26,14 @@ import android.widget.RelativeLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
|
||||||
|
|
||||||
import com.google.android.gms.wearable.DataMap;
|
|
||||||
import com.ustwo.clockwise.common.WatchFaceTime;
|
import com.ustwo.clockwise.common.WatchFaceTime;
|
||||||
import com.ustwo.clockwise.common.WatchMode;
|
import com.ustwo.clockwise.common.WatchMode;
|
||||||
import com.ustwo.clockwise.common.WatchShape;
|
import com.ustwo.clockwise.common.WatchShape;
|
||||||
import com.ustwo.clockwise.wearable.WatchFace;
|
import com.ustwo.clockwise.wearable.WatchFace;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
@ -44,12 +41,17 @@ 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.DataLayerListenerService;
|
import info.nightscout.androidaps.events.EventWearPreferenceChange;
|
||||||
import info.nightscout.androidaps.data.RawDisplayData;
|
import info.nightscout.androidaps.events.EventWearToMobile;
|
||||||
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;
|
||||||
|
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||||
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers;
|
||||||
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.weardata.EventData;
|
||||||
|
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
||||||
import lecho.lib.hellocharts.view.LineChartView;
|
import lecho.lib.hellocharts.view.LineChartView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -58,20 +60,27 @@ import lecho.lib.hellocharts.view.LineChartView;
|
||||||
* Refactored by dlvoy on 2019-11-2019
|
* Refactored by dlvoy on 2019-11-2019
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public abstract class BaseWatchFace extends WatchFace implements SharedPreferences.OnSharedPreferenceChangeListener {
|
public abstract class BaseWatchFace extends WatchFace {
|
||||||
|
|
||||||
@Inject WearUtil wearUtil;
|
@Inject WearUtil wearUtil;
|
||||||
@Inject Persistence persistence;
|
@Inject Persistence persistence;
|
||||||
@Inject AAPSLogger aapsLogger;
|
@Inject AAPSLogger aapsLogger;
|
||||||
|
@Inject RxBus rxBus;
|
||||||
|
@Inject AapsSchedulers aapsSchedulers;
|
||||||
|
@Inject SP sp;
|
||||||
|
|
||||||
public final static IntentFilter INTENT_FILTER;
|
CompositeDisposable disposable = new CompositeDisposable();
|
||||||
|
|
||||||
static {
|
protected EventData.SingleBg singleBg = new EventData.SingleBg(0, "---", "-", "--", "--", "--"
|
||||||
INTENT_FILTER = new IntentFilter();
|
, 0, 0.0, 0.0, 0.0, 0);
|
||||||
INTENT_FILTER.addAction(Intent.ACTION_TIME_TICK);
|
protected EventData.Status status = new EventData.Status("no status", "IOB", "-.--", false, "--g", "-.--U/h", "--", "--", -1, "--", false, 1);
|
||||||
INTENT_FILTER.addAction(Intent.ACTION_TIMEZONE_CHANGED);
|
protected EventData.TreatmentData treatmentData = new EventData.TreatmentData(
|
||||||
INTENT_FILTER.addAction(Intent.ACTION_TIME_CHANGED);
|
new ArrayList<>(),
|
||||||
}
|
new ArrayList<>(),
|
||||||
|
new ArrayList<>(),
|
||||||
|
new ArrayList<>()
|
||||||
|
);
|
||||||
|
protected EventData.GraphData graphData = new EventData.GraphData(new ArrayList<>());
|
||||||
|
|
||||||
static IntentFilter iFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
|
static IntentFilter iFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
|
||||||
|
|
||||||
|
@ -96,7 +105,6 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
public int pointSize = 2;
|
public int pointSize = 2;
|
||||||
public BgGraphBuilder bgGraphBuilder;
|
public BgGraphBuilder bgGraphBuilder;
|
||||||
public LineChartView chart;
|
public LineChartView chart;
|
||||||
public RawDisplayData rawData;
|
|
||||||
public PowerManager.WakeLock wakeLock;
|
public PowerManager.WakeLock wakeLock;
|
||||||
// related endTime manual layout
|
// related endTime manual layout
|
||||||
public View layoutView;
|
public View layoutView;
|
||||||
|
@ -104,9 +112,6 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
public boolean forceSquareCanvas = false; // Set to true by the Steampunk watch face.
|
public boolean forceSquareCanvas = false; // Set to true by the Steampunk watch face.
|
||||||
public String sMinute = "0";
|
public String sMinute = "0";
|
||||||
public String sHour = "0";
|
public String sHour = "0";
|
||||||
protected SharedPreferences sharedPrefs;
|
|
||||||
private LocalBroadcastManager localBroadcastManager;
|
|
||||||
private MessageReceiver messageReceiver;
|
|
||||||
private BroadcastReceiver batteryReceiver;
|
private BroadcastReceiver batteryReceiver;
|
||||||
private int colorDarkHigh, colorDarkMid, colorDarkLow;
|
private int colorDarkHigh, colorDarkMid, colorDarkLow;
|
||||||
private java.text.DateFormat timeFormat;
|
private java.text.DateFormat timeFormat;
|
||||||
|
@ -126,7 +131,6 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
colorDarkMid = ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor);
|
colorDarkMid = ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor);
|
||||||
colorDarkLow = ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor);
|
colorDarkLow = ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor);
|
||||||
|
|
||||||
rawData = new RawDisplayData(wearUtil);
|
|
||||||
Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
|
Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
|
||||||
display.getSize(displaySize);
|
display.getSize(displaySize);
|
||||||
wakeLock = ((PowerManager) getSystemService(Context.POWER_SERVICE)).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AndroidAPS:BaseWatchFace");
|
wakeLock = ((PowerManager) getSystemService(Context.POWER_SERVICE)).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AndroidAPS:BaseWatchFace");
|
||||||
|
@ -137,8 +141,49 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
} else {
|
} else {
|
||||||
specH = View.MeasureSpec.makeMeasureSpec(displaySize.y, View.MeasureSpec.EXACTLY);
|
specH = View.MeasureSpec.makeMeasureSpec(displaySize.y, View.MeasureSpec.EXACTLY);
|
||||||
}
|
}
|
||||||
sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
|
|
||||||
sharedPrefs.registerOnSharedPreferenceChangeListener(this);
|
disposable.add(rxBus
|
||||||
|
.toObservable(EventWearPreferenceChange.class)
|
||||||
|
.observeOn(aapsSchedulers.getMain())
|
||||||
|
.subscribe(event -> {
|
||||||
|
setupBatteryReceiver();
|
||||||
|
if (event.getChangedKey() != null && event.getChangedKey().equals("delta_granularity"))
|
||||||
|
rxBus.send(new EventWearToMobile(new EventData.ActionResendData("BaseWatchFace:onSharedPreferenceChanged")));
|
||||||
|
if (layoutSet) setDataFields();
|
||||||
|
invalidate();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
disposable.add(rxBus
|
||||||
|
.toObservable(EventData.SingleBg.class)
|
||||||
|
.observeOn(aapsSchedulers.getMain())
|
||||||
|
.subscribe(event -> singleBg = event)
|
||||||
|
);
|
||||||
|
disposable.add(rxBus
|
||||||
|
.toObservable(EventData.TreatmentData.class)
|
||||||
|
.observeOn(aapsSchedulers.getMain())
|
||||||
|
.subscribe(event -> treatmentData = event)
|
||||||
|
);
|
||||||
|
disposable.add(rxBus
|
||||||
|
.toObservable(EventData.GraphData.class)
|
||||||
|
.observeOn(aapsSchedulers.getMain())
|
||||||
|
.subscribe(event -> graphData = event)
|
||||||
|
);
|
||||||
|
disposable.add(rxBus
|
||||||
|
.toObservable(EventData.Status.class)
|
||||||
|
.observeOn(aapsSchedulers.getMain())
|
||||||
|
.subscribe(event -> {
|
||||||
|
// this event is received as last batch of data
|
||||||
|
if (isSimpleUi()) {
|
||||||
|
if (needUpdate()) {
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setupCharts();
|
||||||
|
setDataFields();
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
persistence.turnOff();
|
persistence.turnOff();
|
||||||
|
|
||||||
|
@ -148,7 +193,7 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupBatteryReceiver() {
|
private void setupBatteryReceiver() {
|
||||||
String setting = sharedPrefs.getString("simplify_ui", "off");
|
String setting = sp.getString("simplify_ui", "off");
|
||||||
if ((setting.equals("charging") || setting.equals("ambient_charging")) && batteryReceiver == null) {
|
if ((setting.equals("charging") || setting.equals("ambient_charging")) && batteryReceiver == null) {
|
||||||
IntentFilter intentBatteryFilter = new IntentFilter();
|
IntentFilter intentBatteryFilter = new IntentFilter();
|
||||||
intentBatteryFilter.addAction(BatteryManager.ACTION_CHARGING);
|
intentBatteryFilter.addAction(BatteryManager.ACTION_CHARGING);
|
||||||
|
@ -215,11 +260,6 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
|
|
||||||
public void performViewSetup() {
|
public void performViewSetup() {
|
||||||
final WatchViewStub layoutStub = layoutView.findViewById(R.id.watch_view_stub);
|
final WatchViewStub layoutStub = layoutView.findViewById(R.id.watch_view_stub);
|
||||||
IntentFilter messageFilter = new IntentFilter(Intent.ACTION_SEND);
|
|
||||||
|
|
||||||
messageReceiver = new MessageReceiver();
|
|
||||||
localBroadcastManager = LocalBroadcastManager.getInstance(this);
|
|
||||||
localBroadcastManager.registerReceiver(messageReceiver, messageFilter);
|
|
||||||
|
|
||||||
layoutStub.setOnLayoutInflatedListener((WatchViewStub stub) -> {
|
layoutStub.setOnLayoutInflatedListener((WatchViewStub stub) -> {
|
||||||
mTime = stub.findViewById(R.id.watch_time);
|
mTime = stub.findViewById(R.id.watch_time);
|
||||||
|
@ -274,11 +314,11 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
}
|
}
|
||||||
|
|
||||||
public double timeSince() {
|
public double timeSince() {
|
||||||
return System.currentTimeMillis() - rawData.datetime;
|
return System.currentTimeMillis() - singleBg.getTimeStamp();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String readingAge(boolean shortString) {
|
public String readingAge(boolean shortString) {
|
||||||
if (rawData.datetime == 0) {
|
if (singleBg.getTimeStamp() == 0) {
|
||||||
return shortString ? "--" : "-- Minute ago";
|
return shortString ? "--" : "-- Minute ago";
|
||||||
}
|
}
|
||||||
int minutesAgo = (int) Math.floor(timeSince() / (1000 * 60));
|
int minutesAgo = (int) Math.floor(timeSince() / (1000 * 60));
|
||||||
|
@ -290,12 +330,7 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
if (localBroadcastManager != null && messageReceiver != null) {
|
disposable.clear();
|
||||||
localBroadcastManager.unregisterReceiver(messageReceiver);
|
|
||||||
}
|
|
||||||
if (sharedPrefs != null) {
|
|
||||||
sharedPrefs.unregisterOnSharedPreferenceChangeListener(this);
|
|
||||||
}
|
|
||||||
if (batteryReceiver != null) {
|
if (batteryReceiver != null) {
|
||||||
unregisterReceiver(batteryReceiver);
|
unregisterReceiver(batteryReceiver);
|
||||||
}
|
}
|
||||||
|
@ -326,16 +361,16 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
float xHalf = displaySize.x / 2f;
|
float xHalf = displaySize.x / 2f;
|
||||||
float yThird = displaySize.y / 3f;
|
float yThird = displaySize.y / 3f;
|
||||||
|
|
||||||
boolean isOutdated = rawData.datetime > 0 && ageLevel() <= 0;
|
boolean isOutdated = singleBg.getTimeStamp() > 0 && ageLevel() <= 0;
|
||||||
mSvgPaint.setStrikeThruText(isOutdated);
|
mSvgPaint.setStrikeThruText(isOutdated);
|
||||||
|
|
||||||
mSvgPaint.setColor(getBgColour(rawData.sgvLevel));
|
mSvgPaint.setColor(getBgColour(singleBg.getSgvLevel()));
|
||||||
mDirectionPaint.setColor(getBgColour(rawData.sgvLevel));
|
mDirectionPaint.setColor(getBgColour(singleBg.getSgvLevel()));
|
||||||
|
|
||||||
String sSvg = rawData.sSgv;
|
String sSvg = singleBg.getSgvString();
|
||||||
float svgWidth = mSvgPaint.measureText(sSvg);
|
float svgWidth = mSvgPaint.measureText(sSvg);
|
||||||
|
|
||||||
String sDirection = " " + rawData.sDirection + "\uFE0E";
|
String sDirection = " " + singleBg.getSgvString() + "\uFE0E";
|
||||||
float directionWidth = mDirectionPaint.measureText(sDirection);
|
float directionWidth = mDirectionPaint.measureText(sDirection);
|
||||||
|
|
||||||
float xSvg = xHalf - (svgWidth + directionWidth) / 2;
|
float xSvg = xHalf - (svgWidth + directionWidth) / 2;
|
||||||
|
@ -382,7 +417,7 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkVibrateHourly(WatchFaceTime oldTime, WatchFaceTime newTime) {
|
private void checkVibrateHourly(WatchFaceTime oldTime, WatchFaceTime newTime) {
|
||||||
boolean hourlyVibratePref = sharedPrefs.getBoolean("vibrate_Hourly", false);
|
boolean hourlyVibratePref = sp.getBoolean("vibrate_Hourly", false);
|
||||||
if (hourlyVibratePref && layoutSet && newTime.hasHourChanged(oldTime)) {
|
if (hourlyVibratePref && layoutSet && newTime.hasHourChanged(oldTime)) {
|
||||||
aapsLogger.info(LTag.WEAR, "hourlyVibratePref", "true --> " + newTime);
|
aapsLogger.info(LTag.WEAR, "hourlyVibratePref", "true --> " + newTime);
|
||||||
Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
|
Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
|
||||||
|
@ -394,8 +429,8 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
public void setDataFields() {
|
public void setDataFields() {
|
||||||
setDateAndTime();
|
setDateAndTime();
|
||||||
if (mSgv != null) {
|
if (mSgv != null) {
|
||||||
if (sharedPrefs.getBoolean("showBG", true)) {
|
if (sp.getBoolean("showBG", true)) {
|
||||||
mSgv.setText(rawData.sSgv);
|
mSgv.setText(singleBg.getSgvString());
|
||||||
mSgv.setVisibility(View.VISIBLE);
|
mSgv.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
// Leave the textview there but invisible, as a height holder for the empty space above the white line
|
// Leave the textview there but invisible, as a height holder for the empty space above the white line
|
||||||
|
@ -407,8 +442,8 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
strikeThroughSgvIfNeeded();
|
strikeThroughSgvIfNeeded();
|
||||||
|
|
||||||
if (mDirection != null) {
|
if (mDirection != null) {
|
||||||
if (sharedPrefs.getBoolean("show_direction", true)) {
|
if (sp.getBoolean("show_direction", true)) {
|
||||||
mDirection.setText(rawData.sDirection + "\uFE0E");
|
mDirection.setText(singleBg.getSgvString() + "\uFE0E");
|
||||||
mDirection.setVisibility(View.VISIBLE);
|
mDirection.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
mDirection.setVisibility(View.GONE);
|
mDirection.setVisibility(View.GONE);
|
||||||
|
@ -416,8 +451,8 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mDelta != null) {
|
if (mDelta != null) {
|
||||||
if (sharedPrefs.getBoolean("showDelta", true)) {
|
if (sp.getBoolean("showDelta", true)) {
|
||||||
mDelta.setText(rawData.sDelta);
|
mDelta.setText(singleBg.getDelta());
|
||||||
mDelta.setVisibility(View.VISIBLE);
|
mDelta.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
mDelta.setVisibility(View.GONE);
|
mDelta.setVisibility(View.GONE);
|
||||||
|
@ -425,8 +460,8 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mAvgDelta != null) {
|
if (mAvgDelta != null) {
|
||||||
if (sharedPrefs.getBoolean("showAvgDelta", true)) {
|
if (sp.getBoolean("showAvgDelta", true)) {
|
||||||
mAvgDelta.setText(rawData.sAvgDelta);
|
mAvgDelta.setText(singleBg.getAvgDelta());
|
||||||
mAvgDelta.setVisibility(View.VISIBLE);
|
mAvgDelta.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
mAvgDelta.setVisibility(View.GONE);
|
mAvgDelta.setVisibility(View.GONE);
|
||||||
|
@ -434,8 +469,8 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mCOB1 != null && mCOB2 != null) {
|
if (mCOB1 != null && mCOB2 != null) {
|
||||||
mCOB2.setText(rawData.sCOB2);
|
mCOB2.setText(status.getCob());
|
||||||
if (sharedPrefs.getBoolean("show_cob", true)) {
|
if (sp.getBoolean("show_cob", true)) {
|
||||||
mCOB1.setVisibility(View.VISIBLE);
|
mCOB1.setVisibility(View.VISIBLE);
|
||||||
mCOB2.setVisibility(View.VISIBLE);
|
mCOB2.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
|
@ -444,8 +479,8 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
}
|
}
|
||||||
// Deal with cases where there is only the value shown for COB, and not the label
|
// Deal with cases where there is only the value shown for COB, and not the label
|
||||||
} else if (mCOB2 != null) {
|
} else if (mCOB2 != null) {
|
||||||
mCOB2.setText(rawData.sCOB2);
|
mCOB2.setText(status.getCob());
|
||||||
if (sharedPrefs.getBoolean("show_cob", true)) {
|
if (sp.getBoolean("show_cob", true)) {
|
||||||
mCOB2.setVisibility(View.VISIBLE);
|
mCOB2.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
mCOB2.setVisibility(View.GONE);
|
mCOB2.setVisibility(View.GONE);
|
||||||
|
@ -453,15 +488,15 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mIOB1 != null && mIOB2 != null) {
|
if (mIOB1 != null && mIOB2 != null) {
|
||||||
if (sharedPrefs.getBoolean("show_iob", true)) {
|
if (sp.getBoolean("show_iob", true)) {
|
||||||
mIOB1.setVisibility(View.VISIBLE);
|
mIOB1.setVisibility(View.VISIBLE);
|
||||||
mIOB2.setVisibility(View.VISIBLE);
|
mIOB2.setVisibility(View.VISIBLE);
|
||||||
if (rawData.detailedIOB) {
|
if (status.getDetailedIob()) {
|
||||||
mIOB1.setText(rawData.sIOB1);
|
mIOB1.setText(status.getIobSum());
|
||||||
mIOB2.setText(rawData.sIOB2);
|
mIOB2.setText(status.getIobDetail());
|
||||||
} else {
|
} else {
|
||||||
mIOB1.setText(getString(R.string.activity_IOB));
|
mIOB1.setText(getString(R.string.activity_IOB));
|
||||||
mIOB2.setText(rawData.sIOB1);
|
mIOB2.setText(status.getIobSum());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mIOB1.setVisibility(View.GONE);
|
mIOB1.setVisibility(View.GONE);
|
||||||
|
@ -469,12 +504,12 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
}
|
}
|
||||||
// Deal with cases where there is only the value shown for IOB, and not the label
|
// Deal with cases where there is only the value shown for IOB, and not the label
|
||||||
} else if (mIOB2 != null) {
|
} else if (mIOB2 != null) {
|
||||||
if (sharedPrefs.getBoolean("show_iob", true)) {
|
if (sp.getBoolean("show_iob", true)) {
|
||||||
mIOB2.setVisibility(View.VISIBLE);
|
mIOB2.setVisibility(View.VISIBLE);
|
||||||
if (rawData.detailedIOB) {
|
if (status.getDetailedIob()) {
|
||||||
mIOB2.setText(rawData.sIOB2);
|
mIOB2.setText(status.getIobDetail());
|
||||||
} else {
|
} else {
|
||||||
mIOB2.setText(rawData.sIOB1);
|
mIOB2.setText(status.getIobSum());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mIOB2.setText("");
|
mIOB2.setText("");
|
||||||
|
@ -482,11 +517,11 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mTimestamp != null) {
|
if (mTimestamp != null) {
|
||||||
if (sharedPrefs.getBoolean("showAgo", true)) {
|
if (sp.getBoolean("showAgo", true)) {
|
||||||
if (isAAPSv2 != null) {
|
if (isAAPSv2 != null) {
|
||||||
mTimestamp.setText(readingAge(true));
|
mTimestamp.setText(readingAge(true));
|
||||||
} else {
|
} else {
|
||||||
boolean shortString = sharedPrefs.getBoolean("showExternalStatus", true);
|
boolean shortString = sp.getBoolean("showExternalStatus", true);
|
||||||
mTimestamp.setText(readingAge(shortString));
|
mTimestamp.setText(readingAge(shortString));
|
||||||
}
|
}
|
||||||
mTimestamp.setVisibility(View.VISIBLE);
|
mTimestamp.setVisibility(View.VISIBLE);
|
||||||
|
@ -496,15 +531,15 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mUploaderBattery != null) {
|
if (mUploaderBattery != null) {
|
||||||
if (sharedPrefs.getBoolean("show_uploader_battery", true)) {
|
if (sp.getBoolean("show_uploader_battery", true)) {
|
||||||
if (isAAPSv2 != null) {
|
if (isAAPSv2 != null) {
|
||||||
mUploaderBattery.setText(rawData.sUploaderBattery + "%");
|
mUploaderBattery.setText(status.getBattery() + "%");
|
||||||
mUploaderBattery.setVisibility(View.VISIBLE);
|
mUploaderBattery.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
if (sharedPrefs.getBoolean("showExternalStatus", true)) {
|
if (sp.getBoolean("showExternalStatus", true)) {
|
||||||
mUploaderBattery.setText("U: " + rawData.sUploaderBattery + "%");
|
mUploaderBattery.setText("U: " + status.getBattery() + "%");
|
||||||
} else {
|
} else {
|
||||||
mUploaderBattery.setText("Uploader: " + rawData.sUploaderBattery + "%");
|
mUploaderBattery.setText("Uploader: " + status.getBattery() + "%");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -513,8 +548,8 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mRigBattery != null) {
|
if (mRigBattery != null) {
|
||||||
if (sharedPrefs.getBoolean("show_rig_battery", false)) {
|
if (sp.getBoolean("show_rig_battery", false)) {
|
||||||
mRigBattery.setText(rawData.sRigBattery);
|
mRigBattery.setText(status.getRigBattery());
|
||||||
mRigBattery.setVisibility(View.VISIBLE);
|
mRigBattery.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
mRigBattery.setVisibility(View.GONE);
|
mRigBattery.setVisibility(View.GONE);
|
||||||
|
@ -522,8 +557,8 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mBasalRate != null) {
|
if (mBasalRate != null) {
|
||||||
if (sharedPrefs.getBoolean("show_temp_basal", true)) {
|
if (sp.getBoolean("show_temp_basal", true)) {
|
||||||
mBasalRate.setText(rawData.sBasalRate);
|
mBasalRate.setText(status.getCurrentBasal());
|
||||||
mBasalRate.setVisibility(View.VISIBLE);
|
mBasalRate.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
mBasalRate.setVisibility(View.GONE);
|
mBasalRate.setVisibility(View.GONE);
|
||||||
|
@ -531,8 +566,8 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mBgi != null) {
|
if (mBgi != null) {
|
||||||
if (rawData.showBGI) {
|
if (status.getShowBgi()) {
|
||||||
mBgi.setText(rawData.sBgi);
|
mBgi.setText(status.getBgi());
|
||||||
mBgi.setVisibility(View.VISIBLE);
|
mBgi.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
mBgi.setVisibility(View.GONE);
|
mBgi.setVisibility(View.GONE);
|
||||||
|
@ -540,8 +575,8 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mStatus != null) {
|
if (mStatus != null) {
|
||||||
if (sharedPrefs.getBoolean("showExternalStatus", true)) {
|
if (sp.getBoolean("showExternalStatus", true)) {
|
||||||
mStatus.setText(rawData.externalStatusString);
|
mStatus.setText(status.getExternalStatus());
|
||||||
mStatus.setVisibility(View.VISIBLE);
|
mStatus.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
mStatus.setVisibility(View.GONE);
|
mStatus.setVisibility(View.GONE);
|
||||||
|
@ -549,10 +584,10 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mLoop != null) {
|
if (mLoop != null) {
|
||||||
if (sharedPrefs.getBoolean("showExternalStatus", true)) {
|
if (sp.getBoolean("showExternalStatus", true)) {
|
||||||
mLoop.setVisibility(View.VISIBLE);
|
mLoop.setVisibility(View.VISIBLE);
|
||||||
if (rawData.openApsStatus != -1) {
|
if (status.getOpenApsStatus() != -1) {
|
||||||
int mins = (int) ((System.currentTimeMillis() - rawData.openApsStatus) / 1000 / 60);
|
int mins = (int) ((System.currentTimeMillis() - status.getOpenApsStatus()) / 1000 / 60);
|
||||||
mLoop.setText(mins + "'");
|
mLoop.setText(mins + "'");
|
||||||
if (mins > 14) {
|
if (mins > 14) {
|
||||||
loopLevel = 0;
|
loopLevel = 0;
|
||||||
|
@ -605,7 +640,7 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mDate != null && mDay != null && mMonth != null) {
|
if (mDate != null && mDay != null && mMonth != null) {
|
||||||
if (sharedPrefs.getBoolean("show_date", false)) {
|
if (sp.getBoolean("show_date", false)) {
|
||||||
if (mDayName != null) {
|
if (mDayName != null) {
|
||||||
mDayName.setText(sdfDayName.format(mDateTime));
|
mDayName.setText(sdfDayName.format(mDateTime));
|
||||||
}
|
}
|
||||||
|
@ -620,10 +655,10 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setColor() {
|
public void setColor() {
|
||||||
dividerMatchesBg = sharedPrefs.getBoolean("match_divider", false);
|
dividerMatchesBg = sp.getBoolean("match_divider", false);
|
||||||
if (lowResMode) {
|
if (lowResMode) {
|
||||||
setColorLowRes();
|
setColorLowRes();
|
||||||
} else if (sharedPrefs.getBoolean("dark", true)) {
|
} else if (sp.getBoolean("dark", true)) {
|
||||||
setColorDark();
|
setColorDark();
|
||||||
} else {
|
} else {
|
||||||
setColorBright();
|
setColorBright();
|
||||||
|
@ -632,8 +667,8 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
|
|
||||||
public void strikeThroughSgvIfNeeded() {
|
public void strikeThroughSgvIfNeeded() {
|
||||||
if (mSgv != null) {
|
if (mSgv != null) {
|
||||||
if (sharedPrefs.getBoolean("showBG", true)) {
|
if (sp.getBoolean("showBG", true)) {
|
||||||
if (ageLevel() <= 0 && rawData.datetime > 0) {
|
if (ageLevel() <= 0 && singleBg.getTimeStamp() > 0) {
|
||||||
mSgv.setPaintFlags(mSgv.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
|
mSgv.setPaintFlags(mSgv.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
|
||||||
} else {
|
} else {
|
||||||
mSgv.setPaintFlags(mSgv.getPaintFlags() & ~Paint.STRIKE_THRU_TEXT_FLAG);
|
mSgv.setPaintFlags(mSgv.getPaintFlags() & ~Paint.STRIKE_THRU_TEXT_FLAG);
|
||||||
|
@ -664,7 +699,7 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSimpleUi() {
|
private boolean isSimpleUi() {
|
||||||
String simplify = sharedPrefs.getString("simplify_ui", "off");
|
String simplify = sp.getString("simplify_ui", "off");
|
||||||
if (simplify.equals("off")) {
|
if (simplify.equals("off")) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -674,18 +709,6 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
return (simplify.equals("charging") || simplify.equals("ambient_charging")) && isCharging();
|
return (simplify.equals("charging") || simplify.equals("ambient_charging")) && isCharging();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
|
||||||
setupBatteryReceiver();
|
|
||||||
if ("delta_granularity".equals(key)) {
|
|
||||||
DataLayerListenerService.Companion.requestData(this);
|
|
||||||
}
|
|
||||||
if (layoutSet) {
|
|
||||||
setDataFields();
|
|
||||||
}
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract void setColorDark();
|
protected abstract void setColorDark();
|
||||||
|
|
||||||
protected abstract void setColorBright();
|
protected abstract void setColorBright();
|
||||||
|
@ -694,8 +717,9 @@ 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 (singleBg.getTimeStamp() == 0 || minutes_since >= 16 && ((minutes_since - 16) % 5) == 0) {
|
||||||
DataLayerListenerService.Companion.requestData(this); // Attempt endTime recover missing data
|
// Attempt endTime recover missing data
|
||||||
|
rxBus.send(new EventWearToMobile(new EventData.ActionResendData("BaseWatchFace:missedReadingAlert")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -703,12 +727,12 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
if (isSimpleUi()) {
|
if (isSimpleUi()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (rawData.bgDataList.size() > 0) { // Dont crash things just because we dont have values, people dont like crashy things
|
if (chart != null && graphData.getEntries().size() > 0) {
|
||||||
int timeframe = Integer.parseInt(sharedPrefs.getString("chart_timeframe", "3"));
|
int timeframe = sp.getInt("chart_timeframe", 3);
|
||||||
if (lowResMode) {
|
if (lowResMode) {
|
||||||
bgGraphBuilder = new BgGraphBuilder(getApplicationContext(), rawData, pointSize, midColor, gridColor, basalBackgroundColor, basalCenterColor, bolusColor, Color.GREEN, timeframe);
|
bgGraphBuilder = new BgGraphBuilder(getApplicationContext(), graphData.getEntries(), treatmentData.getPredictions(), treatmentData.getTemps(), treatmentData.getBasals(), treatmentData.getBoluses(), pointSize, midColor, gridColor, basalBackgroundColor, basalCenterColor, bolusColor, Color.GREEN, timeframe);
|
||||||
} else {
|
} else {
|
||||||
bgGraphBuilder = new BgGraphBuilder(getApplicationContext(), rawData, pointSize, highColor, lowColor, midColor, gridColor, basalBackgroundColor, basalCenterColor, bolusColor, Color.GREEN, timeframe);
|
bgGraphBuilder = new BgGraphBuilder(getApplicationContext(), graphData.getEntries(), treatmentData.getPredictions(), treatmentData.getTemps(), treatmentData.getBasals(), treatmentData.getBoluses(), pointSize, highColor, lowColor, midColor, gridColor, basalBackgroundColor, basalCenterColor, bolusColor, Color.GREEN, timeframe);
|
||||||
}
|
}
|
||||||
|
|
||||||
chart.setLineChartData(bgGraphBuilder.lineData());
|
chart.setLineChartData(bgGraphBuilder.lineData());
|
||||||
|
@ -717,39 +741,12 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class MessageReceiver extends BroadcastReceiver {
|
|
||||||
@Override
|
|
||||||
public void onReceive(Context context, Intent intent) {
|
|
||||||
PowerManager.WakeLock wl = wearUtil.getWakeLock("readingPrefs", 50);
|
|
||||||
|
|
||||||
final DataMap dataMap = rawData.updateDataFromMessage(intent, wakeLock);
|
|
||||||
if (chart != null && dataMap != null) {
|
|
||||||
rawData.addToWatchSet(dataMap);
|
|
||||||
setupCharts();
|
|
||||||
}
|
|
||||||
rawData.updateStatusFromMessage(intent, wakeLock);
|
|
||||||
rawData.updateBasalsFromMessage(intent);
|
|
||||||
|
|
||||||
if (isSimpleUi()) {
|
|
||||||
if (needUpdate()) {
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
setupCharts();
|
|
||||||
setDataFields();
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
wearUtil.releaseWakeLock(wl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean needUpdate() {
|
private boolean needUpdate() {
|
||||||
if (mLastSvg.equals(rawData.sSgv) && mLastDirection.equals(rawData.sDirection)) {
|
if (mLastSvg.equals(singleBg.getSgvString()) && mLastDirection.equals(singleBg.getSgvString())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
mLastSvg = rawData.sSgv;
|
mLastSvg = singleBg.getSgvString();
|
||||||
mLastDirection = rawData.sDirection;
|
mLastDirection = singleBg.getSgvString();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,17 +14,12 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
import info.nightscout.androidaps.data.BasalWatchData;
|
import info.nightscout.shared.weardata.EventData;
|
||||||
import info.nightscout.androidaps.data.BgWatchData;
|
|
||||||
import info.nightscout.androidaps.data.BolusWatchData;
|
|
||||||
import info.nightscout.androidaps.data.RawDisplayData;
|
|
||||||
import info.nightscout.androidaps.data.TempWatchData;
|
|
||||||
import lecho.lib.hellocharts.model.Axis;
|
import lecho.lib.hellocharts.model.Axis;
|
||||||
import lecho.lib.hellocharts.model.AxisValue;
|
import lecho.lib.hellocharts.model.AxisValue;
|
||||||
import lecho.lib.hellocharts.model.Line;
|
import lecho.lib.hellocharts.model.Line;
|
||||||
import lecho.lib.hellocharts.model.LineChartData;
|
import lecho.lib.hellocharts.model.LineChartData;
|
||||||
import lecho.lib.hellocharts.model.PointValue;
|
import lecho.lib.hellocharts.model.PointValue;
|
||||||
import lecho.lib.hellocharts.model.Viewport;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by emmablack on 11/15/14.
|
* Created by emmablack on 11/15/14.
|
||||||
|
@ -33,10 +28,10 @@ public class BgGraphBuilder {
|
||||||
public static final double MAX_PREDICTION__TIME_RATIO = (3d / 5);
|
public static final double MAX_PREDICTION__TIME_RATIO = (3d / 5);
|
||||||
public static final double UPPER_CUTOFF_SGV = 400;
|
public static final double UPPER_CUTOFF_SGV = 400;
|
||||||
private final long predictionEndTime;
|
private final long predictionEndTime;
|
||||||
private final List<BgWatchData> predictionsList;
|
private final List<EventData.SingleBg> predictionsList;
|
||||||
private final ArrayList<BolusWatchData> bolusWatchDataList;
|
private final ArrayList<EventData.TreatmentData.Treatment> bolusWatchDataList;
|
||||||
private final ArrayList<BasalWatchData> basalWatchDataList;
|
private final ArrayList<EventData.TreatmentData.Basal> basalWatchDataList;
|
||||||
public List<TempWatchData> tempWatchDataList;
|
public List<EventData.TreatmentData.TempBasal> tempWatchDataList;
|
||||||
private final int timespan;
|
private final int timespan;
|
||||||
public long end_time;
|
public long end_time;
|
||||||
public long start_time;
|
public long start_time;
|
||||||
|
@ -44,7 +39,7 @@ public class BgGraphBuilder {
|
||||||
public Context context;
|
public Context context;
|
||||||
public double highMark;
|
public double highMark;
|
||||||
public double lowMark;
|
public double lowMark;
|
||||||
public List<BgWatchData> bgDataList = new ArrayList<BgWatchData>();
|
public List<EventData.SingleBg> bgDataList;
|
||||||
|
|
||||||
public int pointSize;
|
public int pointSize;
|
||||||
public int highColor;
|
public int highColor;
|
||||||
|
@ -58,20 +53,24 @@ public class BgGraphBuilder {
|
||||||
|
|
||||||
public boolean singleLine = false;
|
public boolean singleLine = false;
|
||||||
|
|
||||||
private final List<PointValue> inRangeValues = new ArrayList<PointValue>();
|
private final List<PointValue> inRangeValues = new ArrayList<>();
|
||||||
private final List<PointValue> highValues = new ArrayList<PointValue>();
|
private final List<PointValue> highValues = new ArrayList<>();
|
||||||
private final List<PointValue> lowValues = new ArrayList<PointValue>();
|
private final List<PointValue> lowValues = new ArrayList<>();
|
||||||
public Viewport viewport;
|
|
||||||
|
|
||||||
|
|
||||||
//used for low resolution screen.
|
//used for low resolution screen.
|
||||||
public BgGraphBuilder(Context context, List<BgWatchData> aBgList, List<BgWatchData> predictionsList, List<TempWatchData> tempWatchDataList, ArrayList<BasalWatchData> basalWatchDataList, ArrayList<BolusWatchData> bolusWatchDataList, int aPointSize, int aMidColor, int gridColour, int basalBackgroundColor, int basalCenterColor, int bolusInvalidColor, int carbsColor, int timespan) {
|
public BgGraphBuilder(Context context, List<EventData.SingleBg> aBgList,
|
||||||
this.start_time = System.currentTimeMillis() - (1000 * 60 * 60 * timespan); //timespan hours ago
|
List<EventData.SingleBg> predictionsList,
|
||||||
|
List<EventData.TreatmentData.TempBasal> tempWatchDataList,
|
||||||
|
ArrayList<EventData.TreatmentData.Basal> basalWatchDataList,
|
||||||
|
ArrayList<EventData.TreatmentData.Treatment> bolusWatchDataList,
|
||||||
|
int aPointSize, int aMidColor, int gridColour, int basalBackgroundColor, int basalCenterColor, int bolusInvalidColor, int carbsColor, int timespan) {
|
||||||
|
this.start_time = System.currentTimeMillis() - (1000L * 60 * 60 * timespan); //timespan
|
||||||
|
// hours ago
|
||||||
this.bgDataList = aBgList;
|
this.bgDataList = aBgList;
|
||||||
this.predictionsList = predictionsList;
|
this.predictionsList = predictionsList;
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.highMark = aBgList.get(aBgList.size() - 1).high;
|
this.highMark = aBgList.get(aBgList.size() - 1).getHigh();
|
||||||
this.lowMark = aBgList.get(aBgList.size() - 1).low;
|
this.lowMark = aBgList.get(aBgList.size() - 1).getLow();
|
||||||
this.pointSize = aPointSize;
|
this.pointSize = aPointSize;
|
||||||
this.singleLine = false;
|
this.singleLine = false;
|
||||||
this.midColor = aMidColor;
|
this.midColor = aMidColor;
|
||||||
|
@ -80,24 +79,31 @@ public class BgGraphBuilder {
|
||||||
this.timespan = timespan;
|
this.timespan = timespan;
|
||||||
this.tempWatchDataList = tempWatchDataList;
|
this.tempWatchDataList = tempWatchDataList;
|
||||||
this.basalWatchDataList = basalWatchDataList;
|
this.basalWatchDataList = basalWatchDataList;
|
||||||
this.bolusWatchDataList = (bolusWatchDataList!=null)?bolusWatchDataList:new ArrayList<BolusWatchData>();
|
this.bolusWatchDataList = (bolusWatchDataList != null) ? bolusWatchDataList : new ArrayList<>();
|
||||||
this.gridColour = gridColour;
|
this.gridColour = gridColour;
|
||||||
this.basalCenterColor = basalCenterColor;
|
this.basalCenterColor = basalCenterColor;
|
||||||
this.basalBackgroundColor = basalBackgroundColor;
|
this.basalBackgroundColor = basalBackgroundColor;
|
||||||
this.bolusInvalidColor = bolusInvalidColor;
|
this.bolusInvalidColor = bolusInvalidColor;
|
||||||
this.carbsColor = carbsColor;
|
this.carbsColor = carbsColor;
|
||||||
this.end_time = System.currentTimeMillis() + (1000 * 60 * 6 * timespan); //Now plus 30 minutes padding (for 5 hours. Less if less.)
|
this.end_time = System.currentTimeMillis() + (1000L * 60 * 6 * timespan); //Now plus 30
|
||||||
|
// minutes padding (for 5 hours. Less if less.)
|
||||||
this.predictionEndTime = getPredictionEndTime();
|
this.predictionEndTime = getPredictionEndTime();
|
||||||
this.end_time = (predictionEndTime>end_time)?predictionEndTime:end_time;
|
this.end_time = Math.max(predictionEndTime, end_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BgGraphBuilder(Context context, List<BgWatchData> aBgList, List<BgWatchData> predictionsList, List<TempWatchData> tempWatchDataList, ArrayList<BasalWatchData> basalWatchDataList, ArrayList<BolusWatchData> bolusWatchDataList, int aPointSize, int aHighColor, int aLowColor, int aMidColor, int gridColour, int basalBackgroundColor, int basalCenterColor, int bolusInvalidColor, int carbsColor, int timespan) {
|
public BgGraphBuilder(Context context, List<EventData.SingleBg> aBgList,
|
||||||
this.start_time = System.currentTimeMillis() - (1000 * 60 * 60 * timespan); //timespan hours ago
|
List<EventData.SingleBg> predictionsList,
|
||||||
|
List<EventData.TreatmentData.TempBasal> tempWatchDataList,
|
||||||
|
ArrayList<EventData.TreatmentData.Basal> basalWatchDataList,
|
||||||
|
ArrayList<EventData.TreatmentData.Treatment> bolusWatchDataList,
|
||||||
|
int aPointSize, int aHighColor, int aLowColor, int aMidColor, int gridColour, int basalBackgroundColor, int basalCenterColor, int bolusInvalidColor, int carbsColor, int timespan) {
|
||||||
|
this.start_time = System.currentTimeMillis() - (1000L * 60 * 60 * timespan); //timespan
|
||||||
|
// hours ago
|
||||||
this.bgDataList = aBgList;
|
this.bgDataList = aBgList;
|
||||||
this.predictionsList = predictionsList;
|
this.predictionsList = predictionsList;
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.highMark = aBgList.get(aBgList.size() - 1).high;
|
this.highMark = aBgList.get(aBgList.size() - 1).getHigh();
|
||||||
this.lowMark = aBgList.get(aBgList.size() - 1).low;
|
this.lowMark = aBgList.get(aBgList.size() - 1).getLow();
|
||||||
this.pointSize = aPointSize;
|
this.pointSize = aPointSize;
|
||||||
this.highColor = aHighColor;
|
this.highColor = aHighColor;
|
||||||
this.lowColor = aLowColor;
|
this.lowColor = aLowColor;
|
||||||
|
@ -105,51 +111,16 @@ public class BgGraphBuilder {
|
||||||
this.timespan = timespan;
|
this.timespan = timespan;
|
||||||
this.tempWatchDataList = tempWatchDataList;
|
this.tempWatchDataList = tempWatchDataList;
|
||||||
this.basalWatchDataList = basalWatchDataList;
|
this.basalWatchDataList = basalWatchDataList;
|
||||||
this.bolusWatchDataList = (bolusWatchDataList!=null)?bolusWatchDataList:new ArrayList<BolusWatchData>();
|
this.bolusWatchDataList = (bolusWatchDataList != null) ? bolusWatchDataList : new ArrayList<>();
|
||||||
this.gridColour = gridColour;
|
this.gridColour = gridColour;
|
||||||
this.basalCenterColor = basalCenterColor;
|
this.basalCenterColor = basalCenterColor;
|
||||||
this.basalBackgroundColor = basalBackgroundColor;
|
this.basalBackgroundColor = basalBackgroundColor;
|
||||||
this.bolusInvalidColor = bolusInvalidColor;
|
this.bolusInvalidColor = bolusInvalidColor;
|
||||||
this.carbsColor = carbsColor;
|
this.carbsColor = carbsColor;
|
||||||
this.end_time = System.currentTimeMillis() + (1000 * 60 * 6 * timespan); //Now plus 30 minutes padding (for 5 hours. Less if less.)
|
this.end_time = System.currentTimeMillis() + (1000L * 60 * 6 * timespan); //Now plus 30
|
||||||
|
// minutes padding (for 5 hours. Less if less.)
|
||||||
this.predictionEndTime = getPredictionEndTime();
|
this.predictionEndTime = getPredictionEndTime();
|
||||||
this.end_time = (predictionEndTime>end_time)?predictionEndTime:end_time;
|
this.end_time = Math.max(predictionEndTime, end_time);
|
||||||
}
|
|
||||||
|
|
||||||
public BgGraphBuilder(Context context, RawDisplayData raw, int aPointSize, int aHighColor, int aLowColor, int aMidColor, int gridColour, int basalBackgroundColor, int basalCenterColor, int bolusInvalidColor, int carbsColor, int timespan) {
|
|
||||||
this(context,
|
|
||||||
raw.bgDataList,
|
|
||||||
raw.predictionList,
|
|
||||||
raw.tempWatchDataList,
|
|
||||||
raw.basalWatchDataList,
|
|
||||||
raw.bolusWatchDataList,
|
|
||||||
aPointSize,
|
|
||||||
aHighColor,
|
|
||||||
aLowColor,
|
|
||||||
aMidColor,
|
|
||||||
gridColour,
|
|
||||||
basalBackgroundColor,
|
|
||||||
basalCenterColor,
|
|
||||||
bolusInvalidColor,
|
|
||||||
carbsColor,
|
|
||||||
timespan);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BgGraphBuilder(Context context, RawDisplayData raw, int aPointSize, int aMidColor, int gridColour, int basalBackgroundColor, int basalCenterColor, int bolusInvalidColor, int carbsColor, int timespan) {
|
|
||||||
this(context,
|
|
||||||
raw.bgDataList,
|
|
||||||
raw.predictionList,
|
|
||||||
raw.tempWatchDataList,
|
|
||||||
raw.basalWatchDataList,
|
|
||||||
raw.bolusWatchDataList,
|
|
||||||
aPointSize,
|
|
||||||
aMidColor,
|
|
||||||
gridColour,
|
|
||||||
basalBackgroundColor,
|
|
||||||
basalCenterColor,
|
|
||||||
bolusInvalidColor,
|
|
||||||
carbsColor,
|
|
||||||
timespan);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LineChartData lineData() {
|
public LineChartData lineData() {
|
||||||
|
@ -162,7 +133,7 @@ public class BgGraphBuilder {
|
||||||
public List<Line> defaultLines() {
|
public List<Line> defaultLines() {
|
||||||
|
|
||||||
addBgReadingValues();
|
addBgReadingValues();
|
||||||
List<Line> lines = new ArrayList<Line>();
|
List<Line> lines = new ArrayList<>();
|
||||||
lines.add(highLine());
|
lines.add(highLine());
|
||||||
lines.add(lowLine());
|
lines.add(lowLine());
|
||||||
lines.add(inRangeValuesLine());
|
lines.add(inRangeValuesLine());
|
||||||
|
@ -172,41 +143,41 @@ public class BgGraphBuilder {
|
||||||
double minChart = lowMark;
|
double minChart = lowMark;
|
||||||
double maxChart = highMark;
|
double maxChart = highMark;
|
||||||
|
|
||||||
for ( BgWatchData bgd:bgDataList) {
|
for (EventData.SingleBg bgd : bgDataList) {
|
||||||
if(bgd.sgv > maxChart){
|
if (bgd.getSgv() > maxChart) {
|
||||||
maxChart = bgd.sgv;
|
maxChart = bgd.getSgv();
|
||||||
}
|
}
|
||||||
if(bgd.sgv < minChart){
|
if (bgd.getSgv() < minChart) {
|
||||||
minChart = bgd.sgv;
|
minChart = bgd.getSgv();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double maxBasal = 0.1;
|
double maxBasal = 0.1;
|
||||||
for (BasalWatchData bwd: basalWatchDataList) {
|
for (EventData.TreatmentData.Basal bwd : basalWatchDataList) {
|
||||||
if(bwd.amount > maxBasal){
|
if (bwd.getAmount() > maxBasal) {
|
||||||
maxBasal = bwd.amount;
|
maxBasal = bwd.getAmount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double maxTemp = maxBasal;
|
double maxTemp = maxBasal;
|
||||||
for (TempWatchData twd: tempWatchDataList) {
|
for (EventData.TreatmentData.TempBasal twd : tempWatchDataList) {
|
||||||
if(twd.amount > maxTemp){
|
if (twd.getAmount() > maxTemp) {
|
||||||
maxTemp = twd.amount;
|
maxTemp = twd.getAmount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double factor = (maxChart-minChart)/maxTemp;
|
double factor = (maxChart - minChart) / maxTemp;
|
||||||
// in case basal is the highest, don't paint it totally at the top.
|
// in case basal is the highest, don't paint it totally at the top.
|
||||||
factor = Math.min(factor, ((maxChart-minChart)/maxBasal)*(2/3d));
|
factor = Math.min(factor, ((maxChart - minChart) / maxBasal) * (2 / 3d));
|
||||||
|
|
||||||
boolean highlight = PreferenceManager
|
boolean highlight = PreferenceManager
|
||||||
.getDefaultSharedPreferences(context)
|
.getDefaultSharedPreferences(context)
|
||||||
.getBoolean("highlight_basals", false);
|
.getBoolean("highlight_basals", false);
|
||||||
|
|
||||||
for (TempWatchData twd: tempWatchDataList) {
|
for (EventData.TreatmentData.TempBasal twd : tempWatchDataList) {
|
||||||
if(twd.endTime > start_time) {
|
if (twd.getEndTime() > start_time) {
|
||||||
lines.add(tempValuesLine(twd, (float) minChart, factor, false, highlight?(pointSize+1):pointSize));
|
lines.add(tempValuesLine(twd, (float) minChart, factor, false, highlight ? (pointSize + 1) : pointSize));
|
||||||
if(highlight){
|
if (highlight) {
|
||||||
lines.add(tempValuesLine(twd, (float) minChart, factor, true, 1));
|
lines.add(tempValuesLine(twd, (float) minChart, factor, true, 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -224,13 +195,14 @@ public class BgGraphBuilder {
|
||||||
|
|
||||||
private Line basalLine(float offset, double factor, boolean highlight) {
|
private Line basalLine(float offset, double factor, boolean highlight) {
|
||||||
|
|
||||||
List<PointValue> pointValues = new ArrayList<PointValue>();
|
List<PointValue> pointValues = new ArrayList<>();
|
||||||
|
|
||||||
for (BasalWatchData bwd: basalWatchDataList) {
|
for (EventData.TreatmentData.Basal bwd : basalWatchDataList) {
|
||||||
if(bwd.endTime > start_time) {
|
if (bwd.getEndTime() > start_time) {
|
||||||
long begin = Math.max(start_time, bwd.startTime);
|
long begin = Math.max(start_time, bwd.getStartTime());
|
||||||
pointValues.add(new PointValue(fuzz(begin), offset + (float) (factor * bwd.amount)));
|
pointValues.add(new PointValue(fuzz(begin), offset + (float) (factor * bwd.getAmount())));
|
||||||
pointValues.add(new PointValue(fuzz(bwd.endTime), offset + (float) (factor * bwd.amount)));
|
pointValues.add(new PointValue(fuzz(bwd.getEndTime()),
|
||||||
|
offset + (float) (factor * bwd.getAmount())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,7 +210,7 @@ public class BgGraphBuilder {
|
||||||
basalLine.setHasPoints(false);
|
basalLine.setHasPoints(false);
|
||||||
basalLine.setColor(basalCenterColor);
|
basalLine.setColor(basalCenterColor);
|
||||||
basalLine.setPathEffect(new DashPathEffect(new float[]{4f, 3f}, 4f));
|
basalLine.setPathEffect(new DashPathEffect(new float[]{4f, 3f}, 4f));
|
||||||
basalLine.setStrokeWidth(highlight?2:1);
|
basalLine.setStrokeWidth(highlight ? 2 : 1);
|
||||||
return basalLine;
|
return basalLine;
|
||||||
|
|
||||||
|
|
||||||
|
@ -246,28 +218,28 @@ public class BgGraphBuilder {
|
||||||
|
|
||||||
private Line bolusLine(float offset) {
|
private Line bolusLine(float offset) {
|
||||||
|
|
||||||
List<PointValue> pointValues = new ArrayList<PointValue>();
|
List<PointValue> pointValues = new ArrayList<>();
|
||||||
|
|
||||||
for (BolusWatchData bwd: bolusWatchDataList) {
|
for (EventData.TreatmentData.Treatment bwd : bolusWatchDataList) {
|
||||||
if(bwd.date > start_time && bwd.date <= end_time && !bwd.isSMB && bwd.isValid && bwd.bolus > 0) {
|
if (bwd.getDate() > start_time && bwd.getDate() <= end_time && !bwd.isSMB() && bwd.isValid() && bwd.getBolus() > 0) {
|
||||||
pointValues.add(new PointValue(fuzz(bwd.date), offset -2));
|
pointValues.add(new PointValue(fuzz(bwd.getDate()), offset - 2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Line line = new Line(pointValues);
|
Line line = new Line(pointValues);
|
||||||
line.setColor(basalCenterColor);
|
line.setColor(basalCenterColor);
|
||||||
line.setHasLines(false);
|
line.setHasLines(false);
|
||||||
line.setPointRadius(pointSize*2);
|
line.setPointRadius(pointSize * 2);
|
||||||
line.setHasPoints(true);
|
line.setHasPoints(true);
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Line smbLine(float offset) {
|
private Line smbLine(float offset) {
|
||||||
|
|
||||||
List<PointValue> pointValues = new ArrayList<PointValue>();
|
List<PointValue> pointValues = new ArrayList<>();
|
||||||
|
|
||||||
for (BolusWatchData bwd: bolusWatchDataList) {
|
for (EventData.TreatmentData.Treatment bwd : bolusWatchDataList) {
|
||||||
if(bwd.date > start_time && bwd.date <= end_time && bwd.isSMB && bwd.isValid && bwd.bolus > 0) {
|
if (bwd.getDate() > start_time && bwd.getDate() <= end_time && bwd.isSMB() && bwd.isValid() && bwd.getBolus() > 0) {
|
||||||
pointValues.add(new PointValue(fuzz(bwd.date), offset -2));
|
pointValues.add(new PointValue(fuzz(bwd.getDate()), offset - 2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Line line = new Line(pointValues);
|
Line line = new Line(pointValues);
|
||||||
|
@ -280,11 +252,11 @@ public class BgGraphBuilder {
|
||||||
|
|
||||||
private Line bolusInvalidLine(float offset) {
|
private Line bolusInvalidLine(float offset) {
|
||||||
|
|
||||||
List<PointValue> pointValues = new ArrayList<PointValue>();
|
List<PointValue> pointValues = new ArrayList<>();
|
||||||
|
|
||||||
for (BolusWatchData bwd: bolusWatchDataList) {
|
for (EventData.TreatmentData.Treatment bwd : bolusWatchDataList) {
|
||||||
if(bwd.date > start_time && bwd.date <= end_time && !(bwd.isValid && (bwd.bolus > 0 || bwd.carbs > 0))) {
|
if (bwd.getDate() > start_time && bwd.getDate() <= end_time && !(bwd.isValid() && (bwd.getBolus() > 0 || bwd.getCarbs() > 0))) {
|
||||||
pointValues.add(new PointValue(fuzz(bwd.date), offset -2));
|
pointValues.add(new PointValue(fuzz(bwd.getDate()), offset - 2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Line line = new Line(pointValues);
|
Line line = new Line(pointValues);
|
||||||
|
@ -297,17 +269,17 @@ public class BgGraphBuilder {
|
||||||
|
|
||||||
private Line carbsLine(float offset) {
|
private Line carbsLine(float offset) {
|
||||||
|
|
||||||
List<PointValue> pointValues = new ArrayList<PointValue>();
|
List<PointValue> pointValues = new ArrayList<>();
|
||||||
|
|
||||||
for (BolusWatchData bwd: bolusWatchDataList) {
|
for (EventData.TreatmentData.Treatment bwd : bolusWatchDataList) {
|
||||||
if(bwd.date > start_time && bwd.date <= end_time && !bwd.isSMB && bwd.isValid && bwd.carbs > 0) {
|
if (bwd.getDate() > start_time && bwd.getDate() <= end_time && !bwd.isSMB() && bwd.isValid() && bwd.getCarbs() > 0) {
|
||||||
pointValues.add(new PointValue(fuzz(bwd.date), offset +2));
|
pointValues.add(new PointValue(fuzz(bwd.getDate()), offset + 2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Line line = new Line(pointValues);
|
Line line = new Line(pointValues);
|
||||||
line.setColor(carbsColor);
|
line.setColor(carbsColor);
|
||||||
line.setHasLines(false);
|
line.setHasLines(false);
|
||||||
line.setPointRadius(pointSize*2);
|
line.setPointRadius(pointSize * 2);
|
||||||
line.setHasPoints(true);
|
line.setHasPoints(true);
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
@ -316,13 +288,13 @@ public class BgGraphBuilder {
|
||||||
private void addPredictionLines(List<Line> lines) {
|
private void addPredictionLines(List<Line> lines) {
|
||||||
Map<Integer, List<PointValue>> values = new HashMap<>();
|
Map<Integer, List<PointValue>> values = new HashMap<>();
|
||||||
long endTime = getPredictionEndTime();
|
long endTime = getPredictionEndTime();
|
||||||
for (BgWatchData bwd : predictionsList) {
|
for (EventData.SingleBg bwd : predictionsList) {
|
||||||
if (bwd.timestamp <= endTime) {
|
if (bwd.getTimeStamp() <= endTime) {
|
||||||
double value = Math.min(bwd.sgv, UPPER_CUTOFF_SGV);
|
double value = Math.min(bwd.getSgv(), UPPER_CUTOFF_SGV);
|
||||||
if (!values.containsKey(bwd.color)) {
|
if (!values.containsKey(bwd.getColor())) {
|
||||||
values.put(bwd.color, new ArrayList<>());
|
values.put(bwd.getColor(), new ArrayList<>());
|
||||||
}
|
}
|
||||||
values.get(bwd.color).add(new PointValue(fuzz(bwd.timestamp), (float) value));
|
values.get(bwd.getColor()).add(new PointValue(fuzz(bwd.getTimeStamp()), (float) value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (Map.Entry<Integer, List<PointValue>> entry : values.entrySet()) {
|
for (Map.Entry<Integer, List<PointValue>> entry : values.entrySet()) {
|
||||||
|
@ -358,7 +330,7 @@ public class BgGraphBuilder {
|
||||||
public Line inRangeValuesLine() {
|
public Line inRangeValuesLine() {
|
||||||
Line inRangeValuesLine = new Line(inRangeValues);
|
Line inRangeValuesLine = new Line(inRangeValues);
|
||||||
inRangeValuesLine.setColor(midColor);
|
inRangeValuesLine.setColor(midColor);
|
||||||
if(singleLine) {
|
if (singleLine) {
|
||||||
inRangeValuesLine.setHasLines(true);
|
inRangeValuesLine.setHasLines(true);
|
||||||
inRangeValuesLine.setHasPoints(false);
|
inRangeValuesLine.setHasPoints(false);
|
||||||
inRangeValuesLine.setStrokeWidth(pointSize);
|
inRangeValuesLine.setStrokeWidth(pointSize);
|
||||||
|
@ -371,19 +343,19 @@ public class BgGraphBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Line tempValuesLine(TempWatchData twd, float offset, double factor, boolean isHighlightLine, int strokeWidth) {
|
public Line tempValuesLine(EventData.TreatmentData.TempBasal twd, float offset, double factor, boolean isHighlightLine, int strokeWidth) {
|
||||||
List<PointValue> lineValues = new ArrayList<PointValue>();
|
List<PointValue> lineValues = new ArrayList<>();
|
||||||
long begin = Math.max(start_time, twd.startTime);
|
long begin = Math.max(start_time, twd.getStartTime());
|
||||||
lineValues.add(new PointValue(fuzz(begin), offset + (float) (factor * twd.startBasal)));
|
lineValues.add(new PointValue(fuzz(begin), offset + (float) (factor * twd.getStartBasal())));
|
||||||
lineValues.add(new PointValue(fuzz(begin), offset + (float) (factor * twd.amount)));
|
lineValues.add(new PointValue(fuzz(begin), offset + (float) (factor * twd.getAmount())));
|
||||||
lineValues.add(new PointValue(fuzz(twd.endTime), offset + (float) (factor * twd.amount)));
|
lineValues.add(new PointValue(fuzz(twd.getEndTime()), offset + (float) (factor * twd.getAmount())));
|
||||||
lineValues.add(new PointValue(fuzz(twd.endTime), offset + (float) (factor * twd.endBasal)));
|
lineValues.add(new PointValue(fuzz(twd.getEndTime()), offset + (float) (factor * twd.getEndBasal())));
|
||||||
Line valueLine = new Line(lineValues);
|
Line valueLine = new Line(lineValues);
|
||||||
valueLine.setHasPoints(false);
|
valueLine.setHasPoints(false);
|
||||||
if (isHighlightLine){
|
if (isHighlightLine) {
|
||||||
valueLine.setColor(basalCenterColor);
|
valueLine.setColor(basalCenterColor);
|
||||||
valueLine.setStrokeWidth(1);
|
valueLine.setStrokeWidth(1);
|
||||||
}else {
|
} else {
|
||||||
valueLine.setColor(basalBackgroundColor);
|
valueLine.setColor(basalBackgroundColor);
|
||||||
valueLine.setStrokeWidth(strokeWidth);
|
valueLine.setStrokeWidth(strokeWidth);
|
||||||
}
|
}
|
||||||
|
@ -391,38 +363,36 @@ public class BgGraphBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void addBgReadingValues() {
|
private void addBgReadingValues() {
|
||||||
if(singleLine) {
|
if (singleLine) {
|
||||||
for (BgWatchData bgReading : bgDataList) {
|
for (EventData.SingleBg bgReading : bgDataList) {
|
||||||
if(bgReading.timestamp > start_time) {
|
if (bgReading.getTimeStamp() > start_time) {
|
||||||
if (bgReading.sgv >= 450) {
|
if (bgReading.getSgv() >= 450) {
|
||||||
inRangeValues.add(new PointValue(fuzz(bgReading.timestamp), (float) 450));
|
inRangeValues.add(new PointValue(fuzz(bgReading.getTimeStamp()), (float) 450));
|
||||||
} else if (bgReading.sgv >= highMark) {
|
} else if (bgReading.getSgv() >= highMark) {
|
||||||
inRangeValues.add(new PointValue(fuzz(bgReading.timestamp), (float) bgReading.sgv));
|
inRangeValues.add(new PointValue(fuzz(bgReading.getTimeStamp()), (float) bgReading.getSgv()));
|
||||||
} else if (bgReading.sgv >= lowMark) {
|
} else if (bgReading.getSgv() >= lowMark) {
|
||||||
inRangeValues.add(new PointValue(fuzz(bgReading.timestamp), (float) bgReading.sgv));
|
inRangeValues.add(new PointValue(fuzz(bgReading.getTimeStamp()), (float) bgReading.getSgv()));
|
||||||
} else if (bgReading.sgv >= 40) {
|
} else if (bgReading.getSgv() >= 40) {
|
||||||
inRangeValues.add(new PointValue(fuzz(bgReading.timestamp), (float) bgReading.sgv));
|
inRangeValues.add(new PointValue(fuzz(bgReading.getTimeStamp()), (float) bgReading.getSgv()));
|
||||||
} else if (bgReading.sgv >= 11) {
|
} else if (bgReading.getSgv() >= 11) {
|
||||||
inRangeValues.add(new PointValue(fuzz(bgReading.timestamp), (float) 40));
|
inRangeValues.add(new PointValue(fuzz(bgReading.getTimeStamp()), (float) 40));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (BgWatchData bgReading : bgDataList) {
|
for (EventData.SingleBg bgReading : bgDataList) {
|
||||||
if (bgReading.timestamp > start_time) {
|
if (bgReading.getTimeStamp() > start_time) {
|
||||||
if (bgReading.sgv >= 450) {
|
if (bgReading.getSgv() >= 450) {
|
||||||
highValues.add(new PointValue(fuzz(bgReading.timestamp), (float) 450));
|
highValues.add(new PointValue(fuzz(bgReading.getTimeStamp()), (float) 450));
|
||||||
} else if (bgReading.sgv >= highMark) {
|
} else if (bgReading.getSgv() >= highMark) {
|
||||||
highValues.add(new PointValue(fuzz(bgReading.timestamp), (float) bgReading.sgv));
|
highValues.add(new PointValue(fuzz(bgReading.getTimeStamp()), (float) bgReading.getSgv()));
|
||||||
} else if (bgReading.sgv >= lowMark) {
|
} else if (bgReading.getSgv() >= lowMark) {
|
||||||
inRangeValues.add(new PointValue(fuzz(bgReading.timestamp), (float) bgReading.sgv));
|
inRangeValues.add(new PointValue(fuzz(bgReading.getTimeStamp()), (float) bgReading.getSgv()));
|
||||||
} else if (bgReading.sgv >= 40) {
|
} else if (bgReading.getSgv() >= 40) {
|
||||||
lowValues.add(new PointValue(fuzz(bgReading.timestamp), (float) bgReading.sgv));
|
lowValues.add(new PointValue(fuzz(bgReading.getTimeStamp()), (float) bgReading.getSgv()));
|
||||||
} else if (bgReading.sgv >= 11) {
|
} else if (bgReading.getSgv() >= 11) {
|
||||||
lowValues.add(new PointValue(fuzz(bgReading.timestamp), (float) 40));
|
lowValues.add(new PointValue(fuzz(bgReading.getTimeStamp()), (float) 40));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -430,7 +400,7 @@ public class BgGraphBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Line highLine() {
|
public Line highLine() {
|
||||||
List<PointValue> highLineValues = new ArrayList<PointValue>();
|
List<PointValue> highLineValues = new ArrayList<>();
|
||||||
highLineValues.add(new PointValue(fuzz(start_time), (float) highMark));
|
highLineValues.add(new PointValue(fuzz(start_time), (float) highMark));
|
||||||
highLineValues.add(new PointValue(fuzz(end_time), (float) highMark));
|
highLineValues.add(new PointValue(fuzz(end_time), (float) highMark));
|
||||||
Line highLine = new Line(highLineValues);
|
Line highLine = new Line(highLineValues);
|
||||||
|
@ -441,7 +411,7 @@ public class BgGraphBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Line lowLine() {
|
public Line lowLine() {
|
||||||
List<PointValue> lowLineValues = new ArrayList<PointValue>();
|
List<PointValue> lowLineValues = new ArrayList<>();
|
||||||
lowLineValues.add(new PointValue(fuzz(start_time), (float) lowMark));
|
lowLineValues.add(new PointValue(fuzz(start_time), (float) lowMark));
|
||||||
lowLineValues.add(new PointValue(fuzz(end_time), (float) lowMark));
|
lowLineValues.add(new PointValue(fuzz(end_time), (float) lowMark));
|
||||||
Line lowLine = new Line(lowLineValues);
|
Line lowLine = new Line(lowLineValues);
|
||||||
|
@ -457,7 +427,7 @@ public class BgGraphBuilder {
|
||||||
public Axis yAxis() {
|
public Axis yAxis() {
|
||||||
Axis yAxis = new Axis();
|
Axis yAxis = new Axis();
|
||||||
yAxis.setAutoGenerated(true);
|
yAxis.setAutoGenerated(true);
|
||||||
List<AxisValue> axisValues = new ArrayList<AxisValue>();
|
List<AxisValue> axisValues = new ArrayList<>();
|
||||||
yAxis.setValues(axisValues);
|
yAxis.setValues(axisValues);
|
||||||
yAxis.setHasLines(false);
|
yAxis.setHasLines(false);
|
||||||
yAxis.setLineColor(gridColour);
|
yAxis.setLineColor(gridColour);
|
||||||
|
@ -466,13 +436,13 @@ public class BgGraphBuilder {
|
||||||
|
|
||||||
public Axis xAxis() {
|
public Axis xAxis() {
|
||||||
final boolean is24 = DateFormat.is24HourFormat(context);
|
final boolean is24 = DateFormat.is24HourFormat(context);
|
||||||
SimpleDateFormat timeFormat = new SimpleDateFormat(is24? "HH" : "h a");
|
SimpleDateFormat timeFormat = new SimpleDateFormat(is24 ? "HH" : "h a");
|
||||||
timeFormat.setTimeZone(TimeZone.getDefault());
|
timeFormat.setTimeZone(TimeZone.getDefault());
|
||||||
long timeNow = System.currentTimeMillis();
|
long timeNow = System.currentTimeMillis();
|
||||||
|
|
||||||
Axis xAxis = new Axis();
|
Axis xAxis = new Axis();
|
||||||
xAxis.setAutoGenerated(false);
|
xAxis.setAutoGenerated(false);
|
||||||
List<AxisValue> xAxisValues = new ArrayList<AxisValue>();
|
List<AxisValue> xAxisValues = new ArrayList<>();
|
||||||
|
|
||||||
//get the time-tick at the full hour after start_time
|
//get the time-tick at the full hour after start_time
|
||||||
GregorianCalendar startGC = new GregorianCalendar();
|
GregorianCalendar startGC = new GregorianCalendar();
|
||||||
|
@ -484,14 +454,14 @@ public class BgGraphBuilder {
|
||||||
long start_hour = startGC.getTimeInMillis();
|
long start_hour = startGC.getTimeInMillis();
|
||||||
|
|
||||||
//Display current time on the graph
|
//Display current time on the graph
|
||||||
SimpleDateFormat longTimeFormat = new SimpleDateFormat(is24? "HH:mm" : "h:mm a");
|
SimpleDateFormat longTimeFormat = new SimpleDateFormat(is24 ? "HH:mm" : "h:mm a");
|
||||||
xAxisValues.add(new AxisValue(fuzz(timeNow)).setLabel((longTimeFormat.format(timeNow))));
|
xAxisValues.add(new AxisValue(fuzz(timeNow)).setLabel((longTimeFormat.format(timeNow))));
|
||||||
|
|
||||||
long hourTick = start_hour;
|
long hourTick = start_hour;
|
||||||
|
|
||||||
// add all full hours within the timeframe
|
// add all full hours within the timeframe
|
||||||
while (hourTick < end_time){
|
while (hourTick < end_time) {
|
||||||
if(Math.abs(hourTick - timeNow) > (8 * (end_time-start_time)/60)){
|
if (Math.abs(hourTick - timeNow) > (8 * (end_time - start_time) / 60)) {
|
||||||
xAxisValues.add(new AxisValue(fuzz(hourTick)).setLabel(timeFormat.format(hourTick)));
|
xAxisValues.add(new AxisValue(fuzz(hourTick)).setLabel(timeFormat.format(hourTick)));
|
||||||
} else {
|
} else {
|
||||||
//don't print hour label if too close to now to avoid overlaps
|
//don't print hour label if too close to now to avoid overlaps
|
||||||
|
@ -499,7 +469,7 @@ public class BgGraphBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
//increment by one hour
|
//increment by one hour
|
||||||
hourTick += 60*60*1000;
|
hourTick += 60 * 60 * 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
xAxis.setValues(xAxisValues);
|
xAxis.setValues(xAxisValues);
|
||||||
|
@ -513,16 +483,16 @@ public class BgGraphBuilder {
|
||||||
|
|
||||||
public long getPredictionEndTime() {
|
public long getPredictionEndTime() {
|
||||||
long maxPredictionDate = System.currentTimeMillis();
|
long maxPredictionDate = System.currentTimeMillis();
|
||||||
for (BgWatchData prediction :
|
for (EventData.SingleBg prediction :
|
||||||
predictionsList) {
|
predictionsList) {
|
||||||
if (maxPredictionDate < prediction.timestamp) {
|
if (maxPredictionDate < prediction.getTimeStamp()) {
|
||||||
maxPredictionDate = prediction.timestamp;
|
maxPredictionDate = prediction.getTimeStamp();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (long) Math.min(maxPredictionDate, System.currentTimeMillis() + MAX_PREDICTION__TIME_RATIO *timespan*1000*60*60);
|
return (long) Math.min(maxPredictionDate, System.currentTimeMillis() + MAX_PREDICTION__TIME_RATIO * timespan * 1000 * 60 * 60);
|
||||||
}
|
}
|
||||||
|
|
||||||
public float fuzz(long value) {
|
public float fuzz(long value) {
|
||||||
return (float) Math.round(value / fuzzyTimeDenom);
|
return (float) Math.round(value / fuzzyTimeDenom);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +1,15 @@
|
||||||
package info.nightscout.androidaps.watchfaces;
|
package info.nightscout.androidaps.watchfaces;
|
||||||
|
|
||||||
import android.content.BroadcastReceiver;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.LinearGradient;
|
|
||||||
import android.graphics.Matrix;
|
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.Point;
|
import android.graphics.Point;
|
||||||
import android.graphics.RectF;
|
import android.graphics.RectF;
|
||||||
import android.graphics.Shader;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.os.SystemClock;
|
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
|
||||||
import android.support.wearable.watchface.WatchFaceStyle;
|
import android.support.wearable.watchface.WatchFaceStyle;
|
||||||
import android.util.Log;
|
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
import android.view.Display;
|
import android.view.Display;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
@ -27,21 +17,40 @@ import android.view.View;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.google.android.gms.wearable.DataMap;
|
|
||||||
import com.ustwo.clockwise.common.WatchFaceTime;
|
import com.ustwo.clockwise.common.WatchFaceTime;
|
||||||
import com.ustwo.clockwise.wearable.WatchFace;
|
import com.ustwo.clockwise.wearable.WatchFace;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.TreeSet;
|
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import dagger.android.AndroidInjection;
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.data.BgWatchData;
|
import info.nightscout.androidaps.events.EventWearToMobile;
|
||||||
import info.nightscout.androidaps.interaction.menus.MainMenuActivity;
|
import info.nightscout.androidaps.interaction.menus.MainMenuActivity;
|
||||||
|
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||||
|
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.weardata.EventData;
|
||||||
|
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
||||||
|
|
||||||
|
|
||||||
public class CircleWatchface extends WatchFace implements SharedPreferences.OnSharedPreferenceChangeListener {
|
public class CircleWatchface extends WatchFace {
|
||||||
|
|
||||||
|
@Inject RxBus rxBus;
|
||||||
|
@Inject AapsSchedulers aapsSchedulers;
|
||||||
|
@Inject AAPSLogger aapsLogger;
|
||||||
|
@Inject SP sp;
|
||||||
|
|
||||||
|
CompositeDisposable disposable = new CompositeDisposable();
|
||||||
|
|
||||||
|
private EventData.SingleBg singleBg = new EventData.SingleBg(0, "---", "-", "--", "--", "--", 0, 0.0, 0.0, 0.0, 0);
|
||||||
|
private EventData.GraphData graphData;
|
||||||
|
private EventData.Status status = new EventData.Status("no status", "IOB", "-.--", false, "--g", "-.--U/h", "--", "--", -1, "--", false, 1);
|
||||||
|
|
||||||
public final float PADDING = 20f;
|
public final float PADDING = 20f;
|
||||||
public final float CIRCLE_WIDTH = 10f;
|
public final float CIRCLE_WIDTH = 10f;
|
||||||
public final int BIG_HAND_WIDTH = 16;
|
public final int BIG_HAND_WIDTH = 16;
|
||||||
|
@ -52,43 +61,27 @@ public class CircleWatchface extends WatchFace implements SharedPreferences.OnSh
|
||||||
//variables for time
|
//variables for time
|
||||||
private float angleBig = 0f;
|
private float angleBig = 0f;
|
||||||
private float angleSMALL = 0f;
|
private float angleSMALL = 0f;
|
||||||
private int hour, minute;
|
|
||||||
private int color;
|
private int color;
|
||||||
private final Paint circlePaint = new Paint();
|
private final Paint circlePaint = new Paint();
|
||||||
private final Paint removePaint = new Paint();
|
private final Paint removePaint = new Paint();
|
||||||
private RectF rect, rectDelete;
|
private RectF rect, rectDelete;
|
||||||
private boolean overlapping;
|
private boolean overlapping;
|
||||||
|
|
||||||
private int animationAngle = 0;
|
|
||||||
private boolean isAnimated = false;
|
|
||||||
|
|
||||||
|
|
||||||
public Point displaySize = new Point();
|
public Point displaySize = new Point();
|
||||||
private final MessageReceiver messageReceiver = new MessageReceiver();
|
|
||||||
|
|
||||||
private int sgvLevel = 0;
|
public ArrayList<EventData.SingleBg> bgDataList = new ArrayList<>();
|
||||||
private String sgvString = "999";
|
|
||||||
private String statusString = "no status";
|
|
||||||
|
|
||||||
|
|
||||||
private int batteryLevel = 0;
|
|
||||||
private long datetime = 0;
|
|
||||||
private String direction = "";
|
|
||||||
private String delta = "";
|
|
||||||
private String avgDelta = "";
|
|
||||||
public TreeSet<BgWatchData> bgDataList = new TreeSet<>();
|
|
||||||
|
|
||||||
private int specW;
|
private int specW;
|
||||||
private int specH;
|
private int specH;
|
||||||
private View myLayout;
|
private View myLayout;
|
||||||
|
|
||||||
protected SharedPreferences sharedPrefs;
|
|
||||||
private TextView mSgv;
|
private TextView mSgv;
|
||||||
private long sgvTapTime = 0;
|
private long sgvTapTime = 0;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@SuppressLint("InflateParams") @Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
|
AndroidInjection.inject(this);
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
|
|
||||||
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
|
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
|
||||||
|
@ -104,19 +97,46 @@ public class CircleWatchface extends WatchFace implements SharedPreferences.OnSh
|
||||||
specH = View.MeasureSpec.makeMeasureSpec(displaySize.y,
|
specH = View.MeasureSpec.makeMeasureSpec(displaySize.y,
|
||||||
View.MeasureSpec.EXACTLY);
|
View.MeasureSpec.EXACTLY);
|
||||||
|
|
||||||
sharedPrefs = PreferenceManager
|
|
||||||
.getDefaultSharedPreferences(this);
|
|
||||||
sharedPrefs.registerOnSharedPreferenceChangeListener(this);
|
|
||||||
|
|
||||||
//register Message Receiver
|
//register Message Receiver
|
||||||
LocalBroadcastManager.getInstance(this).registerReceiver(messageReceiver, new IntentFilter(Intent.ACTION_SEND));
|
|
||||||
|
|
||||||
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||||
myLayout = inflater.inflate(R.layout.modern_layout, null);
|
myLayout = inflater.inflate(R.layout.modern_layout, null);
|
||||||
prepareLayout();
|
prepareLayout();
|
||||||
prepareDrawTime();
|
prepareDrawTime();
|
||||||
|
|
||||||
//ListenerService.requestData(this); //usually connection is not set up yet
|
disposable.add(rxBus
|
||||||
|
.toObservable(EventData.SingleBg.class)
|
||||||
|
.observeOn(aapsSchedulers.getMain())
|
||||||
|
.subscribe(event -> singleBg = event)
|
||||||
|
);
|
||||||
|
disposable.add(rxBus
|
||||||
|
.toObservable(EventData.GraphData.class)
|
||||||
|
.observeOn(aapsSchedulers.getMain())
|
||||||
|
.subscribe(event -> graphData = event)
|
||||||
|
);
|
||||||
|
disposable.add(rxBus
|
||||||
|
.toObservable(EventData.Status.class)
|
||||||
|
.observeOn(aapsSchedulers.getMain())
|
||||||
|
.subscribe(event -> {
|
||||||
|
// this event is received as last batch of data
|
||||||
|
aapsLogger.debug(LTag.WEAR, "Status received");
|
||||||
|
status = event;
|
||||||
|
addToWatchSet();
|
||||||
|
prepareLayout();
|
||||||
|
prepareDrawTime();
|
||||||
|
invalidate();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
disposable.add(rxBus
|
||||||
|
.toObservable(EventData.Preferences.class)
|
||||||
|
.observeOn(aapsSchedulers.getMain())
|
||||||
|
.subscribe(event -> {
|
||||||
|
prepareDrawTime();
|
||||||
|
prepareLayout();
|
||||||
|
invalidate();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
rxBus.send(new EventWearToMobile(new EventData.ActionResendData("CircleWatchFace::onCreate")));
|
||||||
|
|
||||||
wakeLock.release();
|
wakeLock.release();
|
||||||
}
|
}
|
||||||
|
@ -124,18 +144,13 @@ public class CircleWatchface extends WatchFace implements SharedPreferences.OnSh
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
if (messageReceiver != null) {
|
disposable.clear();
|
||||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(messageReceiver);
|
|
||||||
}
|
|
||||||
if (sharedPrefs != null) {
|
|
||||||
sharedPrefs.unregisterOnSharedPreferenceChangeListener(this);
|
|
||||||
}
|
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected synchronized void onDraw(Canvas canvas) {
|
protected synchronized void onDraw(Canvas canvas) {
|
||||||
Log.d("CircleWatchface", "start onDraw");
|
aapsLogger.debug(LTag.WEAR, "start onDraw");
|
||||||
canvas.drawColor(getBackgroundColor());
|
canvas.drawColor(getBackgroundColor());
|
||||||
drawTime(canvas);
|
drawTime(canvas);
|
||||||
drawOtherStuff(canvas);
|
drawOtherStuff(canvas);
|
||||||
|
@ -145,27 +160,25 @@ public class CircleWatchface extends WatchFace implements SharedPreferences.OnSh
|
||||||
|
|
||||||
private synchronized void prepareLayout() {
|
private synchronized void prepareLayout() {
|
||||||
|
|
||||||
Log.d("CircleWatchface", "start startPrepareLayout");
|
aapsLogger.debug(LTag.WEAR, "start startPrepareLayout");
|
||||||
|
|
||||||
// prepare fields
|
// prepare fields
|
||||||
|
|
||||||
TextView textView;
|
|
||||||
mSgv = myLayout.findViewById(R.id.sgvString);
|
mSgv = myLayout.findViewById(R.id.sgvString);
|
||||||
textView = myLayout.findViewById(R.id.sgvString);
|
if (sp.getBoolean("showBG", true)) {
|
||||||
if (sharedPrefs.getBoolean("showBG", true)) {
|
mSgv.setVisibility(View.VISIBLE);
|
||||||
textView.setVisibility(View.VISIBLE);
|
mSgv.setText(singleBg.getSgvString());
|
||||||
textView.setText(getSgvString());
|
mSgv.setTextColor(getTextColor());
|
||||||
textView.setTextColor(getTextColor());
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
//Also possible: View.INVISIBLE instead of View.GONE (no layout change)
|
//Also possible: View.INVISIBLE instead of View.GONE (no layout change)
|
||||||
textView.setVisibility(View.INVISIBLE);
|
mSgv.setVisibility(View.INVISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
textView = myLayout.findViewById(R.id.statusString);
|
TextView textView = myLayout.findViewById(R.id.statusString);
|
||||||
if (sharedPrefs.getBoolean("showExternalStatus", true)) {
|
if (sp.getBoolean("showExternalStatus", true)) {
|
||||||
textView.setVisibility(View.VISIBLE);
|
textView.setVisibility(View.VISIBLE);
|
||||||
textView.setText(getStatusString());
|
textView.setText(status.getExternalStatus());
|
||||||
textView.setTextColor(getTextColor());
|
textView.setTextColor(getTextColor());
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -174,10 +187,10 @@ public class CircleWatchface extends WatchFace implements SharedPreferences.OnSh
|
||||||
}
|
}
|
||||||
|
|
||||||
textView = myLayout.findViewById(R.id.agoString);
|
textView = myLayout.findViewById(R.id.agoString);
|
||||||
if (sharedPrefs.getBoolean("showAgo", true)) {
|
if (sp.getBoolean("showAgo", true)) {
|
||||||
textView.setVisibility(View.VISIBLE);
|
textView.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
if (sharedPrefs.getBoolean("showBigNumbers", false)) {
|
if (sp.getBoolean("showBigNumbers", false)) {
|
||||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 26);
|
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 26);
|
||||||
} else {
|
} else {
|
||||||
((TextView) myLayout.findViewById(R.id.agoString)).setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);
|
((TextView) myLayout.findViewById(R.id.agoString)).setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);
|
||||||
|
@ -190,17 +203,17 @@ public class CircleWatchface extends WatchFace implements SharedPreferences.OnSh
|
||||||
}
|
}
|
||||||
|
|
||||||
textView = myLayout.findViewById(R.id.deltaString);
|
textView = myLayout.findViewById(R.id.deltaString);
|
||||||
if (sharedPrefs.getBoolean("showDelta", true)) {
|
if (sp.getBoolean("showDelta", true)) {
|
||||||
textView.setVisibility(View.VISIBLE);
|
textView.setVisibility(View.VISIBLE);
|
||||||
textView.setText(getDelta());
|
textView.setText(singleBg.getDelta());
|
||||||
textView.setTextColor(getTextColor());
|
textView.setTextColor(getTextColor());
|
||||||
if (sharedPrefs.getBoolean("showBigNumbers", false)) {
|
if (sp.getBoolean("showBigNumbers", false)) {
|
||||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 25);
|
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 25);
|
||||||
} else {
|
} else {
|
||||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);
|
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);
|
||||||
}
|
}
|
||||||
if (sharedPrefs.getBoolean("showAvgDelta", true)) {
|
if (sp.getBoolean("showAvgDelta", true)) {
|
||||||
textView.append(" " + getAvgDelta());
|
textView.append(" " + singleBg.getAvgDelta());
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -215,8 +228,8 @@ public class CircleWatchface extends WatchFace implements SharedPreferences.OnSh
|
||||||
|
|
||||||
public String getMinutes() {
|
public String getMinutes() {
|
||||||
String minutes = "--'";
|
String minutes = "--'";
|
||||||
if (getDatetime() != 0) {
|
if (singleBg.getTimeStamp() != 0) {
|
||||||
minutes = ((int) Math.floor((System.currentTimeMillis() - getDatetime()) / 60000.0)) + "'";
|
minutes = ((int) Math.floor((System.currentTimeMillis() - singleBg.getTimeStamp()) / 60000.0)) + "'";
|
||||||
}
|
}
|
||||||
return minutes;
|
return minutes;
|
||||||
}
|
}
|
||||||
|
@ -249,16 +262,16 @@ public class CircleWatchface extends WatchFace implements SharedPreferences.OnSh
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void prepareDrawTime() {
|
private synchronized void prepareDrawTime() {
|
||||||
Log.d("CircleWatchface", "start prepareDrawTime");
|
aapsLogger.debug(LTag.WEAR, "start prepareDrawTime");
|
||||||
|
|
||||||
hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY) % 12;
|
int hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY) % 12;
|
||||||
minute = Calendar.getInstance().get(Calendar.MINUTE);
|
int minute = Calendar.getInstance().get(Calendar.MINUTE);
|
||||||
angleBig = (((hour + minute / 60f) / 12f * 360) - 90 - BIG_HAND_WIDTH / 2f + 360) % 360;
|
angleBig = (((hour + minute / 60f) / 12f * 360) - 90 - BIG_HAND_WIDTH / 2f + 360) % 360;
|
||||||
angleSMALL = ((minute / 60f * 360) - 90 - SMALL_HAND_WIDTH / 2f + 360) % 360;
|
angleSMALL = ((minute / 60f * 360) - 90 - SMALL_HAND_WIDTH / 2f + 360) % 360;
|
||||||
|
|
||||||
|
|
||||||
color = 0;
|
color = 0;
|
||||||
switch (getSgvLevel()) {
|
switch ((int) singleBg.getSgvLevel()) {
|
||||||
case -1:
|
case -1:
|
||||||
color = getLowColor();
|
color = getLowColor();
|
||||||
break;
|
break;
|
||||||
|
@ -271,20 +284,7 @@ public class CircleWatchface extends WatchFace implements SharedPreferences.OnSh
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (isAnimated()) {
|
circlePaint.setShader(null);
|
||||||
//Animation matrix:
|
|
||||||
int[] rainbow = {Color.RED, Color.YELLOW, Color.GREEN, Color.BLUE
|
|
||||||
, Color.CYAN};
|
|
||||||
Shader shader = new LinearGradient(0, 0, 0, 20, rainbow,
|
|
||||||
null, Shader.TileMode.MIRROR);
|
|
||||||
Matrix matrix = new Matrix();
|
|
||||||
matrix.setRotate(animationAngle);
|
|
||||||
shader.setLocalMatrix(matrix);
|
|
||||||
circlePaint.setShader(shader);
|
|
||||||
} else {
|
|
||||||
circlePaint.setShader(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
circlePaint.setStyle(Paint.Style.STROKE);
|
circlePaint.setStyle(Paint.Style.STROKE);
|
||||||
circlePaint.setStrokeWidth(CIRCLE_WIDTH);
|
circlePaint.setStrokeWidth(CIRCLE_WIDTH);
|
||||||
|
@ -299,17 +299,10 @@ public class CircleWatchface extends WatchFace implements SharedPreferences.OnSh
|
||||||
rect = new RectF(PADDING, PADDING, displaySize.x - PADDING, displaySize.y - PADDING);
|
rect = new RectF(PADDING, PADDING, displaySize.x - PADDING, displaySize.y - PADDING);
|
||||||
rectDelete = new RectF(PADDING - CIRCLE_WIDTH / 2, PADDING - CIRCLE_WIDTH / 2, displaySize.x - PADDING + CIRCLE_WIDTH / 2, displaySize.y - PADDING + CIRCLE_WIDTH / 2);
|
rectDelete = new RectF(PADDING - CIRCLE_WIDTH / 2, PADDING - CIRCLE_WIDTH / 2, displaySize.x - PADDING + CIRCLE_WIDTH / 2, displaySize.y - PADDING + CIRCLE_WIDTH / 2);
|
||||||
overlapping = ALWAYS_HIGHLIGT_SMALL || areOverlapping(angleSMALL, angleSMALL + SMALL_HAND_WIDTH + NEAR, angleBig, angleBig + BIG_HAND_WIDTH + NEAR);
|
overlapping = ALWAYS_HIGHLIGT_SMALL || areOverlapping(angleSMALL, angleSMALL + SMALL_HAND_WIDTH + NEAR, angleBig, angleBig + BIG_HAND_WIDTH + NEAR);
|
||||||
Log.d("CircleWatchface", "end prepareDrawTime");
|
aapsLogger.debug(LTag.WEAR, "end prepareDrawTime");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized void animationStep() {
|
|
||||||
animationAngle = (animationAngle + 1) % 360;
|
|
||||||
prepareDrawTime();
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private boolean areOverlapping(float aBegin, float aEnd, float bBegin, float bEnd) {
|
private boolean areOverlapping(float aBegin, float aEnd, float bBegin, float bEnd) {
|
||||||
return
|
return
|
||||||
aBegin <= bBegin && aEnd >= bBegin ||
|
aBegin <= bBegin && aEnd >= bBegin ||
|
||||||
|
@ -338,7 +331,7 @@ public class CircleWatchface extends WatchFace implements SharedPreferences.OnSh
|
||||||
|
|
||||||
// defining color for dark and bright
|
// defining color for dark and bright
|
||||||
public int getLowColor() {
|
public int getLowColor() {
|
||||||
if (sharedPrefs.getBoolean("dark", true)) {
|
if (sp.getBoolean("dark", true)) {
|
||||||
return Color.argb(255, 255, 120, 120);
|
return Color.argb(255, 255, 120, 120);
|
||||||
} else {
|
} else {
|
||||||
return Color.argb(255, 255, 80, 80);
|
return Color.argb(255, 255, 80, 80);
|
||||||
|
@ -346,7 +339,7 @@ public class CircleWatchface extends WatchFace implements SharedPreferences.OnSh
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getInRangeColor() {
|
public int getInRangeColor() {
|
||||||
if (sharedPrefs.getBoolean("dark", true)) {
|
if (sp.getBoolean("dark", true)) {
|
||||||
return Color.argb(255, 120, 255, 120);
|
return Color.argb(255, 120, 255, 120);
|
||||||
} else {
|
} else {
|
||||||
return Color.argb(255, 0, 240, 0);
|
return Color.argb(255, 0, 240, 0);
|
||||||
|
@ -355,7 +348,7 @@ public class CircleWatchface extends WatchFace implements SharedPreferences.OnSh
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getHighColor() {
|
public int getHighColor() {
|
||||||
if (sharedPrefs.getBoolean("dark", true)) {
|
if (sp.getBoolean("dark", true)) {
|
||||||
return Color.argb(255, 255, 255, 120);
|
return Color.argb(255, 255, 255, 120);
|
||||||
} else {
|
} else {
|
||||||
return Color.argb(255, 255, 200, 0);
|
return Color.argb(255, 255, 200, 0);
|
||||||
|
@ -364,7 +357,7 @@ public class CircleWatchface extends WatchFace implements SharedPreferences.OnSh
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getBackgroundColor() {
|
public int getBackgroundColor() {
|
||||||
if (sharedPrefs.getBoolean("dark", true)) {
|
if (sp.getBoolean("dark", true)) {
|
||||||
return Color.BLACK;
|
return Color.BLACK;
|
||||||
} else {
|
} else {
|
||||||
return Color.WHITE;
|
return Color.WHITE;
|
||||||
|
@ -373,7 +366,7 @@ public class CircleWatchface extends WatchFace implements SharedPreferences.OnSh
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getTextColor() {
|
public int getTextColor() {
|
||||||
if (sharedPrefs.getBoolean("dark", true)) {
|
if (sp.getBoolean("dark", true)) {
|
||||||
return Color.WHITE;
|
return Color.WHITE;
|
||||||
} else {
|
} else {
|
||||||
return Color.BLACK;
|
return Color.BLACK;
|
||||||
|
@ -382,23 +375,22 @@ public class CircleWatchface extends WatchFace implements SharedPreferences.OnSh
|
||||||
}
|
}
|
||||||
|
|
||||||
public void drawOtherStuff(Canvas canvas) {
|
public void drawOtherStuff(Canvas canvas) {
|
||||||
Log.d("CircleWatchface", "start onDrawOtherStuff. bgDataList.size(): " + bgDataList.size());
|
aapsLogger.debug(LTag.WEAR, "start onDrawOtherStuff. bgDataList.size(): " + bgDataList.size());
|
||||||
|
|
||||||
if (isAnimated()) return; // too many repaints when animated
|
if (sp.getBoolean("showRingHistory", false)) {
|
||||||
if (sharedPrefs.getBoolean("showRingHistory", false)) {
|
|
||||||
//Perfect low and High indicators
|
//Perfect low and High indicators
|
||||||
if (bgDataList.size() > 0) {
|
if (bgDataList.size() > 0) {
|
||||||
addIndicator(canvas, 100, Color.LTGRAY);
|
addIndicator(canvas, 100, Color.LTGRAY);
|
||||||
addIndicator(canvas, (float) bgDataList.iterator().next().low, getLowColor());
|
addIndicator(canvas, (float) bgDataList.iterator().next().getLow(), getLowColor());
|
||||||
addIndicator(canvas, (float) bgDataList.iterator().next().high, getHighColor());
|
addIndicator(canvas, (float) bgDataList.iterator().next().getHigh(), getHighColor());
|
||||||
|
|
||||||
|
|
||||||
if (sharedPrefs.getBoolean("softRingHistory", true)) {
|
if (sp.getBoolean("softRingHistory", true)) {
|
||||||
for (BgWatchData data : bgDataList) {
|
for (EventData.SingleBg data : bgDataList) {
|
||||||
addReadingSoft(canvas, data);
|
addReadingSoft(canvas, data);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (BgWatchData data : bgDataList) {
|
for (EventData.SingleBg data : bgDataList) {
|
||||||
addReading(canvas, data);
|
addReading(canvas, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -406,202 +398,15 @@ public class CircleWatchface extends WatchFace implements SharedPreferences.OnSh
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int holdInMemory() {
|
public synchronized void addToWatchSet() {
|
||||||
return 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
//getters & setters
|
bgDataList.clear();
|
||||||
|
if (!sp.getBoolean("showRingHistory", false)) return;
|
||||||
|
|
||||||
private synchronized int getSgvLevel() {
|
double threshold = (System.currentTimeMillis() - (1000L * 60 * 30)); // 30 min
|
||||||
return sgvLevel;
|
for (EventData.SingleBg entry : graphData.getEntries())
|
||||||
}
|
if (entry.getTimeStamp() >= threshold) bgDataList.add(entry);
|
||||||
|
aapsLogger.debug(LTag.WEAR, "addToWatchSet size=" + bgDataList.size());
|
||||||
private synchronized void setSgvLevel(int sgvLevel) {
|
|
||||||
this.sgvLevel = sgvLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized int getBatteryLevel() {
|
|
||||||
return batteryLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized void setBatteryLevel(int batteryLevel) {
|
|
||||||
this.batteryLevel = batteryLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private synchronized long getDatetime() {
|
|
||||||
return datetime;
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized void setDatetime(long datetime) {
|
|
||||||
this.datetime = datetime;
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized String getDirection() {
|
|
||||||
return direction;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setDirection(String direction) {
|
|
||||||
this.direction = direction;
|
|
||||||
}
|
|
||||||
|
|
||||||
String getSgvString() {
|
|
||||||
return sgvString;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setSgvString(String sgvString) {
|
|
||||||
this.sgvString = sgvString;
|
|
||||||
}
|
|
||||||
|
|
||||||
String getStatusString() {
|
|
||||||
return statusString;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setStatusString(String statusString) {
|
|
||||||
this.statusString = statusString;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDelta() {
|
|
||||||
return delta;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setDelta(String delta) {
|
|
||||||
this.delta = delta;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getAvgDelta() {
|
|
||||||
return avgDelta;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setAvgDelta(String avgDelta) {
|
|
||||||
this.avgDelta = avgDelta;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
|
||||||
prepareDrawTime();
|
|
||||||
prepareLayout();
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized boolean isAnimated() {
|
|
||||||
return isAnimated;
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized void setIsAnimated(boolean isAnimated) {
|
|
||||||
this.isAnimated = isAnimated;
|
|
||||||
}
|
|
||||||
|
|
||||||
void startAnimation() {
|
|
||||||
Log.d("CircleWatchface", "start startAnimation");
|
|
||||||
|
|
||||||
Thread animator = new Thread() {
|
|
||||||
|
|
||||||
|
|
||||||
public void run() {
|
|
||||||
setIsAnimated(true);
|
|
||||||
for (int i = 0; i <= 8 * 1000 / 40; i++) {
|
|
||||||
animationStep();
|
|
||||||
SystemClock.sleep(40);
|
|
||||||
}
|
|
||||||
setIsAnimated(false);
|
|
||||||
prepareDrawTime();
|
|
||||||
invalidate();
|
|
||||||
System.gc();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
animator.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public class MessageReceiver extends BroadcastReceiver {
|
|
||||||
@Override
|
|
||||||
public void onReceive(Context context, Intent intent) {
|
|
||||||
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
|
|
||||||
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AndroidAPS:MessageReceiver");
|
|
||||||
wakeLock.acquire(30000);
|
|
||||||
Bundle bundle = intent.getBundleExtra("data");
|
|
||||||
if (bundle != null) {
|
|
||||||
DataMap dataMap = DataMap.fromBundle(bundle);
|
|
||||||
setSgvLevel((int) dataMap.getLong("sgvLevel"));
|
|
||||||
Log.d("CircleWatchface", "sgv level : " + getSgvLevel());
|
|
||||||
setSgvString(dataMap.getString("sgvString"));
|
|
||||||
Log.d("CircleWatchface", "sgv string : " + getSgvString());
|
|
||||||
setDelta(dataMap.getString("delta"));
|
|
||||||
setAvgDelta(dataMap.getString("avgDelta"));
|
|
||||||
setDatetime(dataMap.getLong("timestamp"));
|
|
||||||
addToWatchSet(dataMap);
|
|
||||||
|
|
||||||
|
|
||||||
//start animation?
|
|
||||||
// dataMap.getDataMapArrayList("entries") == null -> not on "resend data".
|
|
||||||
if (sharedPrefs.getBoolean("animation", false) && dataMap.getDataMapArrayList("entries") == null && (getSgvString().equals("100") || getSgvString().equals("5.5") || getSgvString().equals("5,5"))) {
|
|
||||||
startAnimation();
|
|
||||||
}
|
|
||||||
|
|
||||||
prepareLayout();
|
|
||||||
prepareDrawTime();
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
//status
|
|
||||||
bundle = intent.getBundleExtra("status");
|
|
||||||
if (bundle != null) {
|
|
||||||
DataMap dataMap = DataMap.fromBundle(bundle);
|
|
||||||
wakeLock.acquire(50);
|
|
||||||
setStatusString(dataMap.getString("externalStatusString"));
|
|
||||||
|
|
||||||
prepareLayout();
|
|
||||||
prepareDrawTime();
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
wakeLock.release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void addToWatchSet(DataMap dataMap) {
|
|
||||||
|
|
||||||
if (!sharedPrefs.getBoolean("showRingHistory", false)) {
|
|
||||||
bgDataList.clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.d("CircleWatchface", "start addToWatchSet");
|
|
||||||
ArrayList<DataMap> entries = dataMap.getDataMapArrayList("entries");
|
|
||||||
if (entries == null) {
|
|
||||||
double sgv = dataMap.getDouble("sgvDouble");
|
|
||||||
double high = dataMap.getDouble("high");
|
|
||||||
double low = dataMap.getDouble("low");
|
|
||||||
long timestamp = dataMap.getLong("timestamp");
|
|
||||||
int color = dataMap.getInt("color", 0);
|
|
||||||
bgDataList.add(new BgWatchData(sgv, high, low, timestamp, color));
|
|
||||||
} else if (!sharedPrefs.getBoolean("animation", false)) {
|
|
||||||
// don't load history at once if animations are set (less resource consumption)
|
|
||||||
Log.d("addToWatchSet", "entries.size(): " + entries.size());
|
|
||||||
|
|
||||||
for (DataMap entry : entries) {
|
|
||||||
double sgv = entry.getDouble("sgvDouble");
|
|
||||||
double high = entry.getDouble("high");
|
|
||||||
double low = entry.getDouble("low");
|
|
||||||
long timestamp = entry.getLong("timestamp");
|
|
||||||
int color = entry.getInt("color", 0);
|
|
||||||
bgDataList.add(new BgWatchData(sgv, high, low, timestamp, color));
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
|
|
||||||
Log.d("addToWatchSet", "start removing bgDataList.size(): " + bgDataList.size());
|
|
||||||
HashSet<BgWatchData> removeSet = new HashSet<>();
|
|
||||||
double threshold = (System.currentTimeMillis() - (1000 * 60 * 5 * holdInMemory()));
|
|
||||||
for (BgWatchData data : bgDataList) {
|
|
||||||
if (data.timestamp < threshold) {
|
|
||||||
removeSet.add(data);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bgDataList.removeAll(removeSet);
|
|
||||||
Log.d("addToWatchSet", "after bgDataList.size(): " + bgDataList.size());
|
|
||||||
removeSet = null;
|
|
||||||
System.gc();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int darken(int color, double fraction) {
|
public int darken(int color, double fraction) {
|
||||||
|
@ -618,10 +423,7 @@ public class CircleWatchface extends WatchFace implements SharedPreferences.OnSh
|
||||||
|
|
||||||
private int darkenColor(int color, double fraction) {
|
private int darkenColor(int color, double fraction) {
|
||||||
|
|
||||||
//if (sharedPrefs.getBoolean("dark", false)) {
|
|
||||||
return (int) Math.max(color - (color * fraction), 0);
|
return (int) Math.max(color - (color * fraction), 0);
|
||||||
//}
|
|
||||||
// return (int)Math.min(color + (color * fraction), 255);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -659,44 +461,46 @@ public class CircleWatchface extends WatchFace implements SharedPreferences.OnSh
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void addReadingSoft(Canvas canvas, BgWatchData entry) {
|
public void addReadingSoft(Canvas canvas, EventData.SingleBg entry) {
|
||||||
|
|
||||||
Log.d("CircleWatchface", "addReadingSoft");
|
aapsLogger.debug(LTag.WEAR, "addReadingSoft");
|
||||||
double size;
|
double size;
|
||||||
int color = Color.LTGRAY;
|
int color = Color.LTGRAY;
|
||||||
if (sharedPrefs.getBoolean("dark", true)) {
|
if (sp.getBoolean("dark", true)) {
|
||||||
color = Color.DKGRAY;
|
color = Color.DKGRAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
float offsetMultiplier = (((displaySize.x / 2f) - PADDING) / 12f);
|
float offsetMultiplier = (((displaySize.x / 2f) - PADDING) / 12f);
|
||||||
float offset = (float) Math.max(1, Math.ceil((System.currentTimeMillis() - entry.timestamp) / (1000 * 60 * 5.0)));
|
float offset = (float) Math.max(1,
|
||||||
size = bgToAngle((float) entry.sgv);
|
Math.ceil((System.currentTimeMillis() - entry.getTimeStamp()) / (1000 * 60 * 5.0)));
|
||||||
|
size = bgToAngle((float) entry.getSgv());
|
||||||
addArch(canvas, offset * offsetMultiplier + 10, color, (float) size);
|
addArch(canvas, offset * offsetMultiplier + 10, color, (float) size);
|
||||||
addArch(canvas, (float) size, offset * offsetMultiplier + 10, getBackgroundColor(), (float) (360 - size));
|
addArch(canvas, (float) size, offset * offsetMultiplier + 10, getBackgroundColor(), (float) (360 - size));
|
||||||
addArch(canvas, (offset + .8f) * offsetMultiplier + 10, getBackgroundColor(), 360);
|
addArch(canvas, (offset + .8f) * offsetMultiplier + 10, getBackgroundColor(), 360);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addReading(Canvas canvas, BgWatchData entry) {
|
public void addReading(Canvas canvas, EventData.SingleBg entry) {
|
||||||
Log.d("CircleWatchface", "addReading");
|
aapsLogger.debug(LTag.WEAR, "addReading");
|
||||||
|
|
||||||
double size;
|
double size;
|
||||||
int color = Color.LTGRAY;
|
int color = Color.LTGRAY;
|
||||||
int indicatorColor = Color.DKGRAY;
|
int indicatorColor = Color.DKGRAY;
|
||||||
if (sharedPrefs.getBoolean("dark", true)) {
|
if (sp.getBoolean("dark", true)) {
|
||||||
color = Color.DKGRAY;
|
color = Color.DKGRAY;
|
||||||
indicatorColor = Color.LTGRAY;
|
indicatorColor = Color.LTGRAY;
|
||||||
}
|
}
|
||||||
int barColor = Color.GRAY;
|
int barColor = Color.GRAY;
|
||||||
if (entry.sgv >= entry.high) {
|
if (entry.getSgv() >= entry.getHigh()) {
|
||||||
indicatorColor = getHighColor();
|
indicatorColor = getHighColor();
|
||||||
barColor = darken(getHighColor(), .5);
|
barColor = darken(getHighColor(), .5);
|
||||||
} else if (entry.sgv <= entry.low) {
|
} else if (entry.getSgv() <= entry.getLow()) {
|
||||||
indicatorColor = getLowColor();
|
indicatorColor = getLowColor();
|
||||||
barColor = darken(getLowColor(), .5);
|
barColor = darken(getLowColor(), .5);
|
||||||
}
|
}
|
||||||
float offsetMultiplier = (((displaySize.x / 2f) - PADDING) / 12f);
|
float offsetMultiplier = (((displaySize.x / 2f) - PADDING) / 12f);
|
||||||
float offset = (float) Math.max(1, Math.ceil((System.currentTimeMillis() - entry.timestamp) / (1000 * 60 * 5.0)));
|
float offset = (float) Math.max(1,
|
||||||
size = bgToAngle((float) entry.sgv);
|
Math.ceil((System.currentTimeMillis() - entry.getTimeStamp()) / (1000 * 60 * 5.0)));
|
||||||
|
size = bgToAngle((float) entry.getSgv());
|
||||||
addArch(canvas, offset * offsetMultiplier + 11, barColor, (float) size - 2); // Dark Color Bar
|
addArch(canvas, offset * offsetMultiplier + 11, barColor, (float) size - 2); // Dark Color Bar
|
||||||
addArch(canvas, (float) size - 2, offset * offsetMultiplier + 11, indicatorColor, 2f); // Indicator at end of bar
|
addArch(canvas, (float) size - 2, offset * offsetMultiplier + 11, indicatorColor, 2f); // Indicator at end of bar
|
||||||
addArch(canvas, (float) size, offset * offsetMultiplier + 11, color, (float) (360f - size)); // Dark fill
|
addArch(canvas, (float) size, offset * offsetMultiplier + 11, color, (float) (360f - size)); // Dark fill
|
||||||
|
@ -705,8 +509,8 @@ public class CircleWatchface extends WatchFace implements SharedPreferences.OnSh
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onTapCommand(int tapType, int x, int y, long eventTime) {
|
protected void onTapCommand(int tapType, int x, int y, long eventTime) {
|
||||||
|
if (mSgv == null) return;
|
||||||
int extra = mSgv != null ? (mSgv.getRight() - mSgv.getLeft()) / 2 : 0;
|
int extra = (mSgv.getRight() - mSgv.getLeft()) / 2;
|
||||||
|
|
||||||
if (tapType == TAP_TYPE_TAP &&
|
if (tapType == TAP_TYPE_TAP &&
|
||||||
x + extra >= mSgv.getLeft() &&
|
x + extra >= mSgv.getLeft() &&
|
||||||
|
@ -726,6 +530,4 @@ public class CircleWatchface extends WatchFace implements SharedPreferences.OnSh
|
||||||
protected WatchFaceStyle getWatchFaceStyle() {
|
protected WatchFaceStyle getWatchFaceStyle() {
|
||||||
return new WatchFaceStyle.Builder(this).setAcceptsTapEvents(true).build();
|
return new WatchFaceStyle.Builder(this).setAcceptsTapEvents(true).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package info.nightscout.androidaps.watchfaces;
|
package info.nightscout.androidaps.watchfaces;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.support.wearable.watchface.WatchFaceStyle;
|
import android.support.wearable.watchface.WatchFaceStyle;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
@ -16,7 +17,7 @@ public class Cockpit extends BaseWatchFace {
|
||||||
|
|
||||||
private long sgvTapTime = 0;
|
private long sgvTapTime = 0;
|
||||||
|
|
||||||
@Override
|
@SuppressLint("InflateParams") @Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
|
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
|
||||||
|
@ -48,13 +49,13 @@ public class Cockpit extends BaseWatchFace {
|
||||||
setTextSizes();
|
setTextSizes();
|
||||||
|
|
||||||
if (mHighLight != null && mLowLight != null) {
|
if (mHighLight != null && mLowLight != null) {
|
||||||
if (rawData.sgvLevel == 1) {
|
if (singleBg.getSgvLevel() == 1) {
|
||||||
mHighLight.setBackgroundResource(R.drawable.airplane_led_yellow_lit);
|
mHighLight.setBackgroundResource(R.drawable.airplane_led_yellow_lit);
|
||||||
mLowLight.setBackgroundResource(R.drawable.airplane_led_grey_unlit);
|
mLowLight.setBackgroundResource(R.drawable.airplane_led_grey_unlit);
|
||||||
} else if (rawData.sgvLevel == 0) {
|
} else if (singleBg.getSgvLevel() == 0) {
|
||||||
mHighLight.setBackgroundResource(R.drawable.airplane_led_grey_unlit);
|
mHighLight.setBackgroundResource(R.drawable.airplane_led_grey_unlit);
|
||||||
mLowLight.setBackgroundResource(R.drawable.airplane_led_grey_unlit);
|
mLowLight.setBackgroundResource(R.drawable.airplane_led_grey_unlit);
|
||||||
} else if (rawData.sgvLevel == -1) {
|
} else if (singleBg.getSgvLevel() == -1) {
|
||||||
mHighLight.setBackgroundResource(R.drawable.airplane_led_grey_unlit);
|
mHighLight.setBackgroundResource(R.drawable.airplane_led_grey_unlit);
|
||||||
mLowLight.setBackgroundResource(R.drawable.airplane_led_red_lit);
|
mLowLight.setBackgroundResource(R.drawable.airplane_led_red_lit);
|
||||||
}
|
}
|
||||||
|
@ -84,7 +85,7 @@ public class Cockpit extends BaseWatchFace {
|
||||||
protected void setTextSizes() {
|
protected void setTextSizes() {
|
||||||
|
|
||||||
if (mIOB2 != null) {
|
if (mIOB2 != null) {
|
||||||
if (rawData.detailedIOB) {
|
if (status.getDetailedIob()) {
|
||||||
if (bIsRound) {
|
if (bIsRound) {
|
||||||
mIOB2.setTextSize(10);
|
mIOB2.setTextSize(10);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package info.nightscout.androidaps.watchfaces;
|
package info.nightscout.androidaps.watchfaces;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.res.ColorStateList;
|
import android.content.res.ColorStateList;
|
||||||
import android.support.wearable.watchface.WatchFaceStyle;
|
import android.support.wearable.watchface.WatchFaceStyle;
|
||||||
|
@ -19,10 +20,9 @@ import info.nightscout.androidaps.interaction.menus.MainMenuActivity;
|
||||||
|
|
||||||
public class DigitalStyle extends BaseWatchFace {
|
public class DigitalStyle extends BaseWatchFace {
|
||||||
private static final long TIME_TAP_THRESHOLD = 800;
|
private static final long TIME_TAP_THRESHOLD = 800;
|
||||||
private final long chartTapTime = 0;
|
|
||||||
private long sgvTapTime = 0;
|
private long sgvTapTime = 0;
|
||||||
|
|
||||||
@Override
|
@SuppressLint("InflateParams") @Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
|
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
|
||||||
|
@ -57,13 +57,13 @@ public class DigitalStyle extends BaseWatchFace {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setColorDark() {
|
protected void setColorDark() {
|
||||||
if (rawData.sgvLevel == 1) {
|
if (singleBg.getSgvLevel() == 1) {
|
||||||
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor));
|
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor));
|
||||||
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor));
|
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor));
|
||||||
} else if (rawData.sgvLevel == 0) {
|
} else if (singleBg.getSgvLevel() == 0) {
|
||||||
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
|
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
|
||||||
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
|
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
|
||||||
} else if (rawData.sgvLevel == -1) {
|
} else if (singleBg.getSgvLevel() == -1) {
|
||||||
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor));
|
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor));
|
||||||
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor));
|
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor));
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,7 @@ public class DigitalStyle extends BaseWatchFace {
|
||||||
mTimestamp.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_TimestampOld));
|
mTimestamp.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_TimestampOld));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rawData.batteryLevel == 1) {
|
if (status.getBatteryLevel() == 1) {
|
||||||
mUploaderBattery.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
|
mUploaderBattery.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
|
||||||
} else {
|
} else {
|
||||||
mUploaderBattery.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_uploaderBatteryEmpty));
|
mUploaderBattery.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_uploaderBatteryEmpty));
|
||||||
|
@ -99,10 +99,11 @@ public class DigitalStyle extends BaseWatchFace {
|
||||||
LinearLayout mShapesElements = layoutView.findViewById(R.id.shapes_elements);
|
LinearLayout mShapesElements = layoutView.findViewById(R.id.shapes_elements);
|
||||||
if (mShapesElements != null) {
|
if (mShapesElements != null) {
|
||||||
String displayFormatType = (mShapesElements.getContentDescription().toString().startsWith("round") ? "round" : "rect");
|
String displayFormatType = (mShapesElements.getContentDescription().toString().startsWith("round") ? "round" : "rect");
|
||||||
String displayStyle=sharedPrefs.getString("digitalstyle_frameStyle", "full");
|
String displayStyle=sp.getString("digitalstyle_frameStyle", "full");
|
||||||
String displayFrameColor=sharedPrefs.getString("digitalstyle_frameColor", "red");
|
String displayFrameColor=sp.getString("digitalstyle_frameColor", "red");
|
||||||
String displayFrameColorSaturation=sharedPrefs.getString("digitalstyle_frameColorSaturation", "500");
|
String displayFrameColorSaturation=sp.getString("digitalstyle_frameColorSaturation",
|
||||||
String displayFrameColorOpacity=sharedPrefs.getString("digitalstyle_frameColorOpacity", "1");
|
"500");
|
||||||
|
String displayFrameColorOpacity=sp.getString("digitalstyle_frameColorOpacity", "1");
|
||||||
|
|
||||||
// Load image with shapes
|
// Load image with shapes
|
||||||
String styleDrawableName = "digitalstyle_bg_" + displayStyle + "_" + displayFormatType;
|
String styleDrawableName = "digitalstyle_bg_" + displayStyle + "_" + displayFormatType;
|
||||||
|
@ -133,7 +134,7 @@ public class DigitalStyle extends BaseWatchFace {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* optimize font-size --> when date is off then increase font-size of time */
|
/* optimize font-size --> when date is off then increase font-size of time */
|
||||||
Boolean isShowDate = sharedPrefs.getBoolean("show_date", false);
|
Boolean isShowDate = sp.getBoolean("show_date", false);
|
||||||
if (!isShowDate) {
|
if (!isShowDate) {
|
||||||
layoutView.findViewById(R.id.date_time).setVisibility(View.GONE);
|
layoutView.findViewById(R.id.date_time).setVisibility(View.GONE);
|
||||||
mHour.setTextSize(62);
|
mHour.setTextSize(62);
|
||||||
|
@ -148,7 +149,7 @@ public class DigitalStyle extends BaseWatchFace {
|
||||||
mMinute.setLetterSpacing((float) 0);
|
mMinute.setLetterSpacing((float) 0);
|
||||||
|
|
||||||
/* display week number */
|
/* display week number */
|
||||||
Boolean isShowWeekNumber = sharedPrefs.getBoolean("show_weeknumber", false);
|
Boolean isShowWeekNumber = sp.getBoolean("show_weeknumber", false);
|
||||||
Log.i("---------------------------------","weeknumber refresh ");
|
Log.i("---------------------------------","weeknumber refresh ");
|
||||||
TextView mWeekNumber= layoutView.findViewById(R.id.weeknumber);
|
TextView mWeekNumber= layoutView.findViewById(R.id.weeknumber);
|
||||||
if (isShowWeekNumber) {
|
if (isShowWeekNumber) {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package info.nightscout.androidaps.watchfaces;
|
package info.nightscout.androidaps.watchfaces;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
|
@ -16,7 +17,7 @@ public class Home extends BaseWatchFace {
|
||||||
private long chartTapTime = 0;
|
private long chartTapTime = 0;
|
||||||
private long sgvTapTime = 0;
|
private long sgvTapTime = 0;
|
||||||
|
|
||||||
@Override
|
@SuppressLint("InflateParams") @Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
|
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
|
||||||
|
@ -53,9 +54,9 @@ public class Home extends BaseWatchFace {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void changeChartTimeframe() {
|
private void changeChartTimeframe() {
|
||||||
int timeframe = Integer.parseInt(sharedPrefs.getString("chart_timeframe", "3"));
|
int timeframe = sp.getInt("chart_timeframe", 3);
|
||||||
timeframe = (timeframe%5) + 1;
|
timeframe = (timeframe%5) + 1;
|
||||||
sharedPrefs.edit().putString("chart_timeframe", "" + timeframe).apply();
|
sp.putString("chart_timeframe", "" + timeframe);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -69,15 +70,15 @@ public class Home extends BaseWatchFace {
|
||||||
R.color.dark_background : R.color.dark_statusView));
|
R.color.dark_background : R.color.dark_statusView));
|
||||||
mTime.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_mTime));
|
mTime.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_mTime));
|
||||||
mRelativeLayout.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_background));
|
mRelativeLayout.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_background));
|
||||||
if (rawData.sgvLevel == 1) {
|
if (singleBg.getSgvLevel() == 1) {
|
||||||
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor));
|
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor));
|
||||||
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor));
|
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor));
|
||||||
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor));
|
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor));
|
||||||
} else if (rawData.sgvLevel == 0) {
|
} else if (singleBg.getSgvLevel() == 0) {
|
||||||
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
|
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
|
||||||
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
|
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
|
||||||
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
|
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
|
||||||
} else if (rawData.sgvLevel == -1) {
|
} else if (singleBg.getSgvLevel() == -1) {
|
||||||
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor));
|
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor));
|
||||||
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor));
|
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor));
|
||||||
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor));
|
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor));
|
||||||
|
@ -90,7 +91,7 @@ public class Home extends BaseWatchFace {
|
||||||
mTimestamp.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_TimestampOld));
|
mTimestamp.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_TimestampOld));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rawData.batteryLevel == 1) {
|
if (status.getBatteryLevel() == 1) {
|
||||||
mUploaderBattery.setTextColor(ContextCompat.getColor(getApplicationContext(), dividerMatchesBg ?
|
mUploaderBattery.setTextColor(ContextCompat.getColor(getApplicationContext(), dividerMatchesBg ?
|
||||||
R.color.dark_midColor : R.color.dark_uploaderBattery));
|
R.color.dark_midColor : R.color.dark_uploaderBattery));
|
||||||
} else {
|
} else {
|
||||||
|
@ -138,15 +139,15 @@ public class Home extends BaseWatchFace {
|
||||||
mLinearLayout.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), dividerMatchesBg ?
|
mLinearLayout.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), dividerMatchesBg ?
|
||||||
R.color.light_background : R.color.light_stripe_background));
|
R.color.light_background : R.color.light_stripe_background));
|
||||||
mRelativeLayout.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.light_background));
|
mRelativeLayout.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.light_background));
|
||||||
if (rawData.sgvLevel == 1) {
|
if (singleBg.getSgvLevel() == 1) {
|
||||||
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_highColor));
|
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_highColor));
|
||||||
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_highColor));
|
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_highColor));
|
||||||
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_highColor));
|
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_highColor));
|
||||||
} else if (rawData.sgvLevel == 0) {
|
} else if (singleBg.getSgvLevel() == 0) {
|
||||||
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_midColor));
|
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_midColor));
|
||||||
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_midColor));
|
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_midColor));
|
||||||
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_midColor));
|
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_midColor));
|
||||||
} else if (rawData.sgvLevel == -1) {
|
} else if (singleBg.getSgvLevel() == -1) {
|
||||||
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_lowColor));
|
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_lowColor));
|
||||||
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_lowColor));
|
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_lowColor));
|
||||||
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_lowColor));
|
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_lowColor));
|
||||||
|
@ -158,7 +159,7 @@ public class Home extends BaseWatchFace {
|
||||||
mTimestamp.setTextColor(Color.RED);
|
mTimestamp.setTextColor(Color.RED);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rawData.batteryLevel == 1) {
|
if (status.getBatteryLevel() == 1) {
|
||||||
mUploaderBattery.setTextColor(dividerMatchesBg ? Color.BLACK : Color.WHITE);
|
mUploaderBattery.setTextColor(dividerMatchesBg ? Color.BLACK : Color.WHITE);
|
||||||
} else {
|
} else {
|
||||||
mUploaderBattery.setTextColor(Color.RED);
|
mUploaderBattery.setTextColor(Color.RED);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package info.nightscout.androidaps.watchfaces;
|
package info.nightscout.androidaps.watchfaces;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
|
|
||||||
|
@ -19,7 +20,7 @@ public class Home2 extends BaseWatchFace {
|
||||||
private long chartTapTime = 0;
|
private long chartTapTime = 0;
|
||||||
private long sgvTapTime = 0;
|
private long sgvTapTime = 0;
|
||||||
|
|
||||||
@Override
|
@SuppressLint("InflateParams") @Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
|
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
|
||||||
|
@ -57,9 +58,9 @@ public class Home2 extends BaseWatchFace {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void changeChartTimeframe() {
|
private void changeChartTimeframe() {
|
||||||
int timeframe = Integer.parseInt(sharedPrefs.getString("chart_timeframe", "3"));
|
int timeframe = sp.getInt("chart_timeframe", 3);
|
||||||
timeframe = (timeframe % 5) + 1;
|
timeframe = (timeframe % 5) + 1;
|
||||||
sharedPrefs.edit().putString("chart_timeframe", "" + timeframe).apply();
|
sp.putString("chart_timeframe", "" + timeframe);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -89,13 +90,13 @@ public class Home2 extends BaseWatchFace {
|
||||||
|
|
||||||
setTextSizes();
|
setTextSizes();
|
||||||
|
|
||||||
if (rawData.sgvLevel == 1) {
|
if (singleBg.getSgvLevel() == 1) {
|
||||||
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor));
|
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor));
|
||||||
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor));
|
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor));
|
||||||
} else if (rawData.sgvLevel == 0) {
|
} else if (singleBg.getSgvLevel() == 0) {
|
||||||
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
|
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
|
||||||
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
|
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
|
||||||
} else if (rawData.sgvLevel == -1) {
|
} else if (singleBg.getSgvLevel() == -1) {
|
||||||
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor));
|
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor));
|
||||||
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor));
|
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor));
|
||||||
}
|
}
|
||||||
|
@ -106,7 +107,7 @@ public class Home2 extends BaseWatchFace {
|
||||||
mTimestamp.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_TimestampOld));
|
mTimestamp.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_TimestampOld));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rawData.batteryLevel == 1) {
|
if (status.getBatteryLevel() == 1) {
|
||||||
mUploaderBattery.setTextColor(dividerBatteryOkColor);
|
mUploaderBattery.setTextColor(dividerBatteryOkColor);
|
||||||
} else {
|
} else {
|
||||||
mUploaderBattery.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_uploaderBatteryEmpty));
|
mUploaderBattery.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_uploaderBatteryEmpty));
|
||||||
|
@ -200,13 +201,13 @@ public class Home2 extends BaseWatchFace {
|
||||||
|
|
||||||
setTextSizes();
|
setTextSizes();
|
||||||
|
|
||||||
if (rawData.sgvLevel == 1) {
|
if (singleBg.getSgvLevel() == 1) {
|
||||||
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_highColor));
|
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_highColor));
|
||||||
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_highColor));
|
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_highColor));
|
||||||
} else if (rawData.sgvLevel == 0) {
|
} else if (singleBg.getSgvLevel() == 0) {
|
||||||
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_midColor));
|
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_midColor));
|
||||||
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_midColor));
|
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_midColor));
|
||||||
} else if (rawData.sgvLevel == -1) {
|
} else if (singleBg.getSgvLevel() == -1) {
|
||||||
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_lowColor));
|
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_lowColor));
|
||||||
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_lowColor));
|
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_lowColor));
|
||||||
}
|
}
|
||||||
|
@ -217,7 +218,7 @@ public class Home2 extends BaseWatchFace {
|
||||||
mTimestamp.setTextColor(Color.RED);
|
mTimestamp.setTextColor(Color.RED);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rawData.batteryLevel == 1) {
|
if (status.getBatteryLevel() == 1) {
|
||||||
mUploaderBattery.setTextColor(dividerTxtColor);
|
mUploaderBattery.setTextColor(dividerTxtColor);
|
||||||
} else {
|
} else {
|
||||||
mUploaderBattery.setTextColor(Color.RED);
|
mUploaderBattery.setTextColor(Color.RED);
|
||||||
|
@ -255,7 +256,7 @@ public class Home2 extends BaseWatchFace {
|
||||||
|
|
||||||
if (mIOB1 != null && mIOB2 != null) {
|
if (mIOB1 != null && mIOB2 != null) {
|
||||||
|
|
||||||
if (rawData.detailedIOB) {
|
if (status.getDetailedIob()) {
|
||||||
mIOB1.setTextSize(14);
|
mIOB1.setTextSize(14);
|
||||||
mIOB2.setTextSize(10);
|
mIOB2.setTextSize(10);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package info.nightscout.androidaps.watchfaces;
|
package info.nightscout.androidaps.watchfaces;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
|
@ -15,7 +16,7 @@ public class LargeHome extends BaseWatchFace {
|
||||||
|
|
||||||
private long sgvTapTime = 0;
|
private long sgvTapTime = 0;
|
||||||
|
|
||||||
@Override
|
@SuppressLint("InflateParams") @Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
|
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
|
||||||
|
@ -25,8 +26,8 @@ public class LargeHome extends BaseWatchFace {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onTapCommand(int tapType, int x, int y, long eventTime) {
|
protected void onTapCommand(int tapType, int x, int y, long eventTime) {
|
||||||
|
if (mSgv == null) return;
|
||||||
int extra = mSgv!=null?(mSgv.getRight() - mSgv.getLeft())/2:0;
|
int extra = (mSgv.getRight() - mSgv.getLeft())/2;
|
||||||
|
|
||||||
if (tapType == TAP_TYPE_TAP&&
|
if (tapType == TAP_TYPE_TAP&&
|
||||||
x + extra >=mSgv.getLeft() &&
|
x + extra >=mSgv.getLeft() &&
|
||||||
|
@ -53,15 +54,15 @@ public class LargeHome extends BaseWatchFace {
|
||||||
R.color.dark_background : R.color.dark_mLinearLayout));
|
R.color.dark_background : R.color.dark_mLinearLayout));
|
||||||
mTime.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_mTime));
|
mTime.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_mTime));
|
||||||
mRelativeLayout.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_background));
|
mRelativeLayout.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_background));
|
||||||
if (rawData.sgvLevel == 1) {
|
if (singleBg.getSgvLevel() == 1) {
|
||||||
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor));
|
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor));
|
||||||
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor));
|
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor));
|
||||||
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor));
|
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor));
|
||||||
} else if (rawData.sgvLevel == 0) {
|
} else if (singleBg.getSgvLevel() == 0) {
|
||||||
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
|
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
|
||||||
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
|
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
|
||||||
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
|
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
|
||||||
} else if (rawData.sgvLevel == -1) {
|
} else if (singleBg.getSgvLevel() == -1) {
|
||||||
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor));
|
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor));
|
||||||
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor));
|
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor));
|
||||||
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor));
|
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor));
|
||||||
|
@ -74,7 +75,7 @@ public class LargeHome extends BaseWatchFace {
|
||||||
mTimestamp.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_TimestampOld));
|
mTimestamp.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_TimestampOld));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rawData.batteryLevel == 1) {
|
if (status.getBatteryLevel() == 1) {
|
||||||
mUploaderBattery.setTextColor(ContextCompat.getColor(getApplicationContext(), dividerMatchesBg ?
|
mUploaderBattery.setTextColor(ContextCompat.getColor(getApplicationContext(), dividerMatchesBg ?
|
||||||
R.color.dark_midColor : R.color.dark_uploaderBattery));
|
R.color.dark_midColor : R.color.dark_uploaderBattery));
|
||||||
} else {
|
} else {
|
||||||
|
@ -90,15 +91,15 @@ public class LargeHome extends BaseWatchFace {
|
||||||
mLinearLayout.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), dividerMatchesBg ?
|
mLinearLayout.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), dividerMatchesBg ?
|
||||||
R.color.light_background : R.color.light_stripe_background));
|
R.color.light_background : R.color.light_stripe_background));
|
||||||
mRelativeLayout.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.light_background));
|
mRelativeLayout.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.light_background));
|
||||||
if (rawData.sgvLevel == 1) {
|
if (singleBg.getSgvLevel() == 1) {
|
||||||
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_highColor));
|
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_highColor));
|
||||||
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_highColor));
|
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_highColor));
|
||||||
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_highColor));
|
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_highColor));
|
||||||
} else if (rawData.sgvLevel == 0) {
|
} else if (singleBg.getSgvLevel() == 0) {
|
||||||
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_midColor));
|
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_midColor));
|
||||||
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_midColor));
|
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_midColor));
|
||||||
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_midColor));
|
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_midColor));
|
||||||
} else if (rawData.sgvLevel == -1) {
|
} else if (singleBg.getSgvLevel() == -1) {
|
||||||
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_lowColor));
|
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_lowColor));
|
||||||
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_lowColor));
|
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_lowColor));
|
||||||
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_lowColor));
|
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_lowColor));
|
||||||
|
@ -110,7 +111,7 @@ public class LargeHome extends BaseWatchFace {
|
||||||
mTimestamp.setTextColor(Color.RED);
|
mTimestamp.setTextColor(Color.RED);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rawData.batteryLevel == 1) {
|
if (status.getBatteryLevel() == 1) {
|
||||||
mUploaderBattery.setTextColor(dividerMatchesBg ? Color.BLACK : Color.WHITE);
|
mUploaderBattery.setTextColor(dividerMatchesBg ? Color.BLACK : Color.WHITE);
|
||||||
} else {
|
} else {
|
||||||
mUploaderBattery.setTextColor(Color.RED);
|
mUploaderBattery.setTextColor(Color.RED);
|
||||||
|
@ -120,15 +121,15 @@ public class LargeHome extends BaseWatchFace {
|
||||||
} else {
|
} else {
|
||||||
mRelativeLayout.setBackgroundColor(Color.BLACK);
|
mRelativeLayout.setBackgroundColor(Color.BLACK);
|
||||||
mLinearLayout.setBackgroundColor(dividerMatchesBg ? Color.BLACK : Color.LTGRAY);
|
mLinearLayout.setBackgroundColor(dividerMatchesBg ? Color.BLACK : Color.LTGRAY);
|
||||||
if (rawData.sgvLevel == 1) {
|
if (singleBg.getSgvLevel() == 1) {
|
||||||
mSgv.setTextColor(Color.YELLOW);
|
mSgv.setTextColor(Color.YELLOW);
|
||||||
mDirection.setTextColor(Color.YELLOW);
|
mDirection.setTextColor(Color.YELLOW);
|
||||||
mDelta.setTextColor(Color.YELLOW);
|
mDelta.setTextColor(Color.YELLOW);
|
||||||
} else if (rawData.sgvLevel == 0) {
|
} else if (singleBg.getSgvLevel() == 0) {
|
||||||
mSgv.setTextColor(Color.WHITE);
|
mSgv.setTextColor(Color.WHITE);
|
||||||
mDirection.setTextColor(Color.WHITE);
|
mDirection.setTextColor(Color.WHITE);
|
||||||
mDelta.setTextColor(Color.WHITE);
|
mDelta.setTextColor(Color.WHITE);
|
||||||
} else if (rawData.sgvLevel == -1) {
|
} else if (singleBg.getSgvLevel() == -1) {
|
||||||
mSgv.setTextColor(Color.RED);
|
mSgv.setTextColor(Color.RED);
|
||||||
mDirection.setTextColor(Color.RED);
|
mDirection.setTextColor(Color.RED);
|
||||||
mDelta.setTextColor(Color.RED);
|
mDelta.setTextColor(Color.RED);
|
||||||
|
|
|
@ -1,29 +1,17 @@
|
||||||
package info.nightscout.androidaps.watchfaces;
|
package info.nightscout.androidaps.watchfaces;
|
||||||
|
|
||||||
import android.content.BroadcastReceiver;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Color;
|
|
||||||
import android.graphics.LinearGradient;
|
|
||||||
import android.graphics.Matrix;
|
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.Point;
|
import android.graphics.Point;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.graphics.Shader;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.os.SystemClock;
|
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
|
||||||
import android.support.wearable.view.WatchViewStub;
|
import android.support.wearable.view.WatchViewStub;
|
||||||
import android.support.wearable.watchface.WatchFaceStyle;
|
import android.support.wearable.watchface.WatchFaceStyle;
|
||||||
import android.text.format.DateFormat;
|
import android.text.format.DateFormat;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.Display;
|
import android.view.Display;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
@ -32,56 +20,60 @@ import android.view.WindowManager;
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.google.android.gms.wearable.DataMap;
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
import com.ustwo.clockwise.common.WatchFaceTime;
|
import com.ustwo.clockwise.common.WatchFaceTime;
|
||||||
import com.ustwo.clockwise.common.WatchMode;
|
import com.ustwo.clockwise.common.WatchMode;
|
||||||
import com.ustwo.clockwise.common.WatchShape;
|
import com.ustwo.clockwise.common.WatchShape;
|
||||||
import com.ustwo.clockwise.wearable.WatchFace;
|
import com.ustwo.clockwise.wearable.WatchFace;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import dagger.android.AndroidInjection;
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.data.BasalWatchData;
|
import info.nightscout.androidaps.events.EventWearToMobile;
|
||||||
import info.nightscout.androidaps.data.BgWatchData;
|
|
||||||
import info.nightscout.androidaps.data.DataLayerListenerService;
|
|
||||||
import info.nightscout.androidaps.data.TempWatchData;
|
|
||||||
import info.nightscout.androidaps.interaction.menus.MainMenuActivity;
|
import info.nightscout.androidaps.interaction.menus.MainMenuActivity;
|
||||||
|
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||||
|
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.weardata.EventData;
|
||||||
|
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by adrianLxM.
|
* Created by adrianLxM.
|
||||||
*/
|
*/
|
||||||
public class NOChart extends WatchFace implements SharedPreferences.OnSharedPreferenceChangeListener {
|
public class NOChart extends WatchFace {
|
||||||
public final static IntentFilter INTENT_FILTER;
|
|
||||||
|
@Inject RxBus rxBus;
|
||||||
|
@Inject AapsSchedulers aapsSchedulers;
|
||||||
|
@Inject AAPSLogger aapsLogger;
|
||||||
|
@Inject SP sp;
|
||||||
|
|
||||||
|
CompositeDisposable disposable = new CompositeDisposable();
|
||||||
|
|
||||||
|
private EventData.SingleBg singleBg;
|
||||||
|
private EventData.Status status;
|
||||||
|
|
||||||
public static final int SCREENSIZE_SMALL = 280;
|
public static final int SCREENSIZE_SMALL = 280;
|
||||||
public TextView mTime, mSgv, mTimestamp, mDelta, mAvgDelta;
|
public TextView mTime, mSgv, mTimestamp, mDelta, mAvgDelta;
|
||||||
public RelativeLayout mRelativeLayout;
|
public RelativeLayout mRelativeLayout;
|
||||||
public long sgvLevel = 0;
|
public long sgvLevel = 0;
|
||||||
public int batteryLevel = 1;
|
|
||||||
public int ageLevel = 1;
|
public int ageLevel = 1;
|
||||||
public boolean lowResMode = false;
|
public boolean lowResMode = false;
|
||||||
public boolean layoutSet = false;
|
public boolean layoutSet = false;
|
||||||
public long datetime;
|
|
||||||
public ArrayList<BgWatchData> bgDataList = new ArrayList<>();
|
|
||||||
public ArrayList<TempWatchData> tempWatchDataList = new ArrayList<>();
|
|
||||||
public ArrayList<BasalWatchData> basalWatchDataList = new ArrayList<>();
|
|
||||||
public PowerManager.WakeLock wakeLock;
|
public PowerManager.WakeLock wakeLock;
|
||||||
public View layoutView;
|
public View layoutView;
|
||||||
private final Point displaySize = new Point();
|
private final Point displaySize = new Point();
|
||||||
private int specW, specH;
|
private int specW, specH;
|
||||||
private int animationAngle = 0;
|
|
||||||
private boolean isAnimated = false;
|
|
||||||
|
|
||||||
private LocalBroadcastManager localBroadcastManager;
|
|
||||||
private MessageReceiver messageReceiver;
|
|
||||||
|
|
||||||
protected SharedPreferences sharedPrefs;
|
|
||||||
private String sgvString = "--";
|
|
||||||
private String externalStatusString = "no status";
|
|
||||||
private TextView statusView;
|
private TextView statusView;
|
||||||
private long sgvTapTime = 0L;
|
private long sgvTapTime = 0L;
|
||||||
|
|
||||||
@Override
|
@SuppressLint("InflateParams") @Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
|
AndroidInjection.inject(this);
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE))
|
Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE))
|
||||||
.getDefaultDisplay();
|
.getDefaultDisplay();
|
||||||
|
@ -92,17 +84,60 @@ public class NOChart extends WatchFace implements SharedPreferences.OnSharedPref
|
||||||
View.MeasureSpec.EXACTLY);
|
View.MeasureSpec.EXACTLY);
|
||||||
specH = View.MeasureSpec.makeMeasureSpec(displaySize.y,
|
specH = View.MeasureSpec.makeMeasureSpec(displaySize.y,
|
||||||
View.MeasureSpec.EXACTLY);
|
View.MeasureSpec.EXACTLY);
|
||||||
sharedPrefs = PreferenceManager
|
|
||||||
.getDefaultSharedPreferences(this);
|
|
||||||
sharedPrefs.registerOnSharedPreferenceChangeListener(this);
|
|
||||||
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||||
layoutView = inflater.inflate(R.layout.activity_nochart, null);
|
|
||||||
DisplayMetrics metrics = getResources().getDisplayMetrics();
|
DisplayMetrics metrics = getResources().getDisplayMetrics();
|
||||||
if(metrics.widthPixels < SCREENSIZE_SMALL || metrics.heightPixels < SCREENSIZE_SMALL){
|
if (metrics.widthPixels < SCREENSIZE_SMALL || metrics.heightPixels < SCREENSIZE_SMALL) {
|
||||||
layoutView = inflater.inflate(R.layout.activity_nochart_small, null);
|
layoutView = inflater.inflate(R.layout.activity_nochart_small, null);
|
||||||
} else {
|
} else {
|
||||||
layoutView = inflater.inflate(R.layout.activity_nochart, null);
|
layoutView = inflater.inflate(R.layout.activity_nochart, null);
|
||||||
}
|
}
|
||||||
|
disposable.add(rxBus
|
||||||
|
.toObservable(EventData.SingleBg.class)
|
||||||
|
.observeOn(aapsSchedulers.getMain())
|
||||||
|
.subscribe(event -> {
|
||||||
|
aapsLogger.debug(LTag.WEAR, "SingleBg received");
|
||||||
|
singleBg = event;
|
||||||
|
|
||||||
|
mSgv.setText(singleBg.getSgvString());
|
||||||
|
if (ageLevel() <= 0)
|
||||||
|
mSgv.setPaintFlags(mSgv.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
|
||||||
|
else mSgv.setPaintFlags(mSgv.getPaintFlags() & ~Paint.STRIKE_THRU_TEXT_FLAG);
|
||||||
|
final java.text.DateFormat timeFormat = DateFormat.getTimeFormat(this);
|
||||||
|
mTime.setText(timeFormat.format(System.currentTimeMillis()));
|
||||||
|
mDelta.setText(singleBg.getDelta());
|
||||||
|
mAvgDelta.setText(singleBg.getAvgDelta());
|
||||||
|
})
|
||||||
|
);
|
||||||
|
disposable.add(rxBus
|
||||||
|
.toObservable(EventData.Status.class)
|
||||||
|
.observeOn(aapsSchedulers.getMain())
|
||||||
|
.subscribe(event -> {
|
||||||
|
// this event is received as last batch of data
|
||||||
|
aapsLogger.debug(LTag.WEAR, "Status received");
|
||||||
|
status = event;
|
||||||
|
showAgeAndStatus();
|
||||||
|
mRelativeLayout.measure(specW, specH);
|
||||||
|
mRelativeLayout.layout(0, 0, mRelativeLayout.getMeasuredWidth(),
|
||||||
|
mRelativeLayout.getMeasuredHeight());
|
||||||
|
invalidate();
|
||||||
|
setColor();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
disposable.add(rxBus
|
||||||
|
.toObservable(EventData.Preferences.class)
|
||||||
|
.observeOn(aapsSchedulers.getMain())
|
||||||
|
.subscribe(event -> {
|
||||||
|
setColor();
|
||||||
|
if (layoutSet) {
|
||||||
|
showAgeAndStatus();
|
||||||
|
mRelativeLayout.measure(specW, specH);
|
||||||
|
mRelativeLayout.layout(0, 0, mRelativeLayout.getMeasuredWidth(),
|
||||||
|
mRelativeLayout.getMeasuredHeight());
|
||||||
|
}
|
||||||
|
invalidate();
|
||||||
|
})
|
||||||
|
);
|
||||||
performViewSetup();
|
performViewSetup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,44 +149,37 @@ public class NOChart extends WatchFace implements SharedPreferences.OnSharedPref
|
||||||
|
|
||||||
public void performViewSetup() {
|
public void performViewSetup() {
|
||||||
final WatchViewStub stub = layoutView.findViewById(R.id.watch_view_stub);
|
final WatchViewStub stub = layoutView.findViewById(R.id.watch_view_stub);
|
||||||
IntentFilter messageFilter = new IntentFilter(Intent.ACTION_SEND);
|
|
||||||
|
|
||||||
messageReceiver = new MessageReceiver();
|
stub.setOnLayoutInflatedListener(stub1 -> {
|
||||||
localBroadcastManager = LocalBroadcastManager.getInstance(this);
|
mTime = stub1.findViewById(R.id.watch_time);
|
||||||
localBroadcastManager.registerReceiver(messageReceiver, messageFilter);
|
mSgv = stub1.findViewById(R.id.sgv);
|
||||||
|
mTimestamp = stub1.findViewById(R.id.timestamp);
|
||||||
stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
|
mDelta = stub1.findViewById(R.id.delta);
|
||||||
@Override
|
mAvgDelta = stub1.findViewById(R.id.avgdelta);
|
||||||
public void onLayoutInflated(WatchViewStub stub) {
|
mRelativeLayout = stub1.findViewById(R.id.main_layout);
|
||||||
mTime = stub.findViewById(R.id.watch_time);
|
statusView = stub1.findViewById(R.id.aps_status);
|
||||||
mSgv = stub.findViewById(R.id.sgv);
|
layoutSet = true;
|
||||||
mTimestamp = stub.findViewById(R.id.timestamp);
|
showAgeAndStatus();
|
||||||
mDelta = stub.findViewById(R.id.delta);
|
mRelativeLayout.measure(specW, specH);
|
||||||
mAvgDelta = stub.findViewById(R.id.avgdelta);
|
mRelativeLayout.layout(0, 0, mRelativeLayout.getMeasuredWidth(),
|
||||||
mRelativeLayout = stub.findViewById(R.id.main_layout);
|
mRelativeLayout.getMeasuredHeight());
|
||||||
statusView = stub.findViewById(R.id.aps_status);
|
|
||||||
layoutSet = true;
|
|
||||||
showAgeAndStatus();
|
|
||||||
mRelativeLayout.measure(specW, specH);
|
|
||||||
mRelativeLayout.layout(0, 0, mRelativeLayout.getMeasuredWidth(),
|
|
||||||
mRelativeLayout.getMeasuredHeight());
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
DataLayerListenerService.Companion.requestData(this);
|
rxBus.send(new EventWearToMobile(new EventData.ActionResendData("NOChart" +
|
||||||
|
":performViewSetup")));
|
||||||
wakeLock.acquire(50);
|
wakeLock.acquire(50);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onTapCommand(int tapType, int x, int y, long eventTime) {
|
protected void onTapCommand(int tapType, int x, int y, long eventTime) {
|
||||||
|
if (mSgv == null) return;
|
||||||
|
int extra = (mSgv.getRight() - mSgv.getLeft()) / 2;
|
||||||
|
|
||||||
int extra = mSgv!=null?(mSgv.getRight() - mSgv.getLeft())/2:0;
|
if (tapType == TAP_TYPE_TAP &&
|
||||||
|
x + extra >= mSgv.getLeft() &&
|
||||||
if (tapType == TAP_TYPE_TAP&&
|
x - extra <= mSgv.getRight() &&
|
||||||
x + extra >=mSgv.getLeft() &&
|
|
||||||
x - extra <= mSgv.getRight()&&
|
|
||||||
y >= mSgv.getTop() &&
|
y >= mSgv.getTop() &&
|
||||||
y <= mSgv.getBottom()){
|
y <= mSgv.getBottom()) {
|
||||||
if (eventTime - sgvTapTime < 800){
|
if (eventTime - sgvTapTime < 800) {
|
||||||
Intent intent = new Intent(this, MainMenuActivity.class);
|
Intent intent = new Intent(this, MainMenuActivity.class);
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
|
@ -162,10 +190,10 @@ public class NOChart extends WatchFace implements SharedPreferences.OnSharedPref
|
||||||
|
|
||||||
protected void onWatchModeChanged(WatchMode watchMode) {
|
protected void onWatchModeChanged(WatchMode watchMode) {
|
||||||
|
|
||||||
if(lowResMode ^ isLowRes(watchMode)){ //if there was a change in lowResMode
|
if (lowResMode ^ isLowRes(watchMode)) { //if there was a change in lowResMode
|
||||||
lowResMode = isLowRes(watchMode);
|
lowResMode = isLowRes(watchMode);
|
||||||
setColor();
|
setColor();
|
||||||
} else if (! sharedPrefs.getBoolean("dark", true)){
|
} else if (!sp.getBoolean("dark", true)) {
|
||||||
//in bright mode: different colours if active:
|
//in bright mode: different colours if active:
|
||||||
setColor();
|
setColor();
|
||||||
}
|
}
|
||||||
|
@ -177,14 +205,13 @@ public class NOChart extends WatchFace implements SharedPreferences.OnSharedPref
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected WatchFaceStyle getWatchFaceStyle(){
|
protected WatchFaceStyle getWatchFaceStyle() {
|
||||||
return new WatchFaceStyle.Builder(this).setAcceptsTapEvents(true).build();
|
return new WatchFaceStyle.Builder(this).setAcceptsTapEvents(true).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public int ageLevel() {
|
public int ageLevel() {
|
||||||
if(timeSince() <= (1000 * 60 * 12)) {
|
if (timeSince() <= (1000 * 60 * 12)) {
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -192,40 +219,30 @@ public class NOChart extends WatchFace implements SharedPreferences.OnSharedPref
|
||||||
}
|
}
|
||||||
|
|
||||||
public double timeSince() {
|
public double timeSince() {
|
||||||
return System.currentTimeMillis() - datetime;
|
return System.currentTimeMillis() - singleBg.getTimeStamp();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String readingAge(boolean shortString) {
|
public String readingAge(boolean shortString) {
|
||||||
if (datetime == 0) { return shortString?"--'":"-- Minute ago"; }
|
if (singleBg == null || singleBg.getTimeStamp() == 0) {
|
||||||
int minutesAgo = (int) Math.floor(timeSince()/(1000*60));
|
return shortString ? "--'" : "-- Minute ago";
|
||||||
if (minutesAgo == 1) {
|
|
||||||
return minutesAgo + (shortString?"'":" Minute ago");
|
|
||||||
}
|
}
|
||||||
return minutesAgo + (shortString?"'":" Minutes ago");
|
int minutesAgo = (int) Math.floor(timeSince() / (1000 * 60));
|
||||||
|
if (minutesAgo == 1) {
|
||||||
|
return minutesAgo + (shortString ? "'" : " Minute ago");
|
||||||
|
}
|
||||||
|
return minutesAgo + (shortString ? "'" : " Minutes ago");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
if(localBroadcastManager != null && messageReceiver != null){
|
disposable.clear();
|
||||||
localBroadcastManager.unregisterReceiver(messageReceiver);}
|
|
||||||
if (sharedPrefs != null){
|
|
||||||
sharedPrefs.unregisterOnSharedPreferenceChangeListener(this);
|
|
||||||
}
|
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
static {
|
|
||||||
INTENT_FILTER = new IntentFilter();
|
|
||||||
INTENT_FILTER.addAction(Intent.ACTION_TIME_TICK);
|
|
||||||
INTENT_FILTER.addAction(Intent.ACTION_TIMEZONE_CHANGED);
|
|
||||||
INTENT_FILTER.addAction(Intent.ACTION_TIME_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDraw(Canvas canvas) {
|
protected void onDraw(Canvas canvas) {
|
||||||
if(layoutSet) {
|
if (layoutSet) {
|
||||||
this.mRelativeLayout.draw(canvas);
|
this.mRelativeLayout.draw(canvas);
|
||||||
Log.d("onDraw", "draw");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,7 +254,7 @@ public class NOChart extends WatchFace implements SharedPreferences.OnSharedPref
|
||||||
mTime.setText(timeFormat.format(System.currentTimeMillis()));
|
mTime.setText(timeFormat.format(System.currentTimeMillis()));
|
||||||
showAgeAndStatus();
|
showAgeAndStatus();
|
||||||
|
|
||||||
if(ageLevel()<=0) {
|
if (ageLevel() <= 0) {
|
||||||
mSgv.setPaintFlags(mSgv.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
|
mSgv.setPaintFlags(mSgv.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
|
||||||
} else {
|
} else {
|
||||||
mSgv.setPaintFlags(mSgv.getPaintFlags() & ~Paint.STRIKE_THRU_TEXT_FLAG);
|
mSgv.setPaintFlags(mSgv.getPaintFlags() & ~Paint.STRIKE_THRU_TEXT_FLAG);
|
||||||
|
@ -250,142 +267,28 @@ public class NOChart extends WatchFace implements SharedPreferences.OnSharedPref
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class MessageReceiver extends BroadcastReceiver {
|
|
||||||
@Override
|
|
||||||
public void onReceive(Context context, Intent intent) {
|
|
||||||
Bundle bundle = intent.getBundleExtra("data");
|
|
||||||
if (layoutSet && bundle !=null) {
|
|
||||||
DataMap dataMap = DataMap.fromBundle(bundle);
|
|
||||||
wakeLock.acquire(50);
|
|
||||||
sgvLevel = dataMap.getLong("sgvLevel");
|
|
||||||
batteryLevel = dataMap.getInt("batteryLevel");
|
|
||||||
datetime = dataMap.getLong("timestamp");
|
|
||||||
sgvString = dataMap.getString("sgvString");
|
|
||||||
mSgv.setText(dataMap.getString("sgvString"));
|
|
||||||
|
|
||||||
if(ageLevel()<=0) {
|
|
||||||
mSgv.setPaintFlags(mSgv.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
|
|
||||||
} else {
|
|
||||||
mSgv.setPaintFlags(mSgv.getPaintFlags() & ~Paint.STRIKE_THRU_TEXT_FLAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
final java.text.DateFormat timeFormat = DateFormat.getTimeFormat(NOChart.this);
|
|
||||||
mTime.setText(timeFormat.format(System.currentTimeMillis()));
|
|
||||||
|
|
||||||
showAgeAndStatus();
|
|
||||||
|
|
||||||
String delta = dataMap.getString("delta");
|
|
||||||
|
|
||||||
if (delta.endsWith(" mg/dl")) {
|
|
||||||
mDelta.setText(delta.substring(0, delta.length() - 6));
|
|
||||||
} else if (delta.endsWith(" mmol/l")||delta.endsWith(" mmol")) {
|
|
||||||
mDelta.setText(delta.substring(0, delta.length() - 5));
|
|
||||||
} else {
|
|
||||||
mDelta.setText(delta);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
String avgDelta = dataMap.getString("avgDelta");
|
|
||||||
|
|
||||||
if (delta.endsWith(" mg/dl")) {
|
|
||||||
mAvgDelta.setText(avgDelta.substring(0, avgDelta.length() - 6));
|
|
||||||
} else if (avgDelta.endsWith(" mmol/l")||avgDelta.endsWith(" mmol")) {
|
|
||||||
mAvgDelta.setText(avgDelta.substring(0, avgDelta.length() - 5));
|
|
||||||
} else {
|
|
||||||
mAvgDelta.setText(avgDelta);
|
|
||||||
}
|
|
||||||
|
|
||||||
mRelativeLayout.measure(specW, specH);
|
|
||||||
mRelativeLayout.layout(0, 0, mRelativeLayout.getMeasuredWidth(),
|
|
||||||
mRelativeLayout.getMeasuredHeight());
|
|
||||||
invalidate();
|
|
||||||
setColor();
|
|
||||||
|
|
||||||
//start animation?
|
|
||||||
// dataMap.getDataMapArrayList("entries") == null -> not on "resend data".
|
|
||||||
if (!lowResMode && (sharedPrefs.getBoolean("animation", false) && dataMap.getDataMapArrayList("entries") == null && (sgvString.equals("100") || sgvString.equals("5.5") || sgvString.equals("5,5")))) {
|
|
||||||
startAnimation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//status
|
|
||||||
bundle = intent.getBundleExtra("status");
|
|
||||||
if (layoutSet && bundle != null) {
|
|
||||||
DataMap dataMap = DataMap.fromBundle(bundle);
|
|
||||||
wakeLock.acquire(50);
|
|
||||||
externalStatusString = dataMap.getString("externalStatusString");
|
|
||||||
|
|
||||||
showAgeAndStatus();
|
|
||||||
|
|
||||||
mRelativeLayout.measure(specW, specH);
|
|
||||||
mRelativeLayout.layout(0, 0, mRelativeLayout.getMeasuredWidth(),
|
|
||||||
mRelativeLayout.getMeasuredHeight());
|
|
||||||
invalidate();
|
|
||||||
setColor();
|
|
||||||
}
|
|
||||||
//basals and temps
|
|
||||||
bundle = intent.getBundleExtra("basals");
|
|
||||||
if (layoutSet && bundle != null) {
|
|
||||||
DataMap dataMap = DataMap.fromBundle(bundle);
|
|
||||||
wakeLock.acquire(500);
|
|
||||||
|
|
||||||
loadBasalsAndTemps(dataMap);
|
|
||||||
|
|
||||||
mRelativeLayout.measure(specW, specH);
|
|
||||||
mRelativeLayout.layout(0, 0, mRelativeLayout.getMeasuredWidth(),
|
|
||||||
mRelativeLayout.getMeasuredHeight());
|
|
||||||
invalidate();
|
|
||||||
setColor();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadBasalsAndTemps(DataMap dataMap) {
|
|
||||||
ArrayList<DataMap> temps = dataMap.getDataMapArrayList("temps");
|
|
||||||
if (temps != null) {
|
|
||||||
tempWatchDataList = new ArrayList<>();
|
|
||||||
for (DataMap temp : temps) {
|
|
||||||
TempWatchData twd = new TempWatchData();
|
|
||||||
twd.startTime = temp.getLong("starttime");
|
|
||||||
twd.startBasal = temp.getDouble("startBasal");
|
|
||||||
twd.endTime = temp.getLong("endtime");
|
|
||||||
twd.endBasal = temp.getDouble("endbasal");
|
|
||||||
twd.amount = temp.getDouble("amount");
|
|
||||||
tempWatchDataList.add(twd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ArrayList<DataMap> basals = dataMap.getDataMapArrayList("basals");
|
|
||||||
if (basals != null) {
|
|
||||||
basalWatchDataList = new ArrayList<>();
|
|
||||||
for (DataMap basal : basals) {
|
|
||||||
BasalWatchData bwd = new BasalWatchData();
|
|
||||||
bwd.startTime = basal.getLong("starttime");
|
|
||||||
bwd.endTime = basal.getLong("endtime");
|
|
||||||
bwd.amount = basal.getDouble("amount");
|
|
||||||
basalWatchDataList.add(bwd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showAgeAndStatus() {
|
private void showAgeAndStatus() {
|
||||||
|
|
||||||
if( mTimestamp != null){
|
if (mTimestamp != null) {
|
||||||
mTimestamp.setText(readingAge(true));
|
mTimestamp.setText(readingAge(true));
|
||||||
}
|
}
|
||||||
boolean showAvgDelta = sharedPrefs.getBoolean("showAvgDelta", true);
|
boolean showAvgDelta = sp.getBoolean("showAvgDelta", true);
|
||||||
|
|
||||||
if(showAvgDelta){
|
if (showAvgDelta) {
|
||||||
mAvgDelta.setVisibility(View.VISIBLE);
|
mAvgDelta.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
mAvgDelta.setVisibility(View.GONE);
|
mAvgDelta.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
statusView.setText(externalStatusString);
|
if (status != null) {
|
||||||
|
statusView.setText(status.getExternalStatus());
|
||||||
statusView.setVisibility(View.VISIBLE);
|
statusView.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setColor() {
|
public void setColor() {
|
||||||
if(lowResMode){
|
if (lowResMode) {
|
||||||
setColorLowRes();
|
setColorLowRes();
|
||||||
} else if (sharedPrefs.getBoolean("dark", true)) {
|
} else if (sp.getBoolean("dark", true)) {
|
||||||
setColorDark();
|
setColorDark();
|
||||||
} else {
|
} else {
|
||||||
setColorBright();
|
setColorBright();
|
||||||
|
@ -393,62 +296,6 @@ public class NOChart extends WatchFace implements SharedPreferences.OnSharedPref
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key){
|
|
||||||
setColor();
|
|
||||||
if(layoutSet){
|
|
||||||
showAgeAndStatus();
|
|
||||||
mRelativeLayout.measure(specW, specH);
|
|
||||||
mRelativeLayout.layout(0, 0, mRelativeLayout.getMeasuredWidth(),
|
|
||||||
mRelativeLayout.getMeasuredHeight());
|
|
||||||
}
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void updateRainbow() {
|
|
||||||
animationAngle = (animationAngle + 1) % 360;
|
|
||||||
//Animation matrix:
|
|
||||||
int[] rainbow = {Color.RED, Color.YELLOW, Color.GREEN, Color.BLUE
|
|
||||||
, Color.CYAN};
|
|
||||||
Shader shader = new LinearGradient(0, 0, 0, 20, rainbow,
|
|
||||||
null, Shader.TileMode.MIRROR);
|
|
||||||
Matrix matrix = new Matrix();
|
|
||||||
matrix.setRotate(animationAngle);
|
|
||||||
shader.setLocalMatrix(matrix);
|
|
||||||
mSgv.getPaint().setShader(shader);
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized void setIsAnimated(boolean isAnimated) {
|
|
||||||
this.isAnimated = isAnimated;
|
|
||||||
}
|
|
||||||
|
|
||||||
void startAnimation() {
|
|
||||||
Log.d("CircleWatchface", "start startAnimation");
|
|
||||||
|
|
||||||
Thread animator = new Thread() {
|
|
||||||
|
|
||||||
|
|
||||||
public void run() {
|
|
||||||
setIsAnimated(true);
|
|
||||||
for (int i = 0; i <= 8 * 1000 / 40; i++) {
|
|
||||||
updateRainbow();
|
|
||||||
SystemClock.sleep(40);
|
|
||||||
}
|
|
||||||
mSgv.getPaint().setShader(null);
|
|
||||||
setIsAnimated(false);
|
|
||||||
invalidate();
|
|
||||||
setColor();
|
|
||||||
|
|
||||||
System.gc();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
animator.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setColorLowRes() {
|
protected void setColorLowRes() {
|
||||||
mTime.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_mTime));
|
mTime.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_mTime));
|
||||||
statusView.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_statusView));
|
statusView.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_statusView));
|
||||||
|
@ -516,9 +363,11 @@ 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) {
|
||||||
DataLayerListenerService.Companion.requestData(this); // attempt endTime recover missing data
|
// attempt endTime recover missing data
|
||||||
|
rxBus.send(new EventWearToMobile(new EventData.ActionResendData("NOChart" +
|
||||||
|
":missedReadingAlert")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
package info.nightscout.androidaps.watchfaces;
|
package info.nightscout.androidaps.watchfaces;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
import android.support.wearable.watchface.WatchFaceStyle;
|
import android.support.wearable.watchface.WatchFaceStyle;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.animation.Animation;
|
import android.view.animation.Animation;
|
||||||
import android.view.animation.LinearInterpolator;
|
import android.view.animation.LinearInterpolator;
|
||||||
import android.view.animation.RotateAnimation;
|
import android.view.animation.RotateAnimation;
|
||||||
|
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.interaction.menus.MainMenuActivity;
|
import info.nightscout.androidaps.interaction.menus.MainMenuActivity;
|
||||||
import info.nightscout.shared.SafeParse;
|
import info.nightscout.shared.SafeParse;
|
||||||
|
@ -23,7 +25,7 @@ public class Steampunk extends BaseWatchFace {
|
||||||
private float lastEndDegrees = 0f;
|
private float lastEndDegrees = 0f;
|
||||||
private float deltaRotationAngle = 0f;
|
private float deltaRotationAngle = 0f;
|
||||||
|
|
||||||
@Override
|
@SuppressLint("InflateParams") @Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
forceSquareCanvas = true;
|
forceSquareCanvas = true;
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
|
@ -35,22 +37,22 @@ public class Steampunk extends BaseWatchFace {
|
||||||
@Override
|
@Override
|
||||||
protected void onTapCommand(int tapType, int x, int y, long eventTime) {
|
protected void onTapCommand(int tapType, int x, int y, long eventTime) {
|
||||||
|
|
||||||
if (tapType == TAP_TYPE_TAP&&
|
if (tapType == TAP_TYPE_TAP &&
|
||||||
x >= mChartTap.getLeft() &&
|
x >= mChartTap.getLeft() &&
|
||||||
x <= mChartTap.getRight()&&
|
x <= mChartTap.getRight() &&
|
||||||
y >= mChartTap.getTop() &&
|
y >= mChartTap.getTop() &&
|
||||||
y <= mChartTap.getBottom()){
|
y <= mChartTap.getBottom()) {
|
||||||
if (eventTime - chartTapTime < 800){
|
if (eventTime - chartTapTime < 800) {
|
||||||
changeChartTimeframe();
|
changeChartTimeframe();
|
||||||
}
|
}
|
||||||
chartTapTime = eventTime;
|
chartTapTime = eventTime;
|
||||||
|
|
||||||
} else if (tapType == TAP_TYPE_TAP&&
|
} else if (tapType == TAP_TYPE_TAP &&
|
||||||
x >= mMainMenuTap.getLeft() &&
|
x >= mMainMenuTap.getLeft() &&
|
||||||
x <= mMainMenuTap.getRight()&&
|
x <= mMainMenuTap.getRight() &&
|
||||||
y >= mMainMenuTap.getTop() &&
|
y >= mMainMenuTap.getTop() &&
|
||||||
y <= mMainMenuTap.getBottom()){
|
y <= mMainMenuTap.getBottom()) {
|
||||||
if (eventTime - mainMenuTapTime < 800){
|
if (eventTime - mainMenuTapTime < 800) {
|
||||||
Intent intent = new Intent(this, MainMenuActivity.class);
|
Intent intent = new Intent(this, MainMenuActivity.class);
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
|
@ -67,7 +69,7 @@ public class Steampunk extends BaseWatchFace {
|
||||||
protected void setColorDark() {
|
protected void setColorDark() {
|
||||||
|
|
||||||
if (mLinearLayout2 != null) {
|
if (mLinearLayout2 != null) {
|
||||||
if (ageLevel() <= 0 && rawData.datetime != 0) {
|
if (ageLevel() <= 0 && singleBg.getTimeStamp() != 0) {
|
||||||
mLinearLayout2.setBackgroundResource(R.drawable.redline);
|
mLinearLayout2.setBackgroundResource(R.drawable.redline);
|
||||||
mTimestamp.setTextColor(getResources().getColor(R.color.red_600));
|
mTimestamp.setTextColor(getResources().getColor(R.color.red_600));
|
||||||
} else {
|
} else {
|
||||||
|
@ -84,30 +86,32 @@ public class Steampunk extends BaseWatchFace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rawData.sSgv.equals("---")) {
|
if (!singleBg.getSgvString().equals("---")) {
|
||||||
|
|
||||||
float rotationAngle = 0f; //by default, show ? on the dial (? is at 0 degrees on the dial)
|
float rotationAngle = 0f; //by default, show ? on the dial (? is at 0 degrees on the dial)
|
||||||
|
|
||||||
if (!rawData.sUnits.equals("-")) {
|
if (!singleBg.getGlucoseUnits().equals("-")) {
|
||||||
|
|
||||||
//ensure the glucose dial is the correct units
|
//ensure the glucose dial is the correct units
|
||||||
if (rawData.sUnits.equals("mmol")) {
|
if (singleBg.getGlucoseUnits().equals("mmol")) {
|
||||||
mGlucoseDial.setImageResource(R.drawable.steampunk_dial_mmol);
|
mGlucoseDial.setImageResource(R.drawable.steampunk_dial_mmol);
|
||||||
} else {
|
} else {
|
||||||
mGlucoseDial.setImageResource(R.drawable.steampunk_dial_mgdl);
|
mGlucoseDial.setImageResource(R.drawable.steampunk_dial_mgdl);
|
||||||
}
|
}
|
||||||
|
|
||||||
//convert the Sgv to degrees of rotation
|
//convert the Sgv to degrees of rotation
|
||||||
if (rawData.sUnits.equals("mmol")) {
|
if (singleBg.getGlucoseUnits().equals("mmol")) {
|
||||||
rotationAngle = Float.valueOf(rawData.sSgv) * 18f; //convert to mg/dL, which is equivalent to degrees
|
rotationAngle = SafeParse.stringToFloat(singleBg.getSgvString()) * 18f; //convert to
|
||||||
|
// mg/dL, which is equivalent to degrees
|
||||||
} else {
|
} else {
|
||||||
rotationAngle = Float.valueOf(rawData.sSgv); //if glucose a value is received, use it to determine the amount of rotation of the dial.
|
rotationAngle = SafeParse.stringToFloat(singleBg.getSgvString()); //if glucose a value is received, use it to determine the amount of rotation of the dial.
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rotationAngle > 330) rotationAngle = 330; //if the glucose value is higher than 330 then show "HIGH" on the dial. ("HIGH" is at 330 degrees on the dial)
|
if (rotationAngle > 330)
|
||||||
if (rotationAngle != 0 && rotationAngle < 30) rotationAngle = 30; //if the glucose value is lower than 30 show "LOW" on the dial. ("LOW" is at 30 degrees on the dial)
|
rotationAngle = 330; //if the glucose value is higher than 330 then show "HIGH" on the dial. ("HIGH" is at 330 degrees on the dial)
|
||||||
|
if (rotationAngle != 0 && rotationAngle < 30)
|
||||||
|
rotationAngle = 30; //if the glucose value is lower than 30 show "LOW" on the dial. ("LOW" is at 30 degrees on the dial)
|
||||||
if (lastEndDegrees == 0) lastEndDegrees = rotationAngle;
|
if (lastEndDegrees == 0) lastEndDegrees = rotationAngle;
|
||||||
|
|
||||||
//rotate glucose dial
|
//rotate glucose dial
|
||||||
|
@ -124,51 +128,54 @@ public class Steampunk extends BaseWatchFace {
|
||||||
|
|
||||||
//set the delta gauge and rotate the delta pointer
|
//set the delta gauge and rotate the delta pointer
|
||||||
float deltaIsNegative = 1f; //by default go clockwise
|
float deltaIsNegative = 1f; //by default go clockwise
|
||||||
if (!rawData.sAvgDelta.equals("--")) { //if a legitimate delta value is received, then...
|
if (!singleBg.getAvgDelta().equals("--")) { //if a legitimate delta value is
|
||||||
if (rawData.sAvgDelta.charAt(0) == '-') deltaIsNegative = -1f; //if the delta is negative, go counter-clockwise
|
// received,
|
||||||
Float AbssAvgDelta = SafeParse.stringToFloat(rawData.sAvgDelta.substring(1)) ; //get rid of the sign so it can be converted to float.
|
// then...
|
||||||
String autogranularity = "0" ; //autogranularity off
|
if (singleBg.getAvgDelta().charAt(0) == '-')
|
||||||
|
deltaIsNegative = -1f; //if the delta is negative, go counter-clockwise
|
||||||
|
Float AbssAvgDelta = SafeParse.stringToFloat(singleBg.getAvgDelta().substring(1)); //get rid of the sign so it can be converted to float.
|
||||||
|
String autogranularity = "0"; //autogranularity off
|
||||||
//ensure the delta gauge is the right units and granularity
|
//ensure the delta gauge is the right units and granularity
|
||||||
if (!rawData.sUnits.equals("-")) {
|
if (!singleBg.getGlucoseUnits().equals("-")) {
|
||||||
if (rawData.sUnits.equals("mmol")) {
|
if (singleBg.getGlucoseUnits().equals("mmol")) {
|
||||||
if (sharedPrefs.getString("delta_granularity", "2").equals("4")) { //Auto granularity
|
if (sp.getString("delta_granularity", "2").equals("4")) { //Auto granularity
|
||||||
autogranularity = "1"; // low (init)
|
autogranularity = "1"; // low (init)
|
||||||
if (AbssAvgDelta < 0.3 ) {
|
if (AbssAvgDelta < 0.3) {
|
||||||
autogranularity = "3" ; // high if below 0.3 mmol/l
|
autogranularity = "3"; // high if below 0.3 mmol/l
|
||||||
} else if (AbssAvgDelta < 0.5) {
|
} else if (AbssAvgDelta < 0.5) {
|
||||||
autogranularity = "2" ; // medium if below 0.5 mmol/l
|
autogranularity = "2"; // medium if below 0.5 mmol/l
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sharedPrefs.getString("delta_granularity", "2").equals("1") || autogranularity.equals("1")) { //low
|
if (sp.getString("delta_granularity", "2").equals("1") || autogranularity.equals("1")) { //low
|
||||||
mLinearLayout.setBackgroundResource(R.drawable.steampunk_gauge_mmol_10);
|
mLinearLayout.setBackgroundResource(R.drawable.steampunk_gauge_mmol_10);
|
||||||
deltaRotationAngle = (AbssAvgDelta * 30f);
|
deltaRotationAngle = (AbssAvgDelta * 30f);
|
||||||
}
|
}
|
||||||
if (sharedPrefs.getString("delta_granularity", "2").equals("2") || autogranularity.equals("2")) { //medium
|
if (sp.getString("delta_granularity", "2").equals("2") || autogranularity.equals("2")) { //medium
|
||||||
mLinearLayout.setBackgroundResource(R.drawable.steampunk_gauge_mmol_05);
|
mLinearLayout.setBackgroundResource(R.drawable.steampunk_gauge_mmol_05);
|
||||||
deltaRotationAngle = (AbssAvgDelta * 60f);
|
deltaRotationAngle = (AbssAvgDelta * 60f);
|
||||||
}
|
}
|
||||||
if (sharedPrefs.getString("delta_granularity", "2").equals("3") || autogranularity.equals("3")) { //high
|
if (sp.getString("delta_granularity", "2").equals("3") || autogranularity.equals("3")) { //high
|
||||||
mLinearLayout.setBackgroundResource(R.drawable.steampunk_gauge_mmol_03);
|
mLinearLayout.setBackgroundResource(R.drawable.steampunk_gauge_mmol_03);
|
||||||
deltaRotationAngle = (AbssAvgDelta * 100f);
|
deltaRotationAngle = (AbssAvgDelta * 100f);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (sharedPrefs.getString("delta_granularity", "2").equals("4")) { //Auto granularity
|
if (sp.getString("delta_granularity", "2").equals("4")) { //Auto granularity
|
||||||
autogranularity = "1"; // low (init)
|
autogranularity = "1"; // low (init)
|
||||||
if (AbssAvgDelta < 5 ) {
|
if (AbssAvgDelta < 5) {
|
||||||
autogranularity = "3" ; // high if below 5 mg/dl
|
autogranularity = "3"; // high if below 5 mg/dl
|
||||||
} else if (AbssAvgDelta < 10) {
|
} else if (AbssAvgDelta < 10) {
|
||||||
autogranularity = "2" ; // medium if below 10 mg/dl
|
autogranularity = "2"; // medium if below 10 mg/dl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sharedPrefs.getString("delta_granularity", "2").equals("1") || autogranularity.equals("1")) { //low
|
if (sp.getString("delta_granularity", "2").equals("1") || autogranularity.equals("1")) { //low
|
||||||
mLinearLayout.setBackgroundResource(R.drawable.steampunk_gauge_mgdl_20);
|
mLinearLayout.setBackgroundResource(R.drawable.steampunk_gauge_mgdl_20);
|
||||||
deltaRotationAngle = (AbssAvgDelta * 1.5f);
|
deltaRotationAngle = (AbssAvgDelta * 1.5f);
|
||||||
}
|
}
|
||||||
if (sharedPrefs.getString("delta_granularity", "2").equals("2") || autogranularity.equals("2")) { //medium
|
if (sp.getString("delta_granularity", "2").equals("2") || autogranularity.equals("2")) { //medium
|
||||||
mLinearLayout.setBackgroundResource(R.drawable.steampunk_gauge_mgdl_10);
|
mLinearLayout.setBackgroundResource(R.drawable.steampunk_gauge_mgdl_10);
|
||||||
deltaRotationAngle = (AbssAvgDelta * 3f);
|
deltaRotationAngle = (AbssAvgDelta * 3f);
|
||||||
}
|
}
|
||||||
if (sharedPrefs.getString("delta_granularity", "2").equals("3") || autogranularity.equals("3")) { //high
|
if (sp.getString("delta_granularity", "2").equals("3") || autogranularity.equals("3")) { //high
|
||||||
mLinearLayout.setBackgroundResource(R.drawable.steampunk_gauge_mgdl_5);
|
mLinearLayout.setBackgroundResource(R.drawable.steampunk_gauge_mgdl_5);
|
||||||
deltaRotationAngle = (AbssAvgDelta * 6f);
|
deltaRotationAngle = (AbssAvgDelta * 6f);
|
||||||
}
|
}
|
||||||
|
@ -179,10 +186,10 @@ public class Steampunk extends BaseWatchFace {
|
||||||
}
|
}
|
||||||
|
|
||||||
//rotate the minute hand.
|
//rotate the minute hand.
|
||||||
mMinuteHand.setRotation(Float.valueOf(sMinute) * 6f);
|
mMinuteHand.setRotation(Float.parseFloat(sMinute) * 6f);
|
||||||
|
|
||||||
//rotate the hour hand.
|
//rotate the hour hand.
|
||||||
mHourHand.setRotation((Float.valueOf(sHour) * 30f) + (Float.valueOf(sMinute) * 0.5f));
|
mHourHand.setRotation((Float.parseFloat(sHour) * 30f) + (Float.parseFloat(sMinute) * 0.5f));
|
||||||
|
|
||||||
setTextSizes();
|
setTextSizes();
|
||||||
|
|
||||||
|
@ -197,7 +204,7 @@ public class Steampunk extends BaseWatchFace {
|
||||||
gridColor = ContextCompat.getColor(getApplicationContext(), R.color.grey_steampunk);
|
gridColor = ContextCompat.getColor(getApplicationContext(), R.color.grey_steampunk);
|
||||||
basalBackgroundColor = ContextCompat.getColor(getApplicationContext(), R.color.basal_dark);
|
basalBackgroundColor = ContextCompat.getColor(getApplicationContext(), R.color.basal_dark);
|
||||||
basalCenterColor = ContextCompat.getColor(getApplicationContext(), R.color.basal_dark);
|
basalCenterColor = ContextCompat.getColor(getApplicationContext(), R.color.basal_dark);
|
||||||
if (Integer.parseInt(sharedPrefs.getString("chart_timeframe", "3")) < 3) {
|
if (sp.getInt("chart_timeframe", 3) < 3) {
|
||||||
pointSize = 2;
|
pointSize = 2;
|
||||||
} else {
|
} else {
|
||||||
pointSize = 1;
|
pointSize = 1;
|
||||||
|
@ -232,7 +239,7 @@ public class Steampunk extends BaseWatchFace {
|
||||||
//top row. large font unless text too big (i.e. detailedIOB)
|
//top row. large font unless text too big (i.e. detailedIOB)
|
||||||
mCOB2.setTextSize(fontLarge);
|
mCOB2.setTextSize(fontLarge);
|
||||||
mBasalRate.setTextSize(fontLarge);
|
mBasalRate.setTextSize(fontLarge);
|
||||||
if (rawData.sIOB2.length() < 7) {
|
if (status.getIobDetail().length() < 7) {
|
||||||
mIOB2.setTextSize(fontLarge);
|
mIOB2.setTextSize(fontLarge);
|
||||||
} else {
|
} else {
|
||||||
mIOB2.setTextSize(fontSmall);
|
mIOB2.setTextSize(fontSmall);
|
||||||
|
@ -248,7 +255,8 @@ public class Steampunk extends BaseWatchFace {
|
||||||
}
|
}
|
||||||
|
|
||||||
//if both batteries are shown, make them smaller.
|
//if both batteries are shown, make them smaller.
|
||||||
if (sharedPrefs.getBoolean("show_uploader_battery", true) && sharedPrefs.getBoolean("show_rig_battery", false)) {
|
if (sp.getBoolean("show_uploader_battery", true) && sp.getBoolean(
|
||||||
|
"show_rig_battery", false)) {
|
||||||
mUploaderBattery.setTextSize(fontSmall);
|
mUploaderBattery.setTextSize(fontSmall);
|
||||||
mRigBattery.setTextSize(fontSmall);
|
mRigBattery.setTextSize(fontSmall);
|
||||||
} else {
|
} else {
|
||||||
|
@ -258,14 +266,14 @@ public class Steampunk extends BaseWatchFace {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void changeChartTimeframe() {
|
private void changeChartTimeframe() {
|
||||||
int timeframe = Integer.parseInt(sharedPrefs.getString("chart_timeframe", "3"));
|
int timeframe = sp.getInt("chart_timeframe", 3);
|
||||||
timeframe = (timeframe%5) + 1;
|
timeframe = (timeframe % 5) + 1;
|
||||||
if (timeframe < 3) {
|
if (timeframe < 3) {
|
||||||
pointSize = 2;
|
pointSize = 2;
|
||||||
} else {
|
} else {
|
||||||
pointSize = 1;
|
pointSize = 1;
|
||||||
}
|
}
|
||||||
setupCharts();
|
setupCharts();
|
||||||
sharedPrefs.edit().putString("chart_timeframe", "" + timeframe).apply();
|
sp.putString("chart_timeframe", "" + timeframe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,12 +170,6 @@
|
||||||
<string name="bolus_progress_silent_channel_name">AAPS Bolus Progress Silent</string>
|
<string name="bolus_progress_silent_channel_name">AAPS Bolus Progress Silent</string>
|
||||||
<string name="bolus_progress_channel_description">Bolus progress and cancel</string>
|
<string name="bolus_progress_channel_description">Bolus progress and cancel</string>
|
||||||
<string name="bolus_progress_silent_channel_description">Bolus progress and cancel with less vibrations</string>
|
<string name="bolus_progress_silent_channel_description">Bolus progress and cancel with less vibrations</string>
|
||||||
<string name="key_quickwizard" translatable="false">QuickWizard</string>
|
|
||||||
<string name="key_wear_control" translatable="false">wearcontrol</string>
|
|
||||||
<string name="key_units_mgdl" translatable="false">units_mgdl</string>
|
|
||||||
<string name="key_boluswizard_percentage" translatable="false">boluswizard_percentage</string>
|
|
||||||
<string name="key_treatmentssafety_maxcarbs" translatable="false">treatmentssafety_maxcarbs</string>
|
|
||||||
<string name="key_treatmentssafety_maxbolus" translatable="false">treatmentssafety_maxbolus</string>
|
|
||||||
<string name="simple_ui_off">Off</string>
|
<string name="simple_ui_off">Off</string>
|
||||||
<string name="simple_ui_charging">During Charging</string>
|
<string name="simple_ui_charging">During Charging</string>
|
||||||
<string name="simple_ui_always_on">Always On Mode</string>
|
<string name="simple_ui_always_on">Always On Mode</string>
|
||||||
|
@ -189,6 +183,15 @@
|
||||||
<string name="tile_no_config">No config available</string>
|
<string name="tile_no_config">No config available</string>
|
||||||
<string name="wear_control_not_enabled">Wear controls disabled</string>
|
<string name="wear_control_not_enabled">Wear controls disabled</string>
|
||||||
<string name="wear_control_no_data">No data available</string>
|
<string name="wear_control_no_data">No data available</string>
|
||||||
<string name="key_quick_wizard_data_map" translatable="false">quick_wizard_data_map</string>
|
|
||||||
|
<string name="key_quickwizard" translatable="false">QuickWizard</string>
|
||||||
|
<string name="key_wear_control" translatable="false">wearcontrol</string>
|
||||||
|
<string name="key_units_mgdl" translatable="false">units_mgdl</string>
|
||||||
|
<string name="key_boluswizard_percentage" translatable="false">boluswizard_percentage</string>
|
||||||
|
<string name="key_treatmentssafety_maxcarbs" translatable="false">treatmentssafety_maxcarbs</string>
|
||||||
|
<string name="key_treatmentssafety_maxbolus" translatable="false">treatmentssafety_maxbolus</string>
|
||||||
|
<string name="key_quick_wizard_data" translatable="false">quick_wizard_data</string>
|
||||||
|
<string name="key_prime_fill" translatable="false">primefill</string>
|
||||||
|
<string name="key_show_wizard" translatable="false">showWizard</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -1,97 +0,0 @@
|
||||||
package info.nightscout.androidaps.data;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertFalse;
|
|
||||||
import static org.junit.Assert.assertNotEquals;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.TestBase;
|
|
||||||
import info.nightscout.androidaps.interaction.utils.Constants;
|
|
||||||
import info.nightscout.androidaps.testing.mockers.WearUtilMocker;
|
|
||||||
|
|
||||||
public class BgWatchDataTest extends TestBase {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void bgWatchDataHashTest() {
|
|
||||||
// GIVEN
|
|
||||||
BgWatchData inserted = new BgWatchData(
|
|
||||||
88.0, 160.0, 90.0,
|
|
||||||
WearUtilMocker.REF_NOW - Constants.MINUTE_IN_MS * 4, 1
|
|
||||||
);
|
|
||||||
Set<BgWatchData> set = new HashSet<>();
|
|
||||||
|
|
||||||
// THEN
|
|
||||||
//noinspection ConstantConditions
|
|
||||||
assertFalse(set.contains(inserted));
|
|
||||||
set.add(inserted);
|
|
||||||
assertTrue(set.contains(inserted));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* BgWatchData has BIZARRE equals - only timestamp and color are checked!
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void bgWatchDataEqualsTest() {
|
|
||||||
// GIVEN
|
|
||||||
BgWatchData item1 = new BgWatchData(
|
|
||||||
88.0, 160.0, 90.0,
|
|
||||||
WearUtilMocker.REF_NOW - Constants.MINUTE_IN_MS, 1
|
|
||||||
);
|
|
||||||
|
|
||||||
BgWatchData item2sameTimeSameColor = new BgWatchData(
|
|
||||||
123.0, 190, 90.0,
|
|
||||||
WearUtilMocker.REF_NOW - Constants.MINUTE_IN_MS, 1
|
|
||||||
);
|
|
||||||
|
|
||||||
BgWatchData item3sameTimeSameDiffColor = new BgWatchData(
|
|
||||||
96.0, 190, 90.0,
|
|
||||||
WearUtilMocker.REF_NOW - Constants.MINUTE_IN_MS, 0
|
|
||||||
);
|
|
||||||
BgWatchData item4differentTime = new BgWatchData(
|
|
||||||
88.0, 160.0, 90.0,
|
|
||||||
WearUtilMocker.REF_NOW - Constants.MINUTE_IN_MS * 2, 1
|
|
||||||
);
|
|
||||||
|
|
||||||
// THEN
|
|
||||||
assertEquals(item1, item2sameTimeSameColor);
|
|
||||||
assertNotEquals(item1, item3sameTimeSameDiffColor);
|
|
||||||
assertNotEquals(item1, item4differentTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* BgWatchData is ordered by timestamp, reverse order
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void bgWatchDataCompareTest() {
|
|
||||||
// GIVEN
|
|
||||||
BgWatchData item1 = new BgWatchData(
|
|
||||||
85, 160.0, 90.0,
|
|
||||||
WearUtilMocker.REF_NOW - Constants.MINUTE_IN_MS * 2, 1
|
|
||||||
);
|
|
||||||
|
|
||||||
BgWatchData item2 = new BgWatchData(
|
|
||||||
80, 190, 90.0,
|
|
||||||
WearUtilMocker.REF_NOW, 1
|
|
||||||
);
|
|
||||||
|
|
||||||
BgWatchData item3 = new BgWatchData(
|
|
||||||
80, 190, 50.0,
|
|
||||||
WearUtilMocker.REF_NOW + Constants.MINUTE_IN_MS * 5, 0
|
|
||||||
);
|
|
||||||
|
|
||||||
BgWatchData item4 = new BgWatchData(
|
|
||||||
160, 140, 70.0,
|
|
||||||
WearUtilMocker.REF_NOW, 0
|
|
||||||
);
|
|
||||||
|
|
||||||
// THEN
|
|
||||||
assertTrue(item2.compareTo(item1) < 0);
|
|
||||||
assertTrue(item2.compareTo(item3) > 0);
|
|
||||||
assertEquals(0, item2.compareTo(item4));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,123 +0,0 @@
|
||||||
package info.nightscout.androidaps.data;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.os.Bundle;
|
|
||||||
|
|
||||||
import com.google.android.gms.wearable.DataMap;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.TestBase;
|
|
||||||
import info.nightscout.androidaps.interaction.utils.Constants;
|
|
||||||
import info.nightscout.androidaps.testing.mockers.WearUtilMocker;
|
|
||||||
import info.nightscout.androidaps.testing.mocks.BundleMock;
|
|
||||||
import info.nightscout.androidaps.testing.mocks.IntentMock;
|
|
||||||
|
|
||||||
public class RawDataSgvDisplayDataTest extends TestBase {
|
|
||||||
|
|
||||||
//==============================================================================================
|
|
||||||
// SGV DATA
|
|
||||||
//==============================================================================================
|
|
||||||
|
|
||||||
private DataMap dataMapForData() {
|
|
||||||
DataMap dataMap = new DataMap();
|
|
||||||
dataMap.putLong("sgvLevel", 1L);
|
|
||||||
dataMap.putLong("timestamp", WearUtilMocker.REF_NOW - Constants.MINUTE_IN_MS);
|
|
||||||
dataMap.putString("sgvString", "106");
|
|
||||||
dataMap.putString("slopeArrow", "↗");
|
|
||||||
dataMap.putString("delta", "5.4");
|
|
||||||
dataMap.putString("avgDelta", "3.7");
|
|
||||||
dataMap.putString("glucoseUnits", "mg/dl");
|
|
||||||
return dataMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void assertDataEmpty(RawDisplayData newRaw) {
|
|
||||||
assertEquals(newRaw.sgvLevel, 0L);
|
|
||||||
assertEquals(newRaw.datetime, 0L);
|
|
||||||
assertEquals(newRaw.sSgv, "---");
|
|
||||||
assertEquals(newRaw.sDirection, "--");
|
|
||||||
assertEquals(newRaw.sDelta, "--");
|
|
||||||
assertEquals(newRaw.sAvgDelta, "--");
|
|
||||||
assertEquals(newRaw.sUnits, "-");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void assertDataOk(RawDisplayData newRaw) {
|
|
||||||
assertEquals(newRaw.sgvLevel, 1L);
|
|
||||||
assertEquals(newRaw.datetime, WearUtilMocker.REF_NOW - Constants.MINUTE_IN_MS);
|
|
||||||
assertEquals(newRaw.sSgv, "106");
|
|
||||||
assertEquals(newRaw.sDirection, "↗");
|
|
||||||
assertEquals(newRaw.sDelta, "5.4");
|
|
||||||
assertEquals(newRaw.sAvgDelta, "3.7");
|
|
||||||
assertEquals(newRaw.sUnits, "mg/dl");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void updateDataFromEmptyPersistenceTest() {
|
|
||||||
// GIVEN
|
|
||||||
RawDisplayData newRaw = new RawDisplayData(getWearUtil());
|
|
||||||
|
|
||||||
// WHEN
|
|
||||||
newRaw.updateFromPersistence(persistence);
|
|
||||||
|
|
||||||
// THEN
|
|
||||||
assertDataEmpty(newRaw);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void updateDataFromPersistenceTest() {
|
|
||||||
// GIVEN
|
|
||||||
RawDisplayData newRaw = new RawDisplayData(getWearUtil());
|
|
||||||
|
|
||||||
// WHEN
|
|
||||||
persistence.storeDataMap(RawDisplayData.DATA_PERSISTENCE_KEY, dataMapForData());
|
|
||||||
newRaw.updateFromPersistence(persistence);
|
|
||||||
|
|
||||||
// THEN
|
|
||||||
assertDataOk(newRaw);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void partialUpdateDataFromPersistenceTest() {
|
|
||||||
// GIVEN
|
|
||||||
RawDisplayData newRaw = new RawDisplayData(getWearUtil());
|
|
||||||
|
|
||||||
// WHEN
|
|
||||||
persistence.storeDataMap(RawDisplayData.DATA_PERSISTENCE_KEY, dataMapForData());
|
|
||||||
newRaw.updateForComplicationsFromPersistence(persistence);
|
|
||||||
|
|
||||||
// THEN
|
|
||||||
assertDataOk(newRaw);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void updateDataFromMessageTest() {
|
|
||||||
// GIVEN
|
|
||||||
Intent intent = IntentMock.mock();
|
|
||||||
Bundle bundle = BundleMock.mock(dataMapForData());
|
|
||||||
|
|
||||||
intent.putExtra("data", bundle);
|
|
||||||
RawDisplayData newRaw = new RawDisplayData(getWearUtil());
|
|
||||||
|
|
||||||
// WHEN
|
|
||||||
newRaw.updateDataFromMessage(intent, null);
|
|
||||||
|
|
||||||
// THEN
|
|
||||||
assertDataOk(newRaw);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void updateDataFromEmptyMessageTest() {
|
|
||||||
// GIVEN
|
|
||||||
Intent intent = IntentMock.mock();
|
|
||||||
RawDisplayData newRaw = new RawDisplayData(getWearUtil());
|
|
||||||
|
|
||||||
// WHEN
|
|
||||||
newRaw.updateDataFromMessage(intent, null);
|
|
||||||
|
|
||||||
// THEN
|
|
||||||
assertDataEmpty(newRaw);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,242 +0,0 @@
|
||||||
package info.nightscout.androidaps.data;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.os.Bundle;
|
|
||||||
|
|
||||||
import com.google.android.gms.wearable.DataMap;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.TestBase;
|
|
||||||
import info.nightscout.androidaps.interaction.utils.Constants;
|
|
||||||
import info.nightscout.androidaps.testing.mockers.WearUtilMocker;
|
|
||||||
import info.nightscout.androidaps.testing.mocks.BundleMock;
|
|
||||||
import info.nightscout.androidaps.testing.mocks.IntentMock;
|
|
||||||
import info.nightscout.androidaps.testing.utils.BasalWatchDataExt;
|
|
||||||
import info.nightscout.androidaps.testing.utils.BgWatchDataExt;
|
|
||||||
import info.nightscout.androidaps.testing.utils.BolusWatchDataExt;
|
|
||||||
import info.nightscout.androidaps.testing.utils.TempWatchDataExt;
|
|
||||||
|
|
||||||
@SuppressWarnings("SpellCheckingInspection")
|
|
||||||
public class RawDisplayDataBasalsTest extends TestBase {
|
|
||||||
|
|
||||||
|
|
||||||
//==============================================================================================
|
|
||||||
// BASALS for chart
|
|
||||||
//==============================================================================================
|
|
||||||
|
|
||||||
private DataMap dataMapForBasals() {
|
|
||||||
|
|
||||||
DataMap dataMap = new DataMap();
|
|
||||||
|
|
||||||
ArrayList<DataMap> temps = new ArrayList<>();
|
|
||||||
DataMap temp = new DataMap();
|
|
||||||
temp.putLong("starttime", WearUtilMocker.REF_NOW - Constants.MINUTE_IN_MS * 20);
|
|
||||||
temp.putDouble("startBasal", 1.5);
|
|
||||||
temp.putLong("endtime", WearUtilMocker.REF_NOW - Constants.MINUTE_IN_MS * 10);
|
|
||||||
temp.putDouble("endbasal", 1.5);
|
|
||||||
temp.putDouble("amount", 1.8);
|
|
||||||
temps.add(temp);
|
|
||||||
|
|
||||||
DataMap temp2 = new DataMap();
|
|
||||||
temp2.putLong("starttime", WearUtilMocker.REF_NOW - Constants.MINUTE_IN_MS * 10);
|
|
||||||
temp2.putDouble("startBasal", 1.3);
|
|
||||||
temp2.putLong("endtime", WearUtilMocker.REF_NOW - Constants.MINUTE_IN_MS * 2);
|
|
||||||
temp2.putDouble("endbasal", 1.3);
|
|
||||||
temp2.putDouble("amount", 2.3);
|
|
||||||
temps.add(temp2);
|
|
||||||
dataMap.putDataMapArrayList("temps", temps);
|
|
||||||
|
|
||||||
ArrayList<DataMap> basals = new ArrayList<>();
|
|
||||||
DataMap basal = new DataMap();
|
|
||||||
basal.putLong("starttime", WearUtilMocker.REF_NOW - Constants.MINUTE_IN_MS * 20);
|
|
||||||
basal.putLong("endtime", WearUtilMocker.REF_NOW - Constants.MINUTE_IN_MS * 2);
|
|
||||||
basal.putDouble("amount", 1.2);
|
|
||||||
basals.add(basal);
|
|
||||||
dataMap.putDataMapArrayList("basals", basals);
|
|
||||||
|
|
||||||
ArrayList<DataMap> boluses = new ArrayList<>();
|
|
||||||
DataMap bolus = new DataMap();
|
|
||||||
bolus.putLong("date", WearUtilMocker.REF_NOW - Constants.MINUTE_IN_MS * 17);
|
|
||||||
bolus.putDouble("bolus", 5.5);
|
|
||||||
bolus.putDouble("carbs", 20.0);
|
|
||||||
bolus.putBoolean("isSMB", false);
|
|
||||||
bolus.putBoolean("isValid", true);
|
|
||||||
boluses.add(bolus);
|
|
||||||
|
|
||||||
DataMap bolus2 = new DataMap();
|
|
||||||
bolus2.putLong("date", WearUtilMocker.REF_NOW - Constants.MINUTE_IN_MS * 11);
|
|
||||||
bolus2.putDouble("bolus", 3.0);
|
|
||||||
bolus2.putDouble("carbs", 0.0);
|
|
||||||
bolus2.putBoolean("isSMB", false);
|
|
||||||
bolus2.putBoolean("isValid", true);
|
|
||||||
boluses.add(bolus2);
|
|
||||||
|
|
||||||
DataMap bolus3 = new DataMap();
|
|
||||||
bolus3.putLong("date", WearUtilMocker.REF_NOW - Constants.MINUTE_IN_MS * 3);
|
|
||||||
bolus3.putDouble("bolus", 0.0);
|
|
||||||
bolus3.putDouble("carbs", 15.0);
|
|
||||||
bolus3.putBoolean("isSMB", true);
|
|
||||||
bolus3.putBoolean("isValid", false);
|
|
||||||
boluses.add(bolus3);
|
|
||||||
|
|
||||||
dataMap.putDataMapArrayList("boluses", boluses);
|
|
||||||
|
|
||||||
ArrayList<DataMap> predictions = new ArrayList<>();
|
|
||||||
for (int i = 0; i < 10; i++) {
|
|
||||||
DataMap prediction = new DataMap();
|
|
||||||
prediction.putLong("timestamp", WearUtilMocker.REF_NOW + Constants.MINUTE_IN_MS * i);
|
|
||||||
prediction.putDouble("sgv", 160 - 4 * i);
|
|
||||||
prediction.putInt("color", 0);
|
|
||||||
predictions.add(prediction);
|
|
||||||
}
|
|
||||||
dataMap.putDataMapArrayList("predictions", predictions);
|
|
||||||
|
|
||||||
return dataMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void assertBasalsEmpty(RawDisplayData newRaw) {
|
|
||||||
assertEquals(newRaw.tempWatchDataList.size(), 0);
|
|
||||||
assertEquals(newRaw.basalWatchDataList.size(), 0);
|
|
||||||
assertEquals(newRaw.bolusWatchDataList.size(), 0);
|
|
||||||
assertEquals(newRaw.predictionList.size(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void assertBasalsOk(RawDisplayData newRaw) {
|
|
||||||
assertEquals(newRaw.tempWatchDataList.size(), 2);
|
|
||||||
assertEquals(newRaw.basalWatchDataList.size(), 1);
|
|
||||||
assertEquals(newRaw.bolusWatchDataList.size(), 3);
|
|
||||||
assertEquals(newRaw.predictionList.size(), 10);
|
|
||||||
|
|
||||||
assertEquals(new TempWatchDataExt(newRaw.tempWatchDataList.get(0)), TempWatchDataExt.build(
|
|
||||||
WearUtilMocker.REF_NOW - Constants.MINUTE_IN_MS * 20,
|
|
||||||
1.5,
|
|
||||||
WearUtilMocker.REF_NOW - Constants.MINUTE_IN_MS * 10,
|
|
||||||
1.5,
|
|
||||||
1.8
|
|
||||||
));
|
|
||||||
|
|
||||||
assertEquals(new TempWatchDataExt(newRaw.tempWatchDataList.get(1)), TempWatchDataExt.build(
|
|
||||||
WearUtilMocker.REF_NOW - Constants.MINUTE_IN_MS * 10,
|
|
||||||
1.3,
|
|
||||||
WearUtilMocker.REF_NOW - Constants.MINUTE_IN_MS * 2,
|
|
||||||
1.3,
|
|
||||||
2.3
|
|
||||||
));
|
|
||||||
|
|
||||||
assertEquals(new BasalWatchDataExt(newRaw.basalWatchDataList.get(0)), BasalWatchDataExt.build(
|
|
||||||
WearUtilMocker.REF_NOW - Constants.MINUTE_IN_MS * 20,
|
|
||||||
WearUtilMocker.REF_NOW - Constants.MINUTE_IN_MS * 2,
|
|
||||||
1.2
|
|
||||||
));
|
|
||||||
|
|
||||||
assertEquals(new BolusWatchDataExt(newRaw.bolusWatchDataList.get(0)), BolusWatchDataExt.build(
|
|
||||||
WearUtilMocker.REF_NOW - Constants.MINUTE_IN_MS * 17,
|
|
||||||
5.5,
|
|
||||||
20,
|
|
||||||
false,
|
|
||||||
true
|
|
||||||
));
|
|
||||||
|
|
||||||
assertEquals(new BolusWatchDataExt(newRaw.bolusWatchDataList.get(1)), BolusWatchDataExt.build(
|
|
||||||
WearUtilMocker.REF_NOW - Constants.MINUTE_IN_MS * 11,
|
|
||||||
3,
|
|
||||||
0,
|
|
||||||
false,
|
|
||||||
true
|
|
||||||
));
|
|
||||||
|
|
||||||
assertEquals(new BolusWatchDataExt(newRaw.bolusWatchDataList.get(2)), BolusWatchDataExt.build(
|
|
||||||
WearUtilMocker.REF_NOW - Constants.MINUTE_IN_MS * 3,
|
|
||||||
0,
|
|
||||||
15,
|
|
||||||
true,
|
|
||||||
false
|
|
||||||
));
|
|
||||||
|
|
||||||
|
|
||||||
assertEquals(new BgWatchDataExt(newRaw.predictionList.get(3)), BgWatchDataExt.build(
|
|
||||||
160 - 4 * 3,
|
|
||||||
WearUtilMocker.REF_NOW + Constants.MINUTE_IN_MS * 3,
|
|
||||||
0
|
|
||||||
));
|
|
||||||
|
|
||||||
assertEquals(new BgWatchDataExt(newRaw.predictionList.get(7)), BgWatchDataExt.build(
|
|
||||||
160 - 4 * 7,
|
|
||||||
WearUtilMocker.REF_NOW + Constants.MINUTE_IN_MS * 7,
|
|
||||||
0
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void updateBasalsFromEmptyPersistenceTest() {
|
|
||||||
// GIVEN
|
|
||||||
RawDisplayData newRaw = new RawDisplayData(getWearUtil());
|
|
||||||
|
|
||||||
// WHEN
|
|
||||||
newRaw.updateFromPersistence(persistence);
|
|
||||||
|
|
||||||
// THEN
|
|
||||||
assertBasalsEmpty(newRaw);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void updateBasalsFromPersistenceTest() {
|
|
||||||
// GIVEN
|
|
||||||
RawDisplayData newRaw = new RawDisplayData(getWearUtil());
|
|
||||||
|
|
||||||
// WHEN
|
|
||||||
persistence.storeDataMap(RawDisplayData.BASALS_PERSISTENCE_KEY, dataMapForBasals());
|
|
||||||
newRaw.updateFromPersistence(persistence);
|
|
||||||
|
|
||||||
// THEN
|
|
||||||
assertBasalsOk(newRaw);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void partialUpdateBasalsFromPersistenceTest() {
|
|
||||||
// GIVEN
|
|
||||||
RawDisplayData newRaw = new RawDisplayData(getWearUtil());
|
|
||||||
|
|
||||||
// WHEN
|
|
||||||
persistence.storeDataMap(RawDisplayData.BASALS_PERSISTENCE_KEY, dataMapForBasals());
|
|
||||||
newRaw.updateForComplicationsFromPersistence(persistence);
|
|
||||||
|
|
||||||
// THEN
|
|
||||||
assertBasalsEmpty(newRaw);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void updateBasalsFromMessageTest() {
|
|
||||||
// GIVEN
|
|
||||||
Intent intent = IntentMock.mock();
|
|
||||||
Bundle bundle = BundleMock.mock(dataMapForBasals());
|
|
||||||
|
|
||||||
intent.putExtra("basals", bundle);
|
|
||||||
RawDisplayData newRaw = new RawDisplayData(getWearUtil());
|
|
||||||
|
|
||||||
// WHEN
|
|
||||||
newRaw.updateBasalsFromMessage(intent);
|
|
||||||
|
|
||||||
// THEN
|
|
||||||
assertBasalsOk(newRaw);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void updateBasalsFromEmptyMessageTest() {
|
|
||||||
// GIVEN
|
|
||||||
Intent intent = IntentMock.mock();
|
|
||||||
RawDisplayData newRaw = new RawDisplayData(getWearUtil());
|
|
||||||
|
|
||||||
// WHEN
|
|
||||||
newRaw.updateBasalsFromMessage(intent);
|
|
||||||
|
|
||||||
// THEN
|
|
||||||
assertBasalsEmpty(newRaw);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,135 +0,0 @@
|
||||||
package info.nightscout.androidaps.data;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
import com.google.android.gms.wearable.DataMap;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.TestBase;
|
|
||||||
import info.nightscout.androidaps.interaction.utils.Constants;
|
|
||||||
import info.nightscout.androidaps.testing.mockers.WearUtilMocker;
|
|
||||||
import info.nightscout.androidaps.testing.utils.BgWatchDataExt;
|
|
||||||
|
|
||||||
@SuppressWarnings("PointlessArithmeticExpression")
|
|
||||||
public class RawDisplayDataBgEntriesTest extends TestBase {
|
|
||||||
|
|
||||||
//==============================================================================================
|
|
||||||
// ENTRIES for chart
|
|
||||||
//==============================================================================================
|
|
||||||
|
|
||||||
private DataMap dataMapForEntries() {
|
|
||||||
|
|
||||||
DataMap dataMap = new DataMap();
|
|
||||||
ArrayList<DataMap> entries = new ArrayList<>();
|
|
||||||
for (int i = 0; i < 12; i++) {
|
|
||||||
DataMap entry = new DataMap();
|
|
||||||
entry.putLong("timestamp", WearUtilMocker.REF_NOW - Constants.MINUTE_IN_MS * 4 * (16 - i));
|
|
||||||
entry.putDouble("sgvDouble", 145.0 - 5 * i);
|
|
||||||
entry.putDouble("high", 170.0);
|
|
||||||
entry.putDouble("low", 80.0);
|
|
||||||
entry.putInt("color", 0);
|
|
||||||
entries.add(entry);
|
|
||||||
}
|
|
||||||
dataMap.putDataMapArrayList("entries", entries);
|
|
||||||
|
|
||||||
return dataMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
private DataMap dataMapForEntries(long timestamp, double sgv) {
|
|
||||||
DataMap entry = new DataMap();
|
|
||||||
entry.putLong("timestamp", timestamp);
|
|
||||||
entry.putDouble("sgvDouble", sgv);
|
|
||||||
entry.putDouble("high", 160.0);
|
|
||||||
entry.putDouble("low", 90.0);
|
|
||||||
entry.putInt("color", 1);
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void addToWatchSetTest() {
|
|
||||||
// GIVEN
|
|
||||||
RawDisplayData newRaw = new RawDisplayData(getWearUtil());
|
|
||||||
DataMap multipleEntries = dataMapForEntries();
|
|
||||||
DataMap singleEntry1 = dataMapForEntries(WearUtilMocker.REF_NOW - Constants.MINUTE_IN_MS * 4 * 2, 92);
|
|
||||||
DataMap singleEntry2 = dataMapForEntries(WearUtilMocker.REF_NOW - Constants.MINUTE_IN_MS * 4 * 1, 88);
|
|
||||||
|
|
||||||
// WHEN, THEN
|
|
||||||
// add list
|
|
||||||
newRaw.addToWatchSet(multipleEntries);
|
|
||||||
assertEquals(newRaw.bgDataList.size(), 12);
|
|
||||||
|
|
||||||
assertEquals(new BgWatchDataExt(newRaw.bgDataList.get(5)),
|
|
||||||
new BgWatchDataExt(new BgWatchData(
|
|
||||||
120.0, 170.0, 80.0,
|
|
||||||
WearUtilMocker.REF_NOW - Constants.MINUTE_IN_MS * 4 * (16 - 5), 0
|
|
||||||
)));
|
|
||||||
|
|
||||||
assertEquals(new BgWatchDataExt(newRaw.bgDataList.get(11)),
|
|
||||||
new BgWatchDataExt(new BgWatchData(
|
|
||||||
90.0, 170.0, 80.0,
|
|
||||||
WearUtilMocker.REF_NOW - Constants.MINUTE_IN_MS * 4 * (16 - 11), 0
|
|
||||||
)));
|
|
||||||
|
|
||||||
// add single entries
|
|
||||||
newRaw.addToWatchSet(singleEntry1);
|
|
||||||
newRaw.addToWatchSet(singleEntry2);
|
|
||||||
assertEquals(newRaw.bgDataList.size(), 14);
|
|
||||||
|
|
||||||
assertEquals(new BgWatchDataExt(newRaw.bgDataList.get(12)),
|
|
||||||
new BgWatchDataExt(new BgWatchData(
|
|
||||||
92.0, 160.0, 90.0,
|
|
||||||
WearUtilMocker.REF_NOW - Constants.MINUTE_IN_MS * 4 * 2, 1
|
|
||||||
)));
|
|
||||||
assertEquals(new BgWatchDataExt(newRaw.bgDataList.get(13)),
|
|
||||||
new BgWatchDataExt(new BgWatchData(
|
|
||||||
88.0, 160.0, 90.0,
|
|
||||||
WearUtilMocker.REF_NOW - Constants.MINUTE_IN_MS * 4 * 1, 1
|
|
||||||
)));
|
|
||||||
|
|
||||||
// ignore duplicates
|
|
||||||
newRaw.addToWatchSet(singleEntry2);
|
|
||||||
assertEquals(newRaw.bgDataList.size(), 14);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void addToWatchSetCleanupOldTest() {
|
|
||||||
RawDisplayData newRaw = new RawDisplayData(getWearUtil());
|
|
||||||
|
|
||||||
newRaw.addToWatchSet(dataMapForEntries(getWearUtil().timestamp(), 125));
|
|
||||||
assertEquals(newRaw.bgDataList.size(), 1);
|
|
||||||
|
|
||||||
getWearUtilMocker().progressClock(Constants.HOUR_IN_MS * 2);
|
|
||||||
newRaw.addToWatchSet(dataMapForEntries(getWearUtil().timestamp(), 140));
|
|
||||||
assertEquals(newRaw.bgDataList.size(), 2);
|
|
||||||
|
|
||||||
getWearUtilMocker().progressClock(Constants.HOUR_IN_MS * 1);
|
|
||||||
newRaw.addToWatchSet(dataMapForEntries(getWearUtil().timestamp(), 150));
|
|
||||||
getWearUtilMocker().progressClock(Constants.HOUR_IN_MS * 1 + Constants.MINUTE_IN_MS * 30);
|
|
||||||
newRaw.addToWatchSet(dataMapForEntries(getWearUtil().timestamp(), 101));
|
|
||||||
assertEquals(newRaw.bgDataList.size(), 4);
|
|
||||||
|
|
||||||
getWearUtilMocker().progressClock(Constants.MINUTE_IN_MS * 30);
|
|
||||||
newRaw.addToWatchSet(dataMapForEntries(getWearUtil().timestamp(), 90));
|
|
||||||
assertEquals(newRaw.bgDataList.size(), 5);
|
|
||||||
|
|
||||||
getWearUtilMocker().progressClock(Constants.HOUR_IN_MS * 1 + Constants.MINUTE_IN_MS * 30);
|
|
||||||
newRaw.addToWatchSet(dataMapForEntries(getWearUtil().timestamp(), 80));
|
|
||||||
assertEquals(newRaw.bgDataList.size(), 5);
|
|
||||||
|
|
||||||
getWearUtilMocker().progressClock(Constants.HOUR_IN_MS * 4);
|
|
||||||
newRaw.addToWatchSet(dataMapForEntries(getWearUtil().timestamp(), 92));
|
|
||||||
assertEquals(newRaw.bgDataList.size(), 2);
|
|
||||||
|
|
||||||
getWearUtilMocker().progressClock(Constants.HOUR_IN_MS * 5 + Constants.MINUTE_IN_MS * 30);
|
|
||||||
newRaw.addToWatchSet(dataMapForEntries(getWearUtil().timestamp(), 107));
|
|
||||||
assertEquals(newRaw.bgDataList.size(), 1);
|
|
||||||
|
|
||||||
getWearUtilMocker().progressClock(Constants.HOUR_IN_MS * 6 + Constants.MINUTE_IN_MS * 30);
|
|
||||||
newRaw.addToWatchSet(dataMapForEntries(getWearUtil().timestamp() - Constants.HOUR_IN_MS * 6, 138));
|
|
||||||
assertEquals(newRaw.bgDataList.size(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,160 +0,0 @@
|
||||||
package info.nightscout.androidaps.data;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.os.Bundle;
|
|
||||||
|
|
||||||
import com.google.android.gms.wearable.DataMap;
|
|
||||||
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.TestBase;
|
|
||||||
import info.nightscout.androidaps.interaction.utils.Constants;
|
|
||||||
import info.nightscout.androidaps.testing.mockers.RawDataMocker;
|
|
||||||
import info.nightscout.androidaps.testing.mockers.WearUtilMocker;
|
|
||||||
import info.nightscout.androidaps.testing.mocks.BundleMock;
|
|
||||||
import info.nightscout.androidaps.testing.mocks.IntentMock;
|
|
||||||
|
|
||||||
@SuppressWarnings("SimplifiableAssertion")
|
|
||||||
public class RawDisplayDataStatusTest extends TestBase {
|
|
||||||
|
|
||||||
private RawDataMocker rawDataMocker;
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void mock() {
|
|
||||||
rawDataMocker = new RawDataMocker(getWearUtil());
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("AssertBetweenInconvertibleTypes") @Test
|
|
||||||
public void toDebugStringTest() {
|
|
||||||
RawDisplayData raw = rawDataMocker.rawDelta(5, "1.5");
|
|
||||||
raw.externalStatusString = "placeholder-here";
|
|
||||||
|
|
||||||
assertEquals(raw.datetime, WearUtilMocker.REF_NOW - Constants.MINUTE_IN_MS * 5);
|
|
||||||
assertTrue(raw.toDebugString().contains("placeholder-here"));
|
|
||||||
}
|
|
||||||
|
|
||||||
//==============================================================================================
|
|
||||||
// STATUS
|
|
||||||
//==============================================================================================
|
|
||||||
|
|
||||||
private DataMap dataMapForStatus() {
|
|
||||||
DataMap dataMap = new DataMap();
|
|
||||||
dataMap.putString("currentBasal", "120%");
|
|
||||||
dataMap.putString("battery", "76");
|
|
||||||
dataMap.putString("rigBattery", "40%");
|
|
||||||
dataMap.putBoolean("detailedIob", true);
|
|
||||||
dataMap.putString("iobSum", "12.5");
|
|
||||||
dataMap.putString("iobDetail", "(11,2|1,3)");
|
|
||||||
dataMap.putString("cob", "5(10)g");
|
|
||||||
dataMap.putString("bgi", "13");
|
|
||||||
dataMap.putBoolean("showBgi", false);
|
|
||||||
dataMap.putString("externalStatusString", "");
|
|
||||||
dataMap.putInt("batteryLevel", 1);
|
|
||||||
dataMap.putLong("openApsStatus", WearUtilMocker.REF_NOW - Constants.MINUTE_IN_MS * 2);
|
|
||||||
return dataMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void assertStatusEmpty(RawDisplayData newRaw) {
|
|
||||||
assertEquals(newRaw.sBasalRate, "-.--U/h");
|
|
||||||
assertEquals(newRaw.sUploaderBattery, "--");
|
|
||||||
assertEquals(newRaw.sRigBattery, "--");
|
|
||||||
assertEquals(newRaw.detailedIOB, false);
|
|
||||||
assertEquals(newRaw.sIOB1, "IOB");
|
|
||||||
assertEquals(newRaw.sIOB2, "-.--");
|
|
||||||
assertEquals(newRaw.sCOB1, "Carb");
|
|
||||||
assertEquals(newRaw.sCOB2, "--g");
|
|
||||||
assertEquals(newRaw.sBgi, "--");
|
|
||||||
assertEquals(newRaw.showBGI, false);
|
|
||||||
assertEquals(newRaw.externalStatusString, "no status");
|
|
||||||
assertEquals(newRaw.batteryLevel, 1);
|
|
||||||
assertEquals(newRaw.openApsStatus, -1L);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void assertStatusOk(RawDisplayData newRaw) {
|
|
||||||
assertEquals(newRaw.sBasalRate, "120%");
|
|
||||||
assertEquals(newRaw.sUploaderBattery, "76");
|
|
||||||
assertEquals(newRaw.sRigBattery, "40%");
|
|
||||||
assertEquals(newRaw.detailedIOB, true);
|
|
||||||
assertEquals(newRaw.sIOB1, "12.5U");
|
|
||||||
assertEquals(newRaw.sIOB2, "(11,2|1,3)");
|
|
||||||
assertEquals(newRaw.sCOB1, "Carb");
|
|
||||||
assertEquals(newRaw.sCOB2, "5(10)g");
|
|
||||||
assertEquals(newRaw.sBgi, "13");
|
|
||||||
assertEquals(newRaw.showBGI, false);
|
|
||||||
assertEquals(newRaw.externalStatusString, "");
|
|
||||||
assertEquals(newRaw.batteryLevel, 1);
|
|
||||||
assertEquals(newRaw.openApsStatus, WearUtilMocker.REF_NOW - Constants.MINUTE_IN_MS * 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void updateStatusFromEmptyPersistenceTest() {
|
|
||||||
// GIVEN
|
|
||||||
RawDisplayData newRaw = new RawDisplayData(getWearUtil());
|
|
||||||
|
|
||||||
// WHEN
|
|
||||||
newRaw.updateFromPersistence(persistence);
|
|
||||||
|
|
||||||
// THEN
|
|
||||||
assertStatusEmpty(newRaw);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void updateStatusFromPersistenceTest() {
|
|
||||||
// GIVEN
|
|
||||||
RawDisplayData newRaw = new RawDisplayData(getWearUtil());
|
|
||||||
|
|
||||||
// WHEN
|
|
||||||
persistence.storeDataMap(RawDisplayData.STATUS_PERSISTENCE_KEY, dataMapForStatus());
|
|
||||||
newRaw.updateFromPersistence(persistence);
|
|
||||||
|
|
||||||
// THEN
|
|
||||||
assertStatusOk(newRaw);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void partialUpdateStatusFromPersistenceTest() {
|
|
||||||
// GIVEN
|
|
||||||
RawDisplayData newRaw = new RawDisplayData(getWearUtil());
|
|
||||||
|
|
||||||
// WHEN
|
|
||||||
persistence.storeDataMap(RawDisplayData.STATUS_PERSISTENCE_KEY, dataMapForStatus());
|
|
||||||
newRaw.updateForComplicationsFromPersistence(persistence);
|
|
||||||
|
|
||||||
// THEN
|
|
||||||
assertStatusOk(newRaw);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void updateStatusFromMessageTest() {
|
|
||||||
// GIVEN
|
|
||||||
Intent intent = IntentMock.mock();
|
|
||||||
Bundle bundle = BundleMock.mock(dataMapForStatus());
|
|
||||||
|
|
||||||
intent.putExtra("status", bundle);
|
|
||||||
RawDisplayData newRaw = new RawDisplayData(getWearUtil());
|
|
||||||
|
|
||||||
// WHEN
|
|
||||||
newRaw.updateStatusFromMessage(intent, null);
|
|
||||||
|
|
||||||
// THEN
|
|
||||||
assertStatusOk(newRaw);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void updateStatusFromEmptyMessageTest() {
|
|
||||||
// GIVEN
|
|
||||||
Intent intent = IntentMock.mock();
|
|
||||||
RawDisplayData newRaw = new RawDisplayData(getWearUtil());
|
|
||||||
|
|
||||||
// WHEN
|
|
||||||
newRaw.updateStatusFromMessage(intent, null);
|
|
||||||
|
|
||||||
// THEN
|
|
||||||
assertStatusEmpty(newRaw);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -106,10 +106,10 @@ public class DisplayFormatTest extends TestBase {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shortTrendTest() {
|
public void shortTrendTest() {
|
||||||
RawDisplayData raw = new RawDisplayData(wearUtil);
|
RawDisplayData raw = new RawDisplayData();
|
||||||
assertEquals(displayFormat.shortTrend(raw), "-- Δ--");
|
assertEquals(displayFormat.shortTrend(raw), "-- Δ--");
|
||||||
|
|
||||||
raw.datetime = wearUtilMocker.backInTime(0, 0, 2, 0);
|
raw.getSingleBg().setTimeStamp(wearUtilMocker.backInTime(0, 0, 2, 0));
|
||||||
assertEquals(displayFormat.shortTrend(raw), "2' Δ--");
|
assertEquals(displayFormat.shortTrend(raw), "2' Δ--");
|
||||||
|
|
||||||
when(sp.getBoolean("complication_unicode", true)).thenReturn(true);
|
when(sp.getBoolean("complication_unicode", true)).thenReturn(true);
|
||||||
|
|
|
@ -2,12 +2,7 @@ package info.nightscout.androidaps.interaction.utils;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
import static org.junit.Assert.assertNull;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static info.nightscout.androidaps.testing.mockers.WearUtilMocker.REF_NOW;
|
|
||||||
|
|
||||||
import com.google.android.gms.wearable.DataMap;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@ -42,62 +37,6 @@ public class PersistenceTest extends TestBase {
|
||||||
assertTrue(updatedGot);
|
assertTrue(updatedGot);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void whenDataUpdatedTest() {
|
|
||||||
// GIVEN
|
|
||||||
DataMap map = new DataMap();
|
|
||||||
|
|
||||||
// WHEN
|
|
||||||
final long whenNotUpdated = persistence.whenDataUpdated();
|
|
||||||
|
|
||||||
persistence.storeDataMap("data-map", map);
|
|
||||||
final long whenUpdatedFirst = persistence.whenDataUpdated();
|
|
||||||
|
|
||||||
getWearUtilMocker().progressClock(60000);
|
|
||||||
persistence.storeDataMap("data-map", map);
|
|
||||||
final long whenUpdatedNext = persistence.whenDataUpdated();
|
|
||||||
|
|
||||||
// THEN
|
|
||||||
assertEquals(whenNotUpdated, 0L);
|
|
||||||
assertEquals(whenUpdatedFirst, REF_NOW);
|
|
||||||
assertEquals(whenUpdatedNext, REF_NOW + 60000);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getDataMapTest() {
|
|
||||||
// GIVEN
|
|
||||||
DataMap map = new DataMap();
|
|
||||||
map.putByteArray("test-key", new byte[]{9, 42, 127, -5});
|
|
||||||
|
|
||||||
// WHEN
|
|
||||||
DataMap notExisting = persistence.getDataMap("not-there");
|
|
||||||
persistence.storeDataMap("data-map", map);
|
|
||||||
DataMap restoredMap = persistence.getDataMap("data-map");
|
|
||||||
assert restoredMap != null;
|
|
||||||
byte[] restoredMapContents = restoredMap.getByteArray("test-key");
|
|
||||||
|
|
||||||
// THEN
|
|
||||||
assertNull(notExisting);
|
|
||||||
assertNotNull(restoredMap);
|
|
||||||
assertTrue(restoredMap.containsKey("test-key"));
|
|
||||||
|
|
||||||
assertEquals(restoredMapContents.length, 4);
|
|
||||||
assertEquals(restoredMapContents[0], (byte) 9);
|
|
||||||
assertEquals(restoredMapContents[1], (byte) 42);
|
|
||||||
assertEquals(restoredMapContents[2], (byte) 127);
|
|
||||||
assertEquals(restoredMapContents[3], (byte) -5);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void brokenDataMapTest() {
|
|
||||||
// WHEN
|
|
||||||
persistence.putString("data-map", "ZmFrZSBkYXRh");
|
|
||||||
DataMap restoredMap = persistence.getDataMap("data-map");
|
|
||||||
|
|
||||||
// THEN
|
|
||||||
assertNull(restoredMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void setsTest() {
|
public void setsTest() {
|
||||||
// WHEN
|
// WHEN
|
||||||
|
|
|
@ -4,15 +4,14 @@ import com.google.android.gms.wearable.DataMap
|
||||||
import info.nightscout.androidaps.TestBase
|
import info.nightscout.androidaps.TestBase
|
||||||
import info.nightscout.androidaps.testing.mockers.WearUtilMocker
|
import info.nightscout.androidaps.testing.mockers.WearUtilMocker
|
||||||
import info.nightscout.androidaps.testing.mocks.BundleMock
|
import info.nightscout.androidaps.testing.mocks.BundleMock
|
||||||
import org.hamcrest.CoreMatchers
|
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by dlvoy on 22.11.2019.
|
* Created by dlvoy on 22.11.2019.
|
||||||
*/
|
*/
|
||||||
@Suppress("SpellCheckingInspection") class WearUtilTest : TestBase() {
|
@Suppress("SpellCheckingInspection")
|
||||||
|
class WearUtilTest : TestBase() {
|
||||||
|
|
||||||
@Test fun timestampAndTimeDiffsTest() {
|
@Test fun timestampAndTimeDiffsTest() {
|
||||||
|
|
||||||
|
|
|
@ -3,70 +3,138 @@ package info.nightscout.androidaps.testing.mockers;
|
||||||
import info.nightscout.androidaps.data.RawDisplayData;
|
import info.nightscout.androidaps.data.RawDisplayData;
|
||||||
import info.nightscout.androidaps.interaction.utils.WearUtil;
|
import info.nightscout.androidaps.interaction.utils.WearUtil;
|
||||||
import info.nightscout.shared.SafeParse;
|
import info.nightscout.shared.SafeParse;
|
||||||
|
import info.nightscout.shared.weardata.EventData;
|
||||||
|
|
||||||
@SuppressWarnings("PointlessArithmeticExpression")
|
@SuppressWarnings("PointlessArithmeticExpression")
|
||||||
public class RawDataMocker {
|
public class RawDataMocker {
|
||||||
|
|
||||||
private final WearUtil wearUtil;
|
|
||||||
private final WearUtilMocker wearUtilMocker;
|
private final WearUtilMocker wearUtilMocker;
|
||||||
|
|
||||||
public RawDataMocker(WearUtil wearUtil) {
|
public RawDataMocker(WearUtil wearUtil) {
|
||||||
this.wearUtil = wearUtil;
|
|
||||||
wearUtilMocker = new WearUtilMocker(wearUtil);
|
wearUtilMocker = new WearUtilMocker(wearUtil);
|
||||||
}
|
}
|
||||||
|
|
||||||
public RawDisplayData rawSgv(String sgv, int m, String deltaString) {
|
public RawDisplayData rawSgv(String sgv, int m, String deltaString) {
|
||||||
RawDisplayData raw = new RawDisplayData(wearUtil);
|
RawDisplayData raw = new RawDisplayData();
|
||||||
raw.datetime = wearUtilMocker.backInTime(0, 0, m, 0);
|
|
||||||
raw.sDelta = deltaString;
|
|
||||||
raw.sSgv = sgv;
|
|
||||||
|
|
||||||
double delta = SafeParse.stringToDouble(deltaString);
|
double delta = SafeParse.stringToDouble(deltaString);
|
||||||
|
String d;
|
||||||
|
|
||||||
if (delta <= (-3.5 * 5)) {
|
if (delta <= (-3.5 * 5)) {
|
||||||
raw.sDirection = "\u21ca";
|
d = "\u21ca";
|
||||||
} else if (delta <= (-2 * 5)) {
|
} else if (delta <= (-2 * 5)) {
|
||||||
raw.sDirection = "\u2193";
|
d = "\u2193";
|
||||||
} else if (delta <= (-1 * 5)) {
|
} else if (delta <= (-1 * 5)) {
|
||||||
raw.sDirection = "\u2198";
|
d = "\u2198";
|
||||||
} else if (delta <= (1 * 5)) {
|
} else if (delta <= (1 * 5)) {
|
||||||
raw.sDirection = "\u2192";
|
d = "\u2192";
|
||||||
} else if (delta <= (2 * 5)) {
|
} else if (delta <= (2 * 5)) {
|
||||||
raw.sDirection = "\u2197";
|
d = "\u2197";
|
||||||
} else if (delta <= (3.5 * 5)) {
|
} else if (delta <= (3.5 * 5)) {
|
||||||
raw.sDirection = "\u2191";
|
d = "\u2191";
|
||||||
} else {
|
} else {
|
||||||
raw.sDirection = "\u21c8";
|
d = "\u21c8";
|
||||||
}
|
}
|
||||||
|
raw.setSingleBg(
|
||||||
|
new EventData.SingleBg(
|
||||||
|
wearUtilMocker.backInTime(0, 0, m, 0),
|
||||||
|
sgv,
|
||||||
|
"",
|
||||||
|
d,
|
||||||
|
deltaString,
|
||||||
|
"",
|
||||||
|
0,
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
0
|
||||||
|
)
|
||||||
|
);
|
||||||
return raw;
|
return raw;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RawDisplayData rawDelta(int m, String delta) {
|
public RawDisplayData rawDelta(int m, String delta) {
|
||||||
RawDisplayData raw = new RawDisplayData(wearUtil);
|
RawDisplayData raw = new RawDisplayData();
|
||||||
raw.datetime = wearUtilMocker.backInTime(0, 0, m, 0);
|
raw.setSingleBg(
|
||||||
raw.sDelta = delta;
|
new EventData.SingleBg(
|
||||||
|
wearUtilMocker.backInTime(0, 0, m, 0),
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
delta,
|
||||||
|
"",
|
||||||
|
0,
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
0
|
||||||
|
)
|
||||||
|
);
|
||||||
return raw;
|
return raw;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RawDisplayData rawCobIobBr(String cob, String iob, String br) {
|
public RawDisplayData rawCobIobBr(String cob, String iob, String br) {
|
||||||
RawDisplayData raw = new RawDisplayData(wearUtil);
|
RawDisplayData raw = new RawDisplayData();
|
||||||
raw.sCOB2 = cob;
|
raw.setStatus(
|
||||||
raw.sIOB1 = iob;
|
new EventData.Status(
|
||||||
raw.sBasalRate = br;
|
"",
|
||||||
|
iob,
|
||||||
|
"",
|
||||||
|
true,
|
||||||
|
cob,
|
||||||
|
br,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
0L,
|
||||||
|
"",
|
||||||
|
true,
|
||||||
|
0
|
||||||
|
|
||||||
|
)
|
||||||
|
);
|
||||||
return raw;
|
return raw;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RawDisplayData rawIob(String iob, String iob2) {
|
public RawDisplayData rawIob(String iob, String iob2) {
|
||||||
RawDisplayData raw = new RawDisplayData(wearUtil);
|
RawDisplayData raw = new RawDisplayData();
|
||||||
raw.sIOB1 = iob;
|
raw.setStatus(
|
||||||
raw.sIOB2 = iob2;
|
new EventData.Status(
|
||||||
|
"",
|
||||||
|
iob,
|
||||||
|
iob2,
|
||||||
|
true,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
0L,
|
||||||
|
"",
|
||||||
|
true,
|
||||||
|
0
|
||||||
|
|
||||||
|
)
|
||||||
|
);
|
||||||
return raw;
|
return raw;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RawDisplayData rawCob(String cob) {
|
public RawDisplayData rawCob(String cob) {
|
||||||
RawDisplayData raw = new RawDisplayData(wearUtil);
|
RawDisplayData raw = new RawDisplayData();
|
||||||
raw.sCOB2 = cob;
|
raw.setStatus(
|
||||||
|
new EventData.Status(
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
true,
|
||||||
|
cob,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
0L,
|
||||||
|
"",
|
||||||
|
true,
|
||||||
|
0
|
||||||
|
|
||||||
|
)
|
||||||
|
);
|
||||||
return raw;
|
return raw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,59 +0,0 @@
|
||||||
package info.nightscout.androidaps.testing.utils;
|
|
||||||
|
|
||||||
import static info.nightscout.androidaps.testing.utils.ExtUtil.assertClassHaveSameFields;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.data.BasalWatchData;
|
|
||||||
|
|
||||||
public class BasalWatchDataExt extends BasalWatchData {
|
|
||||||
|
|
||||||
private BasalWatchDataExt() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public BasalWatchDataExt(BasalWatchData ref) {
|
|
||||||
super();
|
|
||||||
|
|
||||||
// since we do not want modify BasalWatchData - we use this wrapper class
|
|
||||||
// but we make sure it has same fields
|
|
||||||
assertClassHaveSameFields(BasalWatchData.class, "startTime,endTime,amount");
|
|
||||||
|
|
||||||
this.startTime = ref.startTime;
|
|
||||||
this.endTime = ref.endTime;
|
|
||||||
this.amount = ref.amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BasalWatchDataExt build(long startTime, long endTime, double amount) {
|
|
||||||
BasalWatchDataExt bwd = new BasalWatchDataExt();
|
|
||||||
bwd.startTime = startTime;
|
|
||||||
bwd.endTime = endTime;
|
|
||||||
bwd.amount = amount;
|
|
||||||
return bwd;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(@Nullable Object obj) {
|
|
||||||
if (obj instanceof BasalWatchData) {
|
|
||||||
return (this.startTime == ((BasalWatchData) obj).startTime)
|
|
||||||
&& (this.endTime == ((BasalWatchData) obj).endTime)
|
|
||||||
&& (this.amount == ((BasalWatchData) obj).amount);
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull @Override
|
|
||||||
public String toString() {
|
|
||||||
return startTime + ", " + endTime + ", " + amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(startTime, endTime, amount);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,68 +0,0 @@
|
||||||
package info.nightscout.androidaps.testing.utils;
|
|
||||||
|
|
||||||
import static info.nightscout.androidaps.testing.utils.ExtUtil.assertClassHaveSameFields;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.data.BgWatchData;
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public class BgWatchDataExt extends BgWatchData {
|
|
||||||
|
|
||||||
private BgWatchDataExt() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public BgWatchDataExt(double aSgv, double aHigh, double aLow, long aTimestamp, int aColor) {
|
|
||||||
super(aSgv, aHigh, aLow, aTimestamp, aColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BgWatchDataExt(BgWatchData ref) {
|
|
||||||
super();
|
|
||||||
|
|
||||||
// since we do not want modify BgWatchDataExt - we use this wrapper class
|
|
||||||
// but we make sure it has same fields
|
|
||||||
assertClassHaveSameFields(BgWatchData.class, "sgv,high,low,timestamp,color");
|
|
||||||
|
|
||||||
this.sgv = ref.sgv;
|
|
||||||
this.high = ref.high;
|
|
||||||
this.low = ref.low;
|
|
||||||
this.timestamp = ref.timestamp;
|
|
||||||
this.color = ref.color;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BgWatchDataExt build(double sgv, long timestamp, int color) {
|
|
||||||
BgWatchDataExt twd = new BgWatchDataExt();
|
|
||||||
twd.sgv = sgv;
|
|
||||||
twd.timestamp = timestamp;
|
|
||||||
twd.color = color;
|
|
||||||
return twd;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(@Nullable Object obj) {
|
|
||||||
if (obj instanceof BgWatchData) {
|
|
||||||
return (this.sgv == ((BgWatchData) obj).sgv)
|
|
||||||
&& (this.high == ((BgWatchData) obj).high)
|
|
||||||
&& (this.low == ((BgWatchData) obj).low)
|
|
||||||
&& (this.timestamp == ((BgWatchData) obj).timestamp)
|
|
||||||
&& (this.color == ((BgWatchData) obj).color);
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override @NonNull
|
|
||||||
public String toString() {
|
|
||||||
return sgv + ", " + high + ", " + low + ", " + timestamp + ", " + color;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(sgv, high, low, timestamp, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,65 +0,0 @@
|
||||||
package info.nightscout.androidaps.testing.utils;
|
|
||||||
|
|
||||||
import static info.nightscout.androidaps.testing.utils.ExtUtil.assertClassHaveSameFields;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.data.BolusWatchData;
|
|
||||||
|
|
||||||
public class BolusWatchDataExt extends BolusWatchData {
|
|
||||||
|
|
||||||
private BolusWatchDataExt() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public BolusWatchDataExt(BolusWatchData ref) {
|
|
||||||
super();
|
|
||||||
|
|
||||||
// since we do not want modify BolusWatchData - we use this wrapper class
|
|
||||||
// but we make sure it has same fields
|
|
||||||
assertClassHaveSameFields(BolusWatchData.class, "date,bolus,carbs,isSMB,isValid");
|
|
||||||
|
|
||||||
this.date = ref.date;
|
|
||||||
this.bolus = ref.bolus;
|
|
||||||
this.carbs = ref.carbs;
|
|
||||||
this.isSMB = ref.isSMB;
|
|
||||||
this.isValid = ref.isValid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BolusWatchDataExt build(long date, double bolus, double carbs, boolean isSMB, boolean isValid) {
|
|
||||||
BolusWatchDataExt bwd = new BolusWatchDataExt();
|
|
||||||
bwd.date = date;
|
|
||||||
bwd.bolus = bolus;
|
|
||||||
bwd.carbs = carbs;
|
|
||||||
bwd.isSMB = isSMB;
|
|
||||||
bwd.isValid = isValid;
|
|
||||||
return bwd;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(@Nullable Object obj) {
|
|
||||||
if (obj instanceof BolusWatchData) {
|
|
||||||
return (this.date == ((BolusWatchData) obj).date)
|
|
||||||
&& (this.bolus == ((BolusWatchData) obj).bolus)
|
|
||||||
&& (this.carbs == ((BolusWatchData) obj).carbs)
|
|
||||||
&& (this.isSMB == ((BolusWatchData) obj).isSMB)
|
|
||||||
&& (this.isValid == ((BolusWatchData) obj).isValid);
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull @Override
|
|
||||||
public String toString() {
|
|
||||||
return date + ", " + bolus + ", " + carbs + ", " + isSMB + ", " + isValid;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(date, bolus, carbs, isSMB, isValid);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
package info.nightscout.androidaps.testing.utils;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
class ExtUtil {
|
|
||||||
|
|
||||||
static <T> void assertClassHaveSameFields(Class<T> checkedClass, String commaSeparatedFieldList) {
|
|
||||||
Set<String> parentFields = new HashSet<>();
|
|
||||||
for (Field f : checkedClass.getDeclaredFields()) {
|
|
||||||
final String fieldName = f.getName();
|
|
||||||
// skip runtime-injected fields like $jacocoData
|
|
||||||
if (fieldName.startsWith("$")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
parentFields.add(fieldName);
|
|
||||||
}
|
|
||||||
|
|
||||||
Set<String> knownFields = new HashSet<>(Arrays.asList(commaSeparatedFieldList.split(",")));
|
|
||||||
assertEquals(parentFields, knownFields);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,67 +0,0 @@
|
||||||
package info.nightscout.androidaps.testing.utils;
|
|
||||||
|
|
||||||
import static info.nightscout.androidaps.testing.utils.ExtUtil.assertClassHaveSameFields;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.data.TempWatchData;
|
|
||||||
|
|
||||||
|
|
||||||
public class TempWatchDataExt extends TempWatchData {
|
|
||||||
|
|
||||||
private TempWatchDataExt() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public TempWatchDataExt(TempWatchData ref) {
|
|
||||||
super();
|
|
||||||
|
|
||||||
// since we do not want modify BolusWatchData - we use this wrapper class
|
|
||||||
// but we make sure it has same fields
|
|
||||||
assertClassHaveSameFields(TempWatchData.class, "startTime,startBasal,endTime,endBasal,amount");
|
|
||||||
|
|
||||||
this.startTime = ref.startTime;
|
|
||||||
this.startBasal = ref.startBasal;
|
|
||||||
this.endTime = ref.endTime;
|
|
||||||
this.endBasal = ref.endBasal;
|
|
||||||
this.amount = ref.amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static TempWatchDataExt build(long startTime, double startBasal, long endTime,
|
|
||||||
double endBasal, double amount) {
|
|
||||||
TempWatchDataExt twd = new TempWatchDataExt();
|
|
||||||
twd.startTime = startTime;
|
|
||||||
twd.startBasal = startBasal;
|
|
||||||
twd.endTime = endTime;
|
|
||||||
twd.endBasal = endBasal;
|
|
||||||
twd.amount = amount;
|
|
||||||
return twd;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(@Nullable Object obj) {
|
|
||||||
if (obj instanceof TempWatchData) {
|
|
||||||
return (this.startTime == ((TempWatchData) obj).startTime)
|
|
||||||
&& (this.startBasal == ((TempWatchData) obj).startBasal)
|
|
||||||
&& (this.endTime == ((TempWatchData) obj).endTime)
|
|
||||||
&& (this.endBasal == ((TempWatchData) obj).endBasal)
|
|
||||||
&& (this.amount == ((TempWatchData) obj).amount);
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull @Override
|
|
||||||
public String toString() {
|
|
||||||
return startTime + ", " + startBasal + ", " + endTime + ", " + endBasal + ", " + amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(startTime, startBasal, endTime, endBasal, amount);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in a new issue