mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2026-07-31 07:44:24 +02:00
Garmin: Add support for V1
This commit is contained in:
+16
-10
@@ -143,20 +143,26 @@ public class GarminSupport extends AbstractBTLEDeviceSupport implements ICommuni
|
|||||||
protected TransactionBuilder initializeDevice(final TransactionBuilder builder) {
|
protected TransactionBuilder initializeDevice(final TransactionBuilder builder) {
|
||||||
builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZING, getContext()));
|
builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZING, getContext()));
|
||||||
|
|
||||||
if (getSupportedServices().contains(CommunicatorV2.UUID_SERVICE_GARMIN_ML_GFDI)) {
|
|
||||||
communicator = new CommunicatorV2(this);
|
|
||||||
} else if (getSupportedServices().contains(CommunicatorV1.UUID_SERVICE_GARMIN_GFDI)) {
|
|
||||||
communicator = new CommunicatorV1(this);
|
|
||||||
} else {
|
|
||||||
LOG.warn("Failed to find a known Garmin service");
|
|
||||||
builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.NOT_CONNECTED, getContext()));
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getDevicePrefs().getBoolean(PREF_ALLOW_HIGH_MTU, true)) {
|
if (getDevicePrefs().getBoolean(PREF_ALLOW_HIGH_MTU, true)) {
|
||||||
builder.requestMtu(515);
|
builder.requestMtu(515);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final CommunicatorV2 communicatorV2 = new CommunicatorV2(this);
|
||||||
|
if (communicatorV2.initializeDevice(builder)) {
|
||||||
|
communicator = communicatorV2;
|
||||||
|
} else {
|
||||||
|
// V2 did not manage to initialize, attempt V1
|
||||||
|
final CommunicatorV1 communicatorV1 = new CommunicatorV1(this);
|
||||||
|
if (!communicatorV1.initializeDevice(builder)) {
|
||||||
|
// Neither V1 nor V2 worked, not a Garmin device?
|
||||||
|
LOG.warn("Failed to find a known Garmin service");
|
||||||
|
builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.NOT_CONNECTED, getContext()));
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
communicator = communicatorV1;
|
||||||
|
}
|
||||||
|
|
||||||
communicator.initializeDevice(builder);
|
communicator.initializeDevice(builder);
|
||||||
|
|
||||||
return builder;
|
return builder;
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@ public interface ICommunicator {
|
|||||||
|
|
||||||
void onMtuChanged(final int mtu);
|
void onMtuChanged(final int mtu);
|
||||||
|
|
||||||
void initializeDevice(TransactionBuilder builder);
|
boolean initializeDevice(TransactionBuilder builder);
|
||||||
|
|
||||||
boolean onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic);
|
boolean onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic);
|
||||||
|
|
||||||
|
|||||||
+51
-3
@@ -6,40 +6,88 @@ import android.bluetooth.BluetoothGattCharacteristic;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.GarminSupport;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.GarminSupport;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.communicator.CobsCoDec;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.communicator.ICommunicator;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.communicator.ICommunicator;
|
||||||
|
|
||||||
public class CommunicatorV1 implements ICommunicator {
|
public class CommunicatorV1 implements ICommunicator {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(CommunicatorV1.class);
|
private static final Logger LOG = LoggerFactory.getLogger(CommunicatorV1.class);
|
||||||
|
|
||||||
public static final UUID UUID_SERVICE_GARMIN_GFDI = UUID.fromString("6A4E2401-667B-11E3-949A-0800200C9A66");
|
public static final UUID UUID_SERVICE_GARMIN_GFDI = UUID.fromString("6A4E2401-667B-11E3-949A-0800200C9A66");
|
||||||
|
public static final UUID UUID_CHARACTERISTIC_GARMIN_GFDI_SEND = UUID.fromString("6A4E4C80-667B-11E3-949A-0800200C9A66");
|
||||||
|
public static final UUID UUID_CHARACTERISTIC_GARMIN_GFDI_RECEIVE = UUID.fromString("6A4ECD28-667B-11E3-949A-0800200C9A66");
|
||||||
|
|
||||||
|
private BluetoothGattCharacteristic characteristicSend;
|
||||||
|
private BluetoothGattCharacteristic characteristicReceive;
|
||||||
|
|
||||||
private final GarminSupport mSupport;
|
private final GarminSupport mSupport;
|
||||||
|
|
||||||
|
public final CobsCoDec cobsCoDec;
|
||||||
|
public int maxWriteSize = 20;
|
||||||
|
|
||||||
public CommunicatorV1(final GarminSupport garminSupport) {
|
public CommunicatorV1(final GarminSupport garminSupport) {
|
||||||
this.mSupport = garminSupport;
|
this.mSupport = garminSupport;
|
||||||
|
this.cobsCoDec = new CobsCoDec();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMtuChanged(final int mtu) {
|
public void onMtuChanged(final int mtu) {
|
||||||
|
maxWriteSize = mtu - 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initializeDevice(final TransactionBuilder builder) {
|
public boolean initializeDevice(final TransactionBuilder builder) {
|
||||||
LOG.error("Initialization is not implemented for V1");
|
characteristicSend = mSupport.getCharacteristic(UUID_CHARACTERISTIC_GARMIN_GFDI_SEND);
|
||||||
|
characteristicReceive = mSupport.getCharacteristic(UUID_CHARACTERISTIC_GARMIN_GFDI_RECEIVE);
|
||||||
|
|
||||||
|
if (characteristicSend == null || characteristicReceive == null) {
|
||||||
|
LOG.warn("Failed to find V1 GFDI characteristics");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.notify(characteristicReceive, true);
|
||||||
|
|
||||||
|
LOG.debug("Initializing as Garmin V1");
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendMessage(final String taskName, final byte[] message) {
|
public void sendMessage(final String taskName, final byte[] message) {
|
||||||
|
if (null == message)
|
||||||
|
return;
|
||||||
|
|
||||||
|
final byte[] payload = cobsCoDec.encode(message);
|
||||||
|
|
||||||
|
final TransactionBuilder builder = new TransactionBuilder(taskName);
|
||||||
|
int remainingBytes = payload.length;
|
||||||
|
if (remainingBytes > maxWriteSize - 1) {
|
||||||
|
int position = 0;
|
||||||
|
while (remainingBytes > 0) {
|
||||||
|
final byte[] fragment = Arrays.copyOfRange(payload, position, position + Math.min(remainingBytes, maxWriteSize - 1));
|
||||||
|
builder.write(characteristicSend, fragment);
|
||||||
|
position += fragment.length;
|
||||||
|
remainingBytes -= fragment.length;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
builder.write(characteristicSend, payload);
|
||||||
|
}
|
||||||
|
builder.queue(this.mSupport.getQueue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCharacteristicChanged(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
|
public boolean onCharacteristicChanged(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
|
||||||
|
if (characteristic.getUuid().equals(characteristicReceive.getUuid())) {
|
||||||
|
this.cobsCoDec.receivedBytes(characteristic.getValue());
|
||||||
|
this.mSupport.onMessage(this.cobsCoDec.retrieveMessage());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -77,7 +77,7 @@ public class CommunicatorV2 implements ICommunicator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initializeDevice(final TransactionBuilder builder) {
|
public boolean initializeDevice(final TransactionBuilder builder) {
|
||||||
// Iterate through the known ML characteristics until we find a known pair
|
// Iterate through the known ML characteristics until we find a known pair
|
||||||
// send characteristic = read characteristic + 0x10 (eg. 2810 / 2820)
|
// send characteristic = read characteristic + 0x10 (eg. 2810 / 2820)
|
||||||
for (int i = 0x2810; i <= 0x2814; i++) {
|
for (int i = 0x2810; i <= 0x2814; i++) {
|
||||||
@@ -90,13 +90,13 @@ public class CommunicatorV2 implements ICommunicator {
|
|||||||
builder.notify(characteristicReceive, true);
|
builder.notify(characteristicReceive, true);
|
||||||
builder.write(characteristicSend, closeAllServices());
|
builder.write(characteristicSend, closeAllServices());
|
||||||
|
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG.warn("Failed to find any known ML characteristics");
|
LOG.warn("Failed to find any known ML characteristics");
|
||||||
|
|
||||||
builder.add(new SetDeviceStateAction(mSupport.getDevice(), GBDevice.State.NOT_CONNECTED, mSupport.getContext()));
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Reference in New Issue
Block a user