Garmin protocol: use message enum instead of id in GFDI Messages

This commit is contained in:
Daniele Gobbetti 2024-03-27 09:15:28 +01:00 committed by José Rebelo
parent 520a510dd9
commit 07db0ea7a5
20 changed files with 125 additions and 120 deletions

View File

@ -225,30 +225,30 @@ public class ProtocolBufferHandler {
if (null == protobufPayload)
return null;
final int requestId = getNextProtobufRequestId();
return prepareProtobufMessage(protobufPayload.toByteArray(), GFDIMessage.GarminMessage.PROTOBUF_REQUEST.getId(), requestId);
return prepareProtobufMessage(protobufPayload.toByteArray(), GFDIMessage.GarminMessage.PROTOBUF_REQUEST, requestId);
}
private ProtobufMessage prepareProtobufResponse(GdiSmartProto.Smart protobufPayload, int requestId) {
if (null == protobufPayload)
return null;
return prepareProtobufMessage(protobufPayload.toByteArray(), GFDIMessage.GarminMessage.PROTOBUF_RESPONSE.getId(), requestId);
return prepareProtobufMessage(protobufPayload.toByteArray(), GFDIMessage.GarminMessage.PROTOBUF_RESPONSE, requestId);
}
private ProtobufMessage prepareProtobufMessage(byte[] bytes, int messageType, int requestId) {
private ProtobufMessage prepareProtobufMessage(byte[] bytes, GFDIMessage.GarminMessage garminMessage, int requestId) {
if (bytes == null || bytes.length == 0)
return null;
LOG.info("Preparing protobuf message. Type{}, #{}, {}B: {}", messageType, requestId, bytes.length, GB.hexdump(bytes, 0, bytes.length));
LOG.info("Preparing protobuf message. Type{}, #{}, {}B: {}", garminMessage, requestId, bytes.length, GB.hexdump(bytes, 0, bytes.length));
if (bytes.length > maxChunkSize) {
chunkedFragmentsMap.put(requestId, new ProtobufFragment(bytes));
return new ProtobufMessage(messageType,
return new ProtobufMessage(garminMessage,
requestId,
0,
bytes.length,
maxChunkSize,
ArrayUtils.subarray(bytes, 0, maxChunkSize));
}
return new ProtobufMessage(messageType, requestId, 0, bytes.length, bytes.length, bytes);
return new ProtobufMessage(garminMessage, requestId, 0, bytes.length, bytes.length, bytes);
}
class ProtobufFragment {

View File

@ -8,11 +8,10 @@ import nodomain.freeyourgadget.gadgetbridge.devices.vivomovehr.GarminCapability;
public class ConfigurationMessage extends GFDIMessage {
public final Set<GarminCapability> OUR_CAPABILITIES = GarminCapability.ALL_CAPABILITIES;
private final byte[] incomingConfigurationPayload;
private final int messageType;
private final byte[] ourConfigurationPayload = GarminCapability.setToBinary(OUR_CAPABILITIES);
public ConfigurationMessage(int messageType, byte[] configurationPayload) {
this.messageType = messageType;
public ConfigurationMessage(GarminMessage garminMessage, byte[] configurationPayload) {
this.garminMessage = garminMessage;
if (configurationPayload.length > 255)
throw new IllegalArgumentException("Too long payload");
this.incomingConfigurationPayload = configurationPayload;
@ -20,12 +19,12 @@ public class ConfigurationMessage extends GFDIMessage {
Set<GarminCapability> capabilities = GarminCapability.setFromBinary(configurationPayload);
LOG.info("Received configuration message; capabilities: {}", GarminCapability.setToString(capabilities));
this.statusMessage = this.getStatusMessage(messageType);
this.statusMessage = this.getStatusMessage();
}
public static ConfigurationMessage parseIncoming(MessageReader reader, int messageType) {
public static ConfigurationMessage parseIncoming(MessageReader reader, GarminMessage garminMessage) {
final int endOfPayload = reader.readByte();
ConfigurationMessage configurationMessage = new ConfigurationMessage(messageType, reader.readBytes(endOfPayload - reader.getPosition()));
ConfigurationMessage configurationMessage = new ConfigurationMessage(garminMessage, reader.readBytes(endOfPayload - reader.getPosition()));
reader.warnIfLeftover();
return configurationMessage;
}
@ -34,7 +33,7 @@ public class ConfigurationMessage extends GFDIMessage {
protected boolean generateOutgoing() {
final MessageWriter writer = new MessageWriter(response);
writer.writeShort(0); // placeholder for packet size
writer.writeShort(messageType);
writer.writeShort(garminMessage.getId());
writer.writeByte(ourConfigurationPayload.length);
writer.writeBytes(ourConfigurationPayload);
return true;

View File

@ -8,19 +8,18 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.GarminTimeUti
public class CurrentTimeRequestMessage extends GFDIMessage {
private final int referenceID;
private final int messageType;
public CurrentTimeRequestMessage(int messageType, int referenceID) {
this.messageType = messageType;
public CurrentTimeRequestMessage(int referenceID, GarminMessage garminMessage) {
this.garminMessage = garminMessage;
this.referenceID = referenceID;
this.statusMessage = this.getStatusMessage(messageType);
this.statusMessage = this.getStatusMessage();
}
public static CurrentTimeRequestMessage parseIncoming(MessageReader reader, int messageType) {
public static CurrentTimeRequestMessage parseIncoming(MessageReader reader, GarminMessage garminMessage) {
final int referenceID = reader.readInt();
reader.warnIfLeftover();
return new CurrentTimeRequestMessage(messageType, referenceID);
return new CurrentTimeRequestMessage(referenceID, garminMessage);
}
@Override
@ -38,7 +37,7 @@ public class CurrentTimeRequestMessage extends GFDIMessage {
final MessageWriter writer = new MessageWriter(response);
writer.writeShort(0); // packet size will be filled below
writer.writeShort(GarminMessage.RESPONSE.getId());
writer.writeShort(messageType);
writer.writeShort(this.garminMessage.getId());
writer.writeByte(Status.ACK.ordinal());
writer.writeInt(referenceID);
writer.writeInt(garminTimestamp);

View File

@ -12,7 +12,6 @@ public class DeviceInformationMessage extends GFDIMessage {
final int ourUnitNumber = -1;
final int ourSoftwareVersion = 7791;
final int ourMaxPacketSize = -1;
private final int messageType;
private final int incomingProtocolVersion;
private final int ourProtocolVersion = 150;
private final int incomingProductNumber;
@ -25,8 +24,8 @@ public class DeviceInformationMessage extends GFDIMessage {
private final String deviceModel;
// dual-pairing flags & MAC addresses...
public DeviceInformationMessage(int messageType, int protocolVersion, int productNumber, String unitNumber, int softwareVersion, int maxPacketSize, String bluetoothFriendlyName, String deviceName, String deviceModel) {
this.messageType = messageType;
public DeviceInformationMessage(GarminMessage garminMessage, int protocolVersion, int productNumber, String unitNumber, int softwareVersion, int maxPacketSize, String bluetoothFriendlyName, String deviceName, String deviceModel) {
this.garminMessage = garminMessage;
this.incomingProtocolVersion = protocolVersion;
this.incomingProductNumber = productNumber;
this.incomingUnitNumber = unitNumber;
@ -35,9 +34,11 @@ public class DeviceInformationMessage extends GFDIMessage {
this.bluetoothFriendlyName = bluetoothFriendlyName;
this.deviceName = deviceName;
this.deviceModel = deviceModel;
this.statusMessage = getStatusMessage();
}
public static DeviceInformationMessage parseIncoming(MessageReader reader, int messageType) {
public static DeviceInformationMessage parseIncoming(MessageReader reader, GarminMessage garminMessage) {
final int protocolVersion = reader.readShort();
final int productNumber = reader.readShort();
final String unitNumber = Long.toString(reader.readInt() & 0xFFFFFFFFL);
@ -48,7 +49,7 @@ public class DeviceInformationMessage extends GFDIMessage {
final String deviceModel = reader.readString();
reader.warnIfLeftover();
return new DeviceInformationMessage(messageType, protocolVersion, productNumber, unitNumber, softwareVersion, maxPacketSize, bluetoothFriendlyName, deviceName, deviceModel);
return new DeviceInformationMessage(garminMessage, protocolVersion, productNumber, unitNumber, softwareVersion, maxPacketSize, bluetoothFriendlyName, deviceName, deviceModel);
}
@Override
@ -59,7 +60,7 @@ public class DeviceInformationMessage extends GFDIMessage {
final MessageWriter writer = new MessageWriter(response);
writer.writeShort(0); // placeholder for packet size
writer.writeShort(GarminMessage.RESPONSE.getId());
writer.writeShort(messageType);
writer.writeShort(this.garminMessage.getId());
writer.writeByte(Status.ACK.ordinal());
writer.writeShort(ourProtocolVersion);
writer.writeShort(ourProductNumber);

View File

@ -6,24 +6,25 @@ import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventFindPhone;
public class FindMyPhoneRequestMessage extends GFDIMessage {
private final int duration;
private final int messageType;
public FindMyPhoneRequestMessage(int messageType, int duration) {
this.messageType = messageType;
public FindMyPhoneRequestMessage(GarminMessage garminMessage, int duration) {
this.garminMessage = garminMessage;
this.duration = duration;
this.statusMessage = getStatusMessage();
}
public static FindMyPhoneRequestMessage parseIncoming(MessageReader reader, int messageType) {
public static FindMyPhoneRequestMessage parseIncoming(MessageReader reader, GarminMessage garminMessage) {
final int duration = reader.readByte();
reader.warnIfLeftover();
return new FindMyPhoneRequestMessage(messageType, duration);
return new FindMyPhoneRequestMessage(garminMessage, duration);
}
@Override
public GBDeviceEvent getGBDeviceEvent() {
final GBDeviceEventFindPhone findPhoneEvent = new GBDeviceEventFindPhone();
findPhoneEvent.event = messageType == GarminMessage.FIND_MY_PHONE.getId() ? GBDeviceEventFindPhone.Event.START : GBDeviceEventFindPhone.Event.STOP;
findPhoneEvent.event = garminMessage == GarminMessage.FIND_MY_PHONE ? GBDeviceEventFindPhone.Event.START : GBDeviceEventFindPhone.Event.STOP;
return findPhoneEvent;
}

View File

@ -9,19 +9,18 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.RecordHea
public class FitDataMessage extends GFDIMessage {
private final List<RecordData> recordDataList;
private final int messageType;
public FitDataMessage(List<RecordData> recordDataList, int messageType) {
public FitDataMessage(List<RecordData> recordDataList, GarminMessage garminMessage) {
this.recordDataList = recordDataList;
this.messageType = messageType;
this.garminMessage = garminMessage;
}
public FitDataMessage(List<RecordData> recordDataList) {
this.recordDataList = recordDataList;
this.messageType = GarminMessage.FIT_DATA.getId();
this.garminMessage = GarminMessage.FIT_DATA;
}
public static FitDataMessage parseIncoming(MessageReader reader, int messageType) {
public static FitDataMessage parseIncoming(MessageReader reader, GarminMessage garminMessage) {
List<RecordData> recordDataList = new ArrayList<>();
@ -34,7 +33,7 @@ public class FitDataMessage extends GFDIMessage {
recordDataList.add(recordData);
}
return new FitDataMessage(recordDataList, messageType);
return new FitDataMessage(recordDataList, garminMessage);
}
public List<RecordData> getRecordDataList() {
@ -45,7 +44,7 @@ public class FitDataMessage extends GFDIMessage {
protected boolean generateOutgoing() {
final MessageWriter writer = new MessageWriter(response);
writer.writeShort(0); // packet size will be filled below
writer.writeShort(messageType);
writer.writeShort(this.garminMessage.getId());
for (RecordData recordData : recordDataList) {
recordData.generateOutgoingDataPayload(writer);
}

View File

@ -9,19 +9,19 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.RecordHea
public class FitDefinitionMessage extends GFDIMessage {
private final List<RecordDefinition> recordDefinitions;
private final int messageType;
public FitDefinitionMessage(List<RecordDefinition> recordDefinitions, int messageType) {
public FitDefinitionMessage(List<RecordDefinition> recordDefinitions, GarminMessage garminMessage) {
this.recordDefinitions = recordDefinitions;
this.messageType = messageType;
this.garminMessage = garminMessage;
this.statusMessage = this.getStatusMessage();
}
public FitDefinitionMessage(List<RecordDefinition> recordDefinitions) {
this.recordDefinitions = recordDefinitions;
this.messageType = GarminMessage.FIT_DEFINITION.getId();
this.garminMessage = GarminMessage.FIT_DEFINITION;
}
public static FitDefinitionMessage parseIncoming(MessageReader reader, int messageType) {
public static FitDefinitionMessage parseIncoming(MessageReader reader, GarminMessage garminMessage) {
List<RecordDefinition> recordDefinitions = new ArrayList<>();
while (!reader.isEndOfPayload()) {
@ -29,7 +29,7 @@ public class FitDefinitionMessage extends GFDIMessage {
recordDefinitions.add(RecordDefinition.parseIncoming(reader, recordHeader));
}
return new FitDefinitionMessage(recordDefinitions, messageType);
return new FitDefinitionMessage(recordDefinitions, garminMessage);
}
public List<RecordDefinition> getRecordDefinitions() {
@ -40,7 +40,7 @@ public class FitDefinitionMessage extends GFDIMessage {
protected boolean generateOutgoing() {
final MessageWriter writer = new MessageWriter(response);
writer.writeShort(0); // packet size will be filled below
writer.writeShort(messageType);
writer.writeShort(garminMessage.getId());
for (RecordDefinition recordDefinition : recordDefinitions) {
recordDefinition.generateOutgoingPayload(writer);
}

View File

@ -1,5 +1,7 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.messages;
import androidx.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -30,15 +32,16 @@ public abstract class GFDIMessage {
protected static final Logger LOG = LoggerFactory.getLogger(GFDIMessage.class);
protected final ByteBuffer response = ByteBuffer.allocate(1000);
protected GFDIStatusMessage statusMessage;
protected GarminMessage garminMessage;
public static GFDIMessage parseIncoming(byte[] message) {
final MessageReader messageReader = new MessageReader(message);
final int messageType = messageReader.readShort();
try {
// Class<? extends GFDIMessage> objectClass = GarminMessage.getClassFromId(messageType);
Method m = GarminMessage.getClassFromId(messageType).getMethod("parseIncoming", MessageReader.class, int.class);
return GarminMessage.getClassFromId(messageType).cast(m.invoke(null, messageReader, messageType));
GarminMessage garminMessage = GarminMessage.fromId(messageType);
Method m = garminMessage.objectClass.getMethod("parseIncoming", MessageReader.class, GarminMessage.class);
return garminMessage.objectClass.cast(m.invoke(null, messageReader, garminMessage));
} catch (Exception e) {
LOG.error("UNHANDLED GFDI MESSAGE TYPE {}, MESSAGE {}", messageType, message);
return new UnhandledMessage(messageType);
@ -61,8 +64,8 @@ public abstract class GFDIMessage {
return packet;
}
protected GFDIStatusMessage getStatusMessage(int messageType) {
return new GenericStatusMessage(messageType, Status.ACK);
protected GFDIStatusMessage getStatusMessage() {
return new GenericStatusMessage(garminMessage, Status.ACK);
}
public GBDeviceEvent getGBDeviceEvent() {
@ -116,6 +119,7 @@ public abstract class GFDIMessage {
return null;
}
@Nullable
public static GarminMessage fromId(final int id) {
for (final GarminMessage garminMessage : GarminMessage.values()) {
if (garminMessage.getId() == id) {

View File

@ -4,19 +4,18 @@ public class MusicControlCapabilitiesMessage extends GFDIMessage {
private final int supportedCapabilities;
private final GarminMusicControlCommand[] commands = GarminMusicControlCommand.values();
private final int messageType;
public MusicControlCapabilitiesMessage(int messageType, int supportedCapabilities) {
this.messageType = messageType;
public MusicControlCapabilitiesMessage(GarminMessage garminMessage, int supportedCapabilities) {
this.garminMessage = garminMessage;
this.supportedCapabilities = supportedCapabilities;
this.statusMessage = this.getStatusMessage(messageType);
this.statusMessage = this.getStatusMessage();
}
public static MusicControlCapabilitiesMessage parseIncoming(MessageReader reader, int messageType) {
public static MusicControlCapabilitiesMessage parseIncoming(MessageReader reader, GarminMessage garminMessage) {
final int supportedCapabilities = reader.readByte();
reader.warnIfLeftover();
return new MusicControlCapabilitiesMessage(messageType, supportedCapabilities);
return new MusicControlCapabilitiesMessage(garminMessage, supportedCapabilities);
}
@Override
@ -27,7 +26,7 @@ public class MusicControlCapabilitiesMessage extends GFDIMessage {
final MessageWriter writer = new MessageWriter(response);
writer.writeShort(0); // packet size will be filled below
writer.writeShort(GarminMessage.RESPONSE.getId());
writer.writeShort(messageType);
writer.writeShort(this.garminMessage.getId());
writer.writeByte(Status.ACK.ordinal());
writer.writeByte(commands.length);
for (GarminMusicControlCommand command : commands) {

View File

@ -10,6 +10,7 @@ public class MusicControlEntityUpdateMessage extends GFDIMessage {
public MusicControlEntityUpdateMessage(Map<MusicEntity, String> attributes) {
this.attributes = attributes;
this.garminMessage = GarminMessage.MUSIC_CONTROL_ENTITY_UPDATE;
}
@ -17,7 +18,7 @@ public class MusicControlEntityUpdateMessage extends GFDIMessage {
protected boolean generateOutgoing() {
final MessageWriter writer = new MessageWriter(response);
writer.writeShort(0); // packet size will be filled below
writer.writeShort(GarminMessage.MUSIC_CONTROL_ENTITY_UPDATE.getId());
writer.writeShort(this.garminMessage.getId());
for (Map.Entry<MusicEntity, String> entry : attributes.entrySet()) {
MusicEntity a = entry.getKey();

View File

@ -6,12 +6,11 @@ import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventMusicContr
public class MusicControlMessage extends GFDIMessage {
private static final MusicControlCapabilitiesMessage.GarminMusicControlCommand[] commands = MusicControlCapabilitiesMessage.GarminMusicControlCommand.values();
final int messageType;
private final GBDeviceEventMusicControl event;
public MusicControlMessage(int messageType, MusicControlCapabilitiesMessage.GarminMusicControlCommand command) {
public MusicControlMessage(GarminMessage garminMessage, MusicControlCapabilitiesMessage.GarminMusicControlCommand command) {
this.event = new GBDeviceEventMusicControl();
this.messageType = messageType;
this.garminMessage = garminMessage;
switch (command) {
case TOGGLE_PLAY_PAUSE:
event.event = GBDeviceEventMusicControl.Event.PLAYPAUSE;
@ -24,14 +23,14 @@ public class MusicControlMessage extends GFDIMessage {
break;
}
this.statusMessage = this.getStatusMessage(messageType);
this.statusMessage = this.getStatusMessage();
}
public static MusicControlMessage parseIncoming(MessageReader reader, int messageType) {
public static MusicControlMessage parseIncoming(MessageReader reader, GarminMessage garminMessage) {
MusicControlCapabilitiesMessage.GarminMusicControlCommand command = commands[reader.readByte()];
reader.warnIfLeftover();
return new MusicControlMessage(messageType, command);
return new MusicControlMessage(garminMessage, command);
}
public GBDeviceEventMusicControl getGBDeviceEvent() {

View File

@ -11,15 +11,14 @@ public class ProtobufMessage extends GFDIMessage {
private final int requestId;
private final int messageType;
private final int dataOffset;
private final int totalProtobufLength;
private final int protobufDataLength;
private final byte[] messageBytes;
private final boolean sendOutgoing;
public ProtobufMessage(int messageType, int requestId, int dataOffset, int totalProtobufLength, int protobufDataLength, byte[] messageBytes, boolean sendOutgoing) {
this.messageType = messageType;
public ProtobufMessage(GarminMessage garminMessage, int requestId, int dataOffset, int totalProtobufLength, int protobufDataLength, byte[] messageBytes, boolean sendOutgoing) {
this.garminMessage = garminMessage;
this.requestId = requestId;
this.dataOffset = dataOffset;
this.totalProtobufLength = totalProtobufLength;
@ -28,20 +27,21 @@ public class ProtobufMessage extends GFDIMessage {
this.sendOutgoing = sendOutgoing;
if (isComplete()) {
this.statusMessage = new GenericStatusMessage(messageType, GFDIMessage.Status.ACK);
this.statusMessage = new GenericStatusMessage(garminMessage, GFDIMessage.Status.ACK);
} else {
this.statusMessage = new ProtobufStatusMessage(messageType, GFDIMessage.Status.ACK, requestId, dataOffset, KEPT, NO_ERROR);
this.statusMessage = new ProtobufStatusMessage(garminMessage, GFDIMessage.Status.ACK, requestId, dataOffset, KEPT, NO_ERROR);
}
}
public ProtobufMessage(int messageType, int requestId, int dataOffset, int totalProtobufLength, int protobufDataLength, byte[] messageBytes) {
this(messageType, requestId, dataOffset, totalProtobufLength, protobufDataLength, messageBytes, true);
public ProtobufMessage(GarminMessage garminMessage, int requestId, int dataOffset, int totalProtobufLength, int protobufDataLength, byte[] messageBytes) {
this(garminMessage, requestId, dataOffset, totalProtobufLength, protobufDataLength, messageBytes, true);
}
public void setStatusMessage(ProtobufStatusMessage protobufStatusMessage) {
this.statusMessage = protobufStatusMessage;
}
public static ProtobufMessage parseIncoming(MessageReader reader, int messageType) {
public static ProtobufMessage parseIncoming(MessageReader reader, GarminMessage garminMessage) {
final int requestID = reader.readShort();
final int dataOffset = reader.readInt();
final int totalProtobufLength = reader.readInt();
@ -49,15 +49,15 @@ public class ProtobufMessage extends GFDIMessage {
final byte[] messageBytes = reader.readBytes(protobufDataLength);
reader.warnIfLeftover();
return new ProtobufMessage(messageType, requestID, dataOffset, totalProtobufLength, protobufDataLength, messageBytes, false);
return new ProtobufMessage(garminMessage, requestID, dataOffset, totalProtobufLength, protobufDataLength, messageBytes, false);
}
public int getRequestId() {
return requestId;
}
public int getMessageType() {
return messageType;
public GarminMessage getMessageType() {
return garminMessage;
}
public int getDataOffset() {
@ -84,7 +84,7 @@ public class ProtobufMessage extends GFDIMessage {
protected boolean generateOutgoing() {
final MessageWriter writer = new MessageWriter(response);
writer.writeShort(0); // packet size will be filled below
writer.writeShort(messageType);
writer.writeShort(garminMessage.getId());
writer.writeShort(requestId);
writer.writeInt(dataOffset);
writer.writeInt(totalProtobufLength);

View File

@ -6,6 +6,7 @@ public class SetDeviceSettingsMessage extends GFDIMessage {
private final Map<GarminDeviceSetting, Object> settings;
public SetDeviceSettingsMessage(Map<GarminDeviceSetting, Object> settings) {
this.garminMessage = GarminMessage.DEVICE_SETTINGS;
this.settings = settings;
final int settingsCount = settings.size();
if (settingsCount == 0) throw new IllegalArgumentException("Empty settings");
@ -17,7 +18,7 @@ public class SetDeviceSettingsMessage extends GFDIMessage {
protected boolean generateOutgoing() {
final MessageWriter writer = new MessageWriter(response);
writer.writeShort(0); // packet size will be filled below
writer.writeShort(GarminMessage.DEVICE_SETTINGS.getId());
writer.writeShort(this.garminMessage.getId());
writer.writeByte(settings.size());
for (Map.Entry<GarminDeviceSetting, Object> settingPair : settings.entrySet()) {
final GarminDeviceSetting setting = settingPair.getKey();

View File

@ -8,13 +8,14 @@ public class SystemEventMessage extends GFDIMessage {
public SystemEventMessage(GarminSystemEventType eventType, Object value) {
this.eventType = eventType;
this.value = value;
this.garminMessage = GarminMessage.SYSTEM_EVENT;
}
@Override
protected boolean generateOutgoing() {
final MessageWriter writer = new MessageWriter(response);
writer.writeShort(0); // packet size will be filled below
writer.writeShort(GarminMessage.SYSTEM_EVENT.getId());
writer.writeShort(this.garminMessage.getId());
writer.writeByte(eventType.ordinal());
if (value instanceof String) {
writer.writeString((String) value);

View File

@ -11,17 +11,16 @@ public class WeatherMessage extends GFDIMessage {
private final int latitude;
private final int longitude;
private final int hoursOfForecast;
private final int messageType;
private final List<RecordDefinition> weatherDefinitions;
public WeatherMessage(int format, int latitude, int longitude, int hoursOfForecast, int messageType) {
public WeatherMessage(int format, int latitude, int longitude, int hoursOfForecast, GarminMessage garminMessage) {
this.format = format;
this.latitude = latitude;
this.longitude = longitude;
this.hoursOfForecast = hoursOfForecast;
this.messageType = messageType;
this.garminMessage = garminMessage;
weatherDefinitions = new ArrayList<>(3);
@ -29,17 +28,17 @@ public class WeatherMessage extends GFDIMessage {
weatherDefinitions.add(GlobalDefinitionsEnum.HOURLY_WEATHER_FORECAST.getRecordDefinition());
weatherDefinitions.add(GlobalDefinitionsEnum.DAILY_WEATHER_FORECAST.getRecordDefinition());
this.statusMessage = this.getStatusMessage(messageType);
this.statusMessage = this.getStatusMessage();
}
public static WeatherMessage parseIncoming(MessageReader reader, int messageType) {
public static WeatherMessage parseIncoming(MessageReader reader, GarminMessage garminMessage) {
final int format = reader.readByte();
final int latitude = reader.readInt();
final int longitude = reader.readInt();
final int hoursOfForecast = reader.readByte();
return new WeatherMessage(format, latitude, longitude, hoursOfForecast, messageType);
return new WeatherMessage(format, latitude, longitude, hoursOfForecast, garminMessage);
}
@Override

View File

@ -8,10 +8,10 @@ public class FitDataStatusMessage extends GFDIStatusMessage {
private final Status status;
private final FitDataStatusCode fitDataStatusCode;
private final int messageType;
public FitDataStatusMessage(int messageType, Status status, FitDataStatusCode fitDataStatusCode) {
this.messageType = messageType;
public FitDataStatusMessage(GarminMessage garminMessage, Status status, FitDataStatusCode fitDataStatusCode) {
this.garminMessage = garminMessage;
this.status = status;
this.fitDataStatusCode = fitDataStatusCode;
switch (fitDataStatusCode) {
@ -23,12 +23,12 @@ public class FitDataStatusMessage extends GFDIStatusMessage {
}
}
public static FitDataStatusMessage parseIncoming(MessageReader reader, int messageType) {
public static FitDataStatusMessage parseIncoming(MessageReader reader, GarminMessage garminMessage) {
final Status status = Status.fromCode(reader.readByte());
final FitDataStatusCode fitDataStatusCode = FitDataStatusCode.fromCode(reader.readByte());
reader.warnIfLeftover();
return new FitDataStatusMessage(messageType, status, fitDataStatusCode);
return new FitDataStatusMessage(garminMessage, status, fitDataStatusCode);
}
public enum FitDataStatusCode {

View File

@ -8,10 +8,9 @@ public class FitDefinitionStatusMessage extends GFDIStatusMessage {
private final Status status;
private final FitDefinitionStatusCode fitDefinitionStatusCode;
private final int messageType;
public FitDefinitionStatusMessage(int messageType, Status status, FitDefinitionStatusCode fitDefinitionStatusCode) {
this.messageType = messageType;
public FitDefinitionStatusMessage(GarminMessage garminMessage, Status status, FitDefinitionStatusCode fitDefinitionStatusCode) {
this.garminMessage = garminMessage;
this.status = status;
this.fitDefinitionStatusCode = fitDefinitionStatusCode;
switch (fitDefinitionStatusCode) {
@ -23,12 +22,12 @@ public class FitDefinitionStatusMessage extends GFDIStatusMessage {
}
}
public static FitDefinitionStatusMessage parseIncoming(MessageReader reader, int messageType) {
public static FitDefinitionStatusMessage parseIncoming(MessageReader reader, GarminMessage garminMessage) {
final Status status = Status.fromCode(reader.readByte());
final FitDefinitionStatusCode fitDefinitionStatusCode = FitDefinitionStatusCode.fromCode(reader.readByte());
reader.warnIfLeftover();
return new FitDefinitionStatusMessage(messageType, status, fitDefinitionStatusCode);
return new FitDefinitionStatusMessage(garminMessage, status, fitDefinitionStatusCode);
}
public enum FitDefinitionStatusCode {

View File

@ -7,25 +7,25 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.messages.Mess
public abstract class GFDIStatusMessage extends GFDIMessage {
private Status status;
public static GFDIStatusMessage parseIncoming(MessageReader reader, int messageType) {
final GarminMessage garminMessage = GFDIMessage.GarminMessage.fromId(reader.readShort());
if (GarminMessage.PROTOBUF_REQUEST.equals(garminMessage) || GarminMessage.PROTOBUF_RESPONSE.equals(garminMessage)) {
return ProtobufStatusMessage.parseIncoming(reader, messageType);
} else if (GarminMessage.FIT_DEFINITION.equals(garminMessage)) {
return FitDefinitionStatusMessage.parseIncoming(reader, messageType);
} else if (GarminMessage.FIT_DATA.equals(garminMessage)) {
return FitDataStatusMessage.parseIncoming(reader, messageType);
public static GFDIStatusMessage parseIncoming(MessageReader reader, GarminMessage garminMessage) {
final GarminMessage originalGarminMessage = GFDIMessage.GarminMessage.fromId(reader.readShort());
if (GarminMessage.PROTOBUF_REQUEST.equals(originalGarminMessage) || GarminMessage.PROTOBUF_RESPONSE.equals(originalGarminMessage)) {
return ProtobufStatusMessage.parseIncoming(reader, garminMessage);
} else if (GarminMessage.FIT_DEFINITION.equals(originalGarminMessage)) {
return FitDefinitionStatusMessage.parseIncoming(reader, garminMessage);
} else if (GarminMessage.FIT_DATA.equals(originalGarminMessage)) {
return FitDataStatusMessage.parseIncoming(reader, garminMessage);
} else {
final Status status = Status.fromCode(reader.readByte());
if (Status.ACK == status) {
LOG.info("Received ACK for message {}", garminMessage.name());
LOG.info("Received ACK for message {}", originalGarminMessage.name());
} else {
LOG.warn("Received {} for message {}", status, garminMessage.name());
LOG.warn("Received {} for message {}", status, originalGarminMessage.name());
}
reader.warnIfLeftover();
return new GenericStatusMessage(messageType, status);
return new GenericStatusMessage(garminMessage, status);
}
}

View File

@ -4,20 +4,24 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.messages.Mess
public class GenericStatusMessage extends GFDIStatusMessage {
private final int messageType;
private int messageType; // for unsupported message types
private final Status status;
public GenericStatusMessage(int originalRequestID, Status status) {
this.messageType = originalRequestID;
public GenericStatusMessage(GarminMessage originalMessage, Status status) {
this.garminMessage = originalMessage;
this.status = status;
}
public GenericStatusMessage(int messageType, Status status) {
this.messageType = messageType;
this.status = status;
}
@Override
protected boolean generateOutgoing() {
final MessageWriter writer = new MessageWriter(response);
writer.writeShort(0); // packet size will be filled below
writer.writeShort(GarminMessage.RESPONSE.getId());
writer.writeShort(messageType);
writer.writeShort(messageType != 0 ? messageType : garminMessage.getId());
writer.writeByte(status.ordinal());
return true;
}

View File

@ -12,15 +12,14 @@ public class ProtobufStatusMessage extends GFDIStatusMessage {
private final int dataOffset;
private final ProtobufChunkStatus protobufChunkStatus;
private final ProtobufStatusCode protobufStatusCode;
private final int messageType;
private final boolean sendOutgoing;
public ProtobufStatusMessage(int messageType, Status status, int requestId, int dataOffset, ProtobufChunkStatus protobufChunkStatus, ProtobufStatusCode protobufStatusCode) {
this(messageType, status, requestId, dataOffset, protobufChunkStatus, protobufStatusCode, true);
public ProtobufStatusMessage(GarminMessage garminMessage, Status status, int requestId, int dataOffset, ProtobufChunkStatus protobufChunkStatus, ProtobufStatusCode protobufStatusCode) {
this(garminMessage, status, requestId, dataOffset, protobufChunkStatus, protobufStatusCode, true);
}
public ProtobufStatusMessage(int messageType, Status status, int requestId, int dataOffset, ProtobufChunkStatus protobufChunkStatus, ProtobufStatusCode protobufStatusCode, boolean sendOutgoing) {
this.messageType = messageType;
public ProtobufStatusMessage(GarminMessage garminMessage, Status status, int requestId, int dataOffset, ProtobufChunkStatus protobufChunkStatus, ProtobufStatusCode protobufStatusCode, boolean sendOutgoing) {
this.garminMessage = garminMessage;
this.status = status;
this.requestId = requestId;
this.dataOffset = dataOffset;
@ -29,7 +28,7 @@ public class ProtobufStatusMessage extends GFDIStatusMessage {
this.sendOutgoing = sendOutgoing;
}
public static ProtobufStatusMessage parseIncoming(MessageReader reader, int messageType) {
public static ProtobufStatusMessage parseIncoming(MessageReader reader, GarminMessage garminMessage) {
final Status status = Status.fromCode(reader.readByte());
final int requestID = reader.readShort();
final int dataOffset = reader.readInt();
@ -37,7 +36,7 @@ public class ProtobufStatusMessage extends GFDIStatusMessage {
final ProtobufStatusCode error = ProtobufStatusCode.fromCode(reader.readByte());
reader.warnIfLeftover();
return new ProtobufStatusMessage(messageType, status, requestID, dataOffset, protobufStatus, error, false);
return new ProtobufStatusMessage(garminMessage, status, requestID, dataOffset, protobufStatus, error, false);
}
public int getDataOffset() {
@ -52,8 +51,8 @@ public class ProtobufStatusMessage extends GFDIStatusMessage {
return protobufStatusCode;
}
public int getMessageType() {
return messageType;
public GarminMessage getMessageType() {
return garminMessage;
}
public int getRequestId() {
@ -71,7 +70,7 @@ public class ProtobufStatusMessage extends GFDIStatusMessage {
final MessageWriter writer = new MessageWriter(response);
writer.writeShort(0); // packet size will be filled below
writer.writeShort(GarminMessage.RESPONSE.getId());
writer.writeShort(messageType);
writer.writeShort(garminMessage.getId());
writer.writeByte(status.ordinal());
writer.writeShort(requestId);
writer.writeInt(dataOffset);