diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiCoordinator.java index 86daf1d97..36af87081 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiCoordinator.java @@ -487,6 +487,7 @@ public class HuaweiCoordinator { // 0x43 - SupportTemperatureStudy public boolean supportsTemperature() { return supportsExpandCapability(0x1d); } + public boolean supportsBloodPressure() { return supportsExpandCapability(0x3b); } public boolean supportsEventAlarm() { return supportsCommandForService(0x08, 0x01); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiDictTypes.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiDictTypes.java new file mode 100644 index 000000000..3d49e547d --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiDictTypes.java @@ -0,0 +1,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; +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiTemperatureSampleProvider.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiTemperatureSampleProvider.java index 22f11e8a6..1f99b9cd8 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiTemperatureSampleProvider.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiTemperatureSampleProvider.java @@ -84,7 +84,7 @@ public class HuaweiTemperatureSampleProvider implements TimeSampleProvider qb = this.session.getHuaweiDictDataDao().queryBuilder(); qb.where(HuaweiDictDataDao.Properties.DeviceId.eq(deviceId)) .where(HuaweiDictDataDao.Properties.UserId.eq(userId)) - .where(HuaweiDictDataDao.Properties.DictClass.eq(400012)) + .where(HuaweiDictDataDao.Properties.DictClass.eq(HuaweiDictTypes.SKIN_TEMPERATURE_CLASS)) .where(HuaweiDictDataDao.Properties.StartTimestamp.between(timestampFrom, timestampTo)); final List dictData = qb.build().list(); @@ -95,7 +95,7 @@ public class HuaweiTemperatureSampleProvider implements TimeSampleProvider qbv = this.session.getHuaweiDictDataValuesDao().queryBuilder(); - qbv.where(HuaweiDictDataValuesDao.Properties.DictType.eq(400012430)).where(HuaweiDictDataValuesDao.Properties.Tag.eq(10)).where(HuaweiDictDataValuesDao.Properties.DictId.in(ids)); + qbv.where(HuaweiDictDataValuesDao.Properties.DictType.eq(HuaweiDictTypes.SKIN_TEMPERATURE_VALUE)).where(HuaweiDictDataValuesDao.Properties.Tag.eq(10)).where(HuaweiDictDataValuesDao.Properties.DictId.in(ids)); final List valuesData = qbv.build().list(); @@ -141,7 +141,7 @@ public class HuaweiTemperatureSampleProvider implements TimeSampleProvider qb = this.session.getHuaweiDictDataDao().queryBuilder(); qb.where(HuaweiDictDataDao.Properties.DeviceId.eq(deviceId)) .where(HuaweiDictDataDao.Properties.UserId.eq(userId)) - .where(HuaweiDictDataDao.Properties.DictClass.eq(400012)); + .where(HuaweiDictDataDao.Properties.DictClass.eq(HuaweiDictTypes.SKIN_TEMPERATURE_CLASS)); qb.orderDesc(HuaweiDictDataDao.Properties.StartTimestamp).limit(1); final List data = qb.build().list(); @@ -150,7 +150,7 @@ public class HuaweiTemperatureSampleProvider implements TimeSampleProvider qbv = this.session.getHuaweiDictDataValuesDao().queryBuilder(); - qbv.where(HuaweiDictDataValuesDao.Properties.DictType.eq(400012430)).where(HuaweiDictDataValuesDao.Properties.Tag.eq(10)).where(HuaweiDictDataValuesDao.Properties.DictId.eq(data.get(0).getDictId())); + qbv.where(HuaweiDictDataValuesDao.Properties.DictType.eq(HuaweiDictTypes.SKIN_TEMPERATURE_VALUE)).where(HuaweiDictDataValuesDao.Properties.Tag.eq(10)).where(HuaweiDictDataValuesDao.Properties.DictId.eq(data.get(0).getDictId())); final List valuesData = qbv.build().list(); if (valuesData.isEmpty()) @@ -171,7 +171,7 @@ public class HuaweiTemperatureSampleProvider implements TimeSampleProvider qb = this.session.getHuaweiDictDataDao().queryBuilder(); qb.where(HuaweiDictDataDao.Properties.DeviceId.eq(deviceId)) .where(HuaweiDictDataDao.Properties.UserId.eq(userId)) - .where(HuaweiDictDataDao.Properties.DictClass.eq(400012)); + .where(HuaweiDictDataDao.Properties.DictClass.eq(HuaweiDictTypes.SKIN_TEMPERATURE_CLASS)); qb.orderAsc(HuaweiDictDataDao.Properties.StartTimestamp).limit(1); final List data = qb.build().list(); @@ -179,7 +179,7 @@ public class HuaweiTemperatureSampleProvider implements TimeSampleProvider qbv = this.session.getHuaweiDictDataValuesDao().queryBuilder(); - qbv.where(HuaweiDictDataValuesDao.Properties.DictType.eq(400012430)).where(HuaweiDictDataValuesDao.Properties.Tag.eq(10)).where(HuaweiDictDataValuesDao.Properties.DictId.eq(data.get(0).getDictId())); + qbv.where(HuaweiDictDataValuesDao.Properties.DictType.eq(HuaweiDictTypes.SKIN_TEMPERATURE_VALUE)).where(HuaweiDictDataValuesDao.Properties.Tag.eq(10)).where(HuaweiDictDataValuesDao.Properties.DictId.eq(data.get(0).getDictId())); final List valuesData = qbv.build().list(); if (valuesData.isEmpty()) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiSupportProvider.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiSupportProvider.java index 3bf31fcbd..c58a531d7 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiSupportProvider.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiSupportProvider.java @@ -34,6 +34,7 @@ import java.io.File; import java.nio.charset.StandardCharsets; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Random; import java.util.UUID; @@ -56,6 +57,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiCoordinatorSupplier; import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiCoordinatorSupplier.HuaweiDeviceType; import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiCrypto; +import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiDictTypes; import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiGpsParser; import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket; import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiSampleProvider; @@ -1271,15 +1273,19 @@ public class HuaweiSupportProvider { private void fetchActivityDataP2P() { HuaweiP2PDataDictionarySyncService P2PSyncService = HuaweiP2PDataDictionarySyncService.getRegisteredInstance(huaweiP2PManager); - if (P2PSyncService != null && getHuaweiCoordinator().supportsTemperature()) { - syncState.setP2pSync(true); - P2PSyncService.sendSyncRequest(400012, new HuaweiP2PDataDictionarySyncService.DictionarySyncCallback() { - @Override - public void onComplete(boolean complete) { - LOG.info("Sync P2P Temperature complete"); - syncState.setP2pSync(false); - } - }); + + if (P2PSyncService != null) { + List list = P2PSyncService.checkSupported(this.getHuaweiCoordinator(), Arrays.asList(HuaweiDictTypes.SKIN_TEMPERATURE_CLASS, HuaweiDictTypes.BLOOD_PRESSURE_CLASS)); + if(!list.isEmpty()) { + syncState.setP2pSync(true); + P2PSyncService.startSync(list, new HuaweiP2PDataDictionarySyncService.DictionarySyncCallback() { + @Override + public void onComplete(boolean complete) { + LOG.info("Sync P2P Data complete"); + syncState.setP2pSync(false); + } + }); + } } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/p2p/HuaweiBaseP2PService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/p2p/HuaweiBaseP2PService.java index 11e63c0cd..a4b40f840 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/p2p/HuaweiBaseP2PService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/p2p/HuaweiBaseP2PService.java @@ -14,6 +14,11 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.Send public abstract class HuaweiBaseP2PService { private final Logger LOG = LoggerFactory.getLogger(HuaweiBaseP2PService.class); + + public interface HuaweiP2PCallback { + void onResponse(int code, byte[] data); + } + protected final HuaweiP2PManager manager; protected HuaweiBaseP2PService(HuaweiP2PManager manager) { @@ -90,7 +95,11 @@ public abstract class HuaweiBaseP2PService { if (waitPackets.containsKey(packet.sequenceId)) { LOG.info("HuaweiP2PCalendarService handlePacket find handler"); HuaweiP2PCallback handle = waitPackets.remove(packet.sequenceId); - handle.onResponse(packet.respCode, packet.respData); + if(handle != null) { + handle.onResponse(packet.respCode, packet.respData); + } else { + LOG.error("HuaweiP2PCalendarService handler is null"); + } } else { if (packet.cmdId == 1) { //Ping diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/p2p/HuaweiP2PCallback.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/p2p/HuaweiP2PCallback.java deleted file mode 100644 index 175336074..000000000 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/p2p/HuaweiP2PCallback.java +++ /dev/null @@ -1,5 +0,0 @@ -package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p; - -public interface HuaweiP2PCallback { - void onResponse(int code, byte[] data); -} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/p2p/HuaweiP2PDataDictionarySyncService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/p2p/HuaweiP2PDataDictionarySyncService.java index 339a6058e..59d13e2b0 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/p2p/HuaweiP2PDataDictionarySyncService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/p2p/HuaweiP2PDataDictionarySyncService.java @@ -10,6 +10,8 @@ import java.util.List; 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; @@ -21,6 +23,9 @@ public class HuaweiP2PDataDictionarySyncService extends HuaweiBaseP2PService { private AtomicBoolean serviceAvailable = new AtomicBoolean(false); + + private List classesToSync = null; + public interface DictionarySyncCallback { void onComplete(boolean complete); } @@ -54,7 +59,32 @@ public class HuaweiP2PDataDictionarySyncService extends HuaweiBaseP2PService { (byte) value}; } - public void sendSyncRequest(int dictClass, DictionarySyncCallback callback) { + public List checkSupported(HuaweiCoordinator coordinator, List list) { + List result = new ArrayList<>(); + + 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); + } + } + return result; + } + + public void startSync(List dictClasses, DictionarySyncCallback callback) { + LOG.info("P2PDataDictionarySyncService startSync {}", dictClasses); + classesToSync = dictClasses; + if(classesToSync.isEmpty()) { + callback.onComplete(false); + return; + } + sendSyncRequest(classesToSync.remove(0), callback); + } + + private void sendSyncRequest(int dictClass, DictionarySyncCallback callback) { + + LOG.info("P2PDataDictionarySyncService class {}", dictClass); if (!serviceAvailable.get()) { LOG.info("P2PDataDictionarySyncService not available"); @@ -76,8 +106,8 @@ public class HuaweiP2PDataDictionarySyncService extends HuaweiBaseP2PService { HuaweiTLV tlv = new HuaweiTLV() .put(0x1, (byte) 1) .put(0x2, dictToBytes(dictClass)) //-- skin temperature - .put(0x5, Long.valueOf(startTime)) - .put(0x6, Long.valueOf(System.currentTimeMillis())) + .put(0x5, startTime) + .put(0x6, System.currentTimeMillis()) .put(0x0d, (byte) 1); byte[] data = tlv.serialize(); if (data == null) { @@ -261,7 +291,12 @@ public class HuaweiP2PDataDictionarySyncService extends HuaweiBaseP2PService { if (!result.isEmpty()) { sendSyncRequest(dictClass, callback); } else { - callback.onComplete(true); + if(classesToSync.isEmpty()) { + classesToSync = null; + callback.onComplete(true); + } else { + sendSyncRequest(classesToSync.remove(0), callback); + } } } catch (HuaweiPacket.MissingTagException e) { LOG.error("P2PDataDictionarySyncService parse error", e);