mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2025-01-12 10:55:49 +01:00
Garmin: Send location to watch
This commit is contained in:
parent
e46ea03693
commit
3c5eada403
@ -30,6 +30,7 @@ public enum DeviceSpecificSettingsScreen {
|
||||
DEVELOPER("pref_screen_developer", R.xml.devicesettings_root_developer),
|
||||
DISPLAY("pref_screen_display", R.xml.devicesettings_root_display),
|
||||
GENERIC("pref_screen_generic", R.xml.devicesettings_root_generic),
|
||||
LOCATION("pref_screen_location", R.xml.devicesettings_root_location),
|
||||
NOTIFICATIONS("pref_screen_notifications", R.xml.devicesettings_root_notifications),
|
||||
DATE_TIME("pref_screen_date_time", R.xml.devicesettings_root_date_time),
|
||||
WORKOUT("pref_screen_workout", R.xml.devicesettings_root_workout),
|
||||
|
@ -38,10 +38,8 @@ public abstract class GarminCoordinator extends AbstractBLEDeviceCoordinator {
|
||||
public DeviceSpecificSettings getDeviceSpecificSettings(final GBDevice device) {
|
||||
final DeviceSpecificSettings deviceSpecificSettings = new DeviceSpecificSettings();
|
||||
|
||||
final List<Integer> connection = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.CONNECTION);
|
||||
connection.add(R.xml.devicesettings_high_mtu);
|
||||
|
||||
final List<Integer> notifications = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.CALLS_AND_NOTIFICATIONS);
|
||||
|
||||
notifications.add(R.xml.devicesettings_send_app_notifications);
|
||||
|
||||
if (getCannedRepliesSlotCount(device) > 0) {
|
||||
@ -50,6 +48,12 @@ public abstract class GarminCoordinator extends AbstractBLEDeviceCoordinator {
|
||||
notifications.add(R.xml.devicesettings_canned_dismisscall_16);
|
||||
}
|
||||
|
||||
final List<Integer> location = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.LOCATION);
|
||||
location.add(R.xml.devicesettings_workout_send_gps_to_band);
|
||||
|
||||
final List<Integer> connection = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.CONNECTION);
|
||||
connection.add(R.xml.devicesettings_high_mtu);
|
||||
|
||||
final List<Integer> developer = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.DEVELOPER);
|
||||
developer.add(R.xml.devicesettings_keep_activity_data_on_device);
|
||||
|
||||
|
@ -2,6 +2,7 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.garmin;
|
||||
|
||||
import android.bluetooth.BluetoothGatt;
|
||||
import android.bluetooth.BluetoothGattCharacteristic;
|
||||
import android.location.Location;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -26,6 +27,7 @@ import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.garmin.GarminPreferences;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.vivomovehr.GarminCapability;
|
||||
import nodomain.freeyourgadget.gadgetbridge.externalevents.gps.GBLocationService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.CannedMessagesSpec;
|
||||
@ -34,6 +36,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.Weather;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.proto.vivomovehr.GdiCore;
|
||||
import nodomain.freeyourgadget.gadgetbridge.proto.vivomovehr.GdiDeviceStatus;
|
||||
import nodomain.freeyourgadget.gadgetbridge.proto.vivomovehr.GdiFindMyWatch;
|
||||
import nodomain.freeyourgadget.gadgetbridge.proto.vivomovehr.GdiSettingsService;
|
||||
@ -98,8 +101,10 @@ public class GarminSupport extends AbstractBTLEDeviceSupport implements ICommuni
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
super.dispose();
|
||||
LOG.info("Garmin dispose()");
|
||||
GBLocationService.stop(getContext(), getDevice());
|
||||
stopMusicTimer();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
private void stopMusicTimer() {
|
||||
@ -598,5 +603,18 @@ public class GarminSupport extends AbstractBTLEDeviceSupport implements ICommuni
|
||||
return dir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSetGpsLocation(final Location location) {
|
||||
final GdiCore.CoreService.LocationUpdatedNotification.Builder locationUpdatedNotification = GdiCore.CoreService.LocationUpdatedNotification.newBuilder()
|
||||
.addLocationData(
|
||||
GarminUtils.toLocationData(location, GdiCore.CoreService.DataType.REALTIME_TRACKING)
|
||||
);
|
||||
|
||||
final ProtobufMessage locationUpdatedNotificationRequest = protocolBufferHandler.prepareProtobufRequest(
|
||||
GdiSmartProto.Smart.newBuilder().setCoreService(
|
||||
GdiCore.CoreService.newBuilder().setLocationUpdatedNotification(locationUpdatedNotification)
|
||||
).build()
|
||||
);
|
||||
sendOutgoingMessage(locationUpdatedNotificationRequest);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,35 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.garmin;
|
||||
|
||||
import android.location.Location;
|
||||
import android.os.Build;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.proto.vivomovehr.GdiCore;
|
||||
|
||||
public final class GarminUtils {
|
||||
private GarminUtils() {
|
||||
// utility class
|
||||
}
|
||||
|
||||
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))
|
||||
.build();
|
||||
|
||||
float vAccuracy = 0;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
vAccuracy = location.getVerticalAccuracyMeters();
|
||||
}
|
||||
|
||||
return GdiCore.CoreService.LocationData.newBuilder()
|
||||
.setPosition(positionForWatch)
|
||||
.setAltitude((float) location.getAltitude())
|
||||
.setTimestamp(GarminTimeUtils.javaMillisToGarminTimestamp(location.getTime()))
|
||||
.setHAccuracy(location.getAccuracy())
|
||||
.setVAccuracy(vAccuracy)
|
||||
.setPositionType(dataType)
|
||||
.setBearing(location.getBearing())
|
||||
.setSpeed(location.getSpeed())
|
||||
.build();
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.garmin;
|
||||
|
||||
import android.location.Location;
|
||||
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
@ -13,9 +15,12 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventBatteryInfo;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdatePreferences;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.garmin.GarminPreferences;
|
||||
import nodomain.freeyourgadget.gadgetbridge.externalevents.gps.GBLocationProviderType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.externalevents.gps.GBLocationService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.CannedMessagesSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.proto.vivomovehr.GdiCalendarService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.proto.vivomovehr.GdiCore;
|
||||
@ -28,6 +33,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.http.HttpHand
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.messages.GFDIMessage;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.messages.ProtobufMessage;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.messages.status.ProtobufStatusMessage;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.pebble.webview.CurrentPosition;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.calendar.CalendarEvent;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.calendar.CalendarManager;
|
||||
@ -76,9 +82,7 @@ public class ProtocolBufferHandler implements MessageHandler {
|
||||
}
|
||||
boolean processed = false;
|
||||
if (smart.hasCoreService()) { //TODO: unify request and response???
|
||||
processed = true;
|
||||
processProtobufCoreResponse(smart.getCoreService());
|
||||
// return prepareProtobufResponse(processProtobufCoreRequest(smart.getCoreService()), message.getRequestId());
|
||||
return prepareProtobufResponse(processProtobufCoreRequest(smart.getCoreService()), message.getRequestId());
|
||||
}
|
||||
if (smart.hasCalendarService()) {
|
||||
return prepareProtobufResponse(processProtobufCalendarRequest(smart.getCalendarService()), message.getRequestId());
|
||||
@ -203,14 +207,6 @@ public class ProtocolBufferHandler implements MessageHandler {
|
||||
).build();
|
||||
}
|
||||
|
||||
private void processProtobufCoreResponse(GdiCore.CoreService coreService) {
|
||||
if (coreService.hasSyncResponse()) {
|
||||
final GdiCore.CoreService.SyncResponse syncResponse = coreService.getSyncResponse();
|
||||
LOG.info("Received sync status: {}", syncResponse.getStatus());
|
||||
}
|
||||
LOG.warn("Unknown CoreService response: {}", coreService);
|
||||
}
|
||||
|
||||
private void processProtobufDeviceStatusResponse(GdiDeviceStatus.DeviceStatusService deviceStatusService) {
|
||||
if (deviceStatusService.hasRemoteDeviceBatteryStatusResponse()) {
|
||||
final GdiDeviceStatus.DeviceStatusService.RemoteDeviceBatteryStatusResponse batteryStatusResponse = deviceStatusService.getRemoteDeviceBatteryStatusResponse();
|
||||
@ -229,32 +225,81 @@ public class ProtocolBufferHandler implements MessageHandler {
|
||||
LOG.warn("Unknown DeviceStatusService response: {}", deviceStatusService);
|
||||
}
|
||||
|
||||
// private GdiSmartProto.Smart processProtobufCoreRequest(GdiCore.CoreService coreService) {
|
||||
// if (coreService.hasLocationUpdatedSetEnabledRequest()) { //TODO: enable location support in devicesupport
|
||||
// LOG.debug("Location CoreService: {}", coreService);
|
||||
//
|
||||
// final GdiCore.CoreService.LocationUpdatedSetEnabledRequest locationUpdatedSetEnabledRequest = coreService.getLocationUpdatedSetEnabledRequest();
|
||||
//
|
||||
// LOG.info("Received locationUpdatedSetEnabledRequest status: {}", locationUpdatedSetEnabledRequest.getEnabled());
|
||||
//
|
||||
// GdiCore.CoreService.LocationUpdatedSetEnabledResponse.Builder response = GdiCore.CoreService.LocationUpdatedSetEnabledResponse.newBuilder()
|
||||
// .setStatus(GdiCore.CoreService.LocationUpdatedSetEnabledResponse.Status.OK);
|
||||
//
|
||||
// //TODO: check and follow the preference in coordinator (see R.xml.devicesettings_workout_send_gps_to_band )
|
||||
// if(locationUpdatedSetEnabledRequest.getEnabled()) {
|
||||
// response.addRequests(GdiCore.CoreService.LocationUpdatedSetEnabledResponse.Requested.newBuilder()
|
||||
// .setRequested(locationUpdatedSetEnabledRequest.getRequests(0).getRequested())
|
||||
// .setStatus(GdiCore.CoreService.LocationUpdatedSetEnabledResponse.Requested.RequestedStatus.OK));
|
||||
// }
|
||||
//
|
||||
// deviceSupport.processLocationUpdateRequest(locationUpdatedSetEnabledRequest.getEnabled(), locationUpdatedSetEnabledRequest.getRequestsList());
|
||||
//
|
||||
// return GdiSmartProto.Smart.newBuilder().setCoreService(
|
||||
// GdiCore.CoreService.newBuilder().setLocationUpdatedSetEnabledResponse(response)).build();
|
||||
// }
|
||||
// LOG.warn("Unknown CoreService request: {}", coreService);
|
||||
// return null;
|
||||
// }
|
||||
private GdiSmartProto.Smart processProtobufCoreRequest(GdiCore.CoreService coreService) {
|
||||
if (coreService.hasSyncResponse()) {
|
||||
final GdiCore.CoreService.SyncResponse syncResponse = coreService.getSyncResponse();
|
||||
LOG.info("Received sync status: {}", syncResponse.getStatus());
|
||||
return null;
|
||||
}
|
||||
|
||||
if (coreService.hasGetLocationRequest()) {
|
||||
LOG.info("Got location request");
|
||||
final Location location = new CurrentPosition().getLastKnownLocation();
|
||||
final GdiCore.CoreService.GetLocationResponse.Builder response = GdiCore.CoreService.GetLocationResponse.newBuilder();
|
||||
if (location.getLatitude() == 0 && location.getLongitude() == 0) {
|
||||
response.setStatus(GdiCore.CoreService.GetLocationResponse.Status.NO_VALID_LOCATION);
|
||||
} else {
|
||||
response.setStatus(GdiCore.CoreService.GetLocationResponse.Status.OK)
|
||||
.setLocationData(GarminUtils.toLocationData(location, GdiCore.CoreService.DataType.GENERAL_LOCATION));
|
||||
}
|
||||
return GdiSmartProto.Smart.newBuilder().setCoreService(
|
||||
GdiCore.CoreService.newBuilder().setGetLocationResponse(response)).build();
|
||||
}
|
||||
|
||||
if (coreService.hasLocationUpdatedSetEnabledRequest()) {
|
||||
final GdiCore.CoreService.LocationUpdatedSetEnabledRequest locationUpdatedSetEnabledRequest = coreService.getLocationUpdatedSetEnabledRequest();
|
||||
|
||||
LOG.info("Received locationUpdatedSetEnabledRequest status: {}", locationUpdatedSetEnabledRequest.getEnabled());
|
||||
|
||||
GdiCore.CoreService.LocationUpdatedSetEnabledResponse.Builder response = GdiCore.CoreService.LocationUpdatedSetEnabledResponse.newBuilder()
|
||||
.setStatus(GdiCore.CoreService.LocationUpdatedSetEnabledResponse.Status.OK);
|
||||
|
||||
final boolean sendGpsPref = deviceSupport.getDevicePrefs().getBoolean(DeviceSettingsPreferenceConst.PREF_WORKOUT_SEND_GPS_TO_BAND, false);
|
||||
|
||||
GdiCore.CoreService.Request realtimeRequest = null;
|
||||
|
||||
if (locationUpdatedSetEnabledRequest.getEnabled()) {
|
||||
for (final GdiCore.CoreService.Request request : locationUpdatedSetEnabledRequest.getRequestsList()) {
|
||||
final GdiCore.CoreService.LocationUpdatedSetEnabledResponse.Requested.RequestedStatus requestedStatus;
|
||||
if (GdiCore.CoreService.DataType.REALTIME_TRACKING.equals(request.getRequested())) {
|
||||
realtimeRequest = request;
|
||||
if (sendGpsPref) {
|
||||
requestedStatus = GdiCore.CoreService.LocationUpdatedSetEnabledResponse.Requested.RequestedStatus.OK;
|
||||
} else {
|
||||
requestedStatus = GdiCore.CoreService.LocationUpdatedSetEnabledResponse.Requested.RequestedStatus.KO;
|
||||
}
|
||||
} else {
|
||||
requestedStatus = GdiCore.CoreService.LocationUpdatedSetEnabledResponse.Requested.RequestedStatus.KO;
|
||||
}
|
||||
|
||||
response.addRequests(
|
||||
GdiCore.CoreService.LocationUpdatedSetEnabledResponse.Requested.newBuilder()
|
||||
.setRequested(request.getRequested())
|
||||
.setStatus(requestedStatus)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (sendGpsPref) {
|
||||
if (realtimeRequest != null) {
|
||||
GBLocationService.start(
|
||||
deviceSupport.getContext(),
|
||||
deviceSupport.getDevice(),
|
||||
GBLocationProviderType.GPS,
|
||||
1000 // TODO from realtimeRequest
|
||||
);
|
||||
} else {
|
||||
GBLocationService.stop(deviceSupport.getContext(), deviceSupport.getDevice());
|
||||
}
|
||||
}
|
||||
|
||||
return GdiSmartProto.Smart.newBuilder().setCoreService(
|
||||
GdiCore.CoreService.newBuilder().setLocationUpdatedSetEnabledResponse(response)).build();
|
||||
}
|
||||
|
||||
LOG.warn("Unknown CoreService request: {}", coreService);
|
||||
return null;
|
||||
}
|
||||
|
||||
private GdiSmartProto.Smart processProtobufSmsNotificationMessage(GdiSmsNotification.SmsNotificationService smsNotificationService) {
|
||||
if (smsNotificationService.hasSmsCannedListRequest()) {
|
||||
|
@ -70,12 +70,11 @@ message CoreService {
|
||||
optional Status status = 1;
|
||||
repeated Requested requests = 2;
|
||||
|
||||
|
||||
enum Status {
|
||||
OK = 1;
|
||||
UNAVAILABLE = 2;
|
||||
UNKNOWN3 = 3;
|
||||
UNKNOWN4 = 4;
|
||||
OK = 1;
|
||||
UNAVAILABLE = 2;
|
||||
UNKNOWN3 = 3;
|
||||
UNKNOWN4 = 4;
|
||||
}
|
||||
|
||||
message Requested {
|
||||
@ -83,8 +82,8 @@ message CoreService {
|
||||
optional RequestedStatus status = 2;
|
||||
|
||||
enum RequestedStatus {
|
||||
OK = 1;
|
||||
KO = 2;
|
||||
OK = 1;
|
||||
KO = 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
9
app/src/main/res/xml/devicesettings_root_location.xml
Normal file
9
app/src/main/res/xml/devicesettings_root_location.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<PreferenceScreen
|
||||
android:icon="@drawable/ic_gps_location"
|
||||
android:key="pref_screen_location"
|
||||
android:persistent="false"
|
||||
android:title="@string/pref_header_location">
|
||||
</PreferenceScreen>
|
||||
</androidx.preference.PreferenceScreen>
|
Loading…
x
Reference in New Issue
Block a user