mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2026-07-31 07:44:24 +02:00
Garmin: Remove PredefinedLocalMessage class
Refactor FitDataMessage to support a two-step message parsing: at first hold a copy of the incoming bytestream and later parse it according to a list of RecordDefinitions. This allows to remove PredefinedLocalMessage which was already made obsolete by previous changes. This should also allow to support incoming FitDefinition/FitData exchanges.
This commit is contained in:
committed by
José Rebelo
parent
63e0ecba63
commit
a3d732f11a
-58
@@ -1,58 +0,0 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.List;
|
||||
|
||||
public enum PredefinedLocalMessage {
|
||||
TODAY_WEATHER_CONDITIONS(6, GlobalFITMessage.WEATHER,
|
||||
new int[]{0, 253, 9, 1, 14, 13, 2, 3, 5, 4, 6, 7, 10, 11, 17, 15, 8}
|
||||
),
|
||||
HOURLY_WEATHER_FORECAST(9, GlobalFITMessage.WEATHER,
|
||||
new int[]{0, 253, 1, 2, 3, 4, 5, 6, 7, 15, 16, 17}
|
||||
),
|
||||
DAILY_WEATHER_FORECAST(10, GlobalFITMessage.WEATHER,
|
||||
new int[]{0, 253, 14, 13, 2, 5, 12, 17}
|
||||
);
|
||||
|
||||
private final int type;
|
||||
private final GlobalFITMessage globalFITMessage;
|
||||
private final int[] globalDefinitionIds;
|
||||
|
||||
PredefinedLocalMessage(int type, GlobalFITMessage globalFITMessage, int[] globalDefinitionIds) {
|
||||
this.type = type;
|
||||
this.globalFITMessage = globalFITMessage;
|
||||
this.globalDefinitionIds = globalDefinitionIds;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PredefinedLocalMessage fromType(int type) {
|
||||
for (final PredefinedLocalMessage predefinedLocalMessage : PredefinedLocalMessage.values()) {
|
||||
if (predefinedLocalMessage.getType() == type) {
|
||||
return predefinedLocalMessage;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public RecordDefinition getRecordDefinition() {
|
||||
final RecordHeader recordHeader = new RecordHeader(true, false, type, null);
|
||||
final List<FieldDefinition> fieldDefinitions = globalFITMessage.getFieldDefinitions(globalDefinitionIds);
|
||||
return new RecordDefinition(
|
||||
recordHeader,
|
||||
ByteOrder.BIG_ENDIAN,
|
||||
globalFITMessage,
|
||||
fieldDefinitions,
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
public int getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public GlobalFITMessage getGlobalFITMessage() {
|
||||
return globalFITMessage;
|
||||
}
|
||||
}
|
||||
+61
-26
@@ -2,52 +2,87 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.messages;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.PredefinedLocalMessage;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.GarminByteBufferReader;
|
||||
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.messages.status.FitDataStatusMessage;
|
||||
|
||||
public class FitDataMessage extends GFDIMessage {
|
||||
private final List<RecordData> recordDataList;
|
||||
private List<RecordData> recordDataList;
|
||||
private GarminByteBufferReader reader;
|
||||
private final boolean generateOutgoing;
|
||||
private boolean isProcessed = false;
|
||||
|
||||
public FitDataMessage(List<RecordData> recordDataList, GarminMessage garminMessage) {
|
||||
this.recordDataList = recordDataList;
|
||||
public FitDataMessage(GarminByteBufferReader messageReader, GarminMessage garminMessage) {
|
||||
this.reader = messageReader;
|
||||
this.recordDataList = new ArrayList<>();
|
||||
this.garminMessage = garminMessage;
|
||||
this.statusMessage = new FitDataStatusMessage(garminMessage, Status.ACK, FitDataStatusMessage.FitDataStatusCode.APPLIED);
|
||||
this.generateOutgoing = false;
|
||||
}
|
||||
|
||||
public FitDataMessage(List<RecordData> recordDataList) {
|
||||
this.reader = null;
|
||||
this.recordDataList = recordDataList;
|
||||
this.garminMessage = GarminMessage.FIT_DATA;
|
||||
this.statusMessage = null;
|
||||
this.isProcessed = true;
|
||||
this.generateOutgoing = true;
|
||||
}
|
||||
|
||||
public static FitDataMessage parseIncoming(MessageReader reader, GarminMessage garminMessage) {
|
||||
final List<RecordData> recordDataList = new ArrayList<>();
|
||||
|
||||
while (reader.remaining() > 0) {
|
||||
RecordHeader recordHeader = new RecordHeader((byte) reader.readByte());
|
||||
if (recordHeader.isDefinition())
|
||||
return null;
|
||||
PredefinedLocalMessage predefinedLocalMessage = PredefinedLocalMessage.fromType(recordHeader.getLocalMessageType());
|
||||
if (predefinedLocalMessage == null) {
|
||||
LOG.warn("Local message is null");
|
||||
|
||||
return null;
|
||||
}
|
||||
RecordData recordData = new RecordData(
|
||||
predefinedLocalMessage.getRecordDefinition(),
|
||||
predefinedLocalMessage.getRecordDefinition().getRecordHeader()
|
||||
);
|
||||
recordData.parseDataMessage(reader, null);
|
||||
recordDataList.add(recordData);
|
||||
}
|
||||
|
||||
return new FitDataMessage(recordDataList, garminMessage);
|
||||
return new FitDataMessage(new GarminByteBufferReader(reader.readBytes(reader.remaining())), garminMessage);
|
||||
}
|
||||
|
||||
public void applyDefinitions(List<RecordDefinition> recordDefinitions) {
|
||||
Objects.requireNonNull(reader, "reader cannot be null");
|
||||
try {
|
||||
while (reader.remaining() > 0) {
|
||||
RecordHeader recordHeader = new RecordHeader((byte) reader.readByte());
|
||||
if (recordHeader.isDefinition())
|
||||
return;
|
||||
|
||||
RecordDefinition localMessageDefinition = recordDefinitions.stream()
|
||||
.filter(d -> d.getRecordHeader().getLocalMessageType() == recordHeader.getLocalMessageType())
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
if (localMessageDefinition == null) {
|
||||
LOG.warn("Cannot find a local message definition for type: {}", recordHeader.getLocalMessageType());
|
||||
return ;
|
||||
}
|
||||
RecordData recordData = new RecordData(
|
||||
localMessageDefinition,
|
||||
localMessageDefinition.getRecordHeader()
|
||||
);
|
||||
recordData.parseDataMessage(reader, null);
|
||||
recordDataList.add(recordData);
|
||||
}
|
||||
this.isProcessed = true;
|
||||
} catch (Exception e) {
|
||||
LOG.error("Error while applying definitions", e);
|
||||
throw new IllegalStateException("Failed to apply definitions to FIT data", e);
|
||||
} finally {
|
||||
reader = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public List<RecordData> getRecordDataList() {
|
||||
if(!isProcessed())
|
||||
throw new IllegalStateException(
|
||||
"Message has not been processed yet. Call applyDefinitions first."
|
||||
);
|
||||
return recordDataList;
|
||||
}
|
||||
|
||||
public boolean isProcessed() {
|
||||
return isProcessed;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean generateOutgoing() {
|
||||
final MessageWriter writer = new MessageWriter(response);
|
||||
@@ -56,6 +91,6 @@ public class FitDataMessage extends GFDIMessage {
|
||||
for (RecordData recordData : recordDataList) {
|
||||
recordData.generateOutgoingDataPayload(writer);
|
||||
}
|
||||
return true;
|
||||
return this.generateOutgoing;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user