mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-12-25 01:55:50 +01:00
Garmin: Support file archival (deletion) on watch
Also add original timestamp to local cache filename as the file identifier are reused Also fix imports of Test class
This commit is contained in:
parent
5c57392b85
commit
42e44de1ac
@ -10,6 +10,7 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.messages.DownloadRequestMessage;
|
||||
@ -319,7 +320,9 @@ public class FileTransferHandler implements MessageHandler {
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return getFiletype().name() + "_" + getFileIndex() + (getFiletype().isFitFile() ? ".fit" : "");
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
|
||||
String dateString = dateFormat.format(fileDate);
|
||||
return getFiletype().name() + "_" + getFileIndex() + "_" + dateString + (getFiletype().isFitFile() ? ".fit" : "");
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
@ -103,6 +103,7 @@ public abstract class GFDIMessage {
|
||||
UPLOAD_REQUEST(5003, UploadRequestMessage.class),
|
||||
FILE_TRANSFER_DATA(5004, FileTransferDataMessage.class),
|
||||
CREATE_FILE(5005, CreateFileMessage.class),
|
||||
SET_FILE_FLAG(5008, SetFileFlagsMessage.class),
|
||||
FIT_DEFINITION(5011, FitDefinitionMessage.class),
|
||||
FIT_DATA(5012, FitDataMessage.class),
|
||||
WEATHER_REQUEST(5014, WeatherMessage.class),
|
||||
|
@ -0,0 +1,41 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.messages;
|
||||
|
||||
import org.apache.commons.lang3.EnumUtils;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
public class SetFileFlagsMessage extends GFDIMessage {
|
||||
|
||||
private final int fileIndex;
|
||||
private final FileFlags flags;
|
||||
|
||||
public SetFileFlagsMessage(int fileIndex, FileFlags flags) {
|
||||
this.garminMessage = GarminMessage.SET_FILE_FLAG;
|
||||
this.fileIndex = fileIndex;
|
||||
this.flags = flags;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean generateOutgoing() {
|
||||
final MessageWriter writer = new MessageWriter(response);
|
||||
writer.writeShort(0); // packet size will be filled below
|
||||
writer.writeShort(this.garminMessage.getId());
|
||||
writer.writeShort(this.fileIndex);
|
||||
writer.writeByte((int) EnumUtils.generateBitVector(FileFlags.class, this.flags));
|
||||
return true;
|
||||
}
|
||||
|
||||
public enum FileFlags {
|
||||
UNK_00000001,
|
||||
UNK_00000010,
|
||||
UNK_00000100,
|
||||
UNK_00001000,
|
||||
ARCHIVE,
|
||||
;
|
||||
|
||||
public static EnumSet<FileFlags> fromBitMask(final int code) {
|
||||
return EnumUtils.processBitVector(FileFlags.class, code);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -26,6 +26,8 @@ public abstract class GFDIStatusMessage extends GFDIMessage {
|
||||
SupportedFileTypesStatusMessage supportedFileTypesStatusMessage = SupportedFileTypesStatusMessage.parseIncoming(reader, garminMessage);
|
||||
LOG.info("{}", supportedFileTypesStatusMessage);
|
||||
return supportedFileTypesStatusMessage;
|
||||
} else if (GarminMessage.SET_FILE_FLAG.equals(originalGarminMessage)) {
|
||||
return SetFileFlagsStatusMessage.parseIncoming(reader, garminMessage);
|
||||
} else if (GarminMessage.FIT_DEFINITION.equals(originalGarminMessage)) {
|
||||
return FitDefinitionStatusMessage.parseIncoming(reader, originalGarminMessage);
|
||||
} else if (GarminMessage.FIT_DATA.equals(originalGarminMessage)) {
|
||||
|
@ -0,0 +1,58 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.messages.status;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.messages.SetFileFlagsMessage;
|
||||
|
||||
public class SetFileFlagsStatusMessage extends GFDIStatusMessage {
|
||||
private final Status status;
|
||||
private final FlagsStatus flagsStatus;
|
||||
private final int fileIdentifier;
|
||||
private final EnumSet<SetFileFlagsMessage.FileFlags> fileFlags;
|
||||
|
||||
public SetFileFlagsStatusMessage(GarminMessage garminMessage, Status status, FlagsStatus flagsStatus, int fileIdentifier, EnumSet<SetFileFlagsMessage.FileFlags> fileFlags) {
|
||||
this.garminMessage = garminMessage;
|
||||
this.status = status;
|
||||
this.flagsStatus = flagsStatus;
|
||||
this.fileIdentifier = fileIdentifier;
|
||||
this.fileFlags = fileFlags;
|
||||
}
|
||||
|
||||
public static SetFileFlagsStatusMessage parseIncoming(MessageReader reader, GarminMessage garminMessage) {
|
||||
final Status status = Status.fromCode(reader.readByte());
|
||||
|
||||
if (!status.equals(Status.ACK)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final FlagsStatus flagsStatus = FlagsStatus.fromCode(reader.readByte());
|
||||
final int originalFileIdentifier = reader.readShort() + 1; //TODO: check if always or only on archival
|
||||
final EnumSet<SetFileFlagsMessage.FileFlags> fileFlags = SetFileFlagsMessage.FileFlags.fromBitMask(reader.readByte());
|
||||
|
||||
if (!FlagsStatus.APPLIED.equals(flagsStatus)) {
|
||||
LOG.warn("Received {} / {} for file identifier {} and flags {} - message {}", status, flagsStatus, originalFileIdentifier, fileFlags, garminMessage);
|
||||
} else {
|
||||
LOG.info("Received {} / {} for file identifier {} and flags {} - message {}", status, flagsStatus, originalFileIdentifier, fileFlags, garminMessage);
|
||||
}
|
||||
|
||||
return new SetFileFlagsStatusMessage(garminMessage, status, flagsStatus, originalFileIdentifier, fileFlags);
|
||||
|
||||
}
|
||||
|
||||
|
||||
enum FlagsStatus {
|
||||
APPLIED,
|
||||
ERROR, //guessed
|
||||
;
|
||||
|
||||
public static FlagsStatus fromCode(final int code) {
|
||||
for (final FlagsStatus status : FlagsStatus.values()) {
|
||||
if (status.ordinal() == code) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Unknown FlagsStatus code " + code);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -2,27 +2,20 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.garmin;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.threeten.bp.Instant;
|
||||
import org.threeten.bp.ZoneId;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.communicator.CobsCoDec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.FieldDefinition;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.FitFile;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.GlobalFITMessage;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.LocalMessage;
|
||||
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.RecordHeader;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.baseTypes.BaseType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.messages.ChecksumCalculator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user