From 32a18d8d8181197e7f657cf7c1f9a36f68252cb0 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Tue, 28 Apr 2026 22:20:14 +0100 Subject: [PATCH] =?UTF-8?q?Garmin:=20deduplicate=20degrees=20=E2=86=94=20s?= =?UTF-8?q?emicircles=20math=20in=20GarminUtils?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The watch encodes lat/lon as signed 32-bit semicircles (1<<31 == 180°). Move the bidirectional conversion behind named helpers backed by a single constant, and migrate toLocationData and FieldDefinitionCoordinate onto them. --- .../service/devices/garmin/GarminUtils.java | 15 +++++++++++++-- .../FieldDefinitionCoordinate.java | 7 +++---- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/GarminUtils.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/GarminUtils.java index 099a23d75a..7895039a1c 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/GarminUtils.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/GarminUtils.java @@ -10,10 +10,21 @@ public final class GarminUtils { // utility class } + /** Watch lat/lon resolution: 180° spans the signed-32-bit range, so 1 semicircle = 180/2^31 degrees. */ + public static final double SEMICIRCLE_DEGREES = 180.0D / 0x80000000L; + + public static double semicirclesToDegrees(final int semicircles) { + return semicircles * SEMICIRCLE_DEGREES; + } + + public static int degreesToSemicircles(final double degrees) { + return (int) Math.round(degrees / SEMICIRCLE_DEGREES); + } + public static GdiCore.CoreService.LocationData toLocationData(final Location location, final GdiCore.CoreService.DataType dataType) { final GdiCore.CoreService.LatLon positionForWatch = GdiCore.CoreService.LatLon.newBuilder() - .setLat((int) ((location.getLatitude() * 2.147483648E9d) / 180.0d)) - .setLon((int) ((location.getLongitude() * 2.147483648E9d) / 180.0d)) + .setLat(degreesToSemicircles(location.getLatitude())) + .setLon(degreesToSemicircles(location.getLongitude())) .build(); float vAccuracy = 0; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/fieldDefinitions/FieldDefinitionCoordinate.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/fieldDefinitions/FieldDefinitionCoordinate.java index 31d17871b2..4f375e4b59 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/fieldDefinitions/FieldDefinitionCoordinate.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/fieldDefinitions/FieldDefinitionCoordinate.java @@ -2,13 +2,12 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.fieldDef import java.nio.ByteBuffer; +import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.GarminUtils; import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.FieldDefinition; import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.baseTypes.BaseType; public class FieldDefinitionCoordinate extends FieldDefinition { - final double conversionFactor = (180.0D / 0x80000000L); - public FieldDefinitionCoordinate(int localNumber, int size, BaseType baseType, String name) { super(localNumber, size, baseType, name, 1, 0); } @@ -19,12 +18,12 @@ public class FieldDefinitionCoordinate extends FieldDefinition { if (rawValue == null) { return null; } - return ((long) rawValue) * conversionFactor; + return GarminUtils.semicirclesToDegrees(((Number) rawValue).intValue()); } @Override public void encode(ByteBuffer byteBuffer, Object o) { - baseType.encode(byteBuffer, (int) Math.round((double) o / conversionFactor), 1, 0); + baseType.encode(byteBuffer, GarminUtils.degreesToSemicircles((double) o), 1, 0); }