1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-06-01 19:06:06 +02:00
Gadgetbridge/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/RecordHeader.java
José Rebelo 1328ce13e1 Garmin: Improve fit parsing
* Remove the dependency on PredefinedLocalMessage from generic fit parsing code
* Standardize toString methods, omit types for known fields
* Return null on unknown field number or names, instead of crashing
* Map more Global FIT messages (device info, monitoring, sleep stages, sleep stats, stress level)
* Prioritize "timestamp" over "253_timestamp" if specified explicitly in the global message definition
* Introduce RecordData wrappers for each global message, allowing us to have proper types when getting data. If missing or unknown, the getter returns null. All classes are auto-generated by the FitCodeGen.
* Persist a list of RecordData, instead of a Map from RecordDefinition
* Fix parsing of compressed timestamps - keep them in computedTimestamp on each data record
* Use timestamp16 if available in Monitoring records
2024-05-03 20:28:12 +02:00

88 lines
2.5 KiB
Java

package nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
public class RecordHeader {
private final boolean definition;
private final boolean developerData;
private final int localMessageType;
private final Integer timeOffset;
public RecordHeader(boolean definition, boolean developerData, int localMessageType, Integer timeOffset) {
this.definition = definition;
this.developerData = developerData;
this.localMessageType = localMessageType;
this.timeOffset = timeOffset;
}
//see https://github.com/polyvertex/fitdecode/blob/master/fitdecode/reader.py#L512
public RecordHeader(byte header) {
if ((header & 0x80) == 0x80) { //compressed timestamp
definition = false;
developerData = false;
localMessageType = (header >> 5) & 0x3;
timeOffset = header & 0x1f;
} else {
definition = ((header & 0x40) == 0x40);
developerData = ((header & 0x20) == 0x20);
localMessageType = header & 0xf;
timeOffset = null;
}
}
public int getLocalMessageType() {
return localMessageType;
}
@Nullable
public Integer getTimeOffset() {
return timeOffset;
}
public boolean isCompressedTimestamp() {
return timeOffset != null;
}
public boolean isDeveloperData() {
return developerData;
}
public boolean isDefinition() {
return definition;
}
public byte generateOutgoingDefinitionPayload() {
if (!definition && !developerData) {
assert timeOffset != null;
return (byte) (timeOffset | (((byte) localMessageType) << 5));
}
byte base = (byte) localMessageType;
if (definition)
base = (byte) (base | 0x40);
if (developerData)
base = (byte) (base | 0x20);
return base;
}
public byte generateOutgoingDataPayload() { //TODO: unclear if correct
if (!definition && !developerData) {
assert timeOffset != null;
return (byte) (timeOffset | (((byte) localMessageType) << 5));
}
byte base = (byte) localMessageType;
if (developerData)
base = (byte) (base | 0x20);
return base;
}
@NonNull
@Override
public String toString() {
return "Local Message: " + localMessageType;
}
}