1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-12-25 18:15:49 +01:00

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
parent c8c51064c3
commit 4054326535
20 changed files with 125 additions and 120 deletions

View File

@ -225,30 +225,30 @@ public class ProtocolBufferHandler {
if (null == protobufPayload) if (null == protobufPayload)
return null; return null;
final int requestId = getNextProtobufRequestId(); 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) { private ProtobufMessage prepareProtobufResponse(GdiSmartProto.Smart protobufPayload, int requestId) {
if (null == protobufPayload) if (null == protobufPayload)
return null; 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) if (bytes == null || bytes.length == 0)
return null; 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) { if (bytes.length > maxChunkSize) {
chunkedFragmentsMap.put(requestId, new ProtobufFragment(bytes)); chunkedFragmentsMap.put(requestId, new ProtobufFragment(bytes));
return new ProtobufMessage(messageType, return new ProtobufMessage(garminMessage,
requestId, requestId,
0, 0,
bytes.length, bytes.length,
maxChunkSize, maxChunkSize,
ArrayUtils.subarray(bytes, 0, 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 { class ProtobufFragment {

View File

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

View File

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

View File

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

View File

@ -6,24 +6,25 @@ import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventFindPhone;
public class FindMyPhoneRequestMessage extends GFDIMessage { public class FindMyPhoneRequestMessage extends GFDIMessage {
private final int duration; private final int duration;
private final int messageType;
public FindMyPhoneRequestMessage(int messageType, int duration) { public FindMyPhoneRequestMessage(GarminMessage garminMessage, int duration) {
this.messageType = messageType; this.garminMessage = garminMessage;
this.duration = duration; 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(); final int duration = reader.readByte();
reader.warnIfLeftover(); reader.warnIfLeftover();
return new FindMyPhoneRequestMessage(messageType, duration); return new FindMyPhoneRequestMessage(garminMessage, duration);
} }
@Override @Override
public GBDeviceEvent getGBDeviceEvent() { public GBDeviceEvent getGBDeviceEvent() {
final GBDeviceEventFindPhone findPhoneEvent = new GBDeviceEventFindPhone(); 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; return findPhoneEvent;
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -11,17 +11,16 @@ public class WeatherMessage extends GFDIMessage {
private final int latitude; private final int latitude;
private final int longitude; private final int longitude;
private final int hoursOfForecast; private final int hoursOfForecast;
private final int messageType;
private final List<RecordDefinition> weatherDefinitions; 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.format = format;
this.latitude = latitude; this.latitude = latitude;
this.longitude = longitude; this.longitude = longitude;
this.hoursOfForecast = hoursOfForecast; this.hoursOfForecast = hoursOfForecast;
this.messageType = messageType; this.garminMessage = garminMessage;
weatherDefinitions = new ArrayList<>(3); weatherDefinitions = new ArrayList<>(3);
@ -29,17 +28,17 @@ public class WeatherMessage extends GFDIMessage {
weatherDefinitions.add(GlobalDefinitionsEnum.HOURLY_WEATHER_FORECAST.getRecordDefinition()); weatherDefinitions.add(GlobalDefinitionsEnum.HOURLY_WEATHER_FORECAST.getRecordDefinition());
weatherDefinitions.add(GlobalDefinitionsEnum.DAILY_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 format = reader.readByte();
final int latitude = reader.readInt(); final int latitude = reader.readInt();
final int longitude = reader.readInt(); final int longitude = reader.readInt();
final int hoursOfForecast = reader.readByte(); final int hoursOfForecast = reader.readByte();
return new WeatherMessage(format, latitude, longitude, hoursOfForecast, messageType); return new WeatherMessage(format, latitude, longitude, hoursOfForecast, garminMessage);
} }
@Override @Override

View File

@ -8,10 +8,10 @@ public class FitDataStatusMessage extends GFDIStatusMessage {
private final Status status; private final Status status;
private final FitDataStatusCode fitDataStatusCode; 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.status = status;
this.fitDataStatusCode = fitDataStatusCode; this.fitDataStatusCode = fitDataStatusCode;
switch (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 Status status = Status.fromCode(reader.readByte());
final FitDataStatusCode fitDataStatusCode = FitDataStatusCode.fromCode(reader.readByte()); final FitDataStatusCode fitDataStatusCode = FitDataStatusCode.fromCode(reader.readByte());
reader.warnIfLeftover(); reader.warnIfLeftover();
return new FitDataStatusMessage(messageType, status, fitDataStatusCode); return new FitDataStatusMessage(garminMessage, status, fitDataStatusCode);
} }
public enum FitDataStatusCode { public enum FitDataStatusCode {

View File

@ -8,10 +8,9 @@ public class FitDefinitionStatusMessage extends GFDIStatusMessage {
private final Status status; private final Status status;
private final FitDefinitionStatusCode fitDefinitionStatusCode; private final FitDefinitionStatusCode fitDefinitionStatusCode;
private final int messageType;
public FitDefinitionStatusMessage(int messageType, Status status, FitDefinitionStatusCode fitDefinitionStatusCode) { public FitDefinitionStatusMessage(GarminMessage garminMessage, Status status, FitDefinitionStatusCode fitDefinitionStatusCode) {
this.messageType = messageType; this.garminMessage = garminMessage;
this.status = status; this.status = status;
this.fitDefinitionStatusCode = fitDefinitionStatusCode; this.fitDefinitionStatusCode = fitDefinitionStatusCode;
switch (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 Status status = Status.fromCode(reader.readByte());
final FitDefinitionStatusCode fitDefinitionStatusCode = FitDefinitionStatusCode.fromCode(reader.readByte()); final FitDefinitionStatusCode fitDefinitionStatusCode = FitDefinitionStatusCode.fromCode(reader.readByte());
reader.warnIfLeftover(); reader.warnIfLeftover();
return new FitDefinitionStatusMessage(messageType, status, fitDefinitionStatusCode); return new FitDefinitionStatusMessage(garminMessage, status, fitDefinitionStatusCode);
} }
public enum 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 { public abstract class GFDIStatusMessage extends GFDIMessage {
private Status status; private Status status;
public static GFDIStatusMessage parseIncoming(MessageReader reader, int messageType) { public static GFDIStatusMessage parseIncoming(MessageReader reader, GarminMessage garminMessage) {
final GarminMessage garminMessage = GFDIMessage.GarminMessage.fromId(reader.readShort()); final GarminMessage originalGarminMessage = GFDIMessage.GarminMessage.fromId(reader.readShort());
if (GarminMessage.PROTOBUF_REQUEST.equals(garminMessage) || GarminMessage.PROTOBUF_RESPONSE.equals(garminMessage)) { if (GarminMessage.PROTOBUF_REQUEST.equals(originalGarminMessage) || GarminMessage.PROTOBUF_RESPONSE.equals(originalGarminMessage)) {
return ProtobufStatusMessage.parseIncoming(reader, messageType); return ProtobufStatusMessage.parseIncoming(reader, garminMessage);
} else if (GarminMessage.FIT_DEFINITION.equals(garminMessage)) { } else if (GarminMessage.FIT_DEFINITION.equals(originalGarminMessage)) {
return FitDefinitionStatusMessage.parseIncoming(reader, messageType); return FitDefinitionStatusMessage.parseIncoming(reader, garminMessage);
} else if (GarminMessage.FIT_DATA.equals(garminMessage)) { } else if (GarminMessage.FIT_DATA.equals(originalGarminMessage)) {
return FitDataStatusMessage.parseIncoming(reader, messageType); return FitDataStatusMessage.parseIncoming(reader, garminMessage);
} else { } else {
final Status status = Status.fromCode(reader.readByte()); final Status status = Status.fromCode(reader.readByte());
if (Status.ACK == status) { if (Status.ACK == status) {
LOG.info("Received ACK for message {}", garminMessage.name()); LOG.info("Received ACK for message {}", originalGarminMessage.name());
} else { } else {
LOG.warn("Received {} for message {}", status, garminMessage.name()); LOG.warn("Received {} for message {}", status, originalGarminMessage.name());
} }
reader.warnIfLeftover(); 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 { public class GenericStatusMessage extends GFDIStatusMessage {
private final int messageType; private int messageType; // for unsupported message types
private final Status status; private final Status status;
public GenericStatusMessage(int originalRequestID, Status status) { public GenericStatusMessage(GarminMessage originalMessage, Status status) {
this.messageType = originalRequestID; this.garminMessage = originalMessage;
this.status = status; this.status = status;
} }
public GenericStatusMessage(int messageType, Status status) {
this.messageType = messageType;
this.status = status;
}
@Override @Override
protected boolean generateOutgoing() { protected boolean generateOutgoing() {
final MessageWriter writer = new MessageWriter(response); final MessageWriter writer = new MessageWriter(response);
writer.writeShort(0); // packet size will be filled below writer.writeShort(0); // packet size will be filled below
writer.writeShort(GarminMessage.RESPONSE.getId()); writer.writeShort(GarminMessage.RESPONSE.getId());
writer.writeShort(messageType); writer.writeShort(messageType != 0 ? messageType : garminMessage.getId());
writer.writeByte(status.ordinal()); writer.writeByte(status.ordinal());
return true; return true;
} }

View File

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