mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2026-07-31 07:44:24 +02:00
GloryFit: Add screen timeout setting
This commit is contained in:
+1
@@ -196,6 +196,7 @@ abstract class GloryFitCoordinator : AbstractBLEDeviceCoordinator() {
|
||||
|
||||
val display = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.DISPLAY)
|
||||
display.add(R.xml.devicesettings_liftwrist_display_noshed)
|
||||
display.add(R.xml.devicesettings_screen_timeout)
|
||||
|
||||
val health = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.HEALTH)
|
||||
health.add(R.xml.devicesettings_heartrate_automatic_enable)
|
||||
|
||||
+14
@@ -16,6 +16,7 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.devices.gloryfit
|
||||
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.Preference
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import nodomain.freeyourgadget.gadgetbridge.R
|
||||
@@ -62,6 +63,19 @@ class GloryFitSettingsCustomizer : DeviceSpecificSettingsCustomizer {
|
||||
dndStart?.isVisible = false
|
||||
val dndEnd = handler.findPreference<Preference>(DeviceSettingsPreferenceConst.PREF_INACTIVITY_DND_END)
|
||||
dndEnd?.isVisible = false
|
||||
|
||||
handler.findPreference<ListPreference>(DeviceSettingsPreferenceConst.PREF_SCREEN_TIMEOUT)?.let {
|
||||
it.entries = arrayOf(
|
||||
handler.context.getString(R.string.seconds_5),
|
||||
handler.context.getString(R.string.seconds_10),
|
||||
handler.context.getString(R.string.seconds_15),
|
||||
)
|
||||
it.entryValues = arrayOf(
|
||||
"5",
|
||||
"10",
|
||||
"15",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getPreferenceKeysWithSummary(): Set<String> {
|
||||
|
||||
+7
-8
@@ -59,7 +59,7 @@ import java.util.Calendar
|
||||
import java.util.GregorianCalendar
|
||||
import java.util.Locale
|
||||
import java.util.UUID
|
||||
import kotlin.math.roundToInt
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.kotlin.coerceIn
|
||||
|
||||
class GloryFitSupport() : AbstractBTLESingleDeviceSupport(LOG) {
|
||||
init {
|
||||
@@ -944,10 +944,10 @@ class GloryFitSupport() : AbstractBTLESingleDeviceSupport(LOG) {
|
||||
buf.put(CMD_USER_INFO)
|
||||
buf.putShort(activityUser.heightCm.coerceIn(91, 241).toShort())
|
||||
buf.putShort(activityUser.weightKg.coerceIn(20, 255).toShort())
|
||||
buf.put(0x05) // ?
|
||||
buf.put(devicePrefs.screenTimeout.coerceIn(5, 15, 5).toByte())
|
||||
buf.put(0x00) // ?
|
||||
buf.put(0x00) // ?
|
||||
buf.putShort(((activityUser.stepsGoal / 1000.0).roundToInt() * 1000).coerceIn(1000, 30000).toShort())
|
||||
buf.putShort(activityUser.stepsGoal.coerceIn(1000, 30000, 1000).toShort())
|
||||
buf.put(if (raiseHandToActivateDisplay) 0x01 else 0x00)
|
||||
buf.put(heartRateAlertHigh)
|
||||
buf.put(0x00) // ?
|
||||
@@ -970,7 +970,7 @@ class GloryFitSupport() : AbstractBTLESingleDeviceSupport(LOG) {
|
||||
fun setGoalSteps(builder: TransactionBuilder) {
|
||||
val activityUser = ActivityUser()
|
||||
|
||||
val stepsCoerced = ((activityUser.stepsGoal / 1000.0).roundToInt() * 1000).coerceIn(1000, 30000).toShort()
|
||||
val stepsCoerced = activityUser.stepsGoal.coerceIn(1000, 30000, 1000).toShort()
|
||||
|
||||
LOG.debug("Setting steps goal to {}", stepsCoerced)
|
||||
|
||||
@@ -988,7 +988,7 @@ class GloryFitSupport() : AbstractBTLESingleDeviceSupport(LOG) {
|
||||
fun setGoalCalories(builder: TransactionBuilder) {
|
||||
val activityUser = ActivityUser()
|
||||
|
||||
val caloriesCoerced = ((activityUser.caloriesBurntGoal / 50.0).roundToInt() * 50).coerceIn(50, 1000).toShort()
|
||||
val caloriesCoerced = activityUser.caloriesBurntGoal.coerceIn(50, 1000, 50).toShort()
|
||||
|
||||
LOG.debug("Setting calories goal to {}", caloriesCoerced)
|
||||
|
||||
@@ -1004,8 +1004,7 @@ class GloryFitSupport() : AbstractBTLESingleDeviceSupport(LOG) {
|
||||
fun setGoalDistance(builder: TransactionBuilder) {
|
||||
val activityUser = ActivityUser()
|
||||
|
||||
val distanceCoerced =
|
||||
((activityUser.distanceGoalMeters / 1000f).roundToInt() * 1000).coerceIn(1000, 20000).toShort()
|
||||
val distanceCoerced = activityUser.distanceGoalMeters.coerceIn(1000, 20000, 1000).toShort()
|
||||
|
||||
LOG.debug("Setting distance goal to {}", distanceCoerced)
|
||||
|
||||
@@ -1037,7 +1036,7 @@ class GloryFitSupport() : AbstractBTLESingleDeviceSupport(LOG) {
|
||||
val buf = ByteBuffer.allocate(12).order(ByteOrder.BIG_ENDIAN)
|
||||
buf.put(CMD_SEDENTARY_REMINDER)
|
||||
buf.put(if (enabled) 0x01 else 0x00)
|
||||
buf.put(((duration / 5.0).roundToInt() * 5).coerceIn(30, 180).toByte())
|
||||
buf.put(duration.coerceIn(30, 180, 5).toByte())
|
||||
buf.put(0x02) // ?
|
||||
buf.put(0x03) // ?
|
||||
buf.put(0x01) // ?
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.util.kotlin
|
||||
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
fun Int.coerceIn(min: Int, max: Int, step: Int): Int {
|
||||
return ((this / step.toDouble()).roundToInt() * step).coerceIn(min, max)
|
||||
}
|
||||
+4
@@ -156,4 +156,8 @@ public class DevicePrefs extends Prefs {
|
||||
public int getHeartRateLowThreshold() {
|
||||
return getInt(DeviceSettingsPreferenceConst.PREF_HEARTRATE_ALERT_LOW_THRESHOLD, 0);
|
||||
}
|
||||
|
||||
public int getScreenTimeout() {
|
||||
return getInt(PREF_SCREEN_TIMEOUT, 5);
|
||||
}
|
||||
}
|
||||
|
||||
-12
@@ -1,32 +1,20 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.DebugActivity;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.weather.WeatherMapper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.GarminSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.FieldDefinition;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.FitLocalMessageBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.RecordData;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.RecordDefinition;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.fieldDefinitions.FieldDefinitionWeatherAqi;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.fieldDefinitions.FieldDefinitionWeatherCondition;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.messages.MessageWriter;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
|
||||
|
||||
+135
@@ -0,0 +1,135 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.util.kotlin
|
||||
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
|
||||
class IntExtensionsTest {
|
||||
@Test
|
||||
fun testCoerceInWithStep_valueWithinRange() {
|
||||
// Value already on a step boundary within range
|
||||
assertEquals(50, 50.coerceIn(0, 100, 10))
|
||||
|
||||
// Value within range but not on step boundary - should round to nearest step
|
||||
assertEquals(50, 52.coerceIn(0, 100, 10))
|
||||
assertEquals(50, 48.coerceIn(0, 100, 10))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCoerceInWithStep_valueBelowMin() {
|
||||
// Value below minimum should be coerced to minimum (respecting step)
|
||||
assertEquals(0, (-10).coerceIn(0, 100, 10))
|
||||
assertEquals(10, 5.coerceIn(10, 100, 10))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCoerceInWithStep_valueAboveMax() {
|
||||
// Value above maximum should be coerced to maximum
|
||||
assertEquals(100, 150.coerceIn(0, 100, 10))
|
||||
assertEquals(100, 105.coerceIn(0, 100, 10))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCoerceInWithStep_roundingToNearestStep() {
|
||||
// Test rounding behavior: rounds to nearest step
|
||||
assertEquals(10, 6.coerceIn(0, 100, 10))
|
||||
assertEquals(10, 7.coerceIn(0, 100, 10))
|
||||
assertEquals(10, 8.coerceIn(0, 100, 10))
|
||||
assertEquals(10, 9.coerceIn(0, 100, 10))
|
||||
assertEquals(10, 10.coerceIn(0, 100, 10))
|
||||
assertEquals(10, 11.coerceIn(0, 100, 10))
|
||||
assertEquals(10, 12.coerceIn(0, 100, 10))
|
||||
assertEquals(10, 13.coerceIn(0, 100, 10))
|
||||
assertEquals(10, 14.coerceIn(0, 100, 10))
|
||||
// > 15 should round to 20
|
||||
assertEquals(20, 15.coerceIn(0, 100, 10))
|
||||
assertEquals(20, 16.coerceIn(0, 100, 10))
|
||||
assertEquals(20, 17.coerceIn(0, 100, 10))
|
||||
assertEquals(20, 18.coerceIn(0, 100, 10))
|
||||
assertEquals(20, 19.coerceIn(0, 100, 10))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCoerceInWithStep_differentStepSizes() {
|
||||
// Test with step size of 5
|
||||
assertEquals(15, 14.coerceIn(0, 100, 5))
|
||||
assertEquals(15, 16.coerceIn(0, 100, 5))
|
||||
|
||||
// Test with step size of 25
|
||||
assertEquals(25, 24.coerceIn(0, 100, 25))
|
||||
assertEquals(25, 30.coerceIn(0, 100, 25))
|
||||
|
||||
// Test with step size of 1 (should behave like normal coerceIn)
|
||||
assertEquals(42, 42.coerceIn(0, 100, 1))
|
||||
assertEquals(10, 10.coerceIn(0, 100, 1))
|
||||
assertEquals(15, 15.coerceIn(0, 100, 1))
|
||||
assertEquals(0, (-5).coerceIn(0, 100, 1))
|
||||
assertEquals(100, 105.coerceIn(0, 100, 1))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCoerceInWithStep_negativeRanges() {
|
||||
// Test with negative min and max
|
||||
assertEquals(-50, (-52).coerceIn(-100, 0, 10))
|
||||
assertEquals(-50, (-48).coerceIn(-100, 0, 10))
|
||||
assertEquals(-100, (-150).coerceIn(-100, 0, 10))
|
||||
assertEquals(0, 50.coerceIn(-100, 0, 10))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCoerceInWithStep_rangeSpanningZero() {
|
||||
// Test with range spanning negative to positive
|
||||
assertEquals(0, 2.coerceIn(-50, 50, 10))
|
||||
assertEquals(10, 12.coerceIn(-50, 50, 10))
|
||||
assertEquals(-10, (-12).coerceIn(-50, 50, 10))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCoerceInWithStep_edgeCases() {
|
||||
// Value exactly at minimum
|
||||
assertEquals(0, 0.coerceIn(0, 100, 10))
|
||||
|
||||
// Value exactly at maximum
|
||||
assertEquals(100, 100.coerceIn(0, 100, 10))
|
||||
|
||||
// Single value range (min == max)
|
||||
assertEquals(50, 50.coerceIn(50, 50, 10))
|
||||
assertEquals(50, 45.coerceIn(50, 50, 10))
|
||||
assertEquals(50, 55.coerceIn(50, 50, 10))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCoerceInWithStep_largeStepSize() {
|
||||
// Step size larger than range
|
||||
assertEquals(0, 25.coerceIn(0, 50, 100))
|
||||
assertEquals(0, 49.coerceIn(0, 50, 100))
|
||||
assertEquals(50, 51.coerceIn(0, 50, 100))
|
||||
assertEquals(50, 99.coerceIn(0, 50, 100))
|
||||
assertEquals(50, 101.coerceIn(0, 50, 100))
|
||||
assertEquals(50, 150.coerceIn(0, 50, 100))
|
||||
assertEquals(50, 200.coerceIn(0, 50, 100))
|
||||
assertEquals(50, 250.coerceIn(0, 50, 100))
|
||||
assertEquals(0, (-10).coerceIn(0, 50, 100))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCoerceInWithStep_smallValues() {
|
||||
// Test with small ranges and steps
|
||||
assertEquals(0, 0.coerceIn(0, 10, 2))
|
||||
assertEquals(2, 1.coerceIn(0, 10, 2))
|
||||
assertEquals(2, 2.coerceIn(0, 10, 2))
|
||||
assertEquals(4, 3.coerceIn(0, 10, 2))
|
||||
assertEquals(4, 4.coerceIn(0, 10, 2))
|
||||
assertEquals(6, 5.coerceIn(0, 10, 2))
|
||||
assertEquals(6, 6.coerceIn(0, 10, 2))
|
||||
assertEquals(8, 7.coerceIn(0, 10, 2))
|
||||
assertEquals(8, 8.coerceIn(0, 10, 2))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCoerceInWithStep_maxNotOnStepBoundary() {
|
||||
// When max is not on a step boundary
|
||||
// e.g., 0, 10, 20, 30, 40, 50... but max is 45
|
||||
assertEquals(40, 42.coerceIn(0, 45, 10))
|
||||
assertEquals(45, 48.coerceIn(0, 45, 10)) // Rounded to 50, coerced to 45
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user