mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2026-07-31 07:44:24 +02:00
Huawei: refactoring dyct sync. Split to classes
This commit is contained in:
+6
@@ -1028,6 +1028,12 @@ public class HuaweiCoordinator {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean supportsAltitude() {
|
||||
if (supportsExpandCapability())
|
||||
return supportsExpandCapability(72);
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean supportsArterialStiffnessDetection() {
|
||||
if (supportsExpandCapability())
|
||||
return supportsExpandCapability(75);
|
||||
|
||||
-17
@@ -17,27 +17,10 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.devices.huawei;
|
||||
|
||||
public class HuaweiDictTypes {
|
||||
public static final int BLOOD_PRESSURE_CLASS = 10002;
|
||||
|
||||
public static final int BODY_TEMPERATURE_CLASS = 400011;
|
||||
|
||||
public static final int SKIN_TEMPERATURE_CLASS = 400012;
|
||||
public static final int SKIN_TEMPERATURE_VALUE = 400012430;
|
||||
|
||||
public static final int SLEEP_DETAILS_CLASS = 700013;
|
||||
|
||||
public static final int ARRHYTHMIA_CLASS = 700004;
|
||||
|
||||
public static final int HRV_CLASS = 500044;
|
||||
public static final int HRV_RMSSD_VALUE = 500044831;
|
||||
|
||||
public static final int EMOTION_CLASS = 500031;
|
||||
public static final int EMOTION_STATUS_VALUE = 500031195;
|
||||
public static final int EMOTION_VALENCE_CHARACTER_VALUE = 500031347;
|
||||
public static final int EMOTION_ORIGIN_STATUS_VALUE = 500031160;
|
||||
public static final int EMOTION_AROUSAL_CHARACTER_VALUE = 500031842;
|
||||
|
||||
public static final int SLEEP_APNEA_CLASS = 500002;
|
||||
public static final int SLEEP_APNEA_LEVEL_VALUE = 500002847;
|
||||
|
||||
}
|
||||
|
||||
+43
-240
@@ -43,8 +43,6 @@ import java.io.File;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -74,22 +72,17 @@ import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiCoordinatorSupp
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiCrypto;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiDictTypes;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiEcgFileParser;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiEmotionsSampleProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiGpsParser;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiHrvValueSampleProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPdrParser;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiSampleProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiSequenceDataFileParser;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiSleepApneaSampleProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiSleepStageSampleProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiSleepStatsSampleProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiStressParser;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiStressSampleProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiTemperatureSampleProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiTruSleepParser;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiTrueSleepSequenceDataParser;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiUtil;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.CameraRemote;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.GpsAndTime;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Notifications;
|
||||
@@ -104,13 +97,9 @@ import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiEcgDataSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiEcgDataSampleDao;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiEcgSummarySample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiEcgSummarySampleDao;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiEmotionsSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiHrvValueSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiSleepApneaSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiSleepStageSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiSleepStatsSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiStressSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiTemperatureSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutDataSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutDataSampleDao;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutPaceSample;
|
||||
@@ -149,7 +138,6 @@ import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NavigationInfoSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.RecordedDataTypes;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.TemperatureSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.datasync.HuaweiDataSyncNotificationPictures;
|
||||
@@ -168,6 +156,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p.HuaweiP2P
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p.HuaweiP2PDirection;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p.HuaweiP2PTrackService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p.HuaweiP2PDataDictionarySyncService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p.dictionarysync.HuaweiDictionarySyncInterface;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.AcceptAgreementsRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetAppInfoParams;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetContactsCount;
|
||||
@@ -1548,7 +1537,7 @@ public class HuaweiSupportProvider {
|
||||
stepStart = 946684800;
|
||||
|
||||
// To avoid of downloading of very big file and OOM error set ECG start time to step start time.
|
||||
if(ecgStart == 0)
|
||||
if (ecgStart == 0)
|
||||
ecgStart = stepStart;
|
||||
}
|
||||
final GetSleepDataCountRequest getSleepDataCountRequest;
|
||||
@@ -1629,225 +1618,41 @@ public class HuaweiSupportProvider {
|
||||
|
||||
private void fetchActivityDataP2P() {
|
||||
HuaweiP2PDataDictionarySyncService P2PSyncService = HuaweiP2PDataDictionarySyncService.getRegisteredInstance(huaweiP2PManager);
|
||||
|
||||
if (P2PSyncService != null) {
|
||||
List<Integer> list = P2PSyncService.checkSupported(this.getHuaweiCoordinator(), Arrays.asList(
|
||||
HuaweiDictTypes.SKIN_TEMPERATURE_CLASS,
|
||||
HuaweiDictTypes.HRV_CLASS,
|
||||
HuaweiDictTypes.EMOTION_CLASS,
|
||||
HuaweiDictTypes.SLEEP_APNEA_CLASS));
|
||||
if (!list.isEmpty()) {
|
||||
syncState.setP2pSync(true);
|
||||
P2PSyncService.startSync(list, new HuaweiP2PDataDictionarySyncService.DictionarySyncCallback() {
|
||||
@Override
|
||||
public long onGetLastDataSyncTimestamp(int dictClass) {
|
||||
LOG.info("DictionarySyncCallback onGetLastDataDictLastTimestamp: {}", dictClass);
|
||||
if (dictClass == HuaweiDictTypes.SKIN_TEMPERATURE_CLASS) {
|
||||
try (DBHandler db = GBApplication.acquireDB()) {
|
||||
HuaweiTemperatureSampleProvider sleepStatsSampleProvider = new HuaweiTemperatureSampleProvider(gbDevice, db.getDaoSession());
|
||||
return sleepStatsSampleProvider.getLastFetchTimestamp();
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Exception for getting skin temperature start time", e);
|
||||
}
|
||||
return 0;
|
||||
} else if (dictClass == HuaweiDictTypes.HRV_CLASS) {
|
||||
try (DBHandler db = GBApplication.acquireDB()) {
|
||||
HuaweiHrvValueSampleProvider hrvStatsSampleProvider = new HuaweiHrvValueSampleProvider(gbDevice, db.getDaoSession());
|
||||
return hrvStatsSampleProvider.getLastFetchTimestamp();
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Exception for getting HRV start time", e);
|
||||
}
|
||||
return 0;
|
||||
} else if (dictClass == HuaweiDictTypes.EMOTION_CLASS) {
|
||||
try (DBHandler db = GBApplication.acquireDB()) {
|
||||
HuaweiEmotionsSampleProvider emotionsStatsSampleProvider = new HuaweiEmotionsSampleProvider(gbDevice, db.getDaoSession());
|
||||
return emotionsStatsSampleProvider.getLastFetchTimestamp();
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Exception for getting emotion start time", e);
|
||||
}
|
||||
return 0;
|
||||
} else if (dictClass == HuaweiDictTypes.SLEEP_APNEA_CLASS) {
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onData(int dictClass, List<HuaweiP2PDataDictionarySyncService.DictData> dictData) {
|
||||
LOG.info("DictionarySyncCallback onData: {}", dictClass);
|
||||
if (dictClass == HuaweiDictTypes.SKIN_TEMPERATURE_CLASS) {
|
||||
List<HuaweiTemperatureSample> temperatureSamples = new ArrayList<>();
|
||||
for (HuaweiP2PDataDictionarySyncService.DictData dt : dictData) {
|
||||
long timestamp = dt.getStartTimestamp();
|
||||
long lastTime = Math.max(dt.getEndTimestamp(), dt.getModifyTimestamp());
|
||||
Float temperature = null;
|
||||
for (HuaweiP2PDataDictionarySyncService.DictData.DictDataValue val : dt.getData()) {
|
||||
if (val.getTag() != 10) {
|
||||
LOG.info("skin temperature unexpected tag: {}", val.getTag());
|
||||
continue;
|
||||
}
|
||||
if (val.getDataType() == HuaweiDictTypes.SKIN_TEMPERATURE_VALUE) {
|
||||
double value = HuaweiUtil.convBytes2Double(val.getValue());
|
||||
if (value >= 20 && value <= 42) {
|
||||
temperature = (float) value;
|
||||
}
|
||||
} else {
|
||||
LOG.info("skin temperature unknown data type: {}", val.getDataType());
|
||||
}
|
||||
}
|
||||
if(temperature != null) {
|
||||
HuaweiTemperatureSample sample = new HuaweiTemperatureSample();
|
||||
sample.setTimestamp(timestamp);
|
||||
sample.setLastTimestamp(lastTime);
|
||||
sample.setTemperature(temperature);
|
||||
sample.setTemperatureType(TemperatureSample.TYPE_SKIN);
|
||||
sample.setTemperatureLocation(TemperatureSample.LOCATION_WRIST);
|
||||
temperatureSamples.add(sample);
|
||||
}
|
||||
}
|
||||
try (DBHandler db = GBApplication.acquireDB()) {
|
||||
final DaoSession session = db.getDaoSession();
|
||||
new HuaweiTemperatureSampleProvider(gbDevice, session).persistForDevice(context, gbDevice, temperatureSamples);
|
||||
} catch (Exception e) {
|
||||
LOG.error("Cannot save skin temperature samples, continue");
|
||||
}
|
||||
} else if (dictClass == HuaweiDictTypes.HRV_CLASS) {
|
||||
List<HuaweiHrvValueSample> hrvSamples = new ArrayList<>();
|
||||
for (HuaweiP2PDataDictionarySyncService.DictData dt : dictData) {
|
||||
long timestamp = dt.getStartTimestamp();
|
||||
long lastTime = Math.max(dt.getEndTimestamp(), dt.getModifyTimestamp());
|
||||
Integer rmssd = null;
|
||||
for (HuaweiP2PDataDictionarySyncService.DictData.DictDataValue val : dt.getData()) {
|
||||
if (val.getTag() != 10) {
|
||||
LOG.info("HRV unexpected tag: {}", val.getTag());
|
||||
continue;
|
||||
}
|
||||
if (val.getDataType() == HuaweiDictTypes.HRV_RMSSD_VALUE) {
|
||||
double value = HuaweiUtil.convBytes2Double(val.getValue());
|
||||
if (value >= 0 && value <= 200) {
|
||||
rmssd = (int) value;
|
||||
}
|
||||
} else {
|
||||
LOG.info("HRV unknown data type: {}", val.getDataType());
|
||||
}
|
||||
}
|
||||
if(rmssd != null) {
|
||||
HuaweiHrvValueSample sample = new HuaweiHrvValueSample();
|
||||
sample.setTimestamp(timestamp);
|
||||
sample.setLastTimestamp(lastTime);
|
||||
sample.setValue(rmssd);
|
||||
hrvSamples.add(sample);
|
||||
}
|
||||
}
|
||||
try (DBHandler db = GBApplication.acquireDB()) {
|
||||
final DaoSession session = db.getDaoSession();
|
||||
new HuaweiHrvValueSampleProvider(gbDevice, session).persistForDevice(context, gbDevice, hrvSamples);
|
||||
} catch (Exception e) {
|
||||
LOG.error("Cannot save HRV samples, continue");
|
||||
}
|
||||
} else if (dictClass == HuaweiDictTypes.EMOTION_CLASS) {
|
||||
List<HuaweiEmotionsSample> emotionsSamples = new ArrayList<>();
|
||||
for (HuaweiP2PDataDictionarySyncService.DictData dt : dictData) {
|
||||
long timestamp = dt.getStartTimestamp();
|
||||
long lastTime = Math.max(dt.getEndTimestamp(), dt.getModifyTimestamp());
|
||||
Integer status = null;
|
||||
Double valenceCharacter = null;
|
||||
Integer originStatus = null;
|
||||
Double arousalCharacter = null;
|
||||
for (HuaweiP2PDataDictionarySyncService.DictData.DictDataValue val : dt.getData()) {
|
||||
if (val.getTag() != 10) {
|
||||
LOG.info("emotions unexpected tag: {}", val.getTag());
|
||||
continue;
|
||||
}
|
||||
if (val.getDataType() == HuaweiDictTypes.EMOTION_STATUS_VALUE) {
|
||||
double value = HuaweiUtil.convBytes2Double(val.getValue());
|
||||
if (value >= 0 && value < 100) {
|
||||
status = (int) value;
|
||||
}
|
||||
} else if (val.getDataType() == HuaweiDictTypes.EMOTION_VALENCE_CHARACTER_VALUE) {
|
||||
double value = HuaweiUtil.convBytes2Double(val.getValue());
|
||||
if (value >= 0 && value <= 100) {
|
||||
valenceCharacter = value;
|
||||
}
|
||||
} else if (val.getDataType() == HuaweiDictTypes.EMOTION_ORIGIN_STATUS_VALUE) {
|
||||
double value = HuaweiUtil.convBytes2Double(val.getValue());
|
||||
if (value >= 0 && value < 100) {
|
||||
originStatus = (int) value;
|
||||
}
|
||||
} else if (val.getDataType() == HuaweiDictTypes.EMOTION_AROUSAL_CHARACTER_VALUE) {
|
||||
double value = HuaweiUtil.convBytes2Double(val.getValue());
|
||||
if (value >= 0 && value <= 100) {
|
||||
arousalCharacter = value;
|
||||
}
|
||||
} else {
|
||||
LOG.info("emotions unknown data type: {}", val.getDataType());
|
||||
}
|
||||
}
|
||||
if (status != null || valenceCharacter != null || originStatus != null || arousalCharacter != null) {
|
||||
HuaweiEmotionsSample sample = new HuaweiEmotionsSample();
|
||||
sample.setTimestamp(timestamp);
|
||||
sample.setLastTimestamp(lastTime);
|
||||
sample.setStatus(status == null ? 0 : status);
|
||||
sample.setValenceCharacter(valenceCharacter);
|
||||
sample.setOriginStatus(originStatus);
|
||||
sample.setArousalCharacter(arousalCharacter);
|
||||
emotionsSamples.add(sample);
|
||||
}
|
||||
}
|
||||
try (DBHandler db = GBApplication.acquireDB()) {
|
||||
final DaoSession session = db.getDaoSession();
|
||||
new HuaweiEmotionsSampleProvider(gbDevice, session).persistForDevice(context, gbDevice, emotionsSamples);
|
||||
} catch (Exception e) {
|
||||
LOG.error("Cannot save emotions samples, continue");
|
||||
}
|
||||
} else if (dictClass == HuaweiDictTypes.SLEEP_APNEA_CLASS) {
|
||||
List<HuaweiSleepApneaSample> sleepApneaSamples = new ArrayList<>();
|
||||
for (HuaweiP2PDataDictionarySyncService.DictData dt : dictData) {
|
||||
long timestamp = dt.getStartTimestamp();
|
||||
long lastTime = Math.max(dt.getEndTimestamp(), dt.getModifyTimestamp());
|
||||
Integer level = null;
|
||||
for (HuaweiP2PDataDictionarySyncService.DictData.DictDataValue val : dt.getData()) {
|
||||
if (val.getTag() == 10) {
|
||||
if (val.getDataType() == HuaweiDictTypes.SLEEP_APNEA_LEVEL_VALUE) {
|
||||
int value = (int) HuaweiUtil.convBytes2Double(val.getValue());
|
||||
if (value == 1 || value == 2 || value == 3 || value == 4) {
|
||||
level = value;
|
||||
} else {
|
||||
LOG.info("sleep apnea invalid value: {}", value);
|
||||
}
|
||||
} else {
|
||||
LOG.info("sleep apnea unknown data type: {}", val.getDataType());
|
||||
}
|
||||
} else {
|
||||
LOG.info("sleep apnea unsupported tag: {}", val.getTag());
|
||||
}
|
||||
}
|
||||
if(level != null) {
|
||||
LOG.info("APNEA timestamp: {} lastTime: {} level: {}", new Date(timestamp), lastTime, level);
|
||||
HuaweiSleepApneaSample sample = new HuaweiSleepApneaSample();
|
||||
sample.setTimestamp(timestamp);
|
||||
sample.setLastTimestamp(lastTime);
|
||||
sample.setLevel(level);
|
||||
sleepApneaSamples.add(sample);
|
||||
}
|
||||
}
|
||||
try (DBHandler db = GBApplication.acquireDB()) {
|
||||
final DaoSession session = db.getDaoSession();
|
||||
new HuaweiSleepApneaSampleProvider(gbDevice, session).persistForDevice(context, gbDevice, sleepApneaSamples);
|
||||
} catch (Exception e) {
|
||||
LOG.error("Cannot save sleep apnea samples, continue");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete(boolean complete) {
|
||||
LOG.info("Sync P2P Data complete");
|
||||
syncState.setP2pSync(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (P2PSyncService == null) {
|
||||
return;
|
||||
}
|
||||
Map<Integer, HuaweiDictionarySyncInterface> sup = P2PSyncService.getAllSupported(this.getHuaweiCoordinator());
|
||||
if (sup.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
syncState.setP2pSync(true);
|
||||
List<Integer> dictClasses = new ArrayList<>(sup.keySet());
|
||||
P2PSyncService.startSync(dictClasses, new HuaweiP2PDataDictionarySyncService.DictionarySyncCallback() {
|
||||
@Override
|
||||
public long onGetLastDataSyncTimestamp(int dictClass) {
|
||||
LOG.info("DictionarySyncCallback onGetLastDataDictLastTimestamp: {}", dictClass);
|
||||
HuaweiDictionarySyncInterface cur = sup.get(dictClass);
|
||||
if(cur == null) {
|
||||
return -1;
|
||||
}
|
||||
return cur.getLastDataSyncTimestamp(gbDevice);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onData(int dictClass, List<HuaweiP2PDataDictionarySyncService.DictData> dictData) {
|
||||
LOG.info("DictionarySyncCallback onData: {}", dictClass);
|
||||
HuaweiDictionarySyncInterface cur = sup.get(dictClass);
|
||||
if(cur != null) {
|
||||
cur.handleData(context, gbDevice, dictData);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete(boolean complete) {
|
||||
LOG.info("Sync P2P Data complete");
|
||||
syncState.setP2pSync(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void fetchWorkoutData() {
|
||||
@@ -2036,15 +1841,15 @@ public class HuaweiSupportProvider {
|
||||
} else if (
|
||||
callSpec.command == CallSpec.CALL_ACCEPT ||
|
||||
callSpec.command == CallSpec.CALL_START) {
|
||||
byte type = getHuaweiCoordinator().supportsNotificationsStartCall()?Notifications.NotificationType.startCall:Notifications.NotificationType.stopNotification;
|
||||
byte type = getHuaweiCoordinator().supportsNotificationsStartCall() ? Notifications.NotificationType.startCall : Notifications.NotificationType.stopNotification;
|
||||
StopNotificationRequest stopNotificationRequest = new StopNotificationRequest(this, type);
|
||||
try {
|
||||
stopNotificationRequest.doPerform();
|
||||
} catch (IOException e) {
|
||||
LOG.error("Failed to send stop call notification", e);
|
||||
}
|
||||
}else if (
|
||||
callSpec.command == CallSpec.CALL_REJECT ||
|
||||
} else if (
|
||||
callSpec.command == CallSpec.CALL_REJECT ||
|
||||
callSpec.command == CallSpec.CALL_END
|
||||
) {
|
||||
StopNotificationRequest stopNotificationRequest = new StopNotificationRequest(this, Notifications.NotificationType.stopNotification);
|
||||
@@ -2189,10 +1994,10 @@ public class HuaweiSupportProvider {
|
||||
.buildDelete();
|
||||
tableDeleteQuery.executeDeleteWithoutDetachingEntities();
|
||||
|
||||
int sampleRate = (int) (data.getEcgData().size() / ((data.getEndTime() - data.getStartTime())/ 1000));
|
||||
int sampleRate = (int) (data.getEcgData().size() / ((data.getEndTime() - data.getStartTime()) / 1000));
|
||||
int delta = 0;
|
||||
List<HuaweiEcgDataSample> res = new ArrayList<>();
|
||||
for (Float d: data.getEcgData()) {
|
||||
for (Float d : data.getEcgData()) {
|
||||
HuaweiEcgDataSample dataSample = new HuaweiEcgDataSample(summarySample.getEcgId(), delta, d);
|
||||
res.add(dataSample);
|
||||
delta += sampleRate;
|
||||
@@ -3306,8 +3111,6 @@ public class HuaweiSupportProvider {
|
||||
}
|
||||
|
||||
public boolean downloadTruSleepData(int start, int end) {
|
||||
|
||||
|
||||
// We only get the data if TruSleep is supported
|
||||
if (!getHuaweiCoordinator().supportsTruSleep())
|
||||
return false;
|
||||
@@ -3427,7 +3230,7 @@ public class HuaweiSupportProvider {
|
||||
}
|
||||
LOG.info("ECG result: {}", results);
|
||||
if (results != null && !results.getEcgDataList().isEmpty()) {
|
||||
for(HuaweiEcgFileParser.EcgData dt: results.getEcgDataList()) {
|
||||
for (HuaweiEcgFileParser.EcgData dt : results.getEcgDataList()) {
|
||||
addEcgData(dt);
|
||||
}
|
||||
}
|
||||
@@ -3673,7 +3476,7 @@ public class HuaweiSupportProvider {
|
||||
public void onSetNavigationInfo(NavigationInfoSpec navigationInfoSpec) {
|
||||
LOG.info("navigation: {}", navigationInfoSpec);
|
||||
HuaweiP2PDirection nav = HuaweiP2PDirection.getRegisteredInstance(huaweiP2PManager);
|
||||
if(nav != null) {
|
||||
if (nav != null) {
|
||||
nav.updateInstruction(navigationInfoSpec.distanceToTurn, HuaweiP2PDirection.actionToIconId(navigationInfoSpec.nextAction), navigationInfoSpec.instruction);
|
||||
}
|
||||
}
|
||||
|
||||
+52
-37
@@ -29,10 +29,18 @@ import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiDictTypes;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiTLV;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiP2PManager;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p.dictionarysync.HuaweiDictionarySyncAltitude;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p.dictionarysync.HuaweiDictionarySyncArterialStiffness;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p.dictionarysync.HuaweiDictionarySyncBloodPressure;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p.dictionarysync.HuaweiDictionarySyncEmotion;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p.dictionarysync.HuaweiDictionarySyncHRV;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p.dictionarysync.HuaweiDictionarySyncInterface;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p.dictionarysync.HuaweiDictionarySyncLakeLouiseAMS;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p.dictionarysync.HuaweiDictionarySyncSkinTemperature;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p.dictionarysync.HuaweiDictionarySyncSleepApnea;
|
||||
|
||||
public class HuaweiP2PDataDictionarySyncService extends HuaweiBaseP2PService {
|
||||
private final Logger LOG = LoggerFactory.getLogger(HuaweiP2PDataDictionarySyncService.class);
|
||||
@@ -46,7 +54,9 @@ public class HuaweiP2PDataDictionarySyncService extends HuaweiBaseP2PService {
|
||||
|
||||
public interface DictionarySyncCallback {
|
||||
long onGetLastDataSyncTimestamp(int dictClass);
|
||||
|
||||
void onData(int dictClass, List<HuaweiP2PDataDictionarySyncService.DictData> dictData);
|
||||
|
||||
void onComplete(boolean complete);
|
||||
}
|
||||
|
||||
@@ -79,33 +89,38 @@ public class HuaweiP2PDataDictionarySyncService extends HuaweiBaseP2PService {
|
||||
(byte) value};
|
||||
}
|
||||
|
||||
public List<Integer> checkSupported(HuaweiCoordinator coordinator, List<Integer> list) {
|
||||
List<Integer> result = new ArrayList<>();
|
||||
private List<HuaweiDictionarySyncInterface> getSyncHandlers() {
|
||||
List<HuaweiDictionarySyncInterface> ret = new ArrayList<>();
|
||||
ret.add(new HuaweiDictionarySyncSkinTemperature());
|
||||
ret.add(new HuaweiDictionarySyncHRV());
|
||||
ret.add(new HuaweiDictionarySyncEmotion());
|
||||
ret.add(new HuaweiDictionarySyncSleepApnea());
|
||||
ret.add(new HuaweiDictionarySyncArterialStiffness());
|
||||
ret.add(new HuaweiDictionarySyncAltitude());
|
||||
ret.add(new HuaweiDictionarySyncBloodPressure());
|
||||
ret.add(new HuaweiDictionarySyncLakeLouiseAMS());
|
||||
return ret;
|
||||
}
|
||||
|
||||
for(Integer cl: list) {
|
||||
if((cl == HuaweiDictTypes.BODY_TEMPERATURE_CLASS || cl == HuaweiDictTypes.SKIN_TEMPERATURE_CLASS) && coordinator.supportsTemperature()) {
|
||||
result.add(cl);
|
||||
} else if(cl == HuaweiDictTypes.BLOOD_PRESSURE_CLASS && coordinator.supportsBloodPressure()) {
|
||||
result.add(cl);
|
||||
} else if(cl == HuaweiDictTypes.HRV_CLASS && coordinator.supportsHRV()) {
|
||||
result.add(cl);
|
||||
} else if(cl == HuaweiDictTypes.EMOTION_CLASS && coordinator.supportsEmotion()) {
|
||||
result.add(cl);
|
||||
} else if(cl == HuaweiDictTypes.SLEEP_APNEA_CLASS && coordinator.supportsSleepApnea()) {
|
||||
result.add(cl);
|
||||
public Map<Integer, HuaweiDictionarySyncInterface> getAllSupported(HuaweiCoordinator coordinator) {
|
||||
List<HuaweiDictionarySyncInterface> handlers = getSyncHandlers();
|
||||
Map<Integer, HuaweiDictionarySyncInterface> ret = new HashMap<>();
|
||||
for(HuaweiDictionarySyncInterface i: handlers) {
|
||||
if(i.supports(coordinator)) {
|
||||
ret.put(i.getDataClass(), i);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void startSync(List<Integer> dictClasses, DictionarySyncCallback callback) {
|
||||
LOG.info("P2PDataDictionarySyncService startSync {}", dictClasses);
|
||||
if(callback == null) {
|
||||
if (callback == null) {
|
||||
LOG.error("P2PDataDictionarySyncService startSync callback is null");
|
||||
return;
|
||||
}
|
||||
classesToSync = dictClasses;
|
||||
if(classesToSync.isEmpty()) {
|
||||
if (classesToSync.isEmpty()) {
|
||||
callback.onComplete(false);
|
||||
return;
|
||||
}
|
||||
@@ -115,7 +130,7 @@ public class HuaweiP2PDataDictionarySyncService extends HuaweiBaseP2PService {
|
||||
private void sendSyncRequest(int dictClass, long startTime, DictionarySyncCallback callback) {
|
||||
|
||||
LOG.info("P2PDataDictionarySyncService class {}", dictClass);
|
||||
if(callback == null) {
|
||||
if (callback == null) {
|
||||
LOG.error("P2PDataDictionarySyncService sendSyncRequest callback is null");
|
||||
return;
|
||||
}
|
||||
@@ -126,21 +141,21 @@ public class HuaweiP2PDataDictionarySyncService extends HuaweiBaseP2PService {
|
||||
return;
|
||||
}
|
||||
|
||||
if(currentRequests.containsKey(dictClass)) {
|
||||
if (currentRequests.containsKey(dictClass)) {
|
||||
LOG.info("P2PDataDictionarySyncService current class in progress");
|
||||
callback.onComplete(false);
|
||||
return;
|
||||
}
|
||||
if(startTime == 0) {
|
||||
if (startTime == 0) {
|
||||
startTime = callback.onGetLastDataSyncTimestamp(dictClass);
|
||||
}
|
||||
if(startTime < 0) {
|
||||
if (startTime < 0) {
|
||||
LOG.info("P2PDataDictionarySyncService start time is less then 0");
|
||||
callback.onComplete(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if(startTime > 0) {
|
||||
if (startTime > 0) {
|
||||
startTime += 1000;
|
||||
}
|
||||
|
||||
@@ -210,7 +225,7 @@ public class HuaweiP2PDataDictionarySyncService extends HuaweiBaseP2PService {
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuffer sb = new StringBuffer("HuaweiDictDataValue{");
|
||||
final StringBuilder sb = new StringBuilder("HuaweiDictDataValue{");
|
||||
sb.append("dataType=").append(dataType);
|
||||
sb.append(", tag=").append(tag);
|
||||
sb.append(", value=");
|
||||
@@ -241,7 +256,9 @@ public class HuaweiP2PDataDictionarySyncService extends HuaweiBaseP2PService {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public int getDictClass() { return dictClass; }
|
||||
public int getDictClass() {
|
||||
return dictClass;
|
||||
}
|
||||
|
||||
public long getStartTimestamp() {
|
||||
return startTimestamp;
|
||||
@@ -262,13 +279,11 @@ public class HuaweiP2PDataDictionarySyncService extends HuaweiBaseP2PService {
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuffer sb = new StringBuffer("HuaweiDictSample{");
|
||||
sb.append("startTime=").append(startTimestamp);
|
||||
sb.append(", endTime=").append(endTimestamp);
|
||||
sb.append(", modifyTime=").append(modifyTimestamp);
|
||||
sb.append(", data=").append(data);
|
||||
sb.append('}');
|
||||
return sb.toString();
|
||||
return "HuaweiDictSample{" + "startTime=" + startTimestamp +
|
||||
", endTime=" + endTimestamp +
|
||||
", modifyTime=" + modifyTimestamp +
|
||||
", data=" + data +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,16 +299,16 @@ public class HuaweiP2PDataDictionarySyncService extends HuaweiBaseP2PService {
|
||||
int operation = tlv.getInteger(0x01);
|
||||
int dictClass = tlv.getInteger(0x02);
|
||||
|
||||
if(!currentRequests.containsKey(dictClass)) {
|
||||
if (!currentRequests.containsKey(dictClass)) {
|
||||
return;
|
||||
}
|
||||
callback = currentRequests.remove(dictClass);
|
||||
|
||||
if(callback == null) {
|
||||
if (callback == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(operation != 1) {
|
||||
if (operation != 1) {
|
||||
return;
|
||||
//I never see value differ from 1. So I don't know how to interpret others. Just ignore for now
|
||||
//callback.onComplete(true);
|
||||
@@ -301,7 +316,7 @@ public class HuaweiP2PDataDictionarySyncService extends HuaweiBaseP2PService {
|
||||
|
||||
//NOTE: all tags with high bit set should be parsed as container
|
||||
|
||||
List<DictData> result = new ArrayList<>();
|
||||
List<DictData> result = new ArrayList<>();
|
||||
|
||||
long lastTimestamp = 0;
|
||||
|
||||
@@ -335,7 +350,7 @@ public class HuaweiP2PDataDictionarySyncService extends HuaweiBaseP2PService {
|
||||
if (!result.isEmpty()) {
|
||||
sendSyncRequest(dictClass, lastTimestamp, callback);
|
||||
} else {
|
||||
if(classesToSync.isEmpty()) {
|
||||
if (classesToSync.isEmpty()) {
|
||||
classesToSync = null;
|
||||
callback.onComplete(true);
|
||||
} else {
|
||||
@@ -344,7 +359,7 @@ public class HuaweiP2PDataDictionarySyncService extends HuaweiBaseP2PService {
|
||||
}
|
||||
} catch (HuaweiPacket.MissingTagException e) {
|
||||
LOG.error("P2PDataDictionarySyncService parse error", e);
|
||||
if(callback != null) {
|
||||
if (callback != null) {
|
||||
callback.onComplete(false);
|
||||
}
|
||||
}
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p.dictionarysync;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p.HuaweiP2PDataDictionarySyncService;
|
||||
|
||||
//TODO: not fully discovered.
|
||||
public class HuaweiDictionarySyncAltitude implements HuaweiDictionarySyncInterface {
|
||||
private final Logger LOG = LoggerFactory.getLogger(HuaweiDictionarySyncAltitude.class);
|
||||
|
||||
public static final int ALTITUDE_CLASS = 200003;
|
||||
|
||||
@Override
|
||||
public int getDataClass() {
|
||||
return ALTITUDE_CLASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(HuaweiCoordinator coordinator) {
|
||||
return false; // coordinator.supportsAltitude()
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastDataSyncTimestamp(GBDevice gbDevice) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleData(Context context, GBDevice gbDevice, List<HuaweiP2PDataDictionarySyncService.DictData> dictData) {
|
||||
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p.dictionarysync;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p.HuaweiP2PDataDictionarySyncService;
|
||||
|
||||
// TODO: not fully discovered.
|
||||
public class HuaweiDictionarySyncArterialStiffness implements HuaweiDictionarySyncInterface {
|
||||
private final Logger LOG = LoggerFactory.getLogger(HuaweiDictionarySyncArterialStiffness.class);
|
||||
|
||||
public static final int ARTERIAL_STIFFNESS_CLASS = 400017;
|
||||
|
||||
@Override
|
||||
public int getDataClass() {
|
||||
return ARTERIAL_STIFFNESS_CLASS ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(HuaweiCoordinator coordinator) {
|
||||
return false; // coordinator.supportsArterialStiffnessDetection()
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastDataSyncTimestamp(GBDevice gbDevice) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleData(Context context, GBDevice gbDevice, List<HuaweiP2PDataDictionarySyncService.DictData> dictData) {
|
||||
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p.dictionarysync;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p.HuaweiP2PDataDictionarySyncService;
|
||||
|
||||
// TODO: not fully discovered.
|
||||
public class HuaweiDictionarySyncBloodPressure implements HuaweiDictionarySyncInterface {
|
||||
private final Logger LOG = LoggerFactory.getLogger(HuaweiDictionarySyncBloodPressure.class);
|
||||
|
||||
public static final int BLOOD_PRESSURE_CLASS = 10002;
|
||||
|
||||
@Override
|
||||
public int getDataClass() {
|
||||
return BLOOD_PRESSURE_CLASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(HuaweiCoordinator coordinator) {
|
||||
return false; //coordinator.supportsBloodPressure()
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastDataSyncTimestamp(GBDevice gbDevice) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleData(Context context, GBDevice gbDevice, List<HuaweiP2PDataDictionarySyncService.DictData> dictData) {
|
||||
|
||||
}
|
||||
}
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p.dictionarysync;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiEmotionsSampleProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiUtil;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiEmotionsSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p.HuaweiP2PDataDictionarySyncService;
|
||||
|
||||
public class HuaweiDictionarySyncEmotion implements HuaweiDictionarySyncInterface {
|
||||
private final Logger LOG = LoggerFactory.getLogger(HuaweiDictionarySyncEmotion.class);
|
||||
|
||||
public static final int EMOTION_CLASS = 500031;
|
||||
public static final int EMOTION_STATUS_VALUE = 500031195;
|
||||
public static final int EMOTION_VALENCE_CHARACTER_VALUE = 500031347;
|
||||
public static final int EMOTION_ORIGIN_STATUS_VALUE = 500031160;
|
||||
public static final int EMOTION_AROUSAL_CHARACTER_VALUE = 500031842;
|
||||
|
||||
@Override
|
||||
public int getDataClass() {
|
||||
return EMOTION_CLASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(HuaweiCoordinator coordinator) {
|
||||
return coordinator.supportsEmotion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastDataSyncTimestamp(GBDevice gbDevice) {
|
||||
try (DBHandler db = GBApplication.acquireDB()) {
|
||||
HuaweiEmotionsSampleProvider emotionsStatsSampleProvider = new HuaweiEmotionsSampleProvider(gbDevice, db.getDaoSession());
|
||||
return emotionsStatsSampleProvider.getLastFetchTimestamp();
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Exception for getting emotion start time", e);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleData(Context context, GBDevice gbDevice, List<HuaweiP2PDataDictionarySyncService.DictData> dictData) {
|
||||
List<HuaweiEmotionsSample> emotionsSamples = new ArrayList<>();
|
||||
for (HuaweiP2PDataDictionarySyncService.DictData dt : dictData) {
|
||||
long timestamp = dt.getStartTimestamp();
|
||||
long lastTime = Math.max(dt.getEndTimestamp(), dt.getModifyTimestamp());
|
||||
Integer status = null;
|
||||
Double valenceCharacter = null;
|
||||
Integer originStatus = null;
|
||||
Double arousalCharacter = null;
|
||||
for (HuaweiP2PDataDictionarySyncService.DictData.DictDataValue val : dt.getData()) {
|
||||
if (val.getTag() != 10) {
|
||||
LOG.info("emotions unexpected tag: {}", val.getTag());
|
||||
continue;
|
||||
}
|
||||
if (val.getDataType() == EMOTION_STATUS_VALUE) {
|
||||
double value = HuaweiUtil.convBytes2Double(val.getValue());
|
||||
if (value >= 0 && value < 100) {
|
||||
status = (int) value;
|
||||
}
|
||||
} else if (val.getDataType() == EMOTION_VALENCE_CHARACTER_VALUE) {
|
||||
double value = HuaweiUtil.convBytes2Double(val.getValue());
|
||||
if (value >= 0 && value <= 100) {
|
||||
valenceCharacter = value;
|
||||
}
|
||||
} else if (val.getDataType() == EMOTION_ORIGIN_STATUS_VALUE) {
|
||||
double value = HuaweiUtil.convBytes2Double(val.getValue());
|
||||
if (value >= 0 && value < 100) {
|
||||
originStatus = (int) value;
|
||||
}
|
||||
} else if (val.getDataType() == EMOTION_AROUSAL_CHARACTER_VALUE) {
|
||||
double value = HuaweiUtil.convBytes2Double(val.getValue());
|
||||
if (value >= 0 && value <= 100) {
|
||||
arousalCharacter = value;
|
||||
}
|
||||
} else {
|
||||
LOG.info("emotions unknown data type: {}", val.getDataType());
|
||||
}
|
||||
}
|
||||
if (status != null || valenceCharacter != null || originStatus != null || arousalCharacter != null) {
|
||||
HuaweiEmotionsSample sample = new HuaweiEmotionsSample();
|
||||
sample.setTimestamp(timestamp);
|
||||
sample.setLastTimestamp(lastTime);
|
||||
sample.setStatus(status == null ? 0 : status);
|
||||
sample.setValenceCharacter(valenceCharacter);
|
||||
sample.setOriginStatus(originStatus);
|
||||
sample.setArousalCharacter(arousalCharacter);
|
||||
emotionsSamples.add(sample);
|
||||
}
|
||||
}
|
||||
try (DBHandler db = GBApplication.acquireDB()) {
|
||||
final DaoSession session = db.getDaoSession();
|
||||
new HuaweiEmotionsSampleProvider(gbDevice, session).persistForDevice(context, gbDevice, emotionsSamples);
|
||||
} catch (Exception e) {
|
||||
LOG.error("Cannot save emotions samples, continue");
|
||||
}
|
||||
}
|
||||
}
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p.dictionarysync;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiHrvValueSampleProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiUtil;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiHrvValueSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p.HuaweiP2PDataDictionarySyncService;
|
||||
|
||||
public class HuaweiDictionarySyncHRV implements HuaweiDictionarySyncInterface {
|
||||
private final Logger LOG = LoggerFactory.getLogger(HuaweiDictionarySyncHRV.class);
|
||||
|
||||
public static final int HRV_CLASS = 500044;
|
||||
public static final int HRV_RMSSD_VALUE = 500044831;
|
||||
|
||||
@Override
|
||||
public int getDataClass() {
|
||||
return HRV_CLASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(HuaweiCoordinator coordinator) {
|
||||
return coordinator.supportsHRV();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastDataSyncTimestamp(GBDevice gbDevice) {
|
||||
try (DBHandler db = GBApplication.acquireDB()) {
|
||||
HuaweiHrvValueSampleProvider hrvStatsSampleProvider = new HuaweiHrvValueSampleProvider(gbDevice, db.getDaoSession());
|
||||
return hrvStatsSampleProvider.getLastFetchTimestamp();
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Exception for getting HRV start time", e);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleData(Context context, GBDevice gbDevice, List<HuaweiP2PDataDictionarySyncService.DictData> dictData) {
|
||||
List<HuaweiHrvValueSample> hrvSamples = new ArrayList<>();
|
||||
for (HuaweiP2PDataDictionarySyncService.DictData dt : dictData) {
|
||||
long timestamp = dt.getStartTimestamp();
|
||||
long lastTime = Math.max(dt.getEndTimestamp(), dt.getModifyTimestamp());
|
||||
Integer rmssd = null;
|
||||
for (HuaweiP2PDataDictionarySyncService.DictData.DictDataValue val : dt.getData()) {
|
||||
if (val.getTag() != 10) {
|
||||
LOG.info("HRV unexpected tag: {}", val.getTag());
|
||||
continue;
|
||||
}
|
||||
if (val.getDataType() == HRV_RMSSD_VALUE) {
|
||||
double value = HuaweiUtil.convBytes2Double(val.getValue());
|
||||
if (value >= 0 && value <= 200) {
|
||||
rmssd = (int) value;
|
||||
}
|
||||
} else {
|
||||
LOG.info("HRV unknown data type: {}", val.getDataType());
|
||||
}
|
||||
}
|
||||
if(rmssd != null) {
|
||||
HuaweiHrvValueSample sample = new HuaweiHrvValueSample();
|
||||
sample.setTimestamp(timestamp);
|
||||
sample.setLastTimestamp(lastTime);
|
||||
sample.setValue(rmssd);
|
||||
hrvSamples.add(sample);
|
||||
}
|
||||
}
|
||||
try (DBHandler db = GBApplication.acquireDB()) {
|
||||
final DaoSession session = db.getDaoSession();
|
||||
new HuaweiHrvValueSampleProvider(gbDevice, session).persistForDevice(context, gbDevice, hrvSamples);
|
||||
} catch (Exception e) {
|
||||
LOG.error("Cannot save HRV samples, continue");
|
||||
}
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p.dictionarysync;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p.HuaweiP2PDataDictionarySyncService;
|
||||
|
||||
public interface HuaweiDictionarySyncInterface {
|
||||
|
||||
int getDataClass();
|
||||
|
||||
boolean supports(HuaweiCoordinator coordinator);
|
||||
|
||||
long getLastDataSyncTimestamp(GBDevice gbDevice);
|
||||
|
||||
void handleData(Context context, GBDevice gbDevice, List<HuaweiP2PDataDictionarySyncService.DictData> dictData);
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p.dictionarysync;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p.HuaweiP2PDataDictionarySyncService;
|
||||
|
||||
// TODO: not fully discovered.
|
||||
public class HuaweiDictionarySyncLakeLouiseAMS implements HuaweiDictionarySyncInterface {
|
||||
private final Logger LOG = LoggerFactory.getLogger(HuaweiDictionarySyncLakeLouiseAMS.class);
|
||||
|
||||
public static final int LAKE_LOUISE_AMS_CLASS = 500006;
|
||||
|
||||
@Override
|
||||
public int getDataClass() {
|
||||
return LAKE_LOUISE_AMS_CLASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(HuaweiCoordinator coordinator) {
|
||||
return false; // coordinator.supportsAltitude()
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastDataSyncTimestamp(GBDevice gbDevice) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleData(Context context, GBDevice gbDevice, List<HuaweiP2PDataDictionarySyncService.DictData> dictData) {
|
||||
|
||||
}
|
||||
}
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p.dictionarysync;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiDictTypes;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiTemperatureSampleProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiUtil;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiTemperatureSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.TemperatureSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p.HuaweiP2PDataDictionarySyncService;
|
||||
|
||||
public class HuaweiDictionarySyncSkinTemperature implements HuaweiDictionarySyncInterface {
|
||||
private final Logger LOG = LoggerFactory.getLogger(HuaweiDictionarySyncSkinTemperature.class);
|
||||
|
||||
@Override
|
||||
public int getDataClass() {
|
||||
return HuaweiDictTypes.SKIN_TEMPERATURE_CLASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(HuaweiCoordinator coordinator) {
|
||||
return coordinator.supportsTemperature();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastDataSyncTimestamp(GBDevice gbDevice) {
|
||||
try (DBHandler db = GBApplication.acquireDB()) {
|
||||
HuaweiTemperatureSampleProvider sleepStatsSampleProvider = new HuaweiTemperatureSampleProvider(gbDevice, db.getDaoSession());
|
||||
return sleepStatsSampleProvider.getLastFetchTimestamp();
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Exception for getting skin temperature start time", e);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleData(Context context, GBDevice gbDevice, List<HuaweiP2PDataDictionarySyncService.DictData> dictData) {
|
||||
List<HuaweiTemperatureSample> temperatureSamples = new ArrayList<>();
|
||||
for (HuaweiP2PDataDictionarySyncService.DictData dt : dictData) {
|
||||
long timestamp = dt.getStartTimestamp();
|
||||
long lastTime = Math.max(dt.getEndTimestamp(), dt.getModifyTimestamp());
|
||||
Float temperature = null;
|
||||
for (HuaweiP2PDataDictionarySyncService.DictData.DictDataValue val : dt.getData()) {
|
||||
if (val.getTag() != 10) {
|
||||
LOG.info("skin temperature unexpected tag: {}", val.getTag());
|
||||
continue;
|
||||
}
|
||||
if (val.getDataType() == HuaweiDictTypes.SKIN_TEMPERATURE_VALUE) {
|
||||
double value = HuaweiUtil.convBytes2Double(val.getValue());
|
||||
if (value >= 20 && value <= 42) {
|
||||
temperature = (float) value;
|
||||
}
|
||||
} else {
|
||||
LOG.info("skin temperature unknown data type: {}", val.getDataType());
|
||||
}
|
||||
}
|
||||
if(temperature != null) {
|
||||
HuaweiTemperatureSample sample = new HuaweiTemperatureSample();
|
||||
sample.setTimestamp(timestamp);
|
||||
sample.setLastTimestamp(lastTime);
|
||||
sample.setTemperature(temperature);
|
||||
sample.setTemperatureType(TemperatureSample.TYPE_SKIN);
|
||||
sample.setTemperatureLocation(TemperatureSample.LOCATION_WRIST);
|
||||
temperatureSamples.add(sample);
|
||||
}
|
||||
}
|
||||
try (DBHandler db = GBApplication.acquireDB()) {
|
||||
final DaoSession session = db.getDaoSession();
|
||||
new HuaweiTemperatureSampleProvider(gbDevice, session).persistForDevice(context, gbDevice, temperatureSamples);
|
||||
} catch (Exception e) {
|
||||
LOG.error("Cannot save skin temperature samples, continue");
|
||||
}
|
||||
}
|
||||
}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p.dictionarysync;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiSleepApneaSampleProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiUtil;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiSleepApneaSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p.HuaweiP2PDataDictionarySyncService;
|
||||
|
||||
public class HuaweiDictionarySyncSleepApnea implements HuaweiDictionarySyncInterface {
|
||||
private final Logger LOG = LoggerFactory.getLogger(HuaweiDictionarySyncSleepApnea.class);
|
||||
|
||||
public static final int SLEEP_APNEA_CLASS = 500002;
|
||||
public static final int SLEEP_APNEA_LEVEL_VALUE = 500002847;
|
||||
|
||||
@Override
|
||||
public int getDataClass() {
|
||||
return SLEEP_APNEA_CLASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(HuaweiCoordinator coordinator) {
|
||||
return coordinator.supportsSleepApnea();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastDataSyncTimestamp(GBDevice gbDevice) {
|
||||
try (DBHandler db = GBApplication.acquireDB()) {
|
||||
HuaweiSleepApneaSampleProvider sleepApneaSampleProvider = new HuaweiSleepApneaSampleProvider(gbDevice, db.getDaoSession());
|
||||
return sleepApneaSampleProvider.getLastFetchTimestamp();
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Exception for getting sleep apnea start time", e);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleData(Context context, GBDevice gbDevice, List<HuaweiP2PDataDictionarySyncService.DictData> dictData) {
|
||||
List<HuaweiSleepApneaSample> sleepApneaSamples = new ArrayList<>();
|
||||
for (HuaweiP2PDataDictionarySyncService.DictData dt : dictData) {
|
||||
long timestamp = dt.getStartTimestamp();
|
||||
long lastTime = Math.max(dt.getEndTimestamp(), dt.getModifyTimestamp());
|
||||
Integer level = null;
|
||||
for (HuaweiP2PDataDictionarySyncService.DictData.DictDataValue val : dt.getData()) {
|
||||
if (val.getTag() == 10) {
|
||||
if (val.getDataType() == SLEEP_APNEA_LEVEL_VALUE) {
|
||||
int value = (int) HuaweiUtil.convBytes2Double(val.getValue());
|
||||
if (value == 1 || value == 2 || value == 3 || value == 4) {
|
||||
level = value;
|
||||
} else {
|
||||
LOG.info("sleep apnea invalid value: {}", value);
|
||||
}
|
||||
} else {
|
||||
LOG.info("sleep apnea unknown data type: {}", val.getDataType());
|
||||
}
|
||||
} else {
|
||||
LOG.info("sleep apnea unsupported tag: {}", val.getTag());
|
||||
}
|
||||
}
|
||||
if(level != null) {
|
||||
LOG.info("APNEA timestamp: {} lastTime: {} level: {}", new Date(timestamp), lastTime, level);
|
||||
HuaweiSleepApneaSample sample = new HuaweiSleepApneaSample();
|
||||
sample.setTimestamp(timestamp);
|
||||
sample.setLastTimestamp(lastTime);
|
||||
sample.setLevel(level);
|
||||
sleepApneaSamples.add(sample);
|
||||
}
|
||||
}
|
||||
try (DBHandler db = GBApplication.acquireDB()) {
|
||||
final DaoSession session = db.getDaoSession();
|
||||
new HuaweiSleepApneaSampleProvider(gbDevice, session).persistForDevice(context, gbDevice, sleepApneaSamples);
|
||||
} catch (Exception e) {
|
||||
LOG.error("Cannot save sleep apnea samples, continue");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user