From caed9dd64b5d84ffeed719ed985cf1fe8b942ff1 Mon Sep 17 00:00:00 2001 From: Navid200 <51497406+Navid200@users.noreply.github.com> Date: Thu, 30 Jan 2025 08:33:42 -0500 Subject: [PATCH 1/5] Notify and log failure to upload to Nightscout consistently --- .../dexdrip/services/DailyIntentService.java | 7 ++++++ .../utilitymodels/NightscoutUploader.java | 22 ++++++++++++++++++- app/src/main/res/values/strings.xml | 4 ++++ app/src/main/res/xml/pref_data_sync.xml | 5 +++++ 4 files changed, 37 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/eveningoutpost/dexdrip/services/DailyIntentService.java b/app/src/main/java/com/eveningoutpost/dexdrip/services/DailyIntentService.java index 25906442e7..0236bd7eb9 100644 --- a/app/src/main/java/com/eveningoutpost/dexdrip/services/DailyIntentService.java +++ b/app/src/main/java/com/eveningoutpost/dexdrip/services/DailyIntentService.java @@ -20,6 +20,7 @@ import com.eveningoutpost.dexdrip.utilitymodels.BgSendQueue; import com.eveningoutpost.dexdrip.utilitymodels.CalibrationSendQueue; import com.eveningoutpost.dexdrip.utilitymodels.IncompatibleApps; +import com.eveningoutpost.dexdrip.utilitymodels.NightscoutUploader; import com.eveningoutpost.dexdrip.utilitymodels.Pref; import com.eveningoutpost.dexdrip.utilitymodels.UploaderQueue; import com.eveningoutpost.dexdrip.cloud.backup.Backup; @@ -173,6 +174,12 @@ public static synchronized void work() { Log.e(TAG, "Exception in SettingsValidation: " + e); } + try { + NightscoutUploader.notifyInconsistentMultiSiteUpload(); + } catch (Exception e) { + Log.e(TAG, "Exception in Nightscout multi site upload failure log: " + e); + } + Log.i(TAG, "DailyIntentService onHandleIntent exiting after " + ((JoH.tsl() - start) / 1000) + " seconds"); //} else { // Log.e(TAG, "DailyIntentService exceeding rate limit"); diff --git a/app/src/main/java/com/eveningoutpost/dexdrip/utilitymodels/NightscoutUploader.java b/app/src/main/java/com/eveningoutpost/dexdrip/utilitymodels/NightscoutUploader.java index f466fdbf4a..621fd0dda1 100644 --- a/app/src/main/java/com/eveningoutpost/dexdrip/utilitymodels/NightscoutUploader.java +++ b/app/src/main/java/com/eveningoutpost/dexdrip/utilitymodels/NightscoutUploader.java @@ -8,6 +8,7 @@ import com.eveningoutpost.dexdrip.Home; import com.eveningoutpost.dexdrip.MegaStatus; +import com.eveningoutpost.dexdrip.R; import com.eveningoutpost.dexdrip.models.BgReading; import com.eveningoutpost.dexdrip.models.BloodTest; import com.eveningoutpost.dexdrip.models.Calibration; @@ -115,6 +116,8 @@ public class NightscoutUploader { public static final int FAIl_COUNT_NOTIFICATION = FAIL_NOTIFICATION_PERIOD / 60 / 5 - 1; // Number of 5-minute read cycles corresponding to notification period public static final int FAIL_LOG_PERIOD = 6 * 60 * 60; // FAILED upload/download log will be shown if there is no upload/download for 6 hours. public static final int FAIL_COUNT_LOG = FAIL_LOG_PERIOD / 60 / 5 - 1; // Number of 5-minute read cycles corresponding to log period + public static boolean inconsistentMultiSteUpload = false; // False if all site uploads fail or all succeed. True only if there is inconsistent upload success. + public static long firstInconsistentMultiSiteUploadTime; private Context mContext; private Boolean enableRESTUpload; @@ -500,14 +503,31 @@ private boolean doRESTUpload(SharedPreferences prefs, List glucoseDat last_success_time = JoH.tsl(); last_exception_count = 0; last_exception_log_count = 0; - } catch (Exception e) { + } catch (Exception e) { // There has been a failure. String msg = "Unable to do REST API Upload: " + e.getMessage() + " marking record: " + (any_successes ? "succeeded" : "failed"); handleRestFailure(msg); + if (any_successes) { // If there has been a success + if (!inconsistentMultiSteUpload) { + firstInconsistentMultiSiteUploadTime = JoH.tsl(); + } + inconsistentMultiSteUpload = true; // There has been success as well as failure. + } } } return any_successes; } + public static void notifyInconsistentMultiSiteUpload() { + if (inconsistentMultiSteUpload) { // We need to inform the user that even though there has been a failure to upload, the queue has been cleared. + // Therefore, the only way to complete the intended upload is to backfill manually. + if (Pref.getBooleanDefaultFalse("warn_nightscout_multi_site_upload_failure")) { // Issue notification only if enabled + JoH.showNotification(xdrip.gs(R.string.title_nightscout_upload_failure_backfill_required), null, null, Constants.NIGHTSCOUT_ERROR_NOTIFICATION_ID, null, false, false, null, null, xdrip.gs(R.string.nightscout_upload_failure_backfill_required, JoH.dateTimeText(firstInconsistentMultiSiteUploadTime)), true); + } + UserError.Log.uel(TAG, "Inconsistent Multi-site Nightscout upload - Backfill recommended - First failure: " + JoH.dateTimeText(firstInconsistentMultiSiteUploadTime)); + inconsistentMultiSteUpload = false; // We have notified. Clearing the flag + } + } + private void doLegacyRESTUploadTo(NightscoutService nightscoutService, List glucoseDataSets) throws Exception { for (BgReading record : glucoseDataSets) { Response r = nightscoutService.upload(populateLegacyAPIEntry(record)).execute(); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6ff060682b..f005c09732 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1225,6 +1225,8 @@ Also try to download treatments from Nightscout Download treatments Skip items from xDrip + Uploads have not succeeded for all sites. Backfill is recommended. First failure: %1$s + Inconsistent Multi-Site Nightscout Upload Avoid downloading items uploaded by xDrip Calibrate using new blood glucose readings if the conditions appear right to do so without asking confirmation (experimental) Automatic Calibration @@ -1237,6 +1239,8 @@ Upload treatments Display and sound a notification if Nightscout upload is failing. Alert on failures + xDrip clears the upload queue even if only one site has a successful upload, leaving others incomplete. This notifies you, allowing you to backfill as needed. + Alert on multi-site upload failure For Dex, sends collector type (e.g. OB1) and reading backfill status (for native) to Nightscout. Append source info to device name Tap to send historical data to Nightscout diff --git a/app/src/main/res/xml/pref_data_sync.xml b/app/src/main/res/xml/pref_data_sync.xml index 342901babb..427fac7049 100644 --- a/app/src/main/res/xml/pref_data_sync.xml +++ b/app/src/main/res/xml/pref_data_sync.xml @@ -122,6 +122,11 @@ android:key="nightscout_device_append_source_info" android:summary="@string/summary_nightscout_device_append_source_info" android:title="@string/title_nightscout_device_append_source_info" /> + Date: Wed, 19 Feb 2025 08:42:31 -0500 Subject: [PATCH 2/5] Corrected sequence --- .../utilitymodels/NightscoutUploader.java | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/eveningoutpost/dexdrip/utilitymodels/NightscoutUploader.java b/app/src/main/java/com/eveningoutpost/dexdrip/utilitymodels/NightscoutUploader.java index 621fd0dda1..357048cf70 100644 --- a/app/src/main/java/com/eveningoutpost/dexdrip/utilitymodels/NightscoutUploader.java +++ b/app/src/main/java/com/eveningoutpost/dexdrip/utilitymodels/NightscoutUploader.java @@ -466,7 +466,9 @@ private boolean doRESTUpload(SharedPreferences prefs, List glucoseDat Log.e(TAG, "Unable to process API Base URL: " + e); return false; } + // Starting a loop run; resetting local failure and success flags boolean any_successes = false; + boolean any_failures = false; for (String baseURI : baseURIs) { try { baseURI = TryResolveName(baseURI); @@ -499,21 +501,22 @@ private boolean doRESTUpload(SharedPreferences prefs, List glucoseDat } else { doLegacyRESTUploadTo(nightscoutService, glucoseDataSets); } - any_successes = true; + any_successes = true; // There has been a success last_success_time = JoH.tsl(); last_exception_count = 0; last_exception_log_count = 0; - } catch (Exception e) { // There has been a failure. + } catch (Exception e) { String msg = "Unable to do REST API Upload: " + e.getMessage() + " marking record: " + (any_successes ? "succeeded" : "failed"); + any_failures = true; // There has been a failure handleRestFailure(msg); - if (any_successes) { // If there has been a success - if (!inconsistentMultiSteUpload) { - firstInconsistentMultiSiteUploadTime = JoH.tsl(); - } - inconsistentMultiSteUpload = true; // There has been success as well as failure. - } } } + if (any_successes && any_failures) { // If there has been success as well as failure (inconsistent upload) + if (!inconsistentMultiSteUpload) { // If there has been no inconsistent upload yet + firstInconsistentMultiSiteUploadTime = JoH.tsl(); // Record this time as the time of the first inconsistent upload + } + inconsistentMultiSteUpload = true; // There has been success as well as failure. + } return any_successes; } From eea678c1f0fa13349c797f63ca4fdab938a4e7f2 Mon Sep 17 00:00:00 2001 From: Navid200 <51497406+Navid200@users.noreply.github.com> Date: Wed, 19 Feb 2025 09:07:30 -0500 Subject: [PATCH 3/5] Cleanup --- .../dexdrip/utilitymodels/NightscoutUploader.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/eveningoutpost/dexdrip/utilitymodels/NightscoutUploader.java b/app/src/main/java/com/eveningoutpost/dexdrip/utilitymodels/NightscoutUploader.java index 357048cf70..527d895bd4 100644 --- a/app/src/main/java/com/eveningoutpost/dexdrip/utilitymodels/NightscoutUploader.java +++ b/app/src/main/java/com/eveningoutpost/dexdrip/utilitymodels/NightscoutUploader.java @@ -512,10 +512,10 @@ private boolean doRESTUpload(SharedPreferences prefs, List glucoseDat } } if (any_successes && any_failures) { // If there has been success as well as failure (inconsistent upload) - if (!inconsistentMultiSteUpload) { // If there has been no inconsistent upload yet + if (!inconsistentMultiSteUpload) { // If there had been no inconsistent uploads yet, which makes this the first firstInconsistentMultiSiteUploadTime = JoH.tsl(); // Record this time as the time of the first inconsistent upload } - inconsistentMultiSteUpload = true; // There has been success as well as failure. + inconsistentMultiSteUpload = true; // There has been inconsistent upload and we have recorded the time. } return any_successes; } From e5d2e5c35c4dad85987bc5255e287d0c1738b2cf Mon Sep 17 00:00:00 2001 From: Navid200 <51497406+Navid200@users.noreply.github.com> Date: Thu, 6 Mar 2025 12:00:04 -0500 Subject: [PATCH 4/5] PersistentStore --- .../utilitymodels/NightscoutUploader.java | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/eveningoutpost/dexdrip/utilitymodels/NightscoutUploader.java b/app/src/main/java/com/eveningoutpost/dexdrip/utilitymodels/NightscoutUploader.java index 527d895bd4..1fe407af7f 100644 --- a/app/src/main/java/com/eveningoutpost/dexdrip/utilitymodels/NightscoutUploader.java +++ b/app/src/main/java/com/eveningoutpost/dexdrip/utilitymodels/NightscoutUploader.java @@ -116,8 +116,6 @@ public class NightscoutUploader { public static final int FAIl_COUNT_NOTIFICATION = FAIL_NOTIFICATION_PERIOD / 60 / 5 - 1; // Number of 5-minute read cycles corresponding to notification period public static final int FAIL_LOG_PERIOD = 6 * 60 * 60; // FAILED upload/download log will be shown if there is no upload/download for 6 hours. public static final int FAIL_COUNT_LOG = FAIL_LOG_PERIOD / 60 / 5 - 1; // Number of 5-minute read cycles corresponding to log period - public static boolean inconsistentMultiSteUpload = false; // False if all site uploads fail or all succeed. True only if there is inconsistent upload success. - public static long firstInconsistentMultiSiteUploadTime; private Context mContext; private Boolean enableRESTUpload; @@ -511,23 +509,23 @@ private boolean doRESTUpload(SharedPreferences prefs, List glucoseDat handleRestFailure(msg); } } - if (any_successes && any_failures) { // If there has been success as well as failure (inconsistent upload) - if (!inconsistentMultiSteUpload) { // If there had been no inconsistent uploads yet, which makes this the first - firstInconsistentMultiSiteUploadTime = JoH.tsl(); // Record this time as the time of the first inconsistent upload + if (any_successes && any_failures) { // Only if there has been success as well as failure (inconsistent upload) + if (!PersistentStore.getBoolean(TAG + "inconsistentMultiSteUpload")) { // If there had been no inconsistent uploads yet, which makes this the first + PersistentStore.setLong(TAG + "firstInconsistentMultiSiteUploadTime", JoH.tsl()); // Record this time as the time of the first inconsistent upload } - inconsistentMultiSteUpload = true; // There has been inconsistent upload and we have recorded the time. + PersistentStore.setBoolean(TAG + "inconsistentMultiSteUpload", true); // There has been inconsistent upload and we have recorded the time. Let's set the flag. } return any_successes; } public static void notifyInconsistentMultiSiteUpload() { - if (inconsistentMultiSteUpload) { // We need to inform the user that even though there has been a failure to upload, the queue has been cleared. - // Therefore, the only way to complete the intended upload is to backfill manually. + long firstInconsistentMultiSiteUploadTime = PersistentStore.getLong(TAG + "firstInconsistentMultiSiteUploadTime"); // Updating the local representation of the last inconsistent upload time + if (PersistentStore.getBoolean(TAG + "inconsistentMultiSteUpload")) { // If there has been a failure to upload and the queue has been cleared if (Pref.getBooleanDefaultFalse("warn_nightscout_multi_site_upload_failure")) { // Issue notification only if enabled JoH.showNotification(xdrip.gs(R.string.title_nightscout_upload_failure_backfill_required), null, null, Constants.NIGHTSCOUT_ERROR_NOTIFICATION_ID, null, false, false, null, null, xdrip.gs(R.string.nightscout_upload_failure_backfill_required, JoH.dateTimeText(firstInconsistentMultiSiteUploadTime)), true); } UserError.Log.uel(TAG, "Inconsistent Multi-site Nightscout upload - Backfill recommended - First failure: " + JoH.dateTimeText(firstInconsistentMultiSiteUploadTime)); - inconsistentMultiSteUpload = false; // We have notified. Clearing the flag + PersistentStore.setBoolean(TAG + "inconsistentMultiSteUpload", false); // We have notified. Clearing the flag } } From 94a39178fcc8b0aefedcb7ed2cf241a9640db7a3 Mon Sep 17 00:00:00 2001 From: Navid200 <51497406+Navid200@users.noreply.github.com> Date: Thu, 6 Mar 2025 23:28:41 -0500 Subject: [PATCH 5/5] Cleanup --- .../dexdrip/utilitymodels/NightscoutUploader.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/eveningoutpost/dexdrip/utilitymodels/NightscoutUploader.java b/app/src/main/java/com/eveningoutpost/dexdrip/utilitymodels/NightscoutUploader.java index 1fe407af7f..0e213b3741 100644 --- a/app/src/main/java/com/eveningoutpost/dexdrip/utilitymodels/NightscoutUploader.java +++ b/app/src/main/java/com/eveningoutpost/dexdrip/utilitymodels/NightscoutUploader.java @@ -510,22 +510,22 @@ private boolean doRESTUpload(SharedPreferences prefs, List glucoseDat } } if (any_successes && any_failures) { // Only if there has been success as well as failure (inconsistent upload) - if (!PersistentStore.getBoolean(TAG + "inconsistentMultiSteUpload")) { // If there had been no inconsistent uploads yet, which makes this the first - PersistentStore.setLong(TAG + "firstInconsistentMultiSiteUploadTime", JoH.tsl()); // Record this time as the time of the first inconsistent upload + if (!PersistentStore.getBoolean(TAG + "_inconsistentMultiSteUpload")) { // If there had been no inconsistent uploads yet, which makes this the first + PersistentStore.setLong(TAG + "_firstInconsistentMultiSiteUploadTime", JoH.tsl()); // Record this time as the time of the first inconsistent upload } - PersistentStore.setBoolean(TAG + "inconsistentMultiSteUpload", true); // There has been inconsistent upload and we have recorded the time. Let's set the flag. + PersistentStore.setBoolean(TAG + "_inconsistentMultiSteUpload", true); // There has been inconsistent upload and we have recorded the time. Let's set the flag. } return any_successes; } public static void notifyInconsistentMultiSiteUpload() { - long firstInconsistentMultiSiteUploadTime = PersistentStore.getLong(TAG + "firstInconsistentMultiSiteUploadTime"); // Updating the local representation of the last inconsistent upload time - if (PersistentStore.getBoolean(TAG + "inconsistentMultiSteUpload")) { // If there has been a failure to upload and the queue has been cleared + long firstInconsistentMultiSiteUploadTime = PersistentStore.getLong(TAG + "_firstInconsistentMultiSiteUploadTime"); // Updating the local representation of the last inconsistent upload time + if (PersistentStore.getBoolean(TAG + "_inconsistentMultiSteUpload")) { // If there has been a failure to upload and the queue has been cleared if (Pref.getBooleanDefaultFalse("warn_nightscout_multi_site_upload_failure")) { // Issue notification only if enabled JoH.showNotification(xdrip.gs(R.string.title_nightscout_upload_failure_backfill_required), null, null, Constants.NIGHTSCOUT_ERROR_NOTIFICATION_ID, null, false, false, null, null, xdrip.gs(R.string.nightscout_upload_failure_backfill_required, JoH.dateTimeText(firstInconsistentMultiSiteUploadTime)), true); } UserError.Log.uel(TAG, "Inconsistent Multi-site Nightscout upload - Backfill recommended - First failure: " + JoH.dateTimeText(firstInconsistentMultiSiteUploadTime)); - PersistentStore.setBoolean(TAG + "inconsistentMultiSteUpload", false); // We have notified. Clearing the flag + PersistentStore.setBoolean(TAG + "_inconsistentMultiSteUpload", false); // We have notified. Clearing the flag } }