1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2025-02-04 14:07:32 +01:00

Huawei: Allow to sync more data over Dict P2P service

This commit is contained in:
Me7c7 2024-12-01 17:48:45 +02:00
parent 86b51683d2
commit ed49f6d323
7 changed files with 81 additions and 25 deletions

View File

@ -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);

View File

@ -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;
}

View File

@ -84,7 +84,7 @@ public class HuaweiTemperatureSampleProvider implements TimeSampleProvider<Tempe
QueryBuilder<HuaweiDictData> 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<HuaweiDictData> dictData = qb.build().list();
@ -95,7 +95,7 @@ public class HuaweiTemperatureSampleProvider implements TimeSampleProvider<Tempe
QueryBuilder<HuaweiDictDataValues> 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<HuaweiDictDataValues> valuesData = qbv.build().list();
@ -141,7 +141,7 @@ public class HuaweiTemperatureSampleProvider implements TimeSampleProvider<Tempe
QueryBuilder<HuaweiDictData> 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<HuaweiDictData> data = qb.build().list();
@ -150,7 +150,7 @@ public class HuaweiTemperatureSampleProvider implements TimeSampleProvider<Tempe
QueryBuilder<HuaweiDictDataValues> 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<HuaweiDictDataValues> valuesData = qbv.build().list();
if (valuesData.isEmpty())
@ -171,7 +171,7 @@ public class HuaweiTemperatureSampleProvider implements TimeSampleProvider<Tempe
QueryBuilder<HuaweiDictData> 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<HuaweiDictData> data = qb.build().list();
@ -179,7 +179,7 @@ public class HuaweiTemperatureSampleProvider implements TimeSampleProvider<Tempe
return null;
QueryBuilder<HuaweiDictDataValues> 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<HuaweiDictDataValues> valuesData = qbv.build().list();
if (valuesData.isEmpty())

View File

@ -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<Integer> 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);
}
});
}
}
}

View File

@ -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

View File

@ -1,5 +0,0 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.p2p;
public interface HuaweiP2PCallback {
void onResponse(int code, byte[] data);
}

View File

@ -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<Integer> 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<Integer> checkSupported(HuaweiCoordinator coordinator, List<Integer> list) {
List<Integer> 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<Integer> 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);