mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2026-07-31 07:44:24 +02:00
fix(withings,scanwatch): Syncing shows connected in the app and becomes stale
This commit is contained in:
+35
@@ -310,7 +310,9 @@ public abstract class WithingsBaseDeviceSupport extends AbstractBTLESingleDevice
|
||||
|
||||
try {
|
||||
getDevice().setBusyTask(R.string.busy_task_syncing, getContext());
|
||||
getDevice().sendDeviceUpdateIntent(getContext());
|
||||
syncInProgress = true;
|
||||
logger.info("Starting Withings sync, trigger={}, shouldSync={}", triggerSource, shoudSync());
|
||||
if (withingsEcgHandler == null) {
|
||||
withingsEcgHandler = createEcgHandler();
|
||||
}
|
||||
@@ -388,6 +390,7 @@ public abstract class WithingsBaseDeviceSupport extends AbstractBTLESingleDevice
|
||||
conversationQueue.clear();
|
||||
} finally {
|
||||
// This must be done in all cases or the watch won't respond anymore!
|
||||
logger.debug("Queueing SYNC_OK terminator for trigger={}", triggerSource);
|
||||
addSimpleConversationToQueue(new WithingsMessage(WithingsMessageType.SYNC_OK), new SyncFinishedHandler(this));
|
||||
}
|
||||
conversationQueue.send();
|
||||
@@ -455,6 +458,17 @@ public abstract class WithingsBaseDeviceSupport extends AbstractBTLESingleDevice
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectionStateChange(final BluetoothGatt gatt, final int status, final int newState) {
|
||||
super.onConnectionStateChange(gatt, status, newState);
|
||||
|
||||
if (newState == BluetoothGatt.STATE_CONNECTED) {
|
||||
clearStaleSyncState("connect");
|
||||
} else if (newState == BluetoothGatt.STATE_DISCONNECTED) {
|
||||
clearStaleSyncState("disconnect");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotification(NotificationSpec notificationSpec) {
|
||||
notificationProvider.notifyClient(notificationSpec);
|
||||
@@ -670,7 +684,28 @@ public abstract class WithingsBaseDeviceSupport extends AbstractBTLESingleDevice
|
||||
logger.debug("Finished initialization.");
|
||||
}
|
||||
|
||||
private void clearStaleSyncState(final String reason) {
|
||||
if (withingsEcgHandler != null) {
|
||||
withingsEcgHandler.reset();
|
||||
} else {
|
||||
GB.updateTransferNotification(null, "", false, 100, getContext());
|
||||
}
|
||||
|
||||
if (syncInProgress) {
|
||||
logger.info("Clearing stale Withings sync state on {}", reason);
|
||||
syncInProgress = false;
|
||||
conversationQueue.clear();
|
||||
}
|
||||
|
||||
final String syncingTask = getContext().getString(R.string.busy_task_syncing);
|
||||
if (syncingTask.equals(getDevice().getBusyTask())) {
|
||||
getDevice().unsetBusyTask();
|
||||
getDevice().sendDeviceUpdateIntent(getContext());
|
||||
}
|
||||
}
|
||||
|
||||
public void finishSync() {
|
||||
logger.info("Finishing Withings sync, busyTask={}, syncInProgress={}", getDevice().getBusyTask(), syncInProgress);
|
||||
syncInProgress = false;
|
||||
if (withingsEcgHandler != null) {
|
||||
withingsEcgHandler.onSyncFinished();
|
||||
|
||||
+5
@@ -16,11 +16,15 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.withingssteelhr.communication.conversation;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.withingssteelhr.WithingsBaseDeviceSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.withingssteelhr.communication.message.Message;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.withingssteelhr.communication.message.WithingsMessageType;
|
||||
|
||||
public class SyncFinishedHandler extends AbstractResponseHandler {
|
||||
private static final Logger logger = LoggerFactory.getLogger(SyncFinishedHandler.class);
|
||||
|
||||
public SyncFinishedHandler(WithingsBaseDeviceSupport support) {
|
||||
super(support);
|
||||
@@ -30,6 +34,7 @@ public class SyncFinishedHandler extends AbstractResponseHandler {
|
||||
|
||||
@Override
|
||||
public void handleResponse(Message response) {
|
||||
logger.info("SyncFinishedHandler received response type={} (0x{})", response.getType(), Integer.toHexString(response.getType() & 0xffff));
|
||||
if (response.getType() == WithingsMessageType.SYNC_OK) {
|
||||
support.finishSync();
|
||||
}
|
||||
|
||||
+51
-29
@@ -106,6 +106,7 @@ public class WithingsEcgHandler implements ResponseHandler {
|
||||
discoveredEcgCount = 0;
|
||||
fetchedEcgCount = 0;
|
||||
deletedEcgCount = 0;
|
||||
logger.info("Starting Withings ECG discovery");
|
||||
updateEcgProgress("Scanning for ECG records", 0, true);
|
||||
queueDiscoveryProbe(true);
|
||||
}
|
||||
@@ -198,6 +199,8 @@ public class WithingsEcgHandler implements ResponseHandler {
|
||||
// Keep the discovery conversation active until its trailing MEASURE_STOP / TRANSFER_COMPLETE.
|
||||
// Otherwise that trailing completion marker can get mis-bound to the next queued 0x0147
|
||||
// request, causing the actual ECG waveform stream to be routed into a stored-measure handler.
|
||||
logger.debug("Queueing Withings ECG discovery probe, initial={}, discoveryPagesSeen={}, waveformFetchQueued={}",
|
||||
initial, discoveryPagesSeen, waveformFetchQueued);
|
||||
final WithingsMessage message = new WithingsMessage(WithingsMessageType.MEASURE_START, ExpectedResponse.EOT);
|
||||
message.addDataStructure(new MeasureCategory(MeasureCategory.ECG));
|
||||
message.addDataStructure(new MeasureLiveAppStatus(initial ? 1 : 0));
|
||||
@@ -207,6 +210,7 @@ public class WithingsEcgHandler implements ResponseHandler {
|
||||
private void handleDiscoveryResponse(final Message response) {
|
||||
final List<WithingsStructure> structures = response.getDataStructures();
|
||||
if (structures == null || structures.isEmpty()) {
|
||||
logger.warn("Withings ECG discovery response type={} had no structures", response.getType());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -226,6 +230,9 @@ public class WithingsEcgHandler implements ResponseHandler {
|
||||
}
|
||||
}
|
||||
|
||||
logger.debug("Withings ECG discovery response type={} hasEot={} hasEcgMarkers={} discovered={} fetched={} deleted={} structures={}",
|
||||
response.getType(), hasEot, hasEcgMarkers, discoveredEcgCount, fetchedEcgCount, deletedEcgCount, describeStructures(structures));
|
||||
|
||||
if (recordKey != null && isNewRecordKey(recordKey)) {
|
||||
seenRecordKeys.add(recordKey.getRawPayload());
|
||||
final long timestampMs = recordKey.getTimestampMs();
|
||||
@@ -257,8 +264,42 @@ public class WithingsEcgHandler implements ResponseHandler {
|
||||
}
|
||||
if (!waveformFetchQueued && hasEcgMarkers && discoveryPagesSeen < MAX_DISCOVERY_PAGES) {
|
||||
queueDiscoveryProbe(false);
|
||||
} else if (!waveformFetchQueued && hasEcgMarkers) {
|
||||
logger.warn("Withings ECG discovery stopped after {} pages without queueing waveform fetch", discoveryPagesSeen);
|
||||
}
|
||||
} else if (!hasEot) {
|
||||
logger.debug("Withings ECG discovery awaiting more packets for response type={}", response.getType());
|
||||
}
|
||||
}
|
||||
|
||||
private String describeStructures(final List<WithingsStructure> structures) {
|
||||
final List<String> descriptions = new ArrayList<>(structures.size());
|
||||
for (final WithingsStructure structure : structures) {
|
||||
if (structure instanceof StoredMeasureMeta) {
|
||||
final StoredMeasureMeta meta = (StoredMeasureMeta) structure;
|
||||
descriptions.add("0116(type=" + meta.getMeasurementType() + ",ts=" + meta.getTimestampMs() + ")");
|
||||
} else if (structure instanceof StoredMeasureData) {
|
||||
final StoredMeasureData data = (StoredMeasureData) structure;
|
||||
descriptions.add("0117(type=" + data.getMeasurementType() + ",raw=" + data.getRawValue() + ")");
|
||||
} else if (structure instanceof StoredMeasureDataExtend) {
|
||||
final StoredMeasureDataExtend dataExt = (StoredMeasureDataExtend) structure;
|
||||
descriptions.add("0149(type=" + dataExt.getMeasurementType() + ",extra=" + dataExt.getExtraData() + ")");
|
||||
} else if (structure instanceof StoredSignalMeta) {
|
||||
final StoredSignalMeta meta = (StoredSignalMeta) structure;
|
||||
descriptions.add("0143(signalType=" + meta.getSignalType() + ",flags=" + meta.getSignalFlags() + ",cursor=" + meta.getCursor() + ")");
|
||||
} else if (structure instanceof StoredSignalMetaExtended) {
|
||||
final byte[] rawPayload = ((StoredSignalMetaExtended) structure).getRawPayload();
|
||||
descriptions.add("0146(" + GB.hexdump(rawPayload) + ")");
|
||||
} else if (structure instanceof StoredSignalData) {
|
||||
descriptions.add("0144(samples)");
|
||||
} else if (structure instanceof RawWithingsStructure) {
|
||||
final RawWithingsStructure raw = (RawWithingsStructure) structure;
|
||||
descriptions.add(String.format("0x%04x(raw=%s)", raw.getType() & 0xffff, GB.hexdump(raw.getRawData())));
|
||||
} else {
|
||||
descriptions.add(String.format("0x%04x", structure.getType() & 0xffff));
|
||||
}
|
||||
}
|
||||
return descriptions.toString();
|
||||
}
|
||||
|
||||
private int computeEcgProgressPercent() {
|
||||
@@ -425,9 +466,19 @@ public class WithingsEcgHandler implements ResponseHandler {
|
||||
}
|
||||
|
||||
if (!support.hasEndOfTransmission(response)) {
|
||||
logger.debug("Withings ECG waveform response awaiting more packets for ts={} structures={}",
|
||||
startTimestampMs > 0 ? startTimestampMs : requestedRecordKey.getTimestampMs(),
|
||||
describeStructures(structures));
|
||||
return;
|
||||
}
|
||||
|
||||
logger.debug("Withings ECG waveform response reached EOT for ts={} deleteKeyPresent={} verifyDeletion={} samples={} structures={}",
|
||||
startTimestampMs > 0 ? startTimestampMs : requestedRecordKey.getTimestampMs(),
|
||||
deleteKey != null,
|
||||
verifyDeletion,
|
||||
waveform.size(),
|
||||
describeStructures(structures));
|
||||
|
||||
if (startTimestampMs <= 0) {
|
||||
startTimestampMs = requestedRecordKey.getTimestampMs();
|
||||
}
|
||||
@@ -508,35 +559,6 @@ public class WithingsEcgHandler implements ResponseHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private String describeStructures(final List<WithingsStructure> structures) {
|
||||
final List<String> descriptions = new ArrayList<>(structures.size());
|
||||
for (final WithingsStructure structure : structures) {
|
||||
if (structure instanceof StoredMeasureMeta) {
|
||||
final StoredMeasureMeta meta = (StoredMeasureMeta) structure;
|
||||
descriptions.add("0116(type=" + meta.getMeasurementType() + ",ts=" + meta.getTimestampMs() + ")");
|
||||
} else if (structure instanceof StoredMeasureData) {
|
||||
final StoredMeasureData data = (StoredMeasureData) structure;
|
||||
descriptions.add("0117(type=" + data.getMeasurementType() + ",raw=" + data.getRawValue() + ")");
|
||||
} else if (structure instanceof StoredMeasureDataExtend) {
|
||||
final StoredMeasureDataExtend dataExt = (StoredMeasureDataExtend) structure;
|
||||
descriptions.add("0149(type=" + dataExt.getMeasurementType() + ",extra=" + dataExt.getExtraData() + ")");
|
||||
} else if (structure instanceof StoredSignalMeta) {
|
||||
final StoredSignalMeta meta = (StoredSignalMeta) structure;
|
||||
descriptions.add("0143(signalType=" + meta.getSignalType() + ",flags=" + meta.getSignalFlags() + ",cursor=" + meta.getCursor() + ")");
|
||||
} else if (structure instanceof StoredSignalMetaExtended) {
|
||||
final byte[] rawPayload = ((StoredSignalMetaExtended) structure).getRawPayload();
|
||||
descriptions.add("0146(" + GB.hexdump(rawPayload) + ")");
|
||||
} else if (structure instanceof StoredSignalData) {
|
||||
descriptions.add("0144(samples)");
|
||||
} else if (structure instanceof RawWithingsStructure) {
|
||||
final RawWithingsStructure raw = (RawWithingsStructure) structure;
|
||||
descriptions.add(String.format("0x%04x(raw=%s)", raw.getType() & 0xffff, GB.hexdump(raw.getRawData())));
|
||||
} else {
|
||||
descriptions.add(String.format("0x%04x", structure.getType() & 0xffff));
|
||||
}
|
||||
}
|
||||
return descriptions.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private void storeWaveform(final long start,
|
||||
|
||||
Reference in New Issue
Block a user