From afcedc83d1b1d5ad75e32c028cd8823fc47eb929 Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Sat, 30 Mar 2019 18:36:50 +0000 Subject: [PATCH] 0.8.2 - done some fixes according to Crashalytics (most common problem from last month) - extended custom actions, to have enabled flag, and if entry is enabled=false button is not added. Added EventCustomActionsChanged event that can refresh custom actions - #111 - do not put multiple statuses into queue - #110 - set driver busy if wake up and tune is running - #104 - when bolus is delivering driver is set to busy, and custom action was added to remove this block --- app/build.gradle | 6 +- .../events/EventCustomActionsChanged.java | 4 + .../general/actions/ActionsFragment.java | 10 + .../general/actions/defs/CustomAction.java | 17 + .../dialog/RileyLinkBLEScanActivity.java | 3 + .../common/hw/rileylink/RileyLinkUtil.java | 5 +- .../common/hw/rileylink/ble/RileyLinkBLE.java | 9 +- .../service/tasks/WakeAndTuneTask.java | 3 + .../pump/medtronic/MedtronicPumpPlugin.java | 98 ++++- .../comm/history/MedtronicHistoryEntry.java | 29 +- .../pump/MedtronicPumpHistoryDecoder.java | 44 +-- .../comm/history/pump/PumpHistoryEntry.java | 8 + .../comm/ui/MedtronicUIPostprocessor.java | 4 +- .../medtronic/data/MedtronicHistoryData.java | 374 ++++++++++++++++-- .../pump/medtronic/data/dto/BasalProfile.java | 12 +- .../medtronic/data/dto/BasalProfileEntry.java | 15 +- .../pump/medtronic/data/dto/ClockDTO.java | 4 +- .../defs/MedtronicCustomActionType.java | 4 +- .../pump/medtronic/util/MedtronicUtil.java | 2 +- .../plugins/treatments/TreatmentsPlugin.java | 3 +- .../androidaps/queue/CommandQueue.java | 13 + app/src/main/res/values/strings.xml | 1 + 22 files changed, 564 insertions(+), 104 deletions(-) create mode 100644 app/src/main/java/info/nightscout/androidaps/events/EventCustomActionsChanged.java diff --git a/app/build.gradle b/app/build.gradle index 812338b963..8220158fae 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -64,7 +64,7 @@ android { multiDexEnabled true versionCode 1500 // dev_version: 2.1 - version "medtronic-0.8.1-SNAPSHOT" + version "medtronic-0.8.2-SNAPSHOT" buildConfigField "String", "VERSION", '"' + version + '"' buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"' buildConfigField "String", "HEAD", '"' + generateGitBuild() + '"' @@ -116,7 +116,7 @@ android { resValue "string", "app_name", "Pumpcontrol" versionName version manifestPlaceholders = [ - appIcon: "@mipmap/ic_pumpcontrol", + appIcon : "@mipmap/ic_pumpcontrol", appIconRound: "@null" ] } @@ -151,7 +151,7 @@ android { unitTests.includeAndroidResources = true } - useLibrary "org.apache.http.legacy" + useLibrary "org.apache.http.legacy" } allprojects { diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventCustomActionsChanged.java b/app/src/main/java/info/nightscout/androidaps/events/EventCustomActionsChanged.java new file mode 100644 index 0000000000..81d1f60271 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventCustomActionsChanged.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.events; + +public class EventCustomActionsChanged extends Event { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.java index 7121e16ff7..958e22b1f3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.java @@ -26,6 +26,7 @@ import info.nightscout.androidaps.activities.HistoryBrowseActivity; import info.nightscout.androidaps.activities.TDDStatsActivity; import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.TemporaryBasal; +import info.nightscout.androidaps.events.EventCustomActionsChanged; import info.nightscout.androidaps.events.EventExtendedBolusChange; import info.nightscout.androidaps.events.EventInitializationChanged; import info.nightscout.androidaps.events.EventRefreshOverview; @@ -135,6 +136,12 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL } + @Subscribe + public void onStatusEvent(final EventCustomActionsChanged ev) { + updateGUI(); + } + + @Override protected void updateGUI() { Activity activity = getActivity(); @@ -257,6 +264,9 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL for (CustomAction customAction : customActions) { + if (!customAction.isEnabled()) + continue; + SingleClickButton btn = new SingleClickButton(getContext(), null, android.R.attr.buttonStyle); btn.setText(MainApp.gs(customAction.getName())); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/defs/CustomAction.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/defs/CustomAction.java index 380abdb3f9..8e0bf1d81b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/defs/CustomAction.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/defs/CustomAction.java @@ -9,11 +9,18 @@ public class CustomAction { private int name; private String iconName; private CustomActionType customActionType; + private boolean enabled = true; public CustomAction(int nameResourceId, CustomActionType actionType) { + this(nameResourceId, actionType, true); + } + + + public CustomAction(int nameResourceId, CustomActionType actionType, boolean enabled) { this.name = nameResourceId; this.customActionType = actionType; + this.enabled = enabled; } @@ -45,4 +52,14 @@ public class CustomAction { this.customActionType = customActionType; } + + + public boolean isEnabled() { + return enabled; + } + + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/dialog/RileyLinkBLEScanActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/dialog/RileyLinkBLEScanActivity.java index c114237ee6..cb68261f25 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/dialog/RileyLinkBLEScanActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/dialog/RileyLinkBLEScanActivity.java @@ -283,6 +283,9 @@ public class RileyLinkBLEScanActivity extends AppCompatActivity { private void scanLeDevice(final boolean enable) { + if (mLEScanner == null) + return; + if (enable) { mLeDeviceListAdapter.clear(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/RileyLinkUtil.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/RileyLinkUtil.java index 954a7de04f..f555ec0295 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/RileyLinkUtil.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/RileyLinkUtil.java @@ -130,10 +130,9 @@ public class RileyLinkUtil { return null; } else { - - return RileyLinkUtil.rileyLinkServiceData.serviceState == null ? RileyLinkServiceState.NotStarted + return (RileyLinkUtil.rileyLinkServiceData == null || RileyLinkUtil.rileyLinkServiceData.serviceState == null) ? // + RileyLinkServiceState.NotStarted : RileyLinkUtil.rileyLinkServiceData.serviceState; - } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/RileyLinkBLE.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/RileyLinkBLE.java index 938b7cc88c..42ca36b528 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/RileyLinkBLE.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/RileyLinkBLE.java @@ -18,7 +18,6 @@ import android.bluetooth.BluetoothGattService; import android.bluetooth.BluetoothProfile; import android.content.Context; import android.os.SystemClock; -import android.widget.Toast; import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst; import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil; @@ -330,6 +329,12 @@ public class RileyLinkBLE { public boolean discoverServices() { + + if (bluetoothConnectionGatt == null) { + // shouldn't happen, but if it does we exit + return false; + } + if (bluetoothConnectionGatt.discoverServices()) { LOG.warn("Starting to discover GATT Services."); return true; @@ -367,7 +372,7 @@ public class RileyLinkBLE { // , BluetoothDevice.TRANSPORT_LE if (bluetoothConnectionGatt == null) { LOG.error("Failed to connect to Bluetooth Low Energy device at " + bluetoothAdapter.getAddress()); - Toast.makeText(context, "No Rileylink at " + bluetoothAdapter.getAddress(), Toast.LENGTH_SHORT).show(); + // Toast.makeText(context, "No Rileylink at " + bluetoothAdapter.getAddress(), Toast.LENGTH_SHORT).show(); } else { if (gattDebugEnabled) { LOG.debug("Gatt Connected?"); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/tasks/WakeAndTuneTask.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/tasks/WakeAndTuneTask.java index 85c125439c..13ffba516a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/tasks/WakeAndTuneTask.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/tasks/WakeAndTuneTask.java @@ -2,6 +2,7 @@ package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.task import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.data.ServiceTransport; import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicFragment; +import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin; import info.nightscout.androidaps.plugins.pump.medtronic.service.RileyLinkMedtronicService; /** @@ -24,7 +25,9 @@ public class WakeAndTuneTask extends PumpTask { @Override public void run() { MedtronicFragment.refreshButtonEnabled(false); + MedtronicPumpPlugin.isBusy = true; RileyLinkMedtronicService.getInstance().doTuneUpDevice(); + MedtronicPumpPlugin.isBusy = false; MedtronicFragment.refreshButtonEnabled(true); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.java index ca55524b5f..5c0e4e08db 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.java @@ -1,6 +1,7 @@ package info.nightscout.androidaps.plugins.pump.medtronic; import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.HashSet; @@ -31,6 +32,7 @@ import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.TemporaryBasal; +import info.nightscout.androidaps.events.EventCustomActionsChanged; import info.nightscout.androidaps.events.EventRefreshOverview; import info.nightscout.androidaps.interfaces.PluginDescription; import info.nightscout.androidaps.interfaces.PluginType; @@ -73,6 +75,8 @@ import info.nightscout.androidaps.utils.SP; /** * Created by andy on 23.04.18. + * + * @author Andy Rozman (andy.rozman@gmail.com) */ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInterface { @@ -98,6 +102,9 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter public static Gson gsonInstancePretty = new GsonBuilder().excludeFieldsWithoutExposeAnnotation() .setPrettyPrinting().create(); + public static boolean isBusy = false; + private List busyTimestamps = new ArrayList<>(); + private MedtronicPumpPlugin() { @@ -198,7 +205,6 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter } - // TODO remove private void migrateSettings() { if ("US (916 MHz)".equals(SP.getString(MedtronicConst.Prefs.PumpFrequency, null))) { @@ -222,7 +228,10 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter StatusRefreshAction.GetData, null, null); if (doWeHaveAnyStatusNeededRefereshing(statusRefresh)) { - ConfigBuilderPlugin.getPlugin().getCommandQueue().readStatus("Scheduled Status Refresh", null); + if (!ConfigBuilderPlugin.getPlugin().getCommandQueue().statusInQueue()) { + ConfigBuilderPlugin.getPlugin().getCommandQueue() + .readStatus("Scheduled Status Refresh", null); + } } } @@ -274,10 +283,49 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter @Override public boolean isBusy() { - // TODO remove - if (isLoggingEnabled()) + if (isLoggingEnabled() && displayConnectionMessages) LOG.debug("MedtronicPumpPlugin::isBusy"); - return isServiceSet() && medtronicService.isBusy(); + + if (isServiceSet()) { + + if (isBusy) + return true; + + if (busyTimestamps.size() > 0) { + + clearBusyQueue(); + + if (busyTimestamps.size() > 0) { + return true; + } + } + } + + return false; + } + + + private void clearBusyQueue() { + + Set deleteFromQueue = new HashSet<>(); + + for (Long busyTimestamp : busyTimestamps) { + + if (System.currentTimeMillis() > busyTimestamp) { + deleteFromQueue.add(busyTimestamp); + } + } + + if (deleteFromQueue.size() == busyTimestamps.size()) { + busyTimestamps.clear(); + this.customActionClearBolusBlock.setEnabled(false); + refreshCustomActionsList(); + } + + if (deleteFromQueue.size() > 0) { + busyTimestamps.removeAll(deleteFromQueue); + } + } @@ -691,7 +739,6 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter }).start(); } - // FIXME this needs to be fixed to read info from history boolean treatmentCreated = TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, true); // we subtract insulin, exact amount will be visible with next remainingInsulin update. @@ -700,6 +747,15 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter incrementStatistics(detailedBolusInfo.isSMB ? MedtronicConst.Statistics.SMBBoluses : MedtronicConst.Statistics.StandardBoluses); + if (response) { + int bolusTime = (int)(detailedBolusInfo.insulin * 42.0d); + long time = System.currentTimeMillis() + (bolusTime * 1000); + + this.busyTimestamps.add(time); + this.customActionClearBolusBlock.setEnabled(true); + refreshCustomActionsList(); + } + return new PumpEnactResult().success(response) // .enacted(response) // .bolusDelivered(detailedBolusInfo.insulin) // @@ -912,13 +968,11 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter if (this.getMDTPumpStatus().basalProfileStatus != BasalProfileStatus.NotInitialized && medtronicHistoryData.hasBasalProfileChanged()) { medtronicHistoryData.processLastBasalProfileChange(getMDTPumpStatus()); - // this.basalProfileChanged = true; } PumpDriverState previousState = this.pumpState; - if (medtronicHistoryData.isPumpSuspended(this.pumpState == PumpDriverState.Suspended)) { - // scheduleNextRefresh(MedtronicStatusRefreshType.PumpTime, -1); + if (medtronicHistoryData.isPumpSuspended()) { this.pumpState = PumpDriverState.Suspended; if (isLoggingEnabled()) LOG.debug(getLogPrefix() + "isPumpSuspended: true"); @@ -1325,17 +1379,18 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter List customActions = null; + CustomAction customActionWakeUpAndTune = new CustomAction(R.string.medtronic_custom_action_wake_and_tune, + MedtronicCustomActionType.WakeUpAndTune); + + CustomAction customActionClearBolusBlock = new CustomAction(R.string.medtronic_custom_action_clear_bolus_block, + MedtronicCustomActionType.ClearBolusBlock); + @Override public List getCustomActions() { if (customActions == null) { - - this.customActions = new ArrayList<>(); - - CustomAction ca = new CustomAction(R.string.medtronic_custom_action_wake_and_tune, - MedtronicCustomActionType.WakeUpAndTune); - this.customActions.add(ca); + this.customActions = Arrays.asList(customActionWakeUpAndTune, customActionClearBolusBlock); } return this.customActions; @@ -1353,10 +1408,23 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter ServiceTaskExecutor.startTask(new WakeAndTuneTask()); break; + case ClearBolusBlock: { + this.busyTimestamps.clear(); + this.customActionClearBolusBlock.setEnabled(false); + refreshCustomActionsList(); + } + break; + default: break; } return null; } + + + private void refreshCustomActionsList() { + MainApp.bus().post(new EventCustomActionsChanged()); + } + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.java index dc267ebf1c..8183997bbe 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.java @@ -4,8 +4,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.joda.time.format.DateTimeFormat; -import org.joda.time.format.DateTimeFormatter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -41,7 +39,6 @@ public abstract class MedtronicHistoryEntry implements MedtronicHistoryEntryInte protected List rawData; - protected static DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern("dd.MM.yyyy HH:mm:ss"); public static final Logger LOG = LoggerFactory.getLogger(MedtronicHistoryEntry.class); protected int[] sizes = new int[3]; @@ -56,11 +53,35 @@ public abstract class MedtronicHistoryEntry implements MedtronicHistoryEntryInte public String DT; @Expose - public long atechDateTime; + public Long atechDateTime; @Expose protected Map decodedData; + public long phoneDateTime; // time on phone + + /** + * Pump id that will be used with AAPS object (time * 1000 + historyType (max is FF = 255) + */ + public long pumpId; + + /** + * if history object is already linked to AAPS object (either Treatment, TempBasal or TDD (tdd's are not actually + * linked)) + */ + public boolean linked = false; + + /** + * Linked object, see linked + */ + public Object linkedObject = null; + + + public void setLinkedObject(Object linkedObject) { + this.linked = true; + this.linkedObject = linkedObject; + } + public void setData(List listRawData, boolean doNotProcess) { this.rawData = listRawData; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.java index cb73a73f31..67a3bed932 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.java @@ -6,7 +6,6 @@ import java.util.List; import java.util.Locale; import java.util.Map; -import org.joda.time.LocalDateTime; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -708,24 +707,24 @@ public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder> 4) + ((dt[1] & 0x80) >> 7)); // int year = fix2DigitYear(dt[1] & 0x3F); - LocalDateTime atdate = null; - LOG.debug("DT: {} {} {}", year, month, dayOfMonth); if (dayOfMonth == 32) { @@ -835,22 +823,16 @@ public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder fakeTBRs; + DatabaseHelper databaseHelper = MainApp.getDbHelper(); + public MedtronicHistoryData() { this.allHistory = new ArrayList<>(); @@ -205,26 +214,57 @@ public class MedtronicHistoryData { // TODO This logic might not be working correctly - public boolean isPumpSuspended(Boolean wasPumpSuspended) { + public boolean isPumpSuspended() { + + List items = getDataForSuspends(false); + + showLogs("isPumpSuspendCheck: ", MedtronicPumpPlugin.gsonInstancePretty.toJson(items)); + + if (!items.isEmpty()) { + + PumpHistoryEntryType pumpHistoryEntryType = items.get(0).getEntryType(); + + LOG.debug("Last entry type: {}", pumpHistoryEntryType); + + return !(pumpHistoryEntryType == PumpHistoryEntryType.TempBasalCombined || // + pumpHistoryEntryType == PumpHistoryEntryType.BasalProfileStart || // + pumpHistoryEntryType == PumpHistoryEntryType.Bolus || // + pumpHistoryEntryType == PumpHistoryEntryType.PumpResume || // + pumpHistoryEntryType == PumpHistoryEntryType.Prime); + } else + return false; + + } + + + private List getDataForSuspends(boolean forHistory) { List newAndAll = new ArrayList<>(); if (!isCollectionEmpty(this.allHistory)) { - newAndAll.addAll(this.allHistory); + + if (forHistory) { + // TODO we filter all history ang get last 2 + } else { + newAndAll.addAll(this.allHistory); + } } if (!isCollectionEmpty(this.newHistory)) { - newAndAll.addAll(this.newHistory); + + for (PumpHistoryEntry pumpHistoryEntry : newHistory) { + if (!newAndAll.contains(pumpHistoryEntry)) { + newAndAll.add(pumpHistoryEntry); + } + } } if (newAndAll.isEmpty()) - return false; + return newAndAll; this.sort(newAndAll); - List newAndAll2 = filterPumpSuspend(newAndAll); - - List items = getFilteredItems(newAndAll, // + List newAndAll2 = getFilteredItems(newAndAll, // PumpHistoryEntryType.Bolus, // PumpHistoryEntryType.TempBasalCombined, // PumpHistoryEntryType.Prime, // @@ -234,30 +274,25 @@ public class MedtronicHistoryData { PumpHistoryEntryType.NoDeliveryAlarm, // PumpHistoryEntryType.BasalProfileStart); - showLogs("isPumpSuspendCheck: ", MedtronicPumpPlugin.gsonInstancePretty.toJson(items)); + if (!forHistory) { + newAndAll2 = filterPumpSuspend(newAndAll2, 10); // just last 10 (of relevant), for history we already + // filtered + } - PumpHistoryEntryType pumpHistoryEntryType = items.get(0).getEntryType(); - - LOG.debug("Last entry type: {}", pumpHistoryEntryType); - - return !(pumpHistoryEntryType == PumpHistoryEntryType.TempBasalCombined || // - pumpHistoryEntryType == PumpHistoryEntryType.BasalProfileStart || // - pumpHistoryEntryType == PumpHistoryEntryType.Bolus || // - pumpHistoryEntryType == PumpHistoryEntryType.PumpResume || // - pumpHistoryEntryType == PumpHistoryEntryType.Prime); + return newAndAll2; } - private List filterPumpSuspend(List newAndAll) { + private List filterPumpSuspend(List newAndAll, int filterCount) { - if (newAndAll.size() < 11) { + if (newAndAll.size() <= filterCount) { return newAndAll; } List newAndAllOut = new ArrayList<>(); - for (int i = 0; i < 10; i++) { + for (int i = 0; i < filterCount; i++) { newAndAllOut.add(newAndAll.get(i)); } @@ -276,24 +311,24 @@ public class MedtronicHistoryData { LOG.debug("ProcessHistoryData: TDD [count={}, items={}]", tdds.size(), gsonPretty.toJson(tdds)); if (!isCollectionEmpty(tdds)) { - processTDDs(tdds); + //processTDDs(tdds); } + pumpTime = MedtronicUtil.getPumpTime(); + // Bolus List treatments = getFilteredListByLastRecord(PumpHistoryEntryType.Bolus); - LOG.debug("ProcessHistoryData: Bolus [count={}, itemsCount={}]", treatments.size()); - showLogs(null, gsonPretty.toJson(treatments)); + LOG.debug("ProcessHistoryData: Bolus [count={}, items={}]", treatments.size(), gsonPretty.toJson(treatments)); if (treatments.size() > 0) { - // processBoluses(treatments); + //processBoluses(treatments); } // TBR List tbrs = getFilteredListByLastRecord(PumpHistoryEntryType.TempBasalCombined); - LOG.debug("ProcessHistoryData: TBRs [count={}, items=", tbrs.size()); - showLogs(null, gsonPretty.toJson(tbrs)); + LOG.debug("ProcessHistoryData: TBRs [count={}, items={}]", tbrs.size(), gsonPretty.toJson(tbrs)); if (tbrs.size() > 0) { // processTBRs(tbrs); @@ -302,8 +337,8 @@ public class MedtronicHistoryData { // Suspends (for suspends/resume, fakeTBR) List suspends = getSuspends(); - LOG.debug("ProcessHistoryData: FakeTBRs (suspend/resume) [count={}, items=", suspends.size()); - showLogs(null, gsonPretty.toJson(suspends)); + LOG.debug("ProcessHistoryData: FakeTBRs (suspend/resume) [count={}, items={}]", suspends.size(), + gsonPretty.toJson(suspends)); if (suspends.size() > 0) { // processSuspends(treatments); @@ -317,7 +352,7 @@ public class MedtronicHistoryData { List tdds = filterTDDs(tddsIn); - pumpTime = MedtronicUtil.getPumpTime(); + // /pumpTime = MedtronicUtil.getPumpTime(); LOG.error(getLogPrefix() + "TDDs found: {}. Not processed.\n{}", tdds.size(), gsonPretty.toJson(tdds)); @@ -360,18 +395,282 @@ public class MedtronicHistoryData { int dateDifference = getOldestDateDifference(boluses); - // List treatmentsFromHistory = TreatmentsPlugin.getPlugin().getTreatmentsFromHistoryXMinutesAgo( - // dateDifference); + List treatmentsFromHistory = TreatmentsPlugin.getPlugin().getTreatmentsFromHistoryXMinutesAgo( + dateDifference); - for (PumpHistoryEntry treatment : boluses) { + LOG.debug("Boluses (before filter): {}, FromDb={}", gsonPretty.toJson(boluses), + gsonPretty.toJson(treatmentsFromHistory)); - LOG.debug("TOE. Treatment: " + treatment); - long inLocalTime = tryToGetByLocalTime(treatment.atechDateTime); + filterOutAlreadyAddedEntries(boluses, treatmentsFromHistory); + LOG.debug("Boluses (after filter): {}, FromDb={}", gsonPretty.toJson(boluses), + gsonPretty.toJson(treatmentsFromHistory)); + + if (treatmentsFromHistory.isEmpty()) { + for (PumpHistoryEntry treatment : boluses) { + LOG.debug("Add Bolus (no treatments): " + treatment); + addBolus(treatment, null); + } + } else { + for (PumpHistoryEntry treatment : boluses) { + Treatment treatmentDb = findTreatment2(treatment, treatmentsFromHistory); + LOG.debug("Add Bolus {} - (treatmentFromDb={}) ", treatment, treatmentDb); + + addBolus(treatment, treatmentDb); + } } } + private void filterOutAlreadyAddedEntries(List boluses, List treatmentsFromHistory) { + + List removeTreatmentsFromHistory = new ArrayList<>(); + + for (Treatment treatment : treatmentsFromHistory) { + + if (treatment.pumpId != 0) { + + PumpHistoryEntry selectedBolus = null; + + for (PumpHistoryEntry bolus : boluses) { + if (bolus.pumpId == treatment.pumpId) { + + selectedBolus = bolus; + break; + } + } + + if (selectedBolus != null) + boluses.remove(selectedBolus); + + removeTreatmentsFromHistory.add(treatment); + } + } + + for (Treatment treatment : removeTreatmentsFromHistory) { + treatmentsFromHistory.remove(treatment); + } + + } + + + private Treatment findTreatment(PumpHistoryEntry treatment, List treatmentsFromHistory) { + + long proposedTime = DateTimeUtil.toMillisFromATD(treatment.atechDateTime); + + proposedTime += (this.pumpTime.timeDifference * 1000); + + treatment.phoneDateTime = proposedTime; + + List outList = new ArrayList<>(); + + for (Treatment treatment1 : treatmentsFromHistory) { + if ((treatment1.date > proposedTime - (5 * 60 * 1000)) + && (treatment1.date < proposedTime + (5 * 60 * 1000))) { + outList.add(treatment1); + } + } + + if (outList.size() == 0) { + return null; + } else if (outList.size() == 1) { + return outList.get(0); + } else { + LOG.error("TODO. Multiple options: {}", outList); + + Map data = new HashMap<>(); + + for (Treatment treatment1 : outList) { + int diff = Math.abs((int)(treatment1.date - proposedTime)); + data.put(treatment1, diff); + } + + for (int i = 1; i < 5; i++) { + + List outList2 = new ArrayList<>(); + + for (Treatment treatment1 : treatmentsFromHistory) { + if ((treatment1.date > proposedTime - (i * 60 * 1000)) + && (treatment1.date < proposedTime + (i * 60 * 1000))) { + outList2.add(treatment1); + } + } + + LOG.error("Treatment List: (timeDiff={},count={},list={})", (i * 60 * 1000), outList2.size(), + gsonPretty.toJson(outList2)); + + if (outList2.size() == 1) { + return outList2.get(0); + } else if (outList2.size() > 1) { + + for (int j = 1; j < 6; j++) { + + List outList3 = new ArrayList<>(); + + int ttt = (i * 60 * 1000) - (10 * j * 1000); + + for (Treatment treatment1 : treatmentsFromHistory) { + + if ((treatment1.date > proposedTime - ttt) && (treatment1.date < proposedTime + ttt)) { + outList3.add(treatment1); + } + } + + LOG.error("Treatment List: (timeDiff={},count={},list={})", ttt, outList3.size(), + gsonPretty.toJson(outList3)); + + if (outList3.size() == 1) { + return outList3.get(0); + } + } // for + + } // outList2 + } + + // TODO + } // outList + + // TODO + return null; + } + + + private Treatment findTreatment2(PumpHistoryEntry treatment, List treatmentsFromHistory) { + + long proposedTime = DateTimeUtil.toMillisFromATD(treatment.atechDateTime); + + proposedTime += (this.pumpTime.timeDifference * 1000); + + treatment.phoneDateTime = proposedTime; + + for (int min = 0; min < 6; min++) { + for (int sec = 0; sec < 60; sec += 10) { + + int diff = (min * 60 * 1000) + (sec * 1000); + + List outList = new ArrayList<>(); + + for (Treatment treatment1 : treatmentsFromHistory) { + + if ((treatment1.date > proposedTime - diff) && (treatment1.date < proposedTime + diff)) { + outList.add(treatment1); + } + } + + LOG.error("Treatments: (timeDiff=[min={},sec={}],count={},list={})", min, sec, outList.size(), + gsonPretty.toJson(outList)); + + if (outList.size() == 1) { + return outList.get(0); + } + + if (min == 0 && sec == 10 && outList.size() > 1) { + LOG.error("Too many treatments (with too small diff): (timeDiff=[min={},sec={}],count={},list={})", + min, sec, outList.size(), gsonPretty.toJson(outList)); + + } + } + } + + return null; + + } + + + private void addBolus(PumpHistoryEntry bolus, Treatment treatment) { + + BolusDTO bolusDTO = (BolusDTO)bolus.getDecodedData().get("Object"); + + if (treatment == null) { + + // treatment.carbs = detailedBolusInfo.carbs; // TODO later support BolusWizard ?? + + switch (bolusDTO.getBolusType()) { + case Normal: { + DetailedBolusInfo normalBolus = new DetailedBolusInfo(); + normalBolus.date = tryToGetByLocalTime(bolus.atechDateTime); + normalBolus.source = Source.PUMP; + normalBolus.insulin = bolusDTO.getDeliveredAmount(); + normalBolus.pumpId = bolus.pumpId; + normalBolus.isValid = true; + normalBolus.isSMB = false; + + bolus.setLinkedObject(normalBolus); + + TreatmentsPlugin.getPlugin().addToHistoryTreatment(normalBolus, true); + + LOG.debug("addBolus - Normal [date={},pumpId={}, insulin={}]", normalBolus.date, + normalBolus.pumpId, normalBolus.insulin); + } + break; + + case Audio: + case Extended: { + ExtendedBolus extendedBolus = new ExtendedBolus(); + extendedBolus.date = tryToGetByLocalTime(bolus.atechDateTime); + extendedBolus.source = Source.PUMP; + extendedBolus.insulin = bolusDTO.getDeliveredAmount(); + extendedBolus.pumpId = bolus.pumpId; + extendedBolus.isValid = true; + extendedBolus.durationInMinutes = bolusDTO.getDuration(); + + bolus.setLinkedObject(extendedBolus); + + TreatmentsPlugin.getPlugin().addToHistoryExtendedBolus(extendedBolus); + + LOG.debug("addBolus - Extended [date={},pumpId={}, insulin={}, duration={}]", extendedBolus.date, + extendedBolus.pumpId, extendedBolus.insulin, extendedBolus.durationInMinutes); + + } + break; + + case Multiwave: { + DetailedBolusInfo normalBolus = new DetailedBolusInfo(); + normalBolus.date = tryToGetByLocalTime(bolus.atechDateTime); + normalBolus.source = Source.PUMP; + normalBolus.insulin = bolusDTO.getImmediateAmount(); + normalBolus.pumpId = bolus.pumpId; + normalBolus.isValid = true; + normalBolus.isSMB = false; + + bolus.setLinkedObject(normalBolus); + + TreatmentsPlugin.getPlugin().addToHistoryTreatment(normalBolus, true); + + LOG.debug("addBolus - Multiwave-Normal [date={},pumpId={}, insulin={}]", normalBolus.date, + normalBolus.pumpId, normalBolus.insulin); + + ExtendedBolus extendedBolus = new ExtendedBolus(); + extendedBolus.date = tryToGetByLocalTime(bolus.atechDateTime); + extendedBolus.source = Source.PUMP; + extendedBolus.insulin = bolusDTO.getDeliveredAmount(); + extendedBolus.pumpId = bolus.pumpId; + extendedBolus.isValid = true; + extendedBolus.durationInMinutes = bolusDTO.getDuration(); + + TreatmentsPlugin.getPlugin().addToHistoryExtendedBolus(extendedBolus); + + LOG.debug("addBolus - Multiwave-Extended [date={},pumpId={}, insulin={}, duration={}]", + extendedBolus.date, extendedBolus.pumpId, extendedBolus.insulin, + extendedBolus.durationInMinutes); + + } + break; + + } + + } else { + treatment.insulin = bolusDTO.getDeliveredAmount(); + treatment.pumpId = bolus.pumpId; + + bolus.setLinkedObject(treatment); + + TreatmentsPlugin.getPlugin().getService().createOrUpdate(treatment); + } + + } + + // TODO needs to be implemented public void processTBRs(List treatments) { @@ -398,7 +697,7 @@ public class MedtronicHistoryData { // TODO needs to be implemented public List getSuspends() { - return new ArrayList<>(); + return new ArrayList(); } @@ -459,7 +758,10 @@ public class MedtronicHistoryData { } LocalDateTime d = DateTimeUtil.toLocalDateTime(dt); - d.minusMinutes(5); + d.minusMinutes(2); + if (this.pumpTime.timeDifference < 0) { + d.plusSeconds(this.pumpTime.timeDifference); + } Minutes minutes = Minutes.minutesBetween(d, new LocalDateTime()); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.java index 3c39026870..894e503783 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.java @@ -222,9 +222,19 @@ public class BasalProfile { if ((mRawData[i] == 0) && (mRawData[i + 1] == 0) && (mRawData[i + 2] == 0)) break; + if ((mRawData[i] == 0) && (mRawData[i + 1] == 0) && (mRawData[i + 2] == 0x3f)) + break; + r = MedtronicUtil.makeUnsignedShort(mRawData[i + 1], mRawData[i]); // readUnsignedByte(mRawData[i]); st = readUnsignedByte(mRawData[i + 2]); - entries.add(new BasalProfileEntry(r, st)); + + try { + entries.add(new BasalProfileEntry(r, st)); + } catch (Exception ex) { + LOG.error("Error decoding basal profile from bytes: {}", ByteUtil.getHex(mRawData)); + throw ex; + } + } return entries; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfileEntry.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfileEntry.java index 535599579a..a9d92d0b40 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfileEntry.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfileEntry.java @@ -1,6 +1,8 @@ package info.nightscout.androidaps.plugins.pump.medtronic.data.dto; import org.joda.time.LocalTime; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil; @@ -11,6 +13,8 @@ import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil; */ public class BasalProfileEntry { + private static final Logger LOG = LoggerFactory.getLogger(BasalProfileEntry.class); + public byte[] rate_raw; public double rate; public byte startTime_raw; @@ -49,7 +53,16 @@ public class BasalProfileEntry { rate_raw = MedtronicUtil.getByteArrayFromUnsignedShort(rateStrokes, true); rate = rateStrokes * 0.025; startTime_raw = (byte)startTimeInterval; - startTime = new LocalTime(startTimeInterval / 2, (startTimeInterval % 2) * 30); + + try { + startTime = new LocalTime(startTimeInterval / 2, (startTimeInterval % 2) * 30); + } catch (Exception ex) { + LOG.error( + "Error creating BasalProfileEntry: startTimeInterval={}, startTime_raw={}, hours={}, rateStrokes={}", + startTimeInterval, startTime_raw, startTimeInterval / 2, rateStrokes); + throw ex; + } + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/ClockDTO.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/ClockDTO.java index 12d123c361..13bbc39e20 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/ClockDTO.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/ClockDTO.java @@ -12,7 +12,7 @@ public class ClockDTO { public LocalDateTime pumpTime; - //public Duration timeDifference; + // public Duration timeDifference; - public int timeDifference; // s + public int timeDifference; // s (pump -> local) } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCustomActionType.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCustomActionType.java index f981154229..2fc23b9546 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCustomActionType.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCustomActionType.java @@ -8,7 +8,9 @@ import info.nightscout.androidaps.plugins.general.actions.defs.CustomActionType; public enum MedtronicCustomActionType implements CustomActionType { - WakeUpAndTune() + WakeUpAndTune(), // + ClearBolusBlock(), // + ResetRileyLink(), // ; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicUtil.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicUtil.java index 7bf36e8aae..75c37eda6d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicUtil.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicUtil.java @@ -489,6 +489,6 @@ public class MedtronicUtil extends RileyLinkUtil { public static ClockDTO getPumpTime() { - return pumpTime; + return MedtronicUtil.pumpTime; } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPlugin.java index 197c178b7b..145741e6ab 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPlugin.java @@ -308,8 +308,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface List in5minback = new ArrayList<>(); long time = System.currentTimeMillis(); synchronized (treatments) { - for (Integer pos = 0; pos < treatments.size(); pos++) { - Treatment t = treatments.get(pos); + for (Treatment t : treatments) { if (!t.isValid) continue; if (t.date <= time && t.date > (time - minutesAgo * 60 * 1000)) diff --git a/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java b/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java index eee92177ab..7c0972cdf2 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java +++ b/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java @@ -433,6 +433,19 @@ public class CommandQueue { return true; } + + public synchronized boolean statusInQueue() { + if (isRunning(Command.CommandType.READSTATUS)) + return true; + for (int i = 0; i < queue.size(); i++) { + if (queue.get(i).commandType == Command.CommandType.READSTATUS) { + return true; + } + } + return false; + } + + // returns true if command is queued public boolean loadHistory(byte type, Callback callback) { if (isRunning(Command.CommandType.LOADHISTORY)) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 30f59459ad..14b5488059 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1337,6 +1337,7 @@ RileyLink 4b6b Encoding RileyLink MAC Address Wake and Tune Up + Clear Bolus Block SCAN