diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiCoordinator.java
index 39d1eb3ee..381cac712 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiCoordinator.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiCoordinator.java
@@ -202,6 +202,7 @@ public class HuaweiCoordinator {
notifications.add(R.xml.devicesettings_donotdisturb_allday_liftwirst_notwear);
// Workout
+ deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.WORKOUT, R.xml.devicesettings_workout_send_gps_to_band);
// Other
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_find_phone);
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiPacket.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiPacket.java
index 066162748..07f1b8c23 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiPacket.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiPacket.java
@@ -509,6 +509,8 @@ public class HuaweiPacket {
switch (this.commandId) {
case GpsAndTime.GpsParameters.id:
return new GpsAndTime.GpsParameters.Response(paramsProvider).fromPacket(this);
+ case GpsAndTime.GpsStatus.id:
+ return new GpsAndTime.GpsStatus.Response(paramsProvider).fromPacket(this);
case GpsAndTime.GpsData.id:
return new GpsAndTime.GpsData.Response(paramsProvider).fromPacket(this);
default:
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/AsynchronousResponse.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/AsynchronousResponse.java
index 8ae597c65..00ccf6981 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/AsynchronousResponse.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/AsynchronousResponse.java
@@ -45,9 +45,12 @@ import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Calls;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.DeviceConfig;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.FindPhone;
+import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.GpsAndTime;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Menstrual;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.MusicControl;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Weather;
+import nodomain.freeyourgadget.gadgetbridge.externalevents.gps.GBLocationListener;
+import nodomain.freeyourgadget.gadgetbridge.externalevents.gps.GBLocationManager;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.Request;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetPhoneInfoRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendMenstrualModifyTimeRequest;
@@ -98,6 +101,7 @@ public class AsynchronousResponse {
handlePhoneInfo(response);
handleMenstrualModifyTime(response);
handleWeatherCheck(response);
+ handleGpsRequest(response);
} catch (Request.ResponseParseException e) {
LOG.error("Response parse exception", e);
}
@@ -395,4 +399,14 @@ public class AsynchronousResponse {
// TODO: send back weather?
}
}
+
+ private void handleGpsRequest(HuaweiPacket response) {
+ if (response.serviceId == GpsAndTime.id && response.commandId == GpsAndTime.GpsStatus.id) {
+ if (!(response instanceof GpsAndTime.GpsStatus.Response)) {
+ // TODO: exception?
+ return;
+ }
+ support.setGps(((GpsAndTime.GpsStatus.Response) response).enableGps);
+ }
+ }
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiBRSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiBRSupport.java
index 999810f91..c56a8dd49 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiBRSupport.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiBRSupport.java
@@ -16,6 +16,8 @@
along with this program. If not, see . */
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei;
+import android.location.Location;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
@@ -123,4 +125,9 @@ public class HuaweiBRSupport extends AbstractBTBRDeviceSupport {
public void onSendWeather(ArrayList weatherSpecs) {
supportProvider.onSendWeather(weatherSpecs);
}
+
+ @Override
+ public void onSetGpsLocation(Location location) {
+ supportProvider.onSetGpsLocation(location);
+ }
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiLESupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiLESupport.java
index bff89da96..d8245eb8e 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiLESupport.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiLESupport.java
@@ -18,6 +18,7 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
+import android.location.Location;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -131,4 +132,9 @@ public class HuaweiLESupport extends AbstractBTLEDeviceSupport {
public void onSendWeather(ArrayList weatherSpecs) {
supportProvider.onSendWeather(weatherSpecs);
}
+
+ @Override
+ public void onSetGpsLocation(Location location) {
+ supportProvider.onSetGpsLocation(location);
+ }
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiSupportProvider.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiSupportProvider.java
index b022fcc84..c13756e23 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiSupportProvider.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiSupportProvider.java
@@ -19,6 +19,7 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei;
import android.bluetooth.BluetoothGattCharacteristic;
import android.content.Context;
import android.content.SharedPreferences;
+import android.location.Location;
import android.widget.Toast;
import androidx.annotation.NonNull;
@@ -43,6 +44,7 @@ import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
+import nodomain.freeyourgadget.gadgetbridge.devices.EventHandler;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiConstants;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiCoordinatorSupplier;
@@ -50,6 +52,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiCoordinatorSupp
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiCrypto;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiSampleProvider;
+import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.GpsAndTime;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Weather;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Workout;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst;
@@ -62,6 +65,7 @@ import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutPaceSample;
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutPaceSampleDao;
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSummarySample;
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSummarySampleDao;
+import nodomain.freeyourgadget.gadgetbridge.externalevents.gps.GBLocationManager;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.entities.Alarm;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
@@ -77,10 +81,12 @@ import nodomain.freeyourgadget.gadgetbridge.model.RecordedDataTypes;
import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.AcceptAgreementsRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetEventAlarmList;
+import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetGpsParameterRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetNotificationConstraintsRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetSmartAlarmList;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendExtendedAccountRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendGpsAndTimeToDeviceRequest;
+import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendGpsDataRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendWeatherCurrentRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendNotifyHeartRateCapabilityRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendNotifyRestHeartRateCapabilityRequest;
@@ -107,7 +113,6 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.Alar
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.DebugRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetActivityTypeRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.Request;
-import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendAccountRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.Request.RequestCallback;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetAuthRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetBatteryLevelRequest;
@@ -168,6 +173,8 @@ public class HuaweiSupportProvider {
private MusicStateSpec musicStateSpec = null;
private MusicSpec musicSpec = null;
+ private GpsAndTime.GpsParameters.Response gpsParametersResponse = null;
+
private final HuaweiPacket.ParamsProvider paramsProvider = new HuaweiPacket.ParamsProvider();
protected ResponseManager responseManager = new ResponseManager(this);
@@ -220,6 +227,39 @@ public class HuaweiSupportProvider {
}
}
+ public void setGps(boolean start) {
+ EventHandler handler;
+ if (isBLE())
+ handler = leSupport;
+ else
+ handler = brSupport;
+ if (start) {
+ if (!GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress()).getBoolean(DeviceSettingsPreferenceConst.PREF_WORKOUT_SEND_GPS_TO_BAND, false))
+ return;
+ if (gpsParametersResponse == null) {
+ GetGpsParameterRequest gpsParameterRequest = new GetGpsParameterRequest(this);
+ gpsParameterRequest.setFinalizeReq(new RequestCallback() {
+ @Override
+ public void call() {
+ GBLocationManager.start(getContext(), handler);
+ }
+ });
+ try {
+ gpsParameterRequest.doPerform();
+ } catch (IOException e) {
+ GB.toast(context, "Failed to get GPS parameters", Toast.LENGTH_SHORT, GB.ERROR, e);
+ LOG.error("Failed to get GPS parameters", e);
+ }
+ } else
+ GBLocationManager.start(getContext(), handler);
+ } else
+ GBLocationManager.stop(getContext(), handler);
+ }
+
+ public void setGpsParametersResponse(GpsAndTime.GpsParameters.Response response) {
+ this.gpsParametersResponse = response;
+ }
+
protected nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder initializeDevice(nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder builder) {
this.gbDevice = leSupport.getDevice();
this.context = leSupport.getContext();
@@ -1768,4 +1808,21 @@ public class HuaweiSupportProvider {
LOG.error("Failed to send weather", e);
}
}
+
+ public void onSetGpsLocation(Location location) {
+ if (gpsParametersResponse == null) {
+ GB.toast(context, "Received location without knowing supported parameters", Toast.LENGTH_SHORT, GB.ERROR);
+ LOG.error("Received location without knowing supported parameters");
+ return;
+ }
+
+ SendGpsDataRequest sendGpsDataRequest = new SendGpsDataRequest(this, location, gpsParametersResponse);
+ try {
+ sendGpsDataRequest.doPerform();
+ } catch (IOException e) {
+ // TODO: Use translatable string
+ GB.toast(context, "Failed to send GPS data", Toast.LENGTH_SHORT, GB.ERROR, e);
+ LOG.error("Failed to send GPS data", e);
+ }
+ }
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetGpsParameterRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetGpsParameterRequest.java
new file mode 100644
index 000000000..2f022152e
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetGpsParameterRequest.java
@@ -0,0 +1,48 @@
+/* Copyright (C) 2024 Martin.JM
+
+ This file is part of Gadgetbridge.
+
+ Gadgetbridge is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Gadgetbridge is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see . */
+package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests;
+
+import java.util.List;
+
+import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
+import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.GpsAndTime;
+import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupportProvider;
+
+public class GetGpsParameterRequest extends Request {
+
+ public GetGpsParameterRequest(HuaweiSupportProvider support) {
+ super(support);
+ this.serviceId = GpsAndTime.id;
+ this.commandId = GpsAndTime.GpsParameters.id;
+ }
+
+ @Override
+ protected List createRequest() throws RequestCreationException {
+ try {
+ return new GpsAndTime.GpsParameters.Request(this.paramsProvider).serialize();
+ } catch (HuaweiPacket.CryptoException e) {
+ throw new RequestCreationException(e);
+ }
+ }
+
+ @Override
+ protected void processResponse() throws ResponseParseException {
+ if (!(receivedPacket instanceof GpsAndTime.GpsParameters.Response))
+ throw new ResponseTypeMismatchException(receivedPacket, GpsAndTime.GpsParameters.Response.class);
+ supportProvider.setGpsParametersResponse((GpsAndTime.GpsParameters.Response) receivedPacket);
+ }
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/SendGpsDataRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/SendGpsDataRequest.java
new file mode 100644
index 000000000..fadf5715b
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/SendGpsDataRequest.java
@@ -0,0 +1,77 @@
+/* Copyright (C) 2024 Martin.JM
+
+ This file is part of Gadgetbridge.
+
+ Gadgetbridge is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Gadgetbridge is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see . */
+package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests;
+
+import android.location.Location;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
+import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.GpsAndTime;
+import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupportProvider;
+
+public class SendGpsDataRequest extends Request {
+ Location location;
+ GpsAndTime.GpsParameters.Response gpsParametersResponse;
+
+ public SendGpsDataRequest(HuaweiSupportProvider support, Location location, GpsAndTime.GpsParameters.Response gpsParametersResponse) {
+ super(support);
+ this.serviceId = GpsAndTime.id;
+ this.commandId = GpsAndTime.GpsData.id;
+ this.location = location;
+ this.gpsParametersResponse = gpsParametersResponse;
+ }
+
+ @Override
+ protected List createRequest() throws RequestCreationException {
+ ArrayList gpsList = new ArrayList<>();
+ GpsAndTime.GpsData.Request.GpsDataContainer gpsData = new GpsAndTime.GpsData.Request.GpsDataContainer();
+
+ if (this.gpsParametersResponse.supportsSpeed && location.hasSpeed()) {
+ gpsData.hasSpeed = true;
+ gpsData.speed = (short) location.getSpeed();
+ }
+ if (this.gpsParametersResponse.supportsAltitude && location.hasAltitude()) {
+ gpsData.hasAltitude = true;
+ gpsData.altitude = (short) location.getAltitude();
+ }
+ if (this.gpsParametersResponse.supportsLatLon) {
+ gpsData.hasLatLon = true;
+ gpsData.lat = location.getLatitude();
+ gpsData.lon = location.getLongitude();
+ }
+ if (this.gpsParametersResponse.supportsDirection && location.hasBearing()) {
+ gpsData.hasBearing = true;
+ gpsData.bearing = location.getBearing();
+ }
+ if (this.gpsParametersResponse.supportsPrecision && location.hasAccuracy()) {
+ gpsData.hasAccuracy = true;
+ gpsData.accuracy = location.getAccuracy();
+ }
+
+ gpsList.add(gpsData);
+ try {
+ return new GpsAndTime.GpsData.Request(
+ this.paramsProvider,
+ gpsList
+ ).serialize();
+ } catch (HuaweiPacket.CryptoException e) {
+ throw new RequestCreationException(e);
+ }
+ }
+}