diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/vivomovehr/GarminCapability.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/vivomovehr/GarminCapability.java index 93a7f419bd..06d258fab1 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/vivomovehr/GarminCapability.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/vivomovehr/GarminCapability.java @@ -16,11 +16,18 @@ along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.devices.vivomovehr; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; +import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent; +import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdatePreferences; +import nodomain.freeyourgadget.gadgetbridge.devices.garmin.GarminPreferences; +import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.deviceevents.CapabilitiesDeviceEvent; + public enum GarminCapability { CONNECT_MOBILE_FIT_LINK, GOLF_FIT_LINK, @@ -187,6 +194,22 @@ public enum GarminCapability { return result; } + public static Set setFromLong(final long capabilitiesMask) { + final Set result = + new HashSet<>(GarminCapability.values().length); + + for (int i = 0; i < Long.SIZE; i++) { + if ((capabilitiesMask & (1L << i)) != 0) { + GarminCapability cap = FROM_ORDINAL.get(i); + if (cap != null) { + result.add(cap); + } + } + } + return result; + } + + public static byte[] setToBinary(final Set capabilities) { final GarminCapability[] values = values(); final byte[] result = new byte[(values.length + 7) / 8]; @@ -213,4 +236,15 @@ public enum GarminCapability { } return result.toString(); } + + public static List getGBDeviceEvent(final Set capabilities) { + final Set capabilitiesPref = new HashSet<>(); + for (final GarminCapability capability : capabilities) { + capabilitiesPref.add(capability.name()); + } + return Arrays.asList( + new CapabilitiesDeviceEvent(capabilities), + new GBDeviceEventUpdatePreferences(GarminPreferences.PREF_GARMIN_CAPABILITIES, capabilitiesPref) + ); + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/FitLocalMessageHandler.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/FitLocalMessageHandler.java index 7a60ff2f52..248ac391ca 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/FitLocalMessageHandler.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/FitLocalMessageHandler.java @@ -6,7 +6,10 @@ import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.List; +import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent; +import nodomain.freeyourgadget.gadgetbridge.devices.vivomovehr.GarminCapability; import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.FitLocalMessageBuilder; +import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.GlobalFITMessage; 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.messages.FitDataMessage; @@ -44,14 +47,32 @@ public class FitLocalMessageHandler implements MessageHandler{ } private void parseIncomingFitDataMessage(FitDataMessage incoming) { + final List deviceEventList = new ArrayList<>(); recordDataList = (incoming).applyDefinitions(recordDefinitionList); for(RecordData d: recordDataList){ LOG.info("Incoming FitDataMessage: {}", d); + List processed = processRecordData(d); + if(processed!=null) { + deviceEventList.addAll(processed); + } + } + LOG.info("Some incoming FitDataMessages are not processed any further, just logged."); + for (final GBDeviceEvent event : deviceEventList) { + deviceSupport.evaluateGBDeviceEvent(event); } - LOG.info("Incoming FitDataMessages are not processed any further, just logged."); unregisterSelf(); } + private List processRecordData(RecordData d) { + if (d.getRecordDefinition().getGlobalFITMessage() == GlobalFITMessage.CAPABILITIES) { + //TODO: we are not sure this is correct! + return GarminCapability.getGBDeviceEvent( + GarminCapability.setFromLong((Long) d.getFieldByName("connectivity_supported")) + ); + } + return null; + } + private void unregisterSelf() { deviceSupport.unregisterHandler(this); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/GarminSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/GarminSupport.java index 60e44dfab2..c4ba0ab4fd 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/GarminSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/GarminSupport.java @@ -312,19 +312,15 @@ public class GarminSupport extends AbstractBTLESingleDeviceSupport implements IC } } - final List events = parsedMessage.getGBDeviceEvent(); - for (final GBDeviceEvent event : events) { - evaluateGBDeviceEvent(event); - } - sendAck("send status", parsedMessage); //send status message sendOutgoingMessage("send reply", parsedMessage); //send reply if any sendOutgoingMessage("send followup", followup); //send followup message if any - if (parsedMessage instanceof GenericStatusMessage && ((GenericStatusMessage) parsedMessage).getGarminMessage() == GFDIMessage.GarminMessage.CONFIGURATION) { //the last forced message exchange - completeInitialization(); + final List events = parsedMessage.getGBDeviceEvent(); + for (final GBDeviceEvent event : events) { + evaluateGBDeviceEvent(event); } processDownloadQueue(); @@ -358,6 +354,7 @@ public class GarminSupport extends AbstractBTLESingleDeviceSupport implements IC } } else if (deviceEvent instanceof CapabilitiesDeviceEvent) { final Set capabilities = ((CapabilitiesDeviceEvent) deviceEvent).capabilities; + completeInitialization(); if (capabilities.contains(GarminCapability.REALTIME_SETTINGS)) { final String language = Locale.getDefault().getLanguage(); final String country = Locale.getDefault().getCountry(); @@ -722,6 +719,11 @@ public class GarminSupport extends AbstractBTLESingleDeviceSupport implements IC } private void completeInitialization() { + if (gbDevice.getState() == GBDevice.State.INITIALIZED) { + LOG.error("completeInitialization() was called, but the device is already initialized. This should never happen! Please report this to the project."); + LOG.warn("preventing double initialization"); + return; + } sendOutgoingMessage("request supported file types", new SupportedFileTypesMessage()); sendDeviceSettings(); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/messages/ConfigurationMessage.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/messages/ConfigurationMessage.java index c936da09d9..e996c6b1a3 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/messages/ConfigurationMessage.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/messages/ConfigurationMessage.java @@ -35,14 +35,7 @@ public class ConfigurationMessage extends GFDIMessage { @Override public List getGBDeviceEvent() { - final Set capabilitiesPref = new HashSet<>(); - for (final GarminCapability capability : capabilities) { - capabilitiesPref.add(capability.name()); - } - return Arrays.asList( - new CapabilitiesDeviceEvent(capabilities), - new GBDeviceEventUpdatePreferences(GarminPreferences.PREF_GARMIN_CAPABILITIES, capabilitiesPref) - ); + return GarminCapability.getGBDeviceEvent(capabilities); } @Override