mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2026-07-31 07:44:24 +02:00
Garmin: prepare for more complex FIT upload scenarios
This commit is contained in:
+1
-19
@@ -43,7 +43,6 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.FileType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.FitFile;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.exception.FitParseException;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitCourse;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitFileId;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitWorkout;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.UriHelper;
|
||||
@@ -87,24 +86,7 @@ public class GarminFitFileInstallHandler implements InstallHandler {
|
||||
try (InputStream in = new BufferedInputStream(uriHelper.openInputStream())) {
|
||||
rawBytes = FileUtils.readAll(in, 10 * 1024 * 1024); // 10MB
|
||||
fitFile = FitFile.parseIncoming(rawBytes);
|
||||
|
||||
final Optional<FitFileId> fitFileIdOpt = fitFile.getRecords().stream()
|
||||
.filter(r -> r instanceof FitFileId)
|
||||
.map(r -> (FitFileId) r)
|
||||
.findFirst();
|
||||
|
||||
if (!fitFileIdOpt.isPresent()) {
|
||||
LOG.error("Fit file has no ID");
|
||||
return;
|
||||
}
|
||||
|
||||
final FitFileId fitFileId = fitFileIdOpt.get();
|
||||
if (fitFileId.getType() == null) {
|
||||
LOG.error("Fit file ID has null type");
|
||||
return;
|
||||
}
|
||||
|
||||
fileType = fitFileId.getType();
|
||||
fileType = fitFile.getFileType();
|
||||
} catch (final FitParseException e) {
|
||||
LOG.error("Fit file is corrupted", e);
|
||||
fitParseException = e;
|
||||
|
||||
+4
-3
@@ -90,7 +90,6 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.GpxRouteF
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.PredefinedLocalMessage;
|
||||
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.exception.FitParseException;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.fieldDefinitions.FieldDefinitionAlarmLabel;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitAlarmSettings;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitDeviceSettings;
|
||||
@@ -947,7 +946,7 @@ public class GarminSupport extends AbstractBTLESingleDeviceSupport implements IC
|
||||
"set alarms",
|
||||
fileTransferHandler.initiateUpload(
|
||||
fitFile.getOutgoingMessage(),
|
||||
FileType.FILETYPE.SETTINGS
|
||||
fitFile.getFileType()
|
||||
).getOutgoingMessage()
|
||||
);
|
||||
}
|
||||
@@ -1193,7 +1192,9 @@ public class GarminSupport extends AbstractBTLESingleDeviceSupport implements IC
|
||||
garminGpxRouteInstallHandler.getGpxFile(),
|
||||
trackName
|
||||
);
|
||||
communicator.sendMessage("upload course file", fileTransferHandler.initiateUpload(gpxRouteFileConverter.getConvertedFile().getOutgoingMessage(), FileType.FILETYPE.DOWNLOAD_COURSE).getOutgoingMessage());
|
||||
final FitFile convertedFile = gpxRouteFileConverter.getConvertedFile();
|
||||
final FileType.FILETYPE fileType = convertedFile.getFileType();
|
||||
communicator.sendMessage("upload " + fileType + " file", fileTransferHandler.initiateUpload(convertedFile.getOutgoingMessage(), fileType).getOutgoingMessage());
|
||||
}
|
||||
|
||||
final GarminPrgFileInstallHandler prgFileInstallHandler = new GarminPrgFileInstallHandler(uri, getContext());
|
||||
|
||||
+45
@@ -1,6 +1,23 @@
|
||||
/* Copyright (C) 2024-2025 Daniele Gobbetti, José Rebelo, Thomas Kuehne
|
||||
|
||||
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 <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -15,10 +32,13 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.ChecksumCalculator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.FileType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.GarminByteBufferReader;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.exception.FitParseException;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitFileId;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitRecordDataFactory;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.messages.MessageWriter;
|
||||
|
||||
@@ -152,6 +172,31 @@ public class FitFile {
|
||||
writer.writeShort(ChecksumCalculator.computeCrc(writer.getBytes(), this.header.getHeaderSize(), writer.getBytes().length - this.header.getHeaderSize()));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public FileType.FILETYPE getFileType() {
|
||||
if (dataRecords == null || dataRecords.isEmpty()) {
|
||||
LOG.error("FIT file has no dataRecords");
|
||||
return null;
|
||||
}
|
||||
|
||||
final Optional<FitFileId> fitFileIdOpt = dataRecords.stream()
|
||||
.filter(r -> r instanceof FitFileId)
|
||||
.map(r -> (FitFileId) r)
|
||||
.findFirst();
|
||||
|
||||
if (!fitFileIdOpt.isPresent()) {
|
||||
LOG.error("FIT file has no FILE_ID message");
|
||||
return null;
|
||||
}
|
||||
|
||||
final FitFileId fitFileId = fitFileIdOpt.get();
|
||||
FileType.FILETYPE type = fitFileId.getType();
|
||||
if (type == null) {
|
||||
LOG.error("FIT file FILE_ID message has 'type' value null");
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
public byte[] getOutgoingMessage() {
|
||||
// Compute the worst case scenario buffer size for the fit file
|
||||
// A ~1.6MB gpx file with ~16k points results in a ~320KB buffer, ~150KB of which get actually used
|
||||
|
||||
Reference in New Issue
Block a user