mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-27 20:36:51 +01:00
Garmin: Manual HR measurements and realtime HR/steps
This commit is contained in:
parent
e5b91d3ac3
commit
5bc114b062
@ -225,9 +225,8 @@ public abstract class GarminCoordinator extends AbstractBLEDeviceCoordinator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsManualHeartRateMeasurement(final GBDevice device) {
|
||||
// TODO: It should be supported, but not yet implemented
|
||||
return false;
|
||||
public boolean supportsRealtimeData() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -827,6 +827,21 @@ public class GarminSupport extends AbstractBTLEDeviceSupport implements ICommuni
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHeartRateTest() {
|
||||
communicator.onHeartRateTest();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnableRealtimeHeartRateMeasurement(final boolean enable) {
|
||||
communicator.onEnableRealtimeHeartRateMeasurement(enable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnableRealtimeSteps(final boolean enable) {
|
||||
communicator.onEnableRealtimeSteps(enable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTestNewFunction() {
|
||||
parseAllFitFilesFromStorage();
|
||||
|
@ -14,6 +14,12 @@ public interface ICommunicator {
|
||||
|
||||
boolean onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic);
|
||||
|
||||
void onHeartRateTest();
|
||||
|
||||
void onEnableRealtimeHeartRateMeasurement(final boolean enable);
|
||||
|
||||
void onEnableRealtimeSteps(final boolean enable);
|
||||
|
||||
interface Callback {
|
||||
void onMessage(byte[] message);
|
||||
}
|
||||
|
@ -3,6 +3,9 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.communicator
|
||||
import android.bluetooth.BluetoothGatt;
|
||||
import android.bluetooth.BluetoothGattCharacteristic;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
@ -10,6 +13,8 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.GarminSupport
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.communicator.ICommunicator;
|
||||
|
||||
public class CommunicatorV1 implements ICommunicator {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(CommunicatorV1.class);
|
||||
|
||||
public static final UUID UUID_SERVICE_GARMIN_GFDI = UUID.fromString("6A4E2401-667B-11E3-949A-0800200C9A66");
|
||||
|
||||
private final GarminSupport mSupport;
|
||||
@ -25,7 +30,7 @@ public class CommunicatorV1 implements ICommunicator {
|
||||
|
||||
@Override
|
||||
public void initializeDevice(final TransactionBuilder builder) {
|
||||
|
||||
LOG.error("Initialization is not implemented for V1");
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -37,4 +42,19 @@ public class CommunicatorV1 implements ICommunicator {
|
||||
public boolean onCharacteristicChanged(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHeartRateTest() {
|
||||
LOG.error("onHeartRateTest is not implemented for V1");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnableRealtimeHeartRateMeasurement(final boolean enable) {
|
||||
LOG.error("onEnableRealtimeHeartRateMeasurement is not implemented for V1");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnableRealtimeSteps(final boolean enable) {
|
||||
LOG.error("onEnableRealtimeSteps is not implemented for V1");
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,10 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.communicator
|
||||
|
||||
import android.bluetooth.BluetoothGatt;
|
||||
import android.bluetooth.BluetoothGattCharacteristic;
|
||||
import android.content.Intent;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.slf4j.Logger;
|
||||
@ -12,7 +16,18 @@ import java.nio.ByteOrder;
|
||||
import java.util.Arrays;
|
||||
import java.util.UUID;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.garmin.GarminActivitySampleProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.GarminActivitySample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.User;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.DeviceService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceStateAction;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.GarminSupport;
|
||||
@ -21,19 +36,29 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.communicator.
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
|
||||
public class CommunicatorV2 implements ICommunicator {
|
||||
public static final String BASE_UUID = "6A4E%04X-667B-11E3-949A-0800200C9A66";
|
||||
private static final Logger LOG = LoggerFactory.getLogger(CommunicatorV2.class);
|
||||
|
||||
public static final String BASE_UUID = "6A4E%04X-667B-11E3-949A-0800200C9A66";
|
||||
public static final UUID UUID_SERVICE_GARMIN_ML_GFDI = UUID.fromString(String.format(BASE_UUID, 0x2800));
|
||||
|
||||
private static final long GADGETBRIDGE_CLIENT_ID = 2L;
|
||||
|
||||
private BluetoothGattCharacteristic characteristicSend;
|
||||
private BluetoothGattCharacteristic characteristicReceive;
|
||||
|
||||
public int maxWriteSize = 20;
|
||||
private static final Logger LOG = LoggerFactory.getLogger(CommunicatorV2.class);
|
||||
public final CobsCoDec cobsCoDec;
|
||||
private final GarminSupport mSupport;
|
||||
private final long gadgetBridgeClientID = 2L;
|
||||
|
||||
private int gfdiHandle = 0;
|
||||
public int maxWriteSize = 20;
|
||||
public final CobsCoDec cobsCoDec;
|
||||
|
||||
private int realtimeHrHandle = 0;
|
||||
private boolean realtimeHrOneShot = false;
|
||||
|
||||
private int realtimeStepsHandle = 0;
|
||||
private int previousSteps = -1;
|
||||
|
||||
private int realtimeAccelHandle = 0;
|
||||
|
||||
public CommunicatorV2(final GarminSupport garminSupport) {
|
||||
this.mSupport = garminSupport;
|
||||
@ -101,85 +126,266 @@ public class CommunicatorV2 implements ICommunicator {
|
||||
return false;
|
||||
}
|
||||
|
||||
ByteBuffer message = ByteBuffer.wrap(characteristic.getValue()).order(ByteOrder.LITTLE_ENDIAN);
|
||||
// LOG.debug("RECEIVED: {}", GB.hexdump(message.array()));
|
||||
final ByteBuffer message = ByteBuffer.wrap(characteristic.getValue()).order(ByteOrder.LITTLE_ENDIAN);
|
||||
final byte handle = message.get();
|
||||
if (0x00 == handle) { //handle management message
|
||||
|
||||
final byte type = message.get();
|
||||
final long incomingClientID = message.getLong();
|
||||
|
||||
if (incomingClientID != this.gadgetBridgeClientID) {
|
||||
LOG.debug("Ignoring incoming message, client ID is not ours. Message: {}", GB.hexdump(message.array()));
|
||||
}
|
||||
RequestType requestType = RequestType.fromCode(type);
|
||||
if (null == requestType) {
|
||||
LOG.error("Unknown request type. Message: {}", message.array());
|
||||
return true;
|
||||
}
|
||||
switch (requestType) {
|
||||
case REGISTER_ML_REQ: //register service request
|
||||
case CLOSE_HANDLE_REQ: //close handle request
|
||||
case CLOSE_ALL_REQ: //close all handles request
|
||||
case UNK_REQ: //unknown request
|
||||
LOG.warn("Received handle request, expecting responses. Message: {}", message.array());
|
||||
case REGISTER_ML_RESP: //register service response
|
||||
LOG.debug("Received register response. Message: {}", message.array());
|
||||
final short registeredService = message.getShort();
|
||||
final byte status = message.get();
|
||||
if (0 == status && 1 == registeredService) { //success
|
||||
this.gfdiHandle = message.get();
|
||||
}
|
||||
break;
|
||||
case CLOSE_HANDLE_RESP: //close handle response
|
||||
LOG.debug("Received close handle response. Message: {}", message.array());
|
||||
break;
|
||||
case CLOSE_ALL_RESP: //close all handles response
|
||||
LOG.debug("Received close all handles response. Message: {}", message.array());
|
||||
new TransactionBuilder("open GFDI")
|
||||
.write(characteristicSend, registerGFDI())
|
||||
.queue(this.mSupport.getQueue());
|
||||
break;
|
||||
case UNK_RESP: //unknown response
|
||||
LOG.debug("Received unknown. Message: {}", message.array());
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
if (0x00 == handle) {
|
||||
processHandleManagement(message);
|
||||
} else if (this.gfdiHandle == handle) {
|
||||
processGfdi(message);
|
||||
} else if (this.realtimeHrHandle == handle) {
|
||||
processRealtimeHeartRate(message);
|
||||
} else if (this.realtimeStepsHandle == handle) {
|
||||
processRealtimeSteps(message);
|
||||
} else if (this.realtimeAccelHandle == handle) {
|
||||
processRealtimeAccelerometer(message);
|
||||
} else {
|
||||
LOG.warn("Got message for unknown handle {}: {}", handle, GB.hexdump(characteristic.getValue()));
|
||||
}
|
||||
|
||||
byte[] partial = new byte[message.remaining()];
|
||||
message.get(partial);
|
||||
this.cobsCoDec.receivedBytes(partial);
|
||||
return true;
|
||||
}
|
||||
|
||||
this.mSupport.onMessage(this.cobsCoDec.retrieveMessage());
|
||||
@Override
|
||||
public void onHeartRateTest() {
|
||||
realtimeHrOneShot = true;
|
||||
if (realtimeHrHandle == 0) {
|
||||
new TransactionBuilder("heart rate test")
|
||||
.write(characteristicSend, registerService(Service.REALTIME_HR, false))
|
||||
.queue(this.mSupport.getQueue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnableRealtimeHeartRateMeasurement(final boolean enable) {
|
||||
toggleService(Service.REALTIME_HR, realtimeHrHandle, enable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnableRealtimeSteps(final boolean enable) {
|
||||
if (toggleService(Service.REALTIME_STEPS, realtimeStepsHandle, enable)) {
|
||||
previousSteps = -1;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean toggleService(final Service service, final int currentHandle, final boolean enable) {
|
||||
if (enable && currentHandle == 0) {
|
||||
new TransactionBuilder(service + " = true")
|
||||
.write(characteristicSend, registerService(service, false))
|
||||
.queue(this.mSupport.getQueue());
|
||||
return true;
|
||||
} else if (!enable && currentHandle != 0) {
|
||||
new TransactionBuilder(service + " = false")
|
||||
.write(characteristicSend, closeService(service, currentHandle))
|
||||
.queue(this.mSupport.getQueue());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected byte[] closeAllServices() {
|
||||
ByteBuffer toSend = ByteBuffer.allocate(13);
|
||||
toSend.order(ByteOrder.BIG_ENDIAN);
|
||||
toSend.putShort((short) RequestType.CLOSE_ALL_REQ.ordinal()); //close all services
|
||||
toSend.order(ByteOrder.LITTLE_ENDIAN);
|
||||
toSend.putLong(this.gadgetBridgeClientID);
|
||||
private void processHandleManagement(final ByteBuffer message) {
|
||||
final byte type = message.get();
|
||||
final long incomingClientID = message.getLong();
|
||||
|
||||
if (incomingClientID != GADGETBRIDGE_CLIENT_ID) {
|
||||
LOG.warn("Ignoring incoming message, client ID {} is not ours. Message: {}", incomingClientID, GB.hexdump(message.array()));
|
||||
return;
|
||||
}
|
||||
|
||||
final RequestType requestType = RequestType.fromCode(type);
|
||||
if (null == requestType) {
|
||||
LOG.error("Unknown request type {}. Message: {}", type, message.array());
|
||||
return;
|
||||
}
|
||||
|
||||
switch (requestType) {
|
||||
case REGISTER_ML_REQ:
|
||||
case CLOSE_HANDLE_REQ:
|
||||
case CLOSE_ALL_REQ:
|
||||
case UNK_REQ:
|
||||
LOG.warn("Received handle request, expecting responses. Message: {}", message.array());
|
||||
return;
|
||||
case REGISTER_ML_RESP: {
|
||||
final short registeredServiceCode = message.getShort();
|
||||
final Service registeredService = Service.fromCode(registeredServiceCode);
|
||||
final byte status = message.get();
|
||||
if (registeredService == null) {
|
||||
LOG.error("Got register response status={} for unknown service {}", status, registeredServiceCode);
|
||||
return;
|
||||
}
|
||||
if (status != 0) {
|
||||
LOG.warn("Failed to register {}, status={}", registeredService, status);
|
||||
return;
|
||||
}
|
||||
final int handle = message.get();
|
||||
final int reliable = message.get();
|
||||
LOG.debug("Got register response for {}, reliable={}", registeredService, reliable);
|
||||
|
||||
switch (registeredService) {
|
||||
case GFDI:
|
||||
this.gfdiHandle = handle;
|
||||
break;
|
||||
case REALTIME_HR:
|
||||
this.realtimeHrHandle = handle;
|
||||
break;
|
||||
case REALTIME_STEPS:
|
||||
this.realtimeStepsHandle = handle;
|
||||
break;
|
||||
case REALTIME_ACCELEROMETER:
|
||||
this.realtimeAccelHandle = handle;
|
||||
new TransactionBuilder("start realtime accel")
|
||||
.write(characteristicSend, new byte[]{(byte) handle, 0x01})
|
||||
.queue(this.mSupport.getQueue());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CLOSE_HANDLE_RESP: {
|
||||
final short serviceCode = message.getShort();
|
||||
final Service service = Service.fromCode(serviceCode);
|
||||
final int handle = message.get();
|
||||
final byte status = message.get();
|
||||
LOG.debug("Received close handle response: service={}, handle={}, status={}", service, handle, status);
|
||||
if (service != null) {
|
||||
switch (service) {
|
||||
case GFDI:
|
||||
this.gfdiHandle = 0;
|
||||
break;
|
||||
case REALTIME_HR:
|
||||
this.realtimeHrHandle = 0;
|
||||
break;
|
||||
case REALTIME_STEPS:
|
||||
this.realtimeStepsHandle = 0;
|
||||
break;
|
||||
case REALTIME_ACCELEROMETER:
|
||||
this.realtimeAccelHandle = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CLOSE_ALL_RESP:
|
||||
LOG.debug("Received close all handles response. Message: {}", message.array());
|
||||
this.gfdiHandle = 0;
|
||||
this.realtimeHrHandle = 0;
|
||||
this.realtimeStepsHandle = 0;
|
||||
this.realtimeAccelHandle = 0;
|
||||
new TransactionBuilder("open GFDI")
|
||||
.write(characteristicSend, registerService(Service.GFDI, false))
|
||||
.queue(this.mSupport.getQueue());
|
||||
break;
|
||||
case UNK_RESP:
|
||||
LOG.debug("Received unknown. Message: {}", message.array());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void processGfdi(final ByteBuffer message) {
|
||||
final byte[] partial = new byte[message.remaining()];
|
||||
message.get(partial);
|
||||
this.cobsCoDec.receivedBytes(partial);
|
||||
|
||||
this.mSupport.onMessage(this.cobsCoDec.retrieveMessage());
|
||||
}
|
||||
|
||||
private void processRealtimeHeartRate(final ByteBuffer buf) {
|
||||
final byte type = buf.get(); // 0/2/3? 3 == realtime?
|
||||
final int hr = buf.get();
|
||||
final int resting = buf.get();
|
||||
// ff ff after
|
||||
LOG.debug("Got realtime HR: type={} hr={} resting={}", type, hr, resting);
|
||||
|
||||
if (hr > 0) {
|
||||
broadcastRealtimeActivity(hr, -1);
|
||||
|
||||
if (realtimeHrOneShot && realtimeHrHandle != 0) {
|
||||
onEnableRealtimeHeartRateMeasurement(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processRealtimeSteps(final ByteBuffer buf) {
|
||||
final int steps = buf.getInt();
|
||||
final int goal = buf.getInt();
|
||||
LOG.debug("Got realtime steps: steps={} goal={}", steps, goal);
|
||||
|
||||
if (previousSteps == -1) {
|
||||
previousSteps = steps;
|
||||
}
|
||||
|
||||
broadcastRealtimeActivity(-1, steps - previousSteps);
|
||||
|
||||
previousSteps = steps;
|
||||
}
|
||||
|
||||
private void processRealtimeAccelerometer(final ByteBuffer message) {
|
||||
final byte[] partial = new byte[message.remaining()];
|
||||
message.get(partial);
|
||||
|
||||
LOG.debug("Got realtime accel: {}", GB.hexdump(partial));
|
||||
}
|
||||
|
||||
private byte[] closeAllServices() {
|
||||
final ByteBuffer toSend = ByteBuffer.allocate(13).order(ByteOrder.LITTLE_ENDIAN);
|
||||
toSend.put((byte) 0); // handle
|
||||
toSend.put((byte) RequestType.CLOSE_ALL_REQ.ordinal());
|
||||
toSend.putLong(GADGETBRIDGE_CLIENT_ID);
|
||||
toSend.putShort((short) 0);
|
||||
return toSend.array();
|
||||
}
|
||||
|
||||
protected byte[] registerGFDI() {
|
||||
ByteBuffer toSend = ByteBuffer.allocate(13);
|
||||
toSend.order(ByteOrder.BIG_ENDIAN);
|
||||
toSend.putShort((short) RequestType.REGISTER_ML_REQ.ordinal()); //register service request
|
||||
toSend.order(ByteOrder.LITTLE_ENDIAN);
|
||||
toSend.putLong(this.gadgetBridgeClientID);
|
||||
toSend.putShort((short) 1); //service GFDI
|
||||
private byte[] registerService(final Service service, final boolean reliable) {
|
||||
final ByteBuffer toSend = ByteBuffer.allocate(13).order(ByteOrder.LITTLE_ENDIAN);
|
||||
toSend.put((byte) 0);
|
||||
toSend.put((byte) RequestType.REGISTER_ML_REQ.ordinal());
|
||||
toSend.putLong(GADGETBRIDGE_CLIENT_ID);
|
||||
toSend.putShort(service.getCode());
|
||||
toSend.put((byte) (reliable ? 2 : 0));
|
||||
return toSend.array();
|
||||
}
|
||||
|
||||
enum RequestType {
|
||||
private byte[] closeService(final Service service, final int handle) {
|
||||
final ByteBuffer toSend = ByteBuffer.allocate(13).order(ByteOrder.LITTLE_ENDIAN);
|
||||
toSend.put((byte) 0);
|
||||
toSend.put((byte) RequestType.CLOSE_HANDLE_REQ.ordinal());
|
||||
toSend.putLong(GADGETBRIDGE_CLIENT_ID);
|
||||
toSend.putShort(service.getCode());
|
||||
toSend.put((byte) handle);
|
||||
return toSend.array();
|
||||
}
|
||||
|
||||
private void broadcastRealtimeActivity(final int hr, final int steps) {
|
||||
final GarminActivitySample sample;
|
||||
try (final DBHandler dbHandler = GBApplication.acquireDB()) {
|
||||
final DaoSession session = dbHandler.getDaoSession();
|
||||
|
||||
final GBDevice gbDevice = mSupport.getDevice();
|
||||
final Device device = DBHelper.getDevice(gbDevice, session);
|
||||
final User user = DBHelper.getUser(session);
|
||||
final GarminActivitySampleProvider provider = new GarminActivitySampleProvider(gbDevice, session);
|
||||
sample = provider.createActivitySample();
|
||||
|
||||
sample.setDeviceId(device.getId());
|
||||
sample.setUserId(user.getId());
|
||||
sample.setTimestamp((int) (System.currentTimeMillis() / 1000));
|
||||
sample.setHeartRate(hr);
|
||||
sample.setSteps(steps);
|
||||
sample.setRawKind(ActivityKind.UNKNOWN.getCode());
|
||||
sample.setRawIntensity(ActivitySample.NOT_MEASURED);
|
||||
sample.setRawKind(ActivityKind.UNKNOWN.getCode());
|
||||
} catch (final Exception e) {
|
||||
LOG.error("Error creating activity sample", e);
|
||||
return;
|
||||
}
|
||||
|
||||
final Intent intent = new Intent(DeviceService.ACTION_REALTIME_SAMPLES)
|
||||
.putExtra(GBDevice.EXTRA_DEVICE, mSupport.getDevice())
|
||||
.putExtra(DeviceService.EXTRA_REALTIME_SAMPLE, sample);
|
||||
LocalBroadcastManager.getInstance(mSupport.getContext()).sendBroadcast(intent);
|
||||
}
|
||||
|
||||
private enum RequestType {
|
||||
REGISTER_ML_REQ,
|
||||
REGISTER_ML_RESP,
|
||||
CLOSE_HANDLE_REQ,
|
||||
@ -190,6 +396,7 @@ public class CommunicatorV2 implements ICommunicator {
|
||||
UNK_REQ,
|
||||
UNK_RESP;
|
||||
|
||||
@Nullable
|
||||
public static RequestType fromCode(final int code) {
|
||||
for (final RequestType requestType : RequestType.values()) {
|
||||
if (requestType.ordinal() == code) {
|
||||
@ -200,4 +407,41 @@ public class CommunicatorV2 implements ICommunicator {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private enum Service {
|
||||
GFDI(1),
|
||||
REGISTRATION(4),
|
||||
REALTIME_HR(6),
|
||||
REALTIME_STEPS(7),
|
||||
REALTIME_CALORIES(8),
|
||||
REALTIME_INTENSITY(10),
|
||||
REALTIME_HRV(12),
|
||||
REALTIME_STRESS(13),
|
||||
REALTIME_ACCELEROMETER(16),
|
||||
REALTIME_SPO2(19),
|
||||
REALTIME_BODY_BATTERY(20),
|
||||
REALTIME_RESPIRATION(21),
|
||||
;
|
||||
|
||||
private final short code;
|
||||
|
||||
Service(final int code) {
|
||||
this.code = (short) code;
|
||||
}
|
||||
|
||||
public short getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Service fromCode(final int code) {
|
||||
for (final Service service : Service.values()) {
|
||||
if (service.code == code) {
|
||||
return service;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,9 +31,7 @@ import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@ -933,9 +931,7 @@ public class XiaomiHealthService extends AbstractXiaomiService {
|
||||
sample.setHeartRate(realTimeStats.getHeartRate());
|
||||
sample.setSteps(realTimeStats.getSteps() - previousSteps);
|
||||
sample.setRawKind(ActivityKind.UNKNOWN.getCode());
|
||||
sample.setHeartRate(realTimeStats.getHeartRate());
|
||||
sample.setRawIntensity(ActivitySample.NOT_MEASURED);
|
||||
sample.setRawKind(ActivityKind.UNKNOWN.getCode());
|
||||
} catch (final Exception e) {
|
||||
LOG.error("Error creating activity sample", e);
|
||||
return;
|
||||
|
Loading…
Reference in New Issue
Block a user