mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2026-07-31 07:44:24 +02:00
Huawei: rewrite sequence parser
This commit is contained in:
+2
-2
@@ -27,8 +27,8 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class HuaweiSequenceDataParser {
|
public class HuaweiSequenceDataFileParser {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(HuaweiSequenceDataParser.class);
|
private static final Logger LOG = LoggerFactory.getLogger(HuaweiSequenceDataFileParser.class);
|
||||||
|
|
||||||
public static class SequenceData {
|
public static class SequenceData {
|
||||||
private int endTime;
|
private int endTime;
|
||||||
+101
@@ -0,0 +1,101 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.devices.huawei;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public abstract class HuaweiSequenceDataParserBase<T> {
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(HuaweiSequenceDataParserBase.class);
|
||||||
|
|
||||||
|
protected static int readAsInteger(byte[] data, int def) {
|
||||||
|
if (data == null || data.length == 0 || data.length > 4) {
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
// NOTE: Looks like validData should be float but the watch returns it as integer.
|
||||||
|
// unsigned integer stored as 0xBF800000 = 10111111 10000000 00000000 00000000
|
||||||
|
// for float -1.
|
||||||
|
if(Arrays.equals(data,new byte[]{(byte) 0xBF, (byte) 0x80, 0x00, 0x00})) {
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
int res = 0;
|
||||||
|
for (int i = 0; i < data.length; i++) {
|
||||||
|
res |= (data[i] & 0xFF) << (((data.length - i) - 1) * 8);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static long readAsLong(byte[] data, long def) {
|
||||||
|
if (data == null || data.length == 0 || data.length > 8) {
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
long res = 0;
|
||||||
|
for (int i = 0; i < data.length; i++) {
|
||||||
|
res |= (long) (data[i] & 0xFF) << (((data.length - i) - 1) * 8);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static long getValueAsLong(int i, byte[] str2, long def) {
|
||||||
|
if (i == 1 || i == 2 || i == 4) { // int, byte, short (I suppose)
|
||||||
|
return readAsInteger(str2, (int) def);
|
||||||
|
} else if (i == 3) { // long
|
||||||
|
return readAsLong(str2, def);
|
||||||
|
} else if (i == 5) { // string
|
||||||
|
return def;
|
||||||
|
} else if (i == 6) { // double
|
||||||
|
return (long) Double.longBitsToDouble(readAsLong(str2, def));
|
||||||
|
} else {
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static double getValueAsDouble(int i, byte[] str2, double def) {
|
||||||
|
if (i == 1 || i == 2 || i == 4) { // int, byte, short (I suppose)
|
||||||
|
return readAsInteger(str2, (int) def);
|
||||||
|
} else if (i == 3) { // long
|
||||||
|
return readAsLong(str2, (int) def);
|
||||||
|
} else if (i == 5) { // string
|
||||||
|
return def;
|
||||||
|
} else if (i == 6) { // double
|
||||||
|
return Double.longBitsToDouble(readAsLong(str2, (int) def));
|
||||||
|
} else {
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void fillData(T details, int dictId, int dataType, byte[] value);
|
||||||
|
|
||||||
|
protected abstract T getNewData();
|
||||||
|
|
||||||
|
private T parseTLVData(byte[] str) {
|
||||||
|
T details = getNewData();
|
||||||
|
HuaweiTLV tlv = new HuaweiTLV().parse(str);
|
||||||
|
List<HuaweiTLV> containers = tlv.getAllContainerObjects();
|
||||||
|
for (HuaweiTLV tv : containers) {
|
||||||
|
List<HuaweiTLV> containers2 = tv.getAllContainerObjects();
|
||||||
|
for (HuaweiTLV tv2 : containers2) {
|
||||||
|
try {
|
||||||
|
int dictId = tv2.getAsInteger(0x03);
|
||||||
|
int dataType = tv2.getAsInteger(0x04);
|
||||||
|
byte[] value = tv2.getBytes(0x5);
|
||||||
|
fillData(details, dictId, dataType, value);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOG.error("SequenceDataParserBase dict sync: tag is missing", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return details;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T parseData(HuaweiSequenceDataFileParser.SequenceFileData fileData, HuaweiSequenceDataFileParser.SequenceData data) {
|
||||||
|
// summary type 2 is TLV. TLV works only for fileType != 2 (or maybe only for 1)
|
||||||
|
// currently only data version 1 supported
|
||||||
|
if (data != null && data.getDataVersion() == 1 && data.getSummaryType() == 2 && fileData.getFileType() != 2) {
|
||||||
|
return parseTLVData(data.getSummary());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
+230
-230
@@ -24,10 +24,9 @@ import org.slf4j.LoggerFactory;
|
|||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class HuaweiTrueSleepSequenceDataParser {
|
public class HuaweiTrueSleepSequenceDataParser extends HuaweiSequenceDataParserBase<HuaweiTrueSleepSequenceDataParser.SleepSummary> {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(HuaweiTrueSleepSequenceDataParser.class);
|
private static final Logger LOG = LoggerFactory.getLogger(HuaweiTrueSleepSequenceDataParser.class);
|
||||||
|
|
||||||
public static class SleepStage {
|
public static class SleepStage {
|
||||||
@@ -50,316 +49,317 @@ public class HuaweiTrueSleepSequenceDataParser {
|
|||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
final StringBuffer sb = new StringBuffer("SleepStages{");
|
return "SleepStages{" + "time=" + time +
|
||||||
sb.append("time=").append(time);
|
", stage=" + stage +
|
||||||
sb.append(", stage=").append(stage);
|
'}';
|
||||||
sb.append('}');
|
|
||||||
return sb.toString();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class SleepSummary {
|
public static class SleepSummary {
|
||||||
private long fallAsleepTime = -1;
|
public long fallAsleepTime = -1;
|
||||||
private long bedTime = -1;
|
public long bedTime = -1;
|
||||||
private long risingTime = -1;
|
public long risingTime = -1;
|
||||||
private long wakeupTime = -1;
|
public long wakeupTime = -1;
|
||||||
private int validData = -1;
|
public int validData = -1;
|
||||||
private int sleepDataQuality = -1;
|
public int sleepDataQuality = -1;
|
||||||
private int deepPart = -1;
|
public int deepPart = -1;
|
||||||
private int snoreFreq = -1;
|
public int snoreFreq = -1;
|
||||||
private int sleepScore = -1;
|
public int sleepScore = -1;
|
||||||
private int sleepLatency = -1;
|
public int sleepLatency = -1;
|
||||||
private int sleepEfficiency = -1;
|
public int sleepEfficiency = -1;
|
||||||
private int minHeartrate = -1;
|
public int minHeartRate = -1;
|
||||||
private int maxHeartrate = -1;
|
public int maxHeartRate = -1;
|
||||||
private double minOxygenSaturation = -1;
|
public double minOxygenSaturation = -1;
|
||||||
private double maxOxygenSaturation = -1;
|
public double maxOxygenSaturation = -1;
|
||||||
private double minBreathrate = -1;
|
public double minBreathRate = -1;
|
||||||
private double maxBreathrate = -1;
|
public double maxBreathRate = -1;
|
||||||
|
public int hrvDayToBaseline = -1;
|
||||||
public long getFallAsleepTime() { return fallAsleepTime; }
|
public int maxHrvBaseline = -1;
|
||||||
|
public int minHrvBaseline = -1;
|
||||||
public void setFallAsleepTime(long fallAsleepTime) { this.fallAsleepTime = fallAsleepTime; }
|
public int avgHrv = -1;
|
||||||
|
public int breathRateDayToBaseline = -1;
|
||||||
public long getBedTime() { return bedTime; }
|
public int maxBreathRateBaseline = -1;
|
||||||
|
public int minBreathRateBaseline = -1;
|
||||||
public void setBedTime(long bedTime) { this.bedTime = bedTime;}
|
public int avgBreathRate = -1;
|
||||||
|
public int oxygenSaturationDayToBaseline = -1;
|
||||||
public long getRisingTime() { return risingTime;}
|
public int maxOxygenSaturationBaseline = -1;
|
||||||
|
public int minOxygenSaturationBaseline = -1;
|
||||||
public void setRisingTime(long risingTime) {this.risingTime = risingTime;}
|
public int avgOxygenSaturation = -1;
|
||||||
|
public int heartRateDayToBaseline = -1;
|
||||||
public long getWakeupTime() {return wakeupTime;}
|
public int maxHeartRateBaseline = -1;
|
||||||
|
public int minHeartRateBaseline = -1;
|
||||||
public void setWakeupTime(long wakeupTime) {this.wakeupTime = wakeupTime;}
|
public int avgHeartRate = -1;
|
||||||
|
public int rdi = -1; // Respiratory Disturbance Index, RDI is a numeric index which helps to define the degree of the apnea.
|
||||||
public int getValidData() { return validData; }
|
public int wakeCount = -1;
|
||||||
|
public int turnOverCount = -1;
|
||||||
public void setValidData(int validData) { this.validData = validData;}
|
public long prepareSleepTime = -1;
|
||||||
|
public int wakeUpFeeling = -1;
|
||||||
public int getSleepDataQuality() { return sleepDataQuality;}
|
public int sleepVersion = -1;
|
||||||
|
|
||||||
public void setSleepDataQuality(int sleepDataQuality) {this.sleepDataQuality = sleepDataQuality;}
|
|
||||||
|
|
||||||
public int getDeepPart() {return deepPart;}
|
|
||||||
|
|
||||||
public void setDeepPart(int deepPart) {this.deepPart = deepPart;}
|
|
||||||
|
|
||||||
public int getSnoreFreq() {return snoreFreq;}
|
|
||||||
|
|
||||||
public void setSnoreFreq(int snoreFreq) {this.snoreFreq = snoreFreq;}
|
|
||||||
|
|
||||||
public int getSleepScore() {return sleepScore;}
|
|
||||||
|
|
||||||
public void setSleepScore(int sleepScore) {this.sleepScore = sleepScore;}
|
|
||||||
|
|
||||||
public int getSleepLatency() {return sleepLatency;}
|
|
||||||
|
|
||||||
public void setSleepLatency(int sleepLatency) {this.sleepLatency = sleepLatency;}
|
|
||||||
|
|
||||||
public int getSleepEfficiency() {return sleepEfficiency;}
|
|
||||||
|
|
||||||
public void setSleepEfficiency(int sleepEfficiency) {this.sleepEfficiency = sleepEfficiency;}
|
|
||||||
|
|
||||||
public int getMinHeartrate() {return minHeartrate;}
|
|
||||||
|
|
||||||
public void setMinHeartrate(int minHeartrate) {this.minHeartrate = minHeartrate;}
|
|
||||||
|
|
||||||
public int getMaxHeartrate() {return maxHeartrate;}
|
|
||||||
|
|
||||||
public void setMaxHeartrate(int maxHeartrate) {this.maxHeartrate = maxHeartrate;}
|
|
||||||
|
|
||||||
public double getMinOxygenSaturation() {return minOxygenSaturation;}
|
|
||||||
|
|
||||||
public void setMinOxygenSaturation(double minOxygenSaturation) {this.minOxygenSaturation = minOxygenSaturation;}
|
|
||||||
|
|
||||||
public double getMaxOxygenSaturation() {return maxOxygenSaturation;}
|
|
||||||
|
|
||||||
public void setMaxOxygenSaturation(double maxOxygenSaturation) {this.maxOxygenSaturation = maxOxygenSaturation;}
|
|
||||||
|
|
||||||
public double getMinBreathrate() {return minBreathrate;}
|
|
||||||
|
|
||||||
public void setMinBreathrate(double minBreathrate) {this.minBreathrate = minBreathrate;}
|
|
||||||
|
|
||||||
public double getMaxBreathrate() {return maxBreathrate;}
|
|
||||||
|
|
||||||
public void setMaxBreathrate(double maxBreathrate) {this.maxBreathrate = maxBreathrate;}
|
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
final StringBuilder sb = new StringBuilder("SleepDetails{");
|
return "SleepSummary{" + "fallAsleepTime=" + fallAsleepTime +
|
||||||
sb.append("fallAsleepTime=").append(fallAsleepTime);
|
", bedTime=" + bedTime +
|
||||||
sb.append(", bedTime=").append(bedTime);
|
", risingTime=" + risingTime +
|
||||||
sb.append(", risingTime=").append(risingTime);
|
", wakeupTime=" + wakeupTime +
|
||||||
sb.append(", wakeupTime=").append(wakeupTime);
|
", validData=" + validData +
|
||||||
sb.append(", validData=").append(validData);
|
", sleepDataQuality=" + sleepDataQuality +
|
||||||
sb.append(", sleepDataQuality=").append(sleepDataQuality);
|
", deepPart=" + deepPart +
|
||||||
sb.append(", deepPart=").append(deepPart);
|
", snoreFreq=" + snoreFreq +
|
||||||
sb.append(", snoreFreq=").append(snoreFreq);
|
", sleepScore=" + sleepScore +
|
||||||
sb.append(", sleepScore=").append(sleepScore);
|
", sleepLatency=" + sleepLatency +
|
||||||
sb.append(", sleepLatency=").append(sleepLatency);
|
", sleepEfficiency=" + sleepEfficiency +
|
||||||
sb.append(", sleepEfficiency=").append(sleepEfficiency);
|
", minHeartRate=" + minHeartRate +
|
||||||
sb.append(", minHeartrate=").append(minHeartrate);
|
", maxHeartRate=" + maxHeartRate +
|
||||||
sb.append(", maxHeartrate=").append(maxHeartrate);
|
", minOxygenSaturation=" + minOxygenSaturation +
|
||||||
sb.append(", minOxygenSaturation=").append(minOxygenSaturation);
|
", maxOxygenSaturation=" + maxOxygenSaturation +
|
||||||
sb.append(", maxOxygenSaturation=").append(maxOxygenSaturation);
|
", minBreathRate=" + minBreathRate +
|
||||||
sb.append(", minBreathrate=").append(minBreathrate);
|
", maxBreathRate=" + maxBreathRate +
|
||||||
sb.append(", maxBreathrate=").append(maxBreathrate);
|
", hrvDayToBaseline=" + hrvDayToBaseline +
|
||||||
sb.append('}');
|
", maxHrvBaseline=" + maxHrvBaseline +
|
||||||
return sb.toString();
|
", minHrvBaseline=" + minHrvBaseline +
|
||||||
|
", avgHrv=" + avgHrv +
|
||||||
|
", breathRateDayToBaseline=" + breathRateDayToBaseline +
|
||||||
|
", maxBreathRateBaseline=" + maxBreathRateBaseline +
|
||||||
|
", minBreathRateBaseline=" + minBreathRateBaseline +
|
||||||
|
", avgBreathRate=" + avgBreathRate +
|
||||||
|
", oxygenSaturationDayToBaseline=" + oxygenSaturationDayToBaseline +
|
||||||
|
", maxOxygenSaturationBaseline=" + maxOxygenSaturationBaseline +
|
||||||
|
", minOxygenSaturationBaseline=" + minOxygenSaturationBaseline +
|
||||||
|
", avgOxygenSaturation=" + avgOxygenSaturation +
|
||||||
|
", heartRateDayToBaseline=" + heartRateDayToBaseline +
|
||||||
|
", maxHeartRateBaseline=" + maxHeartRateBaseline +
|
||||||
|
", minHeartRateBaseline=" + minHeartRateBaseline +
|
||||||
|
", avgHeartRate=" + avgHeartRate +
|
||||||
|
", rdi=" + rdi +
|
||||||
|
", wakeCount=" + wakeCount +
|
||||||
|
", turnOverCount=" + turnOverCount +
|
||||||
|
", prepareSleepTime=" + prepareSleepTime +
|
||||||
|
", wakeUpFeeling=" + wakeUpFeeling +
|
||||||
|
", sleepVersion=" + sleepVersion +
|
||||||
|
'}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int readAsInteger(byte[] data, int def) {
|
|
||||||
if (data == null || data.length == 0 || data.length > 4) {
|
|
||||||
return def;
|
|
||||||
}
|
|
||||||
// NOTE: Looks like validData should be float but the watch returns it as integer.
|
|
||||||
// unsigned integer stored as 0xBF800000 = 10111111 10000000 00000000 00000000
|
|
||||||
// for float -1.
|
|
||||||
if(Arrays.equals(data,new byte[]{(byte) 0xBF, (byte) 0x80, 0x00, 0x00})) {
|
|
||||||
return def;
|
|
||||||
}
|
|
||||||
int res = 0;
|
|
||||||
for (int i = 0; i < data.length; i++) {
|
|
||||||
res |= (data[i] & 0xFF) << (((data.length - i) - 1) * 8);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static long readAsLong(byte[] data, long def) {
|
protected void fillData(SleepSummary details, int dictId, int dataType, byte[] value) {
|
||||||
if (data == null || data.length == 0 || data.length > 8) {
|
|
||||||
return def;
|
|
||||||
}
|
|
||||||
long res = 0;
|
|
||||||
for (int i = 0; i < data.length; i++) {
|
|
||||||
res |= (long) (data[i] & 0xFF) << (((data.length - i) - 1) * 8);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static long getValueAsLong(int i, byte[] str2, long def) {
|
|
||||||
if (i == 1 || i == 2 || i == 4) { // int, byte, short (I suppose)
|
|
||||||
return readAsInteger(str2, (int) def);
|
|
||||||
} else if (i == 3) { // long
|
|
||||||
return readAsLong(str2, def);
|
|
||||||
} else if (i == 5) { // string
|
|
||||||
return def;
|
|
||||||
} else if (i == 6) { // double
|
|
||||||
return (long) Double.longBitsToDouble(readAsLong(str2, def));
|
|
||||||
} else {
|
|
||||||
return def;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static double getValueAsDouble(int i, byte[] str2, double def) {
|
|
||||||
if (i == 1 || i == 2 || i == 4) { // int, byte, short (I suppose)
|
|
||||||
return readAsInteger(str2, (int) def);
|
|
||||||
} else if (i == 3) { // long
|
|
||||||
return readAsLong(str2, (int) def);
|
|
||||||
} else if (i == 5) { // string
|
|
||||||
return def;
|
|
||||||
} else if (i == 6) { // double
|
|
||||||
return Double.longBitsToDouble(readAsLong(str2, (int) def));
|
|
||||||
} else {
|
|
||||||
return def;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void fillSleepSummary(SleepSummary details, int dictId, int dataType, byte[] value) {
|
|
||||||
switch (dictId) {
|
switch (dictId) {
|
||||||
case 700013686:
|
case 700013686:
|
||||||
long fallAsleepTime = getValueAsLong(dataType, value, -1);
|
long fallAsleepTime = getValueAsLong(dataType, value, -1);
|
||||||
if(fallAsleepTime >=0)
|
if(fallAsleepTime >=0)
|
||||||
details.setFallAsleepTime(fallAsleepTime);
|
details.fallAsleepTime = fallAsleepTime;
|
||||||
break;
|
break;
|
||||||
case 700013298:
|
case 700013298:
|
||||||
long bedTime = getValueAsLong(dataType, value, -1);
|
long bedTime = getValueAsLong(dataType, value, -1);
|
||||||
if(bedTime >=0)
|
if(bedTime >=0)
|
||||||
details.setBedTime(bedTime);
|
details.bedTime = bedTime;
|
||||||
break;
|
break;
|
||||||
case 700013973:
|
case 700013973:
|
||||||
long risingTime = getValueAsLong(dataType, value, -1);
|
long risingTime = getValueAsLong(dataType, value, -1);
|
||||||
if(risingTime >=0)
|
if(risingTime >=0)
|
||||||
details.setRisingTime(risingTime);
|
details.risingTime = risingTime;
|
||||||
break;
|
break;
|
||||||
case 700013156:
|
case 700013156:
|
||||||
long wakeupTime = getValueAsLong(dataType, value, -1);
|
long wakeupTime = getValueAsLong(dataType, value, -1);
|
||||||
if(wakeupTime >=0)
|
if(wakeupTime >=0)
|
||||||
details.setWakeupTime(wakeupTime);
|
details.wakeupTime = wakeupTime;
|
||||||
break;
|
break;
|
||||||
case 700013786:
|
case 700013786:
|
||||||
long validData = getValueAsLong(dataType, value, -1);
|
long validData = getValueAsLong(dataType, value, -1);
|
||||||
if(validData >=0 && validData <= Integer.MAX_VALUE)
|
if(validData >=0 && validData <= Integer.MAX_VALUE)
|
||||||
details.setValidData((int) validData);
|
details.validData = (int) validData;
|
||||||
break;
|
break;
|
||||||
case 700013254:
|
case 700013254:
|
||||||
long sleepDataQuality = getValueAsLong(dataType, value, -1);
|
long sleepDataQuality = getValueAsLong(dataType, value, -1);
|
||||||
if(sleepDataQuality >=0 && sleepDataQuality <= Integer.MAX_VALUE)
|
if(sleepDataQuality >=0 && sleepDataQuality <= Integer.MAX_VALUE)
|
||||||
details.setSleepDataQuality((int) sleepDataQuality);
|
details.sleepDataQuality = (int) sleepDataQuality;
|
||||||
break;
|
break;
|
||||||
case 700013679:
|
case 700013679:
|
||||||
long deepPart = getValueAsLong(dataType, value, -1);
|
long deepPart = getValueAsLong(dataType, value, -1);
|
||||||
if(deepPart >=0 && deepPart <= Integer.MAX_VALUE)
|
if(deepPart >=0 && deepPart <= Integer.MAX_VALUE)
|
||||||
details.setDeepPart((int) deepPart);
|
details.deepPart = (int) deepPart;
|
||||||
break;
|
break;
|
||||||
case 700013721:
|
case 700013721:
|
||||||
long snoreFreq = getValueAsLong(dataType, value, -1);
|
long snoreFreq = getValueAsLong(dataType, value, -1);
|
||||||
if(snoreFreq >=0 && snoreFreq <= Integer.MAX_VALUE)
|
if(snoreFreq >=0 && snoreFreq <= Integer.MAX_VALUE)
|
||||||
details.setSnoreFreq((int) snoreFreq);
|
details.snoreFreq = (int) snoreFreq;
|
||||||
break;
|
break;
|
||||||
case 700013245:
|
case 700013245:
|
||||||
long sleepScore = getValueAsLong(dataType, value, -1);
|
long sleepScore = getValueAsLong(dataType, value, -1);
|
||||||
if(sleepScore >=0 && sleepScore <= Integer.MAX_VALUE)
|
if(sleepScore >=0 && sleepScore <= Integer.MAX_VALUE)
|
||||||
details.setSleepScore((int) sleepScore);
|
details.sleepScore = (int) sleepScore;
|
||||||
break;
|
break;
|
||||||
case 700013713:
|
case 700013713:
|
||||||
long sleepLatency = getValueAsLong(dataType, value, -1);
|
long sleepLatency = getValueAsLong(dataType, value, -1);
|
||||||
if(sleepLatency >=0 && sleepLatency <= Integer.MAX_VALUE)
|
if(sleepLatency >=0 && sleepLatency <= Integer.MAX_VALUE)
|
||||||
details.setSleepLatency((int) sleepLatency);
|
details.sleepLatency = (int) sleepLatency;
|
||||||
break;
|
break;
|
||||||
case 700013232:
|
case 700013232:
|
||||||
long sleepEfficiency = getValueAsLong(dataType, value, -1);
|
long sleepEfficiency = getValueAsLong(dataType, value, -1);
|
||||||
if(sleepEfficiency >=0 && sleepEfficiency <= Integer.MAX_VALUE)
|
if(sleepEfficiency >=0 && sleepEfficiency <= Integer.MAX_VALUE)
|
||||||
details.setSleepEfficiency((int) sleepEfficiency);
|
details.sleepEfficiency = (int) sleepEfficiency;
|
||||||
break;
|
break;
|
||||||
case 700013436:
|
case 700013436:
|
||||||
long minHeartrate = getValueAsLong(dataType, value, -1);
|
long minHeartRate = getValueAsLong(dataType, value, -1);
|
||||||
if(minHeartrate >= -1 && minHeartrate <= 255)
|
if(minHeartRate >= -1 && minHeartRate <= 255)
|
||||||
details.setMinHeartrate((int) minHeartrate);
|
details.minHeartRate = (int) minHeartRate;
|
||||||
break;
|
break;
|
||||||
case 700013502:
|
case 700013502:
|
||||||
long maxHeartrate = getValueAsLong(dataType, value, -1);
|
long maxHeartRate = getValueAsLong(dataType, value, -1);
|
||||||
if(maxHeartrate >=0 && maxHeartrate <= 255)
|
if(maxHeartRate >=0 && maxHeartRate <= 255)
|
||||||
details.setMaxHeartrate((int) maxHeartrate);
|
details.maxHeartRate = (int) maxHeartRate;
|
||||||
break;
|
break;
|
||||||
case 700013340:
|
case 700013340:
|
||||||
double minOxygenSaturation = getValueAsDouble(dataType, value, -1);
|
double minOxygenSaturation = getValueAsDouble(dataType, value, -1);
|
||||||
if(minOxygenSaturation >=0)
|
if(minOxygenSaturation >=0)
|
||||||
details.setMinOxygenSaturation((int) minOxygenSaturation);
|
details.minOxygenSaturation = minOxygenSaturation;
|
||||||
break;
|
break;
|
||||||
case 700013026:
|
case 700013026:
|
||||||
double maxOxygenSaturation = getValueAsDouble(dataType, value, -1);
|
double maxOxygenSaturation = getValueAsDouble(dataType, value, -1);
|
||||||
if(maxOxygenSaturation >=0)
|
if(maxOxygenSaturation >=0)
|
||||||
details.setMaxOxygenSaturation((int) maxOxygenSaturation);
|
details.maxOxygenSaturation = maxOxygenSaturation;
|
||||||
break;
|
break;
|
||||||
case 700013646:
|
case 700013646:
|
||||||
double minBreathrate = getValueAsDouble(dataType, value, -1);
|
long minBreathRate = getValueAsLong(dataType, value, -1);
|
||||||
if(minBreathrate >=0 && minBreathrate <= Integer.MAX_VALUE)
|
if(minBreathRate >=0 && minBreathRate <= Integer.MAX_VALUE)
|
||||||
details.setMinBreathrate((int) minBreathrate);
|
details.minBreathRate = (int) minBreathRate;
|
||||||
break;
|
break;
|
||||||
case 700013492:
|
case 700013492:
|
||||||
double maxBreathrate = getValueAsDouble(dataType, value, -1);
|
long maxBreathRate = getValueAsLong(dataType, value, -1);
|
||||||
if(maxBreathrate >=0 && maxBreathrate <= Integer.MAX_VALUE)
|
if(maxBreathRate >=0 && maxBreathRate <= Integer.MAX_VALUE)
|
||||||
details.setMaxBreathrate((int) maxBreathrate);
|
details.maxBreathRate = (int) maxBreathRate;
|
||||||
|
break;
|
||||||
|
case 700013824:
|
||||||
|
long hrvDayToBaseline = getValueAsLong(dataType, value, -1);
|
||||||
|
if(hrvDayToBaseline >=0 && hrvDayToBaseline <= 30)
|
||||||
|
details.hrvDayToBaseline = (int) hrvDayToBaseline;
|
||||||
|
break;
|
||||||
|
case 700013355:
|
||||||
|
long maxHrvBaseline = getValueAsLong(dataType, value, -1);
|
||||||
|
if(maxHrvBaseline >=0 && maxHrvBaseline <= 200)
|
||||||
|
details.maxHrvBaseline = (int) maxHrvBaseline;
|
||||||
|
break;
|
||||||
|
case 700013305:
|
||||||
|
long minHrvBaseline = getValueAsLong(dataType, value, -1);
|
||||||
|
if(minHrvBaseline >=0 && minHrvBaseline <= 200)
|
||||||
|
details.minHrvBaseline = (int) minHrvBaseline;
|
||||||
|
break;
|
||||||
|
case 700013878:
|
||||||
|
long avgHrv = getValueAsLong(dataType, value, -1);
|
||||||
|
if(avgHrv >=0 && avgHrv <= 200)
|
||||||
|
details.avgHrv = (int) avgHrv;
|
||||||
|
break;
|
||||||
|
case 700013236:
|
||||||
|
long breathRateDayToBaseline = getValueAsLong(dataType, value, -1);
|
||||||
|
if(breathRateDayToBaseline >= 0 && breathRateDayToBaseline <= 30)
|
||||||
|
details.breathRateDayToBaseline = (int) breathRateDayToBaseline;
|
||||||
|
break;
|
||||||
|
case 700013225:
|
||||||
|
long maxBreathRateBaseline = getValueAsLong(dataType, value, -1);
|
||||||
|
if(maxBreathRateBaseline >= 0 && maxBreathRateBaseline <= 80)
|
||||||
|
details.maxBreathRateBaseline = (int) maxBreathRateBaseline;
|
||||||
|
break;
|
||||||
|
case 700013839:
|
||||||
|
long minBreathRateBaseline = getValueAsLong(dataType, value, -1);
|
||||||
|
if(minBreathRateBaseline >= 0 && minBreathRateBaseline <= 80)
|
||||||
|
details.minBreathRateBaseline = (int) minBreathRateBaseline;
|
||||||
|
break;
|
||||||
|
case 700013886:
|
||||||
|
long avgBreathRate = getValueAsLong(dataType, value, -1);
|
||||||
|
if(avgBreathRate >= 0 && avgBreathRate <= 80)
|
||||||
|
details.avgBreathRate = (int) avgBreathRate;
|
||||||
|
break;
|
||||||
|
case 700013718:
|
||||||
|
long oxygenSaturationDayToBaseline = getValueAsLong(dataType, value, -1);
|
||||||
|
if(oxygenSaturationDayToBaseline >= 0 && oxygenSaturationDayToBaseline <= 30)
|
||||||
|
details.oxygenSaturationDayToBaseline = (int) oxygenSaturationDayToBaseline;
|
||||||
|
break;
|
||||||
|
case 700013227:
|
||||||
|
long maxOxygenSaturationBaseline = getValueAsLong(dataType, value, -1);
|
||||||
|
if(maxOxygenSaturationBaseline >= 0 && maxOxygenSaturationBaseline <= 100)
|
||||||
|
details.maxOxygenSaturationBaseline = (int) maxOxygenSaturationBaseline;
|
||||||
|
break;
|
||||||
|
case 700013633:
|
||||||
|
long minOxygenSaturationBaseline = getValueAsLong(dataType, value, -1);
|
||||||
|
if(minOxygenSaturationBaseline >= 0 && minOxygenSaturationBaseline <= 100)
|
||||||
|
details.minOxygenSaturationBaseline = (int) minOxygenSaturationBaseline;
|
||||||
|
break;
|
||||||
|
case 700013468:
|
||||||
|
long avgOxygenSaturation = getValueAsLong(dataType, value, -1);
|
||||||
|
if(avgOxygenSaturation >= 0 && avgOxygenSaturation <= 100)
|
||||||
|
details.avgOxygenSaturation = (int) avgOxygenSaturation;
|
||||||
|
break;
|
||||||
|
case 700013810:
|
||||||
|
long heartRateDayToBaseline = getValueAsLong(dataType, value, -1);
|
||||||
|
if(heartRateDayToBaseline >= 0 && heartRateDayToBaseline <= 30)
|
||||||
|
details.heartRateDayToBaseline = (int) heartRateDayToBaseline;
|
||||||
|
break;
|
||||||
|
case 700013841:
|
||||||
|
long maxHeartRateBaseline = getValueAsLong(dataType, value, -1);
|
||||||
|
if(maxHeartRateBaseline >= 0 && maxHeartRateBaseline <= 255)
|
||||||
|
details.maxHeartRateBaseline = (int) maxHeartRateBaseline;
|
||||||
|
break;
|
||||||
|
case 700013722:
|
||||||
|
long minHeartRateBaseline = getValueAsLong(dataType, value, -1);
|
||||||
|
if(minHeartRateBaseline >= 0 && minHeartRateBaseline <= 255)
|
||||||
|
details.minHeartRateBaseline = (int) minHeartRateBaseline;
|
||||||
|
break;
|
||||||
|
case 700013580:
|
||||||
|
long avgHeartRate = getValueAsLong(dataType, value, -1);
|
||||||
|
if(avgHeartRate >= 0 && avgHeartRate <= 255)
|
||||||
|
details.avgHeartRate = (int) avgHeartRate;
|
||||||
|
break;
|
||||||
|
case 700013759:
|
||||||
|
long rdi = getValueAsLong(dataType, value, -1);
|
||||||
|
if(rdi >= 0 && rdi <= 100)
|
||||||
|
details.rdi = (int) rdi;
|
||||||
|
break;
|
||||||
|
case 700013635:
|
||||||
|
long wakeCount = getValueAsLong(dataType, value, -1);
|
||||||
|
if(wakeCount >= 0)
|
||||||
|
details.wakeCount = (int) wakeCount;
|
||||||
|
break;
|
||||||
|
case 700013670:
|
||||||
|
long turnOverCount = getValueAsLong(dataType, value, -1);
|
||||||
|
if(turnOverCount >= 0)
|
||||||
|
details.turnOverCount = (int) turnOverCount;
|
||||||
|
break;
|
||||||
|
case 700013821:
|
||||||
|
long prepareSleepTime = getValueAsLong(dataType, value, -1);
|
||||||
|
if(prepareSleepTime >= 0)
|
||||||
|
details.prepareSleepTime = prepareSleepTime;
|
||||||
|
break;
|
||||||
|
case 700013925:
|
||||||
|
long wakeUpFeeling = getValueAsLong(dataType, value, -1);
|
||||||
|
if(wakeUpFeeling >= 0)
|
||||||
|
details.wakeUpFeeling = (int) wakeUpFeeling;
|
||||||
|
break;
|
||||||
|
case 700013697:
|
||||||
|
long sleepVersion = getValueAsLong(dataType, value, -1);
|
||||||
|
if(sleepVersion >= 0 && sleepVersion <= 100)
|
||||||
|
details.sleepVersion = (int) sleepVersion;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG.info("Unknown dictId: {}", dictId);
|
LOG.info("Unknown dictId: {}", dictId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SleepSummary parseTLVData(byte[] str) {
|
protected SleepSummary getNewData() {
|
||||||
SleepSummary details = new SleepSummary();
|
return new SleepSummary();
|
||||||
HuaweiTLV tlv = new HuaweiTLV().parse(str);
|
|
||||||
List<HuaweiTLV> tlvs = tlv.getAllContainerObjects();
|
|
||||||
for (HuaweiTLV tv : tlvs) {
|
|
||||||
List<HuaweiTLV> tlvs2 = tv.getAllContainerObjects();
|
|
||||||
for (HuaweiTLV tv2 : tlvs2) {
|
|
||||||
try {
|
|
||||||
int dictId = tv2.getAsInteger(0x03);
|
|
||||||
int dataType = tv2.getAsInteger(0x04);
|
|
||||||
byte[] value = tv2.getBytes(0x5);
|
|
||||||
fillSleepSummary(details, dictId, dataType, value);
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOG.error("Sleep dict sync: tag is missing", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return details;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static SleepSummary parseSleepDataSummary(HuaweiSequenceDataParser.SequenceFileData fileData, HuaweiSequenceDataParser.SequenceData data) {
|
|
||||||
// summary type 2 is TLV. TLV works only for fileType != 2 (or maybe only for 1)
|
|
||||||
// currently only data version 1 supported
|
|
||||||
if (data != null && data.getDataVersion() == 1 && data.getSummaryType() == 2 && fileData.getFileType() != 2) {
|
|
||||||
return parseTLVData(data.getSummary());
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void correctSummary(SleepSummary summary) {
|
public static void correctSummary(SleepSummary summary) {
|
||||||
if(summary.validData == -1) {
|
if(summary.validData == -1) {
|
||||||
summary.setBedTime(0);
|
summary.bedTime = 0;
|
||||||
summary.setRisingTime(0);
|
summary.risingTime = 0;
|
||||||
summary.setSleepScore(-1);
|
summary.sleepScore = -1;
|
||||||
summary.setSleepDataQuality(-1);
|
summary.sleepDataQuality = -1;
|
||||||
summary.setDeepPart(-1);
|
summary.deepPart = -1;
|
||||||
summary.setSnoreFreq(-1);
|
summary.snoreFreq = -1;
|
||||||
summary.setSleepEfficiency(-1);
|
summary.sleepEfficiency = -1;
|
||||||
summary.setSleepLatency(-1);
|
summary.sleepLatency = -1;
|
||||||
|
summary.prepareSleepTime = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+41
-21
@@ -74,7 +74,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiDictTypes;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiGpsParser;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiGpsParser;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiSampleProvider;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiSampleProvider;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiSequenceDataParser;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiSequenceDataFileParser;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiSleepStageSampleProvider;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiSleepStageSampleProvider;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiSleepStatsSampleProvider;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiSleepStatsSampleProvider;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiStressParser;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiStressParser;
|
||||||
@@ -2933,16 +2933,17 @@ public class HuaweiSupportProvider {
|
|||||||
new HuaweiFileDownloadManager.FileDownloadCallback() {
|
new HuaweiFileDownloadManager.FileDownloadCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void downloadComplete(HuaweiFileDownloadManager.FileRequest fileRequest) {
|
public void downloadComplete(HuaweiFileDownloadManager.FileRequest fileRequest) {
|
||||||
HuaweiSequenceDataParser.SequenceFileData sequenceFileData = HuaweiSequenceDataParser.parseSequenceFileData(fileRequest.getData());
|
HuaweiSequenceDataFileParser.SequenceFileData sequenceFileData = HuaweiSequenceDataFileParser.parseSequenceFileData(fileRequest.getData());
|
||||||
LOG.info("SLEEP File data: {}", sequenceFileData);
|
LOG.info("SLEEP File data: {}", sequenceFileData);
|
||||||
|
|
||||||
if (sequenceFileData != null) {
|
if (sequenceFileData != null) {
|
||||||
final List<HuaweiSleepStatsSample> sleepStatsSamples = new ArrayList<>();
|
final List<HuaweiSleepStatsSample> sleepStatsSamples = new ArrayList<>();
|
||||||
final List<HuaweiSleepStageSample> sleepStageSamples = new ArrayList<>();
|
final List<HuaweiSleepStageSample> sleepStageSamples = new ArrayList<>();
|
||||||
|
|
||||||
for (HuaweiSequenceDataParser.SequenceData sd : sequenceFileData.getSequenceDataList()) {
|
for (HuaweiSequenceDataFileParser.SequenceData sd : sequenceFileData.getSequenceDataList()) {
|
||||||
LOG.info("SLEEP SequenceData: {}", sd);
|
LOG.info("SLEEP SequenceData: {}", sd);
|
||||||
HuaweiTrueSleepSequenceDataParser.SleepSummary sleepDataSummary = HuaweiTrueSleepSequenceDataParser.parseSleepDataSummary(sequenceFileData, sd);
|
HuaweiTrueSleepSequenceDataParser sleepParser = new HuaweiTrueSleepSequenceDataParser();
|
||||||
|
HuaweiTrueSleepSequenceDataParser.SleepSummary sleepDataSummary = sleepParser.parseData(sequenceFileData, sd);
|
||||||
if (sleepDataSummary == null) {
|
if (sleepDataSummary == null) {
|
||||||
LOG.warn("SLEEP DataSummary is null");
|
LOG.warn("SLEEP DataSummary is null");
|
||||||
continue;
|
continue;
|
||||||
@@ -2953,25 +2954,44 @@ public class HuaweiSupportProvider {
|
|||||||
LOG.info("SLEEP DataSummary: {}", sleepDataSummary);
|
LOG.info("SLEEP DataSummary: {}", sleepDataSummary);
|
||||||
|
|
||||||
HuaweiSleepStatsSample sleepStat = new HuaweiSleepStatsSample();
|
HuaweiSleepStatsSample sleepStat = new HuaweiSleepStatsSample();
|
||||||
sleepStat.setTimestamp(sleepDataSummary.getFallAsleepTime() * 1000L);
|
sleepStat.setTimestamp(sleepDataSummary.fallAsleepTime * 1000L);
|
||||||
sleepStat.setSleepScore(sleepDataSummary.getSleepScore());
|
sleepStat.setSleepScore(sleepDataSummary.sleepScore);
|
||||||
sleepStat.setBedTime(sleepDataSummary.getBedTime() * 1000L);
|
sleepStat.setBedTime(sleepDataSummary.bedTime * 1000L);
|
||||||
sleepStat.setRisingTime(sleepDataSummary.getRisingTime() * 1000L);
|
sleepStat.setRisingTime(sleepDataSummary.risingTime * 1000L);
|
||||||
sleepStat.setWakeupTime(sleepDataSummary.getWakeupTime() * 1000L);
|
sleepStat.setWakeupTime(sleepDataSummary.wakeupTime * 1000L);
|
||||||
sleepStat.setSleepDataQuality(sleepDataSummary.getSleepDataQuality());
|
sleepStat.setSleepDataQuality(sleepDataSummary.sleepDataQuality);
|
||||||
sleepStat.setDeepPart(sleepDataSummary.getDeepPart());
|
sleepStat.setDeepPart(sleepDataSummary.deepPart);
|
||||||
sleepStat.setSnoreFreq(sleepDataSummary.getSnoreFreq());
|
sleepStat.setSnoreFreq(sleepDataSummary.snoreFreq);
|
||||||
sleepStat.setSleepLatency(sleepDataSummary.getSleepLatency());
|
sleepStat.setSleepLatency(sleepDataSummary.sleepLatency);
|
||||||
sleepStat.setSleepEfficiency(sleepDataSummary.getSleepEfficiency());
|
sleepStat.setSleepEfficiency(sleepDataSummary.sleepEfficiency);
|
||||||
sleepStat.setMinHeartRate(sleepDataSummary.getMinHeartrate());
|
sleepStat.setMinHeartRate(sleepDataSummary.minHeartRate);
|
||||||
sleepStat.setMaxHeartRate(sleepDataSummary.getMaxHeartrate());
|
sleepStat.setMaxHeartRate(sleepDataSummary.maxHeartRate);
|
||||||
sleepStat.setMinOxygenSaturation(sleepDataSummary.getMinOxygenSaturation());
|
sleepStat.setMinOxygenSaturation(sleepDataSummary.minOxygenSaturation);
|
||||||
sleepStat.setMaxOxygenSaturation(sleepDataSummary.getMaxOxygenSaturation());
|
sleepStat.setMaxOxygenSaturation(sleepDataSummary.maxOxygenSaturation);
|
||||||
sleepStat.setMinBreathRate(sleepDataSummary.getMinBreathrate());
|
sleepStat.setMinBreathRate(sleepDataSummary.minBreathRate);
|
||||||
sleepStat.setMaxBreathRate(sleepDataSummary.getMaxBreathrate());
|
sleepStat.setMaxBreathRate(sleepDataSummary.maxBreathRate);
|
||||||
|
//TODO:
|
||||||
|
// validData -- not needed
|
||||||
|
// hrvDayToBaseline
|
||||||
|
// maxHrvBaseline
|
||||||
|
// minHrvBaseline
|
||||||
|
// avgHrv
|
||||||
|
// breathRateDayToBaseline
|
||||||
|
// maxBreathRateBaseline
|
||||||
|
// minBreathRateBaseline
|
||||||
|
// avgBreathRate
|
||||||
|
// oxygenSaturationDayToBaseline
|
||||||
|
// maxOxygenSaturationBaseline
|
||||||
|
// minOxygenSaturationBaseline
|
||||||
|
// avgOxygenSaturation
|
||||||
|
// heartRateDayToBaseline
|
||||||
|
// maxHeartRateBaseline
|
||||||
|
// minHeartRateBaseline
|
||||||
|
// avgHeartRate
|
||||||
|
// rdi
|
||||||
sleepStatsSamples.add(sleepStat);
|
sleepStatsSamples.add(sleepStat);
|
||||||
|
|
||||||
long time = HuaweiTrueSleepSequenceDataParser.getTime(sleepDataSummary.getFallAsleepTime(), sleepDataSummary.getBedTime(), sleepDataSummary.getValidData(), getHuaweiCoordinator().supportsBedTime());
|
long time = HuaweiTrueSleepSequenceDataParser.getTime(sleepDataSummary.fallAsleepTime, sleepDataSummary.bedTime, sleepDataSummary.validData, getHuaweiCoordinator().supportsBedTime());
|
||||||
LOG.info("SLEEP Time: {}", time);
|
LOG.info("SLEEP Time: {}", time);
|
||||||
List<HuaweiTrueSleepSequenceDataParser.SleepStage> stages = HuaweiTrueSleepSequenceDataParser.parseSleepDetails(sd.getDetails(), time);
|
List<HuaweiTrueSleepSequenceDataParser.SleepStage> stages = HuaweiTrueSleepSequenceDataParser.parseSleepDetails(sd.getDetails(), time);
|
||||||
LOG.info("SLEEP Stages: {}", stages);
|
LOG.info("SLEEP Stages: {}", stages);
|
||||||
|
|||||||
Reference in New Issue
Block a user