1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-11-28 04:46:51 +01:00

Garmin: Handle realtime hrv, respiration, spo2

This commit is contained in:
José Rebelo 2024-09-16 20:22:30 +01:00 committed by José Rebelo
parent 5bc114b062
commit c14b41b9c6

View File

@ -14,6 +14,7 @@ import org.slf4j.LoggerFactory;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import java.util.Arrays; import java.util.Arrays;
import java.util.Date;
import java.util.UUID; import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.GBApplication;
@ -31,6 +32,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.DeviceService;
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceStateAction; import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceStateAction;
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.GarminSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.GarminSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.GarminTimeUtils;
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.communicator.CobsCoDec; 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;
import nodomain.freeyourgadget.gadgetbridge.util.GB; import nodomain.freeyourgadget.gadgetbridge.util.GB;
@ -60,6 +62,10 @@ public class CommunicatorV2 implements ICommunicator {
private int realtimeAccelHandle = 0; private int realtimeAccelHandle = 0;
private int realtimeSpo2Handle = 0;
private int realtimeRespirationHandle = 0;
private int realtimeHrvHandle = 0;
public CommunicatorV2(final GarminSupport garminSupport) { public CommunicatorV2(final GarminSupport garminSupport) {
this.mSupport = garminSupport; this.mSupport = garminSupport;
this.cobsCoDec = new CobsCoDec(); this.cobsCoDec = new CobsCoDec();
@ -139,6 +145,12 @@ public class CommunicatorV2 implements ICommunicator {
processRealtimeSteps(message); processRealtimeSteps(message);
} else if (this.realtimeAccelHandle == handle) { } else if (this.realtimeAccelHandle == handle) {
processRealtimeAccelerometer(message); processRealtimeAccelerometer(message);
} else if (this.realtimeSpo2Handle == handle) {
processRealtimeSpo2(message);
} else if (this.realtimeRespirationHandle == handle) {
processRealtimeRespiration(message);
} else if (this.realtimeHrvHandle == handle) {
processRealtimeHrv(message);
} else { } else {
LOG.warn("Got message for unknown handle {}: {}", handle, GB.hexdump(characteristic.getValue())); LOG.warn("Got message for unknown handle {}: {}", handle, GB.hexdump(characteristic.getValue()));
} }
@ -220,7 +232,7 @@ public class CommunicatorV2 implements ICommunicator {
} }
final int handle = message.get(); final int handle = message.get();
final int reliable = message.get(); final int reliable = message.get();
LOG.debug("Got register response for {}, reliable={}", registeredService, reliable); LOG.debug("Got register response for {}, handle={}, reliable={}", registeredService, handle, reliable);
switch (registeredService) { switch (registeredService) {
case GFDI: case GFDI:
@ -238,6 +250,15 @@ public class CommunicatorV2 implements ICommunicator {
.write(characteristicSend, new byte[]{(byte) handle, 0x01}) .write(characteristicSend, new byte[]{(byte) handle, 0x01})
.queue(this.mSupport.getQueue()); .queue(this.mSupport.getQueue());
break; break;
case REALTIME_SPO2:
this.realtimeSpo2Handle = handle;
break;
case REALTIME_RESPIRATION:
this.realtimeRespirationHandle = handle;
break;
case REALTIME_HRV:
this.realtimeHrvHandle = handle;
break;
} }
break; break;
} }
@ -261,6 +282,15 @@ public class CommunicatorV2 implements ICommunicator {
case REALTIME_ACCELEROMETER: case REALTIME_ACCELEROMETER:
this.realtimeAccelHandle = 0; this.realtimeAccelHandle = 0;
break; break;
case REALTIME_SPO2:
this.realtimeSpo2Handle = 0;
break;
case REALTIME_RESPIRATION:
this.realtimeRespirationHandle = 0;
break;
case REALTIME_HRV:
this.realtimeHrvHandle = 0;
break;
} }
} }
break; break;
@ -271,6 +301,9 @@ public class CommunicatorV2 implements ICommunicator {
this.realtimeHrHandle = 0; this.realtimeHrHandle = 0;
this.realtimeStepsHandle = 0; this.realtimeStepsHandle = 0;
this.realtimeAccelHandle = 0; this.realtimeAccelHandle = 0;
this.realtimeSpo2Handle = 0;
this.realtimeRespirationHandle = 0;
this.realtimeHrvHandle = 0;
new TransactionBuilder("open GFDI") new TransactionBuilder("open GFDI")
.write(characteristicSend, registerService(Service.GFDI, false)) .write(characteristicSend, registerService(Service.GFDI, false))
.queue(this.mSupport.getQueue()); .queue(this.mSupport.getQueue());
@ -326,6 +359,26 @@ public class CommunicatorV2 implements ICommunicator {
LOG.debug("Got realtime accel: {}", GB.hexdump(partial)); LOG.debug("Got realtime accel: {}", GB.hexdump(partial));
} }
private void processRealtimeSpo2(final ByteBuffer message) {
final int spo2 = message.get(); // -1 when unknown, and the ts is not valid in that case
final int garminTs = message.getInt();
LOG.debug("Got realtime SpO2 at {}: {}", new Date(GarminTimeUtils.garminTimestampToJavaMillis(garminTs)), spo2);
}
private void processRealtimeRespiration(final ByteBuffer message) {
final int breathsPerMinute = message.get(); // can be negative if unknown, usually -2
LOG.debug("Got realtime respiration: {}", breathsPerMinute);
}
private void processRealtimeHrv(final ByteBuffer message) {
final short rr = message.getShort();
final int unk = message.getInt();
LOG.debug("Got realtime HRV: rr={}, unk={}", rr, unk);
}
private byte[] closeAllServices() { private byte[] closeAllServices() {
final ByteBuffer toSend = ByteBuffer.allocate(13).order(ByteOrder.LITTLE_ENDIAN); final ByteBuffer toSend = ByteBuffer.allocate(13).order(ByteOrder.LITTLE_ENDIAN);
toSend.put((byte) 0); // handle toSend.put((byte) 0); // handle