mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2026-07-31 07:44:24 +02:00
Garmin: add support for devices not sending ConfigurationMessage
Infer capabilities from the incoming FitData message (as test/workaround, we're not sure if the field we're using is the correct one). Use the CapabilitiesDeviceEvent instead of the hardcoded ConfigurationMessage instanceof check to call completeInitialization() in GarminSupport. Also centralize the generation of the capabilities-related DeviceEvent in GarminCapability as they are used both in ConfigurationMessage as in FitLocalMessageHandler now.
This commit is contained in:
+34
@@ -16,11 +16,18 @@
|
|||||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||||
package nodomain.freeyourgadget.gadgetbridge.devices.vivomovehr;
|
package nodomain.freeyourgadget.gadgetbridge.devices.vivomovehr;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
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 {
|
public enum GarminCapability {
|
||||||
CONNECT_MOBILE_FIT_LINK,
|
CONNECT_MOBILE_FIT_LINK,
|
||||||
GOLF_FIT_LINK,
|
GOLF_FIT_LINK,
|
||||||
@@ -187,6 +194,22 @@ public enum GarminCapability {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Set<GarminCapability> setFromLong(final long capabilitiesMask) {
|
||||||
|
final Set<GarminCapability> 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<GarminCapability> capabilities) {
|
public static byte[] setToBinary(final Set<GarminCapability> capabilities) {
|
||||||
final GarminCapability[] values = values();
|
final GarminCapability[] values = values();
|
||||||
final byte[] result = new byte[(values.length + 7) / 8];
|
final byte[] result = new byte[(values.length + 7) / 8];
|
||||||
@@ -213,4 +236,15 @@ public enum GarminCapability {
|
|||||||
}
|
}
|
||||||
return result.toString();
|
return result.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<GBDeviceEvent> getGBDeviceEvent(final Set<GarminCapability> capabilities) {
|
||||||
|
final Set<Object> 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)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-1
@@ -6,7 +6,10 @@ import org.slf4j.LoggerFactory;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
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.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.RecordData;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.RecordDefinition;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.RecordDefinition;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.messages.FitDataMessage;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.messages.FitDataMessage;
|
||||||
@@ -44,14 +47,32 @@ public class FitLocalMessageHandler implements MessageHandler{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void parseIncomingFitDataMessage(FitDataMessage incoming) {
|
private void parseIncomingFitDataMessage(FitDataMessage incoming) {
|
||||||
|
final List<GBDeviceEvent> deviceEventList = new ArrayList<>();
|
||||||
recordDataList = (incoming).applyDefinitions(recordDefinitionList);
|
recordDataList = (incoming).applyDefinitions(recordDefinitionList);
|
||||||
for(RecordData d: recordDataList){
|
for(RecordData d: recordDataList){
|
||||||
LOG.info("Incoming FitDataMessage: {}", d);
|
LOG.info("Incoming FitDataMessage: {}", d);
|
||||||
|
List<GBDeviceEvent> 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();
|
unregisterSelf();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<GBDeviceEvent> 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() {
|
private void unregisterSelf() {
|
||||||
deviceSupport.unregisterHandler(this);
|
deviceSupport.unregisterHandler(this);
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-7
@@ -312,19 +312,15 @@ public class GarminSupport extends AbstractBTLESingleDeviceSupport implements IC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<GBDeviceEvent> events = parsedMessage.getGBDeviceEvent();
|
|
||||||
for (final GBDeviceEvent event : events) {
|
|
||||||
evaluateGBDeviceEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
sendAck("send status", parsedMessage); //send status message
|
sendAck("send status", parsedMessage); //send status message
|
||||||
|
|
||||||
sendOutgoingMessage("send reply", parsedMessage); //send reply if any
|
sendOutgoingMessage("send reply", parsedMessage); //send reply if any
|
||||||
|
|
||||||
sendOutgoingMessage("send followup", followup); //send followup message 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
|
final List<GBDeviceEvent> events = parsedMessage.getGBDeviceEvent();
|
||||||
completeInitialization();
|
for (final GBDeviceEvent event : events) {
|
||||||
|
evaluateGBDeviceEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
processDownloadQueue();
|
processDownloadQueue();
|
||||||
@@ -358,6 +354,7 @@ public class GarminSupport extends AbstractBTLESingleDeviceSupport implements IC
|
|||||||
}
|
}
|
||||||
} else if (deviceEvent instanceof CapabilitiesDeviceEvent) {
|
} else if (deviceEvent instanceof CapabilitiesDeviceEvent) {
|
||||||
final Set<GarminCapability> capabilities = ((CapabilitiesDeviceEvent) deviceEvent).capabilities;
|
final Set<GarminCapability> capabilities = ((CapabilitiesDeviceEvent) deviceEvent).capabilities;
|
||||||
|
completeInitialization();
|
||||||
if (capabilities.contains(GarminCapability.REALTIME_SETTINGS)) {
|
if (capabilities.contains(GarminCapability.REALTIME_SETTINGS)) {
|
||||||
final String language = Locale.getDefault().getLanguage();
|
final String language = Locale.getDefault().getLanguage();
|
||||||
final String country = Locale.getDefault().getCountry();
|
final String country = Locale.getDefault().getCountry();
|
||||||
@@ -722,6 +719,11 @@ public class GarminSupport extends AbstractBTLESingleDeviceSupport implements IC
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void completeInitialization() {
|
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());
|
sendOutgoingMessage("request supported file types", new SupportedFileTypesMessage());
|
||||||
sendDeviceSettings();
|
sendDeviceSettings();
|
||||||
|
|
||||||
|
|||||||
+1
-8
@@ -35,14 +35,7 @@ public class ConfigurationMessage extends GFDIMessage {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<GBDeviceEvent> getGBDeviceEvent() {
|
public List<GBDeviceEvent> getGBDeviceEvent() {
|
||||||
final Set<Object> capabilitiesPref = new HashSet<>();
|
return GarminCapability.getGBDeviceEvent(capabilities);
|
||||||
for (final GarminCapability capability : capabilities) {
|
|
||||||
capabilitiesPref.add(capability.name());
|
|
||||||
}
|
|
||||||
return Arrays.asList(
|
|
||||||
new CapabilitiesDeviceEvent(capabilities),
|
|
||||||
new GBDeviceEventUpdatePreferences(GarminPreferences.PREF_GARMIN_CAPABILITIES, capabilitiesPref)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Reference in New Issue
Block a user