diff --git a/app/src/main/kotlin/app/aaps/MainApp.kt b/app/src/main/kotlin/app/aaps/MainApp.kt index d002697cc6f2..5c0d89c080a8 100644 --- a/app/src/main/kotlin/app/aaps/MainApp.kt +++ b/app/src/main/kotlin/app/aaps/MainApp.kt @@ -195,8 +195,10 @@ class MainApp : DaggerApplication() { if (preferences.get(UnitDoubleKey.OverviewActivityTarget) == 0.0) preferences.remove(UnitDoubleKey.OverviewActivityTarget) if (preferences.get(IntKey.OverviewHypoDuration) == 0) preferences.remove(IntKey.OverviewHypoDuration) if (preferences.get(UnitDoubleKey.OverviewHypoTarget) == 0.0) preferences.remove(UnitDoubleKey.OverviewHypoTarget) + if (preferences.get(UnitDoubleKey.OverviewVeryLowMark) == 0.0) preferences.remove(UnitDoubleKey.OverviewVeryLowMark) if (preferences.get(UnitDoubleKey.OverviewLowMark) == 0.0) preferences.remove(UnitDoubleKey.OverviewLowMark) if (preferences.get(UnitDoubleKey.OverviewHighMark) == 0.0) preferences.remove(UnitDoubleKey.OverviewHighMark) + if (preferences.get(UnitDoubleKey.OverviewVeryHighMark) == 0.0) preferences.remove(UnitDoubleKey.OverviewVeryHighMark) if (preferences.getIfExists(BooleanKey.GeneralSimpleMode) == null) preferences.put(BooleanKey.GeneralSimpleMode, !preferences.get(BooleanKey.GeneralSetupWizardProcessed)) // Migrate from OpenAPSSMBDynamicISFPlugin diff --git a/core/graph/src/main/kotlin/app/aaps/core/graph/data/InMemoryGlucoseValueDataPoint.kt b/core/graph/src/main/kotlin/app/aaps/core/graph/data/InMemoryGlucoseValueDataPoint.kt index a7780fa5919e..02fc049a0526 100644 --- a/core/graph/src/main/kotlin/app/aaps/core/graph/data/InMemoryGlucoseValueDataPoint.kt +++ b/core/graph/src/main/kotlin/app/aaps/core/graph/data/InMemoryGlucoseValueDataPoint.kt @@ -34,10 +34,14 @@ class InMemoryGlucoseValueDataPoint( @ColorInt override fun color(context: Context?): Int { val units = profileFunction.getUnits() + val veryLowLine = preferences.get(UnitDoubleKey.OverviewVeryLowMark) val lowLine = preferences.get(UnitDoubleKey.OverviewLowMark) val highLine = preferences.get(UnitDoubleKey.OverviewHighMark) + val veryHighLine = preferences.get(UnitDoubleKey.OverviewVeryHighMark) val color = when { + valueToUnits(units) < veryLowLine -> rh.gac(context, app.aaps.core.ui.R.attr.bgVeryLow) valueToUnits(units) < lowLine -> rh.gac(context, app.aaps.core.ui.R.attr.bgLow) + valueToUnits(units) > veryHighLine -> rh.gac(context, app.aaps.core.ui.R.attr.veryHighColor) valueToUnits(units) > highLine -> rh.gac(context, app.aaps.core.ui.R.attr.highColor) else -> rh.gac(context, app.aaps.core.ui.R.attr.bgInRange) } diff --git a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/overview/LastBgData.kt b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/overview/LastBgData.kt index 3440f7ec21bf..6e24df2aeab0 100644 --- a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/overview/LastBgData.kt +++ b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/overview/LastBgData.kt @@ -20,6 +20,13 @@ interface LastBgData { */ fun lastBg(): InMemoryGlucoseValue? + /** + * Is last value below display very low target? + * + * @return true if below + */ + fun isVeryLow(): Boolean + /** * Is last value below display low target? * @@ -34,6 +41,13 @@ interface LastBgData { */ fun isHigh(): Boolean + /** + * Is last value above display high very target? + * + * @return true if above + */ + fun isVeryHigh(): Boolean + /** * Evaluate color based on low - in - high * diff --git a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/rx/weardata/EventData.kt b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/rx/weardata/EventData.kt index 4f006f74b306..e7e6a4d6af44 100644 --- a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/rx/weardata/EventData.kt +++ b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/rx/weardata/EventData.kt @@ -255,8 +255,10 @@ sealed class EventData : Event() { val avgDeltaDetailed: String = "--", val sgvLevel: Long = 0, val sgv: Double, + val veryHigh: Double, // veryHighLine val high: Double, // highLine val low: Double, // lowLine + val veryLow: Double, // veryLowLine val color: Int = 0, val deltaMgdl: Double? = null, val avgDeltaMgdl: Double? = null, diff --git a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/rx/weardata/ResFormat.kt b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/rx/weardata/ResFormat.kt index 51a53aed39cf..8fc8c0817474 100644 --- a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/rx/weardata/ResFormat.kt +++ b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/rx/weardata/ResFormat.kt @@ -1,6 +1,6 @@ package app.aaps.core.interfaces.rx.weardata -const val CUSTOM_VERSION = "2.0" +const val CUSTOM_VERSION = "2.1" enum class ResFormat(val extension: String) { UNKNOWN(""), diff --git a/core/interfaces/src/test/kotlin/app/aaps/core/interfaces/rx/weardata/EventDataTest.kt b/core/interfaces/src/test/kotlin/app/aaps/core/interfaces/rx/weardata/EventDataTest.kt index 27be941de858..7f6dacfa6f70 100644 --- a/core/interfaces/src/test/kotlin/app/aaps/core/interfaces/rx/weardata/EventDataTest.kt +++ b/core/interfaces/src/test/kotlin/app/aaps/core/interfaces/rx/weardata/EventDataTest.kt @@ -140,11 +140,11 @@ class EventDataTest { assertThat(EventData.deserializeByte(it.serializeByte())).isEqualTo(it) assertThat(EventData.deserialize(it.serialize())).isEqualTo(it) } - EventData.SingleBg(dataset = 0, 1, sgv = 2.0, high = 3.0, low = 4.0).let { + EventData.SingleBg(dataset = 0, 1, sgv = 2.0, veryHigh = 5.0, high = 3.0, low = 4.0, veryLow = 6.0).let { assertThat(EventData.deserializeByte(it.serializeByte())).isEqualTo(it) assertThat(EventData.deserialize(it.serialize())).isEqualTo(it) } - EventData.GraphData(arrayListOf(EventData.SingleBg(dataset = 0, 1, sgv = 2.0, high = 3.0, low = 4.0))).let { + EventData.GraphData(arrayListOf(EventData.SingleBg(dataset = 0, 1, sgv = 2.0, veryHigh = 5.0, high = 3.0, low = 4.0, veryLow = 6.0))).let { assertThat(EventData.deserializeByte(it.serializeByte())).isEqualTo(it) assertThat(EventData.deserialize(it.serialize())).isEqualTo(it) } @@ -152,7 +152,7 @@ class EventDataTest { arrayListOf(EventData.TreatmentData.TempBasal(1, 2.0, 3, 4.0, 5.0)), arrayListOf(EventData.TreatmentData.Basal(1, 2, 3.0)), arrayListOf(EventData.TreatmentData.Treatment(1, 2.0, 3.0, true, isValid = true)), - arrayListOf(EventData.SingleBg(dataset = 0, 1, sgv = 2.0, high = 3.0, low = 4.0)) + arrayListOf(EventData.SingleBg(dataset = 0, 1, sgv = 2.0, veryHigh = 5.0, high = 3.0, low = 4.0, veryLow = 6.0)) ).let { assertThat(EventData.deserializeByte(it.serializeByte())).isEqualTo(it) assertThat(EventData.deserialize(it.serialize())).isEqualTo(it) diff --git a/core/keys/src/main/kotlin/app/aaps/core/keys/UnitDoubleKey.kt b/core/keys/src/main/kotlin/app/aaps/core/keys/UnitDoubleKey.kt index 243195a5a5aa..17b053f298e9 100644 --- a/core/keys/src/main/kotlin/app/aaps/core/keys/UnitDoubleKey.kt +++ b/core/keys/src/main/kotlin/app/aaps/core/keys/UnitDoubleKey.kt @@ -17,7 +17,9 @@ enum class UnitDoubleKey( OverviewEatingSoonTarget("eatingsoon_target", 90.0, 72, 160, defaultedBySM = true), OverviewActivityTarget("activity_target", 140.0, 108, 180, defaultedBySM = true), OverviewHypoTarget("hypo_target", 160.0, 108, 180, defaultedBySM = true), + OverviewVeryLowMark("very_low_mark", 55.0, 40, 80, showInNsClientMode = false), OverviewLowMark("low_mark", 72.0, 25, 160, showInNsClientMode = false, hideParentScreenIfHidden = true), OverviewHighMark("high_mark", 180.0, 90, 250, showInNsClientMode = false), + OverviewVeryHighMark("very_high_mark", 400.0, 200, 400, showInNsClientMode = false), ApsLgsThreshold("lgsThreshold", 65.0, 60, 100, defaultedBySM = true, dependency = BooleanKey.ApsUseDynamicSensitivity) } \ No newline at end of file diff --git a/core/ui/src/main/res/values-night/styles.xml b/core/ui/src/main/res/values-night/styles.xml index d2e283f41992..a684bbe30e81 100644 --- a/core/ui/src/main/res/values-night/styles.xml +++ b/core/ui/src/main/res/values-night/styles.xml @@ -111,8 +111,10 @@ @color/byodaGray @color/colorCalibrationButton - @color/low + @color/low + @color/high @color/high + @color/low @color/inRange @color/helperProfile diff --git a/core/ui/src/main/res/values/attrs.xml b/core/ui/src/main/res/values/attrs.xml index ef80aa97e3be..09c1e1124c25 100644 --- a/core/ui/src/main/res/values/attrs.xml +++ b/core/ui/src/main/res/values/attrs.xml @@ -87,8 +87,10 @@ + + diff --git a/core/ui/src/main/res/values/colors.xml b/core/ui/src/main/res/values/colors.xml index 8a9b23c97a8d..09965ebd532e 100644 --- a/core/ui/src/main/res/values/colors.xml +++ b/core/ui/src/main/res/values/colors.xml @@ -358,8 +358,10 @@ we generate extra colornames only used for the widget Colors for the widget are always taken from the default color.xml--> #00FF00 - #FF0000 + #FF0000 + #FFFF00 #FFFF00 + #FF0000 #f4d700 #FFFFFF #ff0400 diff --git a/core/ui/src/main/res/values/styles.xml b/core/ui/src/main/res/values/styles.xml index acf8bfb44d36..09fd738bfa38 100644 --- a/core/ui/src/main/res/values/styles.xml +++ b/core/ui/src/main/res/values/styles.xml @@ -114,8 +114,10 @@ @color/byodaGray @color/colorCalibrationButton - @color/low + @color/low + @color/high @color/high + @color/low @color/tempTargetConfirmation @color/helperProfile diff --git a/implementation/src/main/kotlin/app/aaps/implementation/overview/LastBgDataImpl.kt b/implementation/src/main/kotlin/app/aaps/implementation/overview/LastBgDataImpl.kt index 04db6298acd0..c39e7df1a90d 100644 --- a/implementation/src/main/kotlin/app/aaps/implementation/overview/LastBgDataImpl.kt +++ b/implementation/src/main/kotlin/app/aaps/implementation/overview/LastBgDataImpl.kt @@ -31,6 +31,11 @@ class LastBgDataImpl @Inject constructor( iobCobCalculator.ads.bucketedData?.firstOrNull() ?: persistenceLayer.getLastGlucoseValue()?.let { InMemoryGlucoseValue.fromGv(it) } + override fun isVeryLow(): Boolean = + lastBg()?.let { lastBg -> + lastBg.valueToUnits(profileFunction.getUnits()) < preferences.get(UnitDoubleKey.OverviewVeryLowMark) + } == true + override fun isLow(): Boolean = lastBg()?.let { lastBg -> lastBg.valueToUnits(profileFunction.getUnits()) < preferences.get(UnitDoubleKey.OverviewLowMark) @@ -41,10 +46,17 @@ class LastBgDataImpl @Inject constructor( lastBg.valueToUnits(profileFunction.getUnits()) > preferences.get(UnitDoubleKey.OverviewHighMark) } == true + override fun isVeryHigh(): Boolean = + lastBg()?.let { lastBg -> + lastBg.valueToUnits(profileFunction.getUnits()) > preferences.get(UnitDoubleKey.OverviewVeryHighMark) + } == true + @ColorInt override fun lastBgColor(context: Context?): Int = when { + isVeryLow() -> rh.gac(context, app.aaps.core.ui.R.attr.bgVeryLow) isLow() -> rh.gac(context, app.aaps.core.ui.R.attr.bgLow) + isVeryHigh() -> rh.gac(context, app.aaps.core.ui.R.attr.veryHighColor) isHigh() -> rh.gac(context, app.aaps.core.ui.R.attr.highColor) else -> rh.gac(context, app.aaps.core.ui.R.attr.bgInRange) } diff --git a/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/setupwizard/SWDefinition.kt b/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/setupwizard/SWDefinition.kt index 21d9330c5007..512579e2feef 100644 --- a/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/setupwizard/SWDefinition.kt +++ b/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/setupwizard/SWDefinition.kt @@ -133,6 +133,14 @@ class SWDefinition @Inject constructor( private val displaySettings get() = SWScreen(injector, R.string.display_settings) .skippable(false) + .add( + SWEditNumberWithUnits(injector, UnitDoubleKey.OverviewVeryLowMark.defaultValue * Constants.MGDL_TO_MMOLL, 3.0, 8.0) + .preference(UnitDoubleKey.OverviewVeryLowMark) + .updateDelay(5) + .label(R.string.very_low_mark) + .comment(R.string.very_low_mark_comment) + ) + .add(SWBreak(injector)) .add( SWEditNumberWithUnits(injector, UnitDoubleKey.OverviewLowMark.defaultValue * Constants.MGDL_TO_MMOLL, 3.0, 8.0) .preference(UnitDoubleKey.OverviewLowMark) @@ -148,6 +156,14 @@ class SWDefinition @Inject constructor( .label(R.string.high_mark) .comment(R.string.high_mark_comment) ) + .add(SWBreak(injector)) + .add( + SWEditNumberWithUnits(injector, UnitDoubleKey.OverviewVeryHighMark.defaultValue * Constants.MGDL_TO_MMOLL, 5.0, 23.0) + .preference(UnitDoubleKey.OverviewVeryHighMark) + .updateDelay(5) + .label(R.string.very_high_mark) + .comment(R.string.very_high_mark_comment) + ) private val screenPermissionWindow get() = SWScreen(injector, R.string.permission) diff --git a/plugins/configuration/src/main/res/values/strings.xml b/plugins/configuration/src/main/res/values/strings.xml index d5bbf9d7c8a4..d32a95dda3f1 100644 --- a/plugins/configuration/src/main/res/values/strings.xml +++ b/plugins/configuration/src/main/res/values/strings.xml @@ -14,10 +14,14 @@ MUST NOT BE USED TO MAKE MEDICAL DECISIONS. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. I UNDERSTAND AND AGREE Display Settings + VERY LOW mark LOW mark HIGH mark + VERY HIGH mark + Very Low value of in range area (display only) Lower value of in range area (display only) Higher value of in range area (display only) + Even Higher value of in range area (display only) Permission Application needs system window permission for notifications Application needs location permission for BT scan and WiFi identification diff --git a/plugins/main/src/main/kotlin/app/aaps/plugins/main/general/overview/OverviewPlugin.kt b/plugins/main/src/main/kotlin/app/aaps/plugins/main/general/overview/OverviewPlugin.kt index 4438cda256bf..26631ed42059 100644 --- a/plugins/main/src/main/kotlin/app/aaps/plugins/main/general/overview/OverviewPlugin.kt +++ b/plugins/main/src/main/kotlin/app/aaps/plugins/main/general/overview/OverviewPlugin.kt @@ -148,8 +148,10 @@ class OverviewPlugin @Inject constructor( .put(UnitDoubleKey.OverviewActivityTarget, preferences) .put(IntKey.OverviewHypoDuration, preferences) .put(UnitDoubleKey.OverviewHypoTarget, preferences) + .put(UnitDoubleKey.OverviewVeryLowMark, preferences) .put(UnitDoubleKey.OverviewLowMark, preferences) .put(UnitDoubleKey.OverviewHighMark, preferences) + .put(UnitDoubleKey.OverviewVeryHighMark, preferences) .put(IntKey.OverviewCageWarning, preferences) .put(IntKey.OverviewCageCritical, preferences) .put(IntKey.OverviewIageWarning, preferences) @@ -178,8 +180,10 @@ class OverviewPlugin @Inject constructor( .store(UnitDoubleKey.OverviewActivityTarget, preferences) .store(IntKey.OverviewHypoDuration, preferences) .store(UnitDoubleKey.OverviewHypoTarget, preferences) + .store(UnitDoubleKey.OverviewVeryLowMark, preferences) .store(UnitDoubleKey.OverviewLowMark, preferences) .store(UnitDoubleKey.OverviewHighMark, preferences) + .store(UnitDoubleKey.OverviewVeryHighMark, preferences) .store(IntKey.OverviewCageWarning, preferences) .store(IntKey.OverviewCageCritical, preferences) .store(IntKey.OverviewIageWarning, preferences) @@ -258,8 +262,10 @@ class OverviewPlugin @Inject constructor( key = "range_settings" summary = rh.gs(R.string.prefs_range_summary) title = rh.gs(R.string.prefs_range_title) + addPreference(AdaptiveUnitPreference(ctx = context, unitKey = UnitDoubleKey.OverviewVeryLowMark, title = R.string.very_low_mark)) addPreference(AdaptiveUnitPreference(ctx = context, unitKey = UnitDoubleKey.OverviewLowMark, title = R.string.low_mark)) addPreference(AdaptiveUnitPreference(ctx = context, unitKey = UnitDoubleKey.OverviewHighMark, title = R.string.high_mark)) + addPreference(AdaptiveUnitPreference(ctx = context, unitKey = UnitDoubleKey.OverviewVeryHighMark, title = R.string.very_high_mark)) }) addPreference(AdaptiveSwitchPreference(ctx = context, booleanKey = BooleanKey.OverviewShortTabTitles, title = R.string.short_tabtitles)) addPreference(AdaptiveSwitchPreference(ctx = context, booleanKey = BooleanKey.OverviewShowNotesInDialogs, title = R.string.overview_show_notes_field_in_dialogs_title)) diff --git a/plugins/main/src/main/res/values/strings.xml b/plugins/main/src/main/res/values/strings.xml index 56ca0bcead67..bb9cb6f6828b 100644 --- a/plugins/main/src/main/res/values/strings.xml +++ b/plugins/main/src/main/res/values/strings.xml @@ -262,8 +262,10 @@ Button 3 Range for visualization High and low mark for the charts in Overview and Smartwatch + VERY LOW mark LOW mark HIGH mark + VERY HIGH mark Shorten tab titles Show notes field in treatment dialogs Bolus wizard performs calculation but only this part of calculated insulin is delivered. Useful with SMB algorithm. diff --git a/plugins/sync/src/main/kotlin/app/aaps/plugins/sync/tizen/TizenPlugin.kt b/plugins/sync/src/main/kotlin/app/aaps/plugins/sync/tizen/TizenPlugin.kt index e261cceb120c..3b00c18be623 100644 --- a/plugins/sync/src/main/kotlin/app/aaps/plugins/sync/tizen/TizenPlugin.kt +++ b/plugins/sync/src/main/kotlin/app/aaps/plugins/sync/tizen/TizenPlugin.kt @@ -125,8 +125,10 @@ class TizenPlugin @Inject constructor( bundle.putString("slopeArrow", lastBG.trendArrow.text) // direction arrow as string bundle.putDouble("deltaMgdl", glucoseStatus.delta) // bg delta in mgdl bundle.putDouble("avgDeltaMgdl", glucoseStatus.shortAvgDelta) // average bg delta + bundle.putDouble("veryHigh", preferences.get(UnitDoubleKey.OverviewVeryHighMark)) // predefined topmost value of in range (yellow area) bundle.putDouble("high", preferences.get(UnitDoubleKey.OverviewHighMark)) // predefined top value of in range (green area) bundle.putDouble("low", preferences.get(UnitDoubleKey.OverviewLowMark)) // predefined bottom value of in range + bundle.putDouble("veryLow", preferences.get(UnitDoubleKey.OverviewVeryLowMark)) // predefined very bottom value of in range } private fun iobCob(bundle: Bundle) { diff --git a/plugins/sync/src/main/kotlin/app/aaps/plugins/sync/wear/wearintegration/DataHandlerMobile.kt b/plugins/sync/src/main/kotlin/app/aaps/plugins/sync/wear/wearintegration/DataHandlerMobile.kt index c4228a97deec..39177b8fee67 100644 --- a/plugins/sync/src/main/kotlin/app/aaps/plugins/sync/wear/wearintegration/DataHandlerMobile.kt +++ b/plugins/sync/src/main/kotlin/app/aaps/plugins/sync/wear/wearintegration/DataHandlerMobile.kt @@ -1331,8 +1331,10 @@ class DataHandlerMobile @Inject constructor( timeStamp = bg.timestamp, glucoseUnits = GlucoseUnit.MGDL.asText, sgv = bg.value, + veryHigh = 0.0, high = 0.0, low = 0.0, + veryLow = 0.0, color = predictionColor(context, bg) ) ) @@ -1466,8 +1468,17 @@ class DataHandlerMobile @Inject constructor( private fun getSingleBG(glucoseValue: InMemoryGlucoseValue): EventData.SingleBg { val glucoseStatus = glucoseStatusProvider.getGlucoseStatusData(true) val units = profileFunction.getUnits() + val veryLowLine = profileUtil.convertToMgdl(preferences.get(UnitDoubleKey.OverviewVeryLowMark), units) val lowLine = profileUtil.convertToMgdl(preferences.get(UnitDoubleKey.OverviewLowMark), units) val highLine = profileUtil.convertToMgdl(preferences.get(UnitDoubleKey.OverviewHighMark), units) + val veryHighLine = profileUtil.convertToMgdl(preferences.get(UnitDoubleKey.OverviewVeryHighMark), units) + val sgvLevel = when { + glucoseValue.recalculated > veryHighLine -> 2L + glucoseValue.recalculated > highLine -> 1L + glucoseValue.recalculated < veryLowLine -> -2L + glucoseValue.recalculated < lowLine -> -1L + else -> 0L + } return EventData.SingleBg( dataset = 0, @@ -1479,10 +1490,12 @@ class DataHandlerMobile @Inject constructor( deltaDetailed = glucoseStatus?.let { deltaStringDetailed(it.delta, it.delta * Constants.MGDL_TO_MMOLL, units) } ?: "--", avgDelta = glucoseStatus?.let { deltaString(it.shortAvgDelta, it.shortAvgDelta * Constants.MGDL_TO_MMOLL, units) } ?: "--", avgDeltaDetailed = glucoseStatus?.let { deltaStringDetailed(it.shortAvgDelta, it.shortAvgDelta * Constants.MGDL_TO_MMOLL, units) } ?: "--", - sgvLevel = if (glucoseValue.recalculated > highLine) 1L else if (glucoseValue.recalculated < lowLine) -1L else 0L, + sgvLevel = sgvLevel, sgv = glucoseValue.recalculated, + veryHigh = veryHighLine, high = highLine, low = lowLine, + veryLow = veryLowLine, color = 0, deltaMgdl = glucoseStatus?.delta, avgDeltaMgdl = glucoseStatus?.shortAvgDelta diff --git a/plugins/sync/src/test/kotlin/app/aaps/plugins/sync/tizen/TizenPluginTest.kt b/plugins/sync/src/test/kotlin/app/aaps/plugins/sync/tizen/TizenPluginTest.kt index 84430b44ea52..9d411bf0265e 100644 --- a/plugins/sync/src/test/kotlin/app/aaps/plugins/sync/tizen/TizenPluginTest.kt +++ b/plugins/sync/src/test/kotlin/app/aaps/plugins/sync/tizen/TizenPluginTest.kt @@ -82,8 +82,10 @@ internal class TizenPluginTest : TestBaseWithProfile() { assertThat(bundle.containsKey("slopeArrow")).isTrue() assertThat(bundle.containsKey("deltaMgdl")).isTrue() assertThat(bundle.containsKey("avgDeltaMgdl")).isTrue() + assertThat(bundle.containsKey("veryHigh")).isTrue() assertThat(bundle.containsKey("high")).isTrue() assertThat(bundle.containsKey("low")).isTrue() + assertThat(bundle.containsKey("veryLow")).isTrue() assertThat(bundle.containsKey("bolusIob")).isTrue() assertThat(bundle.containsKey("basalIob")).isTrue() assertThat(bundle.containsKey("iob")).isTrue() diff --git a/shared/impl/src/main/kotlin/app/aaps/shared/impl/weardata/JsonKeys.kt b/shared/impl/src/main/kotlin/app/aaps/shared/impl/weardata/JsonKeys.kt index a2475be56d26..b4f58a003de8 100644 --- a/shared/impl/src/main/kotlin/app/aaps/shared/impl/weardata/JsonKeys.kt +++ b/shared/impl/src/main/kotlin/app/aaps/shared/impl/weardata/JsonKeys.kt @@ -3,9 +3,11 @@ package app.aaps.shared.impl.weardata enum class JsonKeys(val key: String) { METADATA("metadata"), ENABLESECOND("enableSecond"), + VERYHIGHCOLOR("veryHighColor"), HIGHCOLOR("highColor"), MIDCOLOR("midColor"), LOWCOLOR("lowColor"), + VERYLOWCOLOR("veryLowColor"), LOWBATCOLOR("lowBatColor"), CARBCOLOR("carbColor"), BASALBACKGROUNDCOLOR("basalBackgroundColor"), diff --git a/shared/impl/src/main/kotlin/app/aaps/shared/impl/weardata/ResFileMap.kt b/shared/impl/src/main/kotlin/app/aaps/shared/impl/weardata/ResFileMap.kt index d79c6b93d0a3..0161f91b65b7 100644 --- a/shared/impl/src/main/kotlin/app/aaps/shared/impl/weardata/ResFileMap.kt +++ b/shared/impl/src/main/kotlin/app/aaps/shared/impl/weardata/ResFileMap.kt @@ -6,21 +6,33 @@ enum class ResFileMap(val fileName: String) { BACKGROUND("Background"), BACKGROUND_HIGH("BackgroundHigh"), BACKGROUND_LOW("BackgroundLow"), + BACKGROUND_VERY_HIGH("BackgroundVeryHigh"), + BACKGROUND_VERY_LOW("BackgroundVeryLow"), COVER_CHART("CoverChart"), COVER_CHART_HIGH("CoverChartHigh"), COVER_CHART_LOW("CoverChartLow"), + COVER_CHART_VERY_HIGH("CoverChartVeryHigh"), + COVER_CHART_VERY_LOW("CoverChartVeryLow"), COVER_PLATE("CoverPlate"), COVER_PLATE_HIGH("CoverPlateHigh"), COVER_PLATE_LOW("CoverPlateLow"), + COVER_PLATE_VERY_HIGH("CoverPlateVeryHigh"), + COVER_PLATE_VERY_LOW("CoverPlateVeryLow"), HOUR_HAND("HourHand"), HOUR_HAND_HIGH("HourHandHigh"), HOUR_HAND_LOW("HourHandLow"), + HOUR_HAND_VERY_HIGH("HourHandVeryHigh"), + HOUR_HAND_VERY_LOW("HourHandVeryLow"), MINUTE_HAND("MinuteHand"), MINUTE_HAND_HIGH("MinuteHandHigh"), MINUTE_HAND_LOW("MinuteHandLow"), + MINUTE_HAND_VERY_HIGH("MinuteHandVeryHigh"), + MINUTE_HAND_VERY_LOW("MinuteHandVeryLow"), SECOND_HAND("SecondHand"), SECOND_HAND_HIGH("SecondHandHigh"), SECOND_HAND_LOW("SecondHandLow"), + SECOND_HAND_VERY_HIGH("SecondHandVeryHigh"), + SECOND_HAND_VERY_LOW("SecondHandVeryLow"), ARROW_NONE("ArrowNone"), ARROW_DOUBLE_UP("ArrowDoubleUp"), ARROW_SINGLE_UP("ArrowSingleUp"), diff --git a/ui/src/main/kotlin/app/aaps/ui/widget/Widget.kt b/ui/src/main/kotlin/app/aaps/ui/widget/Widget.kt index 6139fda20283..624c53aa74b7 100644 --- a/ui/src/main/kotlin/app/aaps/ui/widget/Widget.kt +++ b/ui/src/main/kotlin/app/aaps/ui/widget/Widget.kt @@ -149,7 +149,9 @@ class Widget : AppWidgetProvider() { lastBgData.lastBg()?.let { profileUtil.fromMgdlToStringInUnits(it.recalculated) } ?: rh.gs(app.aaps.core.ui.R.string.value_unavailable_short)) views.setTextColor( R.id.bg, when { + lastBgData.isVeryLow() -> rh.gc(app.aaps.core.ui.R.color.widget_very_low) lastBgData.isLow() -> rh.gc(app.aaps.core.ui.R.color.widget_low) + lastBgData.isVeryHigh() -> rh.gc(app.aaps.core.ui.R.color.widget_very_high) lastBgData.isHigh() -> rh.gc(app.aaps.core.ui.R.color.widget_high) else -> rh.gc(app.aaps.core.ui.R.color.widget_inrange) } @@ -160,7 +162,9 @@ class Widget : AppWidgetProvider() { views.setViewVisibility(R.id.arrow, (trendCalculator.getTrendArrow(iobCobCalculator.ads) != null).toVisibilityKeepSpace()) views.setInt( R.id.arrow, "setColorFilter", when { + lastBgData.isVeryLow() -> rh.gc(app.aaps.core.ui.R.color.widget_very_low) lastBgData.isLow() -> rh.gc(app.aaps.core.ui.R.color.widget_low) + lastBgData.isVeryHigh() -> rh.gc(app.aaps.core.ui.R.color.widget_very_high) lastBgData.isHigh() -> rh.gc(app.aaps.core.ui.R.color.widget_high) else -> rh.gc(app.aaps.core.ui.R.color.widget_inrange) } diff --git a/wear/src/main/kotlin/app/aaps/wear/data/RawDisplayData.kt b/wear/src/main/kotlin/app/aaps/wear/data/RawDisplayData.kt index 5696d8218bc1..4a386c7de717 100644 --- a/wear/src/main/kotlin/app/aaps/wear/data/RawDisplayData.kt +++ b/wear/src/main/kotlin/app/aaps/wear/data/RawDisplayData.kt @@ -27,8 +27,10 @@ class RawDisplayData { avgDeltaDetailed = "--", sgvLevel = 0, sgv = 0.0, + veryHigh = 0.0, high = 0.0, low = 0.0, + veryLow = 0.0, color = 0, deltaMgdl = null, avgDeltaMgdl = null @@ -44,8 +46,10 @@ class RawDisplayData { avgDeltaDetailed = "--", sgvLevel = 0, sgv = 0.0, + veryHigh = 0.0, high = 0.0, low = 0.0, + veryLow = 0.0, color = 0, deltaMgdl = null, avgDeltaMgdl = null, @@ -61,8 +65,10 @@ class RawDisplayData { avgDeltaDetailed = "--", sgvLevel = 0, sgv = 0.0, + veryHigh = 0.0, high = 0.0, low = 0.0, + veryLow = 0.0, color = 0, deltaMgdl = null, avgDeltaMgdl = null, diff --git a/wear/src/main/kotlin/app/aaps/wear/watchfaces/CircleWatchface.kt b/wear/src/main/kotlin/app/aaps/wear/watchfaces/CircleWatchface.kt index fcadf1080113..60e2279b35fe 100644 --- a/wear/src/main/kotlin/app/aaps/wear/watchfaces/CircleWatchface.kt +++ b/wear/src/main/kotlin/app/aaps/wear/watchfaces/CircleWatchface.kt @@ -252,11 +252,12 @@ class CircleWatchface : WatchFace() { val minute = Calendar.getInstance()[Calendar.MINUTE] angleBig = ((hour + minute / 60f) / 12f * 360 - 90 - BIG_HAND_WIDTH / 2f + 360) % 360 angleSMALL = (minute / 60f * 360 - 90 - SMALL_HAND_WIDTH / 2f + 360) % 360 - color = 0 - when (singleBg[0].sgvLevel.toInt()) { - -1 -> color = lowColor - 0 -> color = inRangeColor - 1 -> color = highColor + color = when (singleBg[0].sgvLevel.toInt()) { + -2 -> veryLowColor + -1 -> lowColor + 1 -> highColor + 2 -> veryHighColor + else -> inRangeColor } circlePaint.shader = null circlePaint.style = Paint.Style.STROKE @@ -292,12 +293,16 @@ class CircleWatchface : WatchFace() { } // defining color for dark and bright - private val lowColor: Int + private val veryLowColor: Int get() = if (sp.getBoolean(R.string.key_dark, true)) Color.argb(255, 255, 120, 120) else Color.argb(255, 255, 80, 80) + private val lowColor: Int + get() = if (sp.getBoolean(R.string.key_dark, true)) Color.argb(255, 255, 255, 120) else Color.argb(255, 255, 80, 80) private val inRangeColor: Int get() = if (sp.getBoolean(R.string.key_dark, true)) Color.argb(255, 120, 255, 120) else Color.argb(255, 0, 240, 0) private val highColor: Int get() = if (sp.getBoolean(R.string.key_dark, true)) Color.argb(255, 255, 255, 120) else Color.argb(255, 255, 200, 0) + private val veryHighColor: Int + get() = if (sp.getBoolean(R.string.key_dark, true)) Color.argb(255, 255, 120, 120) else Color.argb(255, 255, 200, 0) private val backgroundColor: Int get() = if (sp.getBoolean(R.string.key_dark, true)) Color.BLACK else Color.WHITE val textColor: Int @@ -309,8 +314,10 @@ class CircleWatchface : WatchFace() { //Perfect low and High indicators if (bgDataList.isNotEmpty()) { addIndicator(canvas, 100f, Color.LTGRAY) + addIndicator(canvas, bgDataList.iterator().next().veryLow.toFloat(), veryLowColor) addIndicator(canvas, bgDataList.iterator().next().low.toFloat(), lowColor) addIndicator(canvas, bgDataList.iterator().next().high.toFloat(), highColor) + addIndicator(canvas, bgDataList.iterator().next().veryHigh.toFloat(), veryHighColor) if (sp.getBoolean("softRingHistory", true)) { for (data in bgDataList) { addReadingSoft(canvas, data) @@ -406,9 +413,15 @@ class CircleWatchface : WatchFace() { indicatorColor = Color.LTGRAY } var barColor = Color.GRAY - if (entry.sgv >= entry.high) { + if (entry.sgv >= entry.veryHigh) { + indicatorColor = veryHighColor + barColor = darken(veryHighColor) + } else if (entry.sgv >= entry.high) { indicatorColor = highColor barColor = darken(highColor) + } else if (entry.sgv <= entry.veryLow) { + indicatorColor = veryLowColor + barColor = darken(veryLowColor) } else if (entry.sgv <= entry.low) { indicatorColor = lowColor barColor = darken(lowColor) diff --git a/wear/src/main/kotlin/app/aaps/wear/watchfaces/CustomWatchface.kt b/wear/src/main/kotlin/app/aaps/wear/watchfaces/CustomWatchface.kt index 6955d6d9d5c6..eec1e44fd5e1 100644 --- a/wear/src/main/kotlin/app/aaps/wear/watchfaces/CustomWatchface.kt +++ b/wear/src/main/kotlin/app/aaps/wear/watchfaces/CustomWatchface.kt @@ -72,9 +72,11 @@ class CustomWatchface : BaseWatchFace() { private var jsonString = "" private fun bgColor(dataSet: Int): Int = when (singleBg[dataSet].sgvLevel) { + 2L -> veryHighColor 1L -> highColor 0L -> midColor -1L -> lowColor + -2L -> veryLowColor else -> midColor } @@ -240,8 +242,10 @@ class CustomWatchface : BaseWatchFace() { binding.month.text = dateUtil.monthString(monthFormat).substringBeforeLast(".") val jsonColor = dynPref[json.optString(JsonKeys.DYNPREFCOLOR.key)] ?: json highColor = getColor(jsonColor.optString(JsonKeys.HIGHCOLOR.key), ContextCompat.getColor(this, R.color.dark_highColor)) + veryHighColor = getColor(jsonColor.optString(JsonKeys.VERYHIGHCOLOR.key), highColor) midColor = getColor(jsonColor.optString(JsonKeys.MIDCOLOR.key), ContextCompat.getColor(this, R.color.inrange)) lowColor = getColor(jsonColor.optString(JsonKeys.LOWCOLOR.key), ContextCompat.getColor(this, R.color.low)) + veryLowColor = getColor(jsonColor.optString(JsonKeys.VERYLOWCOLOR.key), lowColor) lowBatColor = getColor(jsonColor.optString(JsonKeys.LOWBATCOLOR.key), ContextCompat.getColor(this, R.color.dark_uploaderBatteryEmpty)) carbColor = getColor(jsonColor.optString(JsonKeys.CARBCOLOR.key), ContextCompat.getColor(this, R.color.carbs)) basalBackgroundColor = getColor(jsonColor.optString(JsonKeys.BASALBACKGROUNDCOLOR.key), ContextCompat.getColor(this, R.color.basal_dark)) @@ -300,9 +304,11 @@ class CustomWatchface : BaseWatchFace() { .put(CwfMetadataKey.CWF_COMMENT.key, if (externalViews) getString(app.aaps.core.interfaces.R.string.default_custom_watchface_external_comment) else getString(app.aaps.core.interfaces.R.string.default_custom_watchface_comment)) val json = JSONObject() .put(JsonKeys.METADATA.key, metadata) + .put(JsonKeys.VERYHIGHCOLOR.key, String.format("#%06X", 0xFFFFFF and veryHighColor)) .put(JsonKeys.HIGHCOLOR.key, String.format("#%06X", 0xFFFFFF and highColor)) .put(JsonKeys.MIDCOLOR.key, String.format("#%06X", 0xFFFFFF and midColor)) .put(JsonKeys.LOWCOLOR.key, String.format("#%06X", 0xFFFFFF and lowColor)) + .put(JsonKeys.VERYLOWCOLOR.key, String.format("#%06X", 0xFFFFFF and veryLowColor)) .put(JsonKeys.LOWBATCOLOR.key, String.format("#%06X", 0xFFFFFF and lowBatColor)) .put(JsonKeys.CARBCOLOR.key, String.format("#%06X", 0xFFFFFF and carbColor)) .put(JsonKeys.BASALBACKGROUNDCOLOR.key, String.format("#%06X", 0xFFFFFF and basalBackgroundColor)) @@ -361,9 +367,11 @@ class CustomWatchface : BaseWatchFace() { } private fun setDefaultColors() { + veryHighColor = Color.parseColor("#FF0000") highColor = Color.parseColor("#FFFF00") midColor = Color.parseColor("#00FF00") - lowColor = Color.parseColor("#FF0000") + lowColor = Color.parseColor("#FFFF00") + veryLowColor = Color.parseColor("#FF0000") carbColor = ContextCompat.getColor(this, R.color.carbs) basalBackgroundColor = ContextCompat.getColor(this, R.color.basal_dark) basalCenterColor = ContextCompat.getColor(this, R.color.basal_light) @@ -452,6 +460,8 @@ class CustomWatchface : BaseWatchFace() { val customDrawable: ResFileMap? = null, val customHigh: ResFileMap? = null, val customLow: ResFileMap? = null, + val customVeryHigh: ResFileMap? = null, + val customVeryLow: ResFileMap? = null, val external: Int = 0 ) { @@ -461,7 +471,9 @@ class CustomWatchface : BaseWatchFace() { defaultDrawable = R.drawable.background, customDrawable = ResFileMap.BACKGROUND, customHigh = ResFileMap.BACKGROUND_HIGH, - customLow = ResFileMap.BACKGROUND_LOW + customLow = ResFileMap.BACKGROUND_LOW, + customVeryHigh = ResFileMap.BACKGROUND_VERY_HIGH, + customVeryLow = ResFileMap.BACKGROUND_VERY_LOW ), CHART(ViewKeys.CHART.key, R.id.chart), COVER_CHART( @@ -469,7 +481,9 @@ class CustomWatchface : BaseWatchFace() { id = R.id.cover_chart, customDrawable = ResFileMap.COVER_CHART, customHigh = ResFileMap.COVER_CHART_HIGH, - customLow = ResFileMap.COVER_CHART_LOW + customLow = ResFileMap.COVER_CHART_LOW, + customVeryHigh = ResFileMap.COVER_CHART_VERY_HIGH, + customVeryLow = ResFileMap.COVER_CHART_VERY_LOW ), FREETEXT1(ViewKeys.FREETEXT1.key, R.id.freetext1), FREETEXT2(ViewKeys.FREETEXT2.key, R.id.freetext2), @@ -542,7 +556,9 @@ class CustomWatchface : BaseWatchFace() { defaultDrawable = R.drawable.simplified_dial, customDrawable = ResFileMap.COVER_PLATE, customHigh = ResFileMap.COVER_PLATE_HIGH, - customLow = ResFileMap.COVER_PLATE_LOW + customLow = ResFileMap.COVER_PLATE_LOW, + customVeryHigh = ResFileMap.COVER_PLATE_VERY_HIGH, + customVeryLow = ResFileMap.COVER_PLATE_VERY_LOW ), HOUR_HAND( key = ViewKeys.HOUR_HAND.key, @@ -550,7 +566,9 @@ class CustomWatchface : BaseWatchFace() { defaultDrawable = R.drawable.hour_hand, customDrawable = ResFileMap.HOUR_HAND, customHigh = ResFileMap.HOUR_HAND_HIGH, - customLow = ResFileMap.HOUR_HAND_LOW + customLow = ResFileMap.HOUR_HAND_LOW, + customVeryHigh = ResFileMap.HOUR_HAND_VERY_HIGH, + customVeryLow = ResFileMap.HOUR_HAND_VERY_LOW ), MINUTE_HAND( key = ViewKeys.MINUTE_HAND.key, @@ -558,7 +576,9 @@ class CustomWatchface : BaseWatchFace() { defaultDrawable = R.drawable.minute_hand, customDrawable = ResFileMap.MINUTE_HAND, customHigh = ResFileMap.MINUTE_HAND_HIGH, - customLow = ResFileMap.MINUTE_HAND_LOW + customLow = ResFileMap.MINUTE_HAND_LOW, + customVeryHigh = ResFileMap.MINUTE_HAND_VERY_HIGH, + customVeryLow = ResFileMap.MINUTE_HAND_VERY_LOW ), SECOND_HAND( key = ViewKeys.SECOND_HAND.key, @@ -567,7 +587,9 @@ class CustomWatchface : BaseWatchFace() { defaultDrawable = R.drawable.second_hand, customDrawable = ResFileMap.SECOND_HAND, customHigh = ResFileMap.SECOND_HAND_HIGH, - customLow = ResFileMap.SECOND_HAND_LOW + customLow = ResFileMap.SECOND_HAND_LOW, + customVeryHigh = ResFileMap.SECOND_HAND_VERY_HIGH, + customVeryLow = ResFileMap.SECOND_HAND_VERY_LOW ); companion object { @@ -604,12 +626,18 @@ class CustomWatchface : BaseWatchFace() { get() = field ?: customHigh?.let { cd -> cwf.resDataMap[cd.fileName]?.toDrawable(cwf.resources).also { highCustom = it } } var lowCustom: Drawable? = null get() = field ?: customLow?.let { cd -> cwf.resDataMap[cd.fileName]?.toDrawable(cwf.resources).also { lowCustom = it } } + var veryHighCustom: Drawable? = null + get() = field ?: customVeryHigh?.let { cd -> cwf.resDataMap[cd.fileName]?.toDrawable(cwf.resources).also { veryHighCustom = it } } + var veryLowCustom: Drawable? = null + get() = field ?: customVeryLow?.let { cd -> cwf.resDataMap[cd.fileName]?.toDrawable(cwf.resources).also { veryLowCustom = it } } var textDrawable: Drawable? = null val drawable: Drawable? get() = dynData?.getDrawable() ?: when (cwf.singleBg[0].sgvLevel) { + 2L -> veryHighCustom ?: highCustom ?: rangeCustom 1L -> highCustom ?: rangeCustom 0L -> rangeCustom -1L -> lowCustom ?: rangeCustom + -2L -> veryLowCustom ?: lowCustom ?: rangeCustom else -> rangeCustom } var twinView: ViewMap? = null @@ -852,7 +880,7 @@ class CustomWatchface : BaseWatchFace() { private enum class ValueMap(val key: String, val min: Double, val max: Double) { NONE("", 0.0, 0.0), SGV(ViewKeys.SGV.key, 39.0, 400.0), - SGV_LEVEL(JsonKeyValues.SGV_LEVEL.key, -1.0, 1.0), + SGV_LEVEL(JsonKeyValues.SGV_LEVEL.key, -2.0, 2.0), DIRECTION(ViewKeys.DIRECTION.key, 1.0, 7.0), DELTA(ViewKeys.DELTA.key, -25.0, 25.0), AVG_DELTA(ViewKeys.AVG_DELTA.key, -25.0, 25.0), @@ -868,7 +896,7 @@ class CustomWatchface : BaseWatchFace() { MONTH(ViewKeys.MONTH.key, 1.0, 12.0), WEEK_NUMBER(ViewKeys.WEEK_NUMBER.key, 1.0, 53.0), SGV_EXT1(ViewKeys.SGV_EXT1.key, 39.0, 400.0), - SGV_LEVEL_EXT1(JsonKeyValues.SGV_LEVEL_EXT1.key, -1.0, 1.0), + SGV_LEVEL_EXT1(JsonKeyValues.SGV_LEVEL_EXT1.key, -2.0, 2.0), DIRECTION_EXT1(ViewKeys.DIRECTION_EXT1.key, 1.0, 7.0), DELTA_EXT1(ViewKeys.DELTA_EXT1.key, -25.0, 25.0), AVG_DELTA_EXT1(ViewKeys.AVG_DELTA_EXT1.key, -25.0, 25.0), @@ -879,7 +907,7 @@ class CustomWatchface : BaseWatchFace() { TIMESTAMP_EXT1(ViewKeys.TIMESTAMP_EXT1.key, 0.0, 60.0), LOOP_EXT1(ViewKeys.LOOP_EXT1.key, 0.0, 28.0), SGV_EXT2(ViewKeys.SGV_EXT2.key, 39.0, 400.0), - SGV_LEVEL_EXT2(JsonKeyValues.SGV_LEVEL_EXT2.key, -1.0, 1.0), + SGV_LEVEL_EXT2(JsonKeyValues.SGV_LEVEL_EXT2.key, -2.0, 2.0), DIRECTION_EXT2(ViewKeys.DIRECTION_EXT2.key, 1.0, 7.0), DELTA_EXT2(ViewKeys.DELTA_EXT2.key, -25.0, 25.0), AVG_DELTA_EXT2(ViewKeys.AVG_DELTA_EXT2.key, -25.0, 25.0), diff --git a/wear/src/main/kotlin/app/aaps/wear/watchfaces/DigitalStyleWatchface.kt b/wear/src/main/kotlin/app/aaps/wear/watchfaces/DigitalStyleWatchface.kt index 0c9410d0ad6b..bd7336adeec7 100644 --- a/wear/src/main/kotlin/app/aaps/wear/watchfaces/DigitalStyleWatchface.kt +++ b/wear/src/main/kotlin/app/aaps/wear/watchfaces/DigitalStyleWatchface.kt @@ -37,9 +37,11 @@ class DigitalStyleWatchface : BaseWatchFace() { override fun setColorDark() { val color = when (singleBg[0].sgvLevel) { + 2L -> R.color.dark_veryHighColor 1L -> R.color.dark_highColor 0L -> R.color.dark_midColor -1L -> R.color.dark_lowColor + -2L -> R.color.dark_veryLowColor else -> R.color.dark_midColor } binding.sgv.setTextColor(ContextCompat.getColor(this, color)) diff --git a/wear/src/main/kotlin/app/aaps/wear/watchfaces/utils/BaseWatchFace.kt b/wear/src/main/kotlin/app/aaps/wear/watchfaces/utils/BaseWatchFace.kt index d3f7700d934b..0e2579c92051 100644 --- a/wear/src/main/kotlin/app/aaps/wear/watchfaces/utils/BaseWatchFace.kt +++ b/wear/src/main/kotlin/app/aaps/wear/watchfaces/utils/BaseWatchFace.kt @@ -73,8 +73,10 @@ abstract class BaseWatchFace : WatchFace() { var loopLevelExt2 = -1 var enableExt1 = false var enableExt2 = false + var veryHighColor = Color.RED var highColor = Color.YELLOW - var lowColor = Color.RED + var lowColor = Color.YELLOW + var veryLowColor = Color.RED var midColor = Color.WHITE var gridColor = Color.WHITE var basalBackgroundColor = Color.BLUE @@ -552,12 +554,14 @@ abstract class BaseWatchFace : WatchFace() { if (lowResMode) BgGraphBuilder( sp, dateUtil, graphData.entries, treatmentData.predictions, treatmentData.temps, treatmentData.basals, treatmentData.boluses, pointSize, - midColor, gridColor, basalBackgroundColor, basalCenterColor, bolusColor, carbColor, timeframe + midColor, gridColor, + basalBackgroundColor, basalCenterColor, bolusColor, carbColor, timeframe ) else BgGraphBuilder( - sp, dateUtil, graphData.entries, treatmentData.predictions, treatmentData.temps, treatmentData.basals, treatmentData.boluses, - pointSize, highColor, lowColor, midColor, gridColor, basalBackgroundColor, basalCenterColor, bolusColor, carbColor, timeframe + sp, dateUtil, graphData.entries, treatmentData.predictions, treatmentData.temps, treatmentData.basals, treatmentData.boluses, pointSize, + veryHighColor, highColor, lowColor, veryLowColor, midColor, gridColor, + basalBackgroundColor, basalCenterColor, bolusColor, carbColor, timeframe ) binding.chart?.lineChartData = bgGraphBuilder.lineData() binding.chart?.isViewportCalculationEnabled = true diff --git a/wear/src/main/kotlin/app/aaps/wear/watchfaces/utils/BgGraphBuilder.kt b/wear/src/main/kotlin/app/aaps/wear/watchfaces/utils/BgGraphBuilder.kt index c488257a45cd..710206c936f1 100644 --- a/wear/src/main/kotlin/app/aaps/wear/watchfaces/utils/BgGraphBuilder.kt +++ b/wear/src/main/kotlin/app/aaps/wear/watchfaces/utils/BgGraphBuilder.kt @@ -28,8 +28,10 @@ class BgGraphBuilder( private val basalWatchDataList: ArrayList, private val bolusWatchDataList: ArrayList, private val pointSize: Int, + private val veryHighColor: Int, private val highColor: Int, private val lowColor: Int, + private val veryLowColor: Int, private val midColor: Int, private val gridColour: Int, private val basalBackgroundColor: Int, @@ -42,11 +44,15 @@ class BgGraphBuilder( private var endingTime: Long = System.currentTimeMillis() + 1000L * 60 * 6 * timeSpan private var startingTime: Long = System.currentTimeMillis() - 1000L * 60 * 60 * timeSpan private var fuzzyTimeDiv = (1000 * 60 * 1).toDouble() + private var veryHighMark: Double = bgDataList[bgDataList.size - 1].veryHigh private var highMark: Double = bgDataList[bgDataList.size - 1].high private var lowMark: Double = bgDataList[bgDataList.size - 1].low + private var veryLowMark: Double = bgDataList[bgDataList.size - 1].veryLow private val inRangeValues: MutableList = ArrayList() + private val veryHighValues: MutableList = ArrayList() private val highValues: MutableList = ArrayList() private val lowValues: MutableList = ArrayList() + private val veryLowValues: MutableList = ArrayList() private val predictionEndTime: Long get() { @@ -72,11 +78,17 @@ class BgGraphBuilder( tempWatchDataList: List, basalWatchDataList: ArrayList, bolusWatchDataList: ArrayList, - aPointSize: Int, aMidColor: Int, gridColour: Int, basalBackgroundColor: Int, basalCenterColor: Int, bolusInvalidColor: Int, carbsColor: Int, timeSpan: Int + aPointSize: Int, + aMidColor: Int, + gridColour: Int, + basalBackgroundColor: Int, + basalCenterColor: Int, + bolusInvalidColor: Int, + carbsColor: Int, + timeSpan: Int ) : this( - sp, dateUtil, - aBgList, predictionsList, tempWatchDataList, basalWatchDataList, - bolusWatchDataList, aPointSize, aMidColor, aMidColor, aMidColor, gridColour, + sp, dateUtil, aBgList, predictionsList, tempWatchDataList, basalWatchDataList, bolusWatchDataList, aPointSize, + aMidColor, aMidColor, aMidColor, aMidColor, aMidColor, gridColour, basalBackgroundColor, basalCenterColor, bolusInvalidColor, carbsColor, timeSpan ) @@ -92,11 +104,15 @@ class BgGraphBuilder( private fun defaultLines(): List { addBgReadingValues() val lines: MutableList = ArrayList() + lines.add(veryHighLine()) lines.add(highLine()) lines.add(lowLine()) + lines.add(veryLowLine()) lines.add(inRangeValuesLine()) + lines.add(veryLowValuesLine()) lines.add(lowValuesLine()) lines.add(highValuesLine()) + lines.add(veryHighValuesLine()) var minChart = lowMark var maxChart = highMark for ((_, _, _, _, _, _, _, _, _, _, sgv) in bgDataList) { @@ -215,7 +231,7 @@ class BgGraphBuilder( private fun addPredictionLines(lines: MutableList) { val values: MutableMap> = HashMap() - for ((_, timeStamp, _, _, _, _, _, _, _, _, sgv, _, _, color) in predictionsList) { + for ((_, timeStamp, _, _, _, _, _, _, _, _, _, _, sgv, _, _, color) in predictionsList) { if (timeStamp <= predictionEndTime) { val value = min(sgv, UPPER_CUTOFF_SGV) if (!values.containsKey(color)) { @@ -236,6 +252,14 @@ class BgGraphBuilder( } } + private fun veryHighValuesLine(): Line = + Line(veryHighValues).also { veryHighValuesLine -> + veryHighValuesLine.color = veryHighColor + veryHighValuesLine.setHasLines(false) + veryHighValuesLine.pointRadius = pointSize + veryHighValuesLine.setHasPoints(true) + } + private fun highValuesLine(): Line = Line(highValues).also { highValuesLine -> highValuesLine.color = highColor @@ -252,6 +276,14 @@ class BgGraphBuilder( lowValuesLine.setHasPoints(true) } + private fun veryLowValuesLine(): Line = + Line(veryLowValues).also { veryLowValuesLine -> + veryLowValuesLine.color = veryLowColor + veryLowValuesLine.setHasLines(false) + veryLowValuesLine.pointRadius = pointSize + veryLowValuesLine.setHasPoints(true) + } + private fun inRangeValuesLine(): Line = Line(inRangeValues).also { inRangeValuesLine -> inRangeValuesLine.color = midColor @@ -283,11 +315,13 @@ class BgGraphBuilder( for ((_, timeStamp, _, _, _, _, _, _, _, _, sgv) in bgDataList) { if (timeStamp > startingTime) { when { - sgv >= 450 -> highValues.add(PointValue(fuzz(timeStamp), 450.toFloat())) + sgv >= 450 -> veryHighValues.add(PointValue(fuzz(timeStamp), 450.toFloat())) + sgv >= veryHighMark -> veryHighValues.add(PointValue(fuzz(timeStamp), sgv.toFloat())) sgv >= highMark -> highValues.add(PointValue(fuzz(timeStamp), sgv.toFloat())) sgv >= lowMark -> inRangeValues.add(PointValue(fuzz(timeStamp), sgv.toFloat())) - sgv >= 40 -> lowValues.add(PointValue(fuzz(timeStamp), sgv.toFloat())) - sgv >= 11 -> lowValues.add(PointValue(fuzz(timeStamp), 40.toFloat())) + sgv >= veryLowMark -> veryLowValues.add(PointValue(fuzz(timeStamp), sgv.toFloat())) + sgv >= 40 -> veryLowValues.add(PointValue(fuzz(timeStamp), sgv.toFloat())) + sgv >= 11 -> veryLowValues.add(PointValue(fuzz(timeStamp), 40.toFloat())) } } } @@ -304,6 +338,17 @@ class BgGraphBuilder( } } + private fun veryHighLine(): Line { + val veryHighLineValues: MutableList = ArrayList() + veryHighLineValues.add(PointValue(fuzz(startingTime), veryHighMark.toFloat())) + veryHighLineValues.add(PointValue(fuzz(endingTime), veryHighMark.toFloat())) + return Line(veryHighLineValues).also { veryHighLine -> + veryHighLine.setHasPoints(false) + veryHighLine.strokeWidth = 1 + veryHighLine.color = veryHighColor + } + } + private fun lowLine(): Line { val lowLineValues: MutableList = ArrayList() lowLineValues.add(PointValue(fuzz(startingTime), lowMark.toFloat())) @@ -315,6 +360,17 @@ class BgGraphBuilder( } } + private fun veryLowLine(): Line { + val veryLowLineValues: MutableList = ArrayList() + veryLowLineValues.add(PointValue(fuzz(startingTime), veryLowMark.toFloat())) + veryLowLineValues.add(PointValue(fuzz(endingTime), veryLowMark.toFloat())) + return Line(veryLowLineValues).also { veryLowLine -> + veryLowLine.setHasPoints(false) + veryLowLine.color = veryLowColor + veryLowLine.strokeWidth = 1 + } + } + /////////AXIS RELATED////////////// private fun yAxis(): Axis = Axis().also { yAxis -> diff --git a/wear/src/main/res/values/colors.xml b/wear/src/main/res/values/colors.xml index c5d0cd2368e0..fa68a0a29a67 100644 --- a/wear/src/main/res/values/colors.xml +++ b/wear/src/main/res/values/colors.xml @@ -31,8 +31,10 @@ #ffff00 #ff4444 + @color/RED @color/yellow_A200 - @color/RED + @color/yellow_A200 + @color/RED @color/grey_50 @color/grey_50 @@ -52,7 +54,8 @@ #00FF00 #67DFE8 #FFFB8C00 - #FF0000 + #FFFF00 + #FF0000 #77dd77 diff --git a/wear/src/test/kotlin/app/aaps/wear/testing/mockers/RawDataMocker.kt b/wear/src/test/kotlin/app/aaps/wear/testing/mockers/RawDataMocker.kt index 0890c0fa12fb..30447277092b 100644 --- a/wear/src/test/kotlin/app/aaps/wear/testing/mockers/RawDataMocker.kt +++ b/wear/src/test/kotlin/app/aaps/wear/testing/mockers/RawDataMocker.kt @@ -38,7 +38,8 @@ class RawDataMocker { 0.0, 0.0, 0.0, - 0 + 0.0, + 0.0 ) ) return raw @@ -61,7 +62,8 @@ class RawDataMocker { 0.0, 0.0, 0.0, - 0 + 0.0, + 0.0 ) ) return raw