- Process Suspend delivery items

This commit is contained in:
Andy Rozman 2019-06-16 20:12:10 +01:00
parent 1290457b5a
commit c460d1d3ef
6 changed files with 307 additions and 33 deletions

View file

@ -105,7 +105,7 @@ android {
multiDexEnabled true multiDexEnabled true
versionCode 1500 versionCode 1500
// dev_version: 2.3.1-dev // dev_version: 2.3.1-dev
version "medtronic-0.10" version "medtronic-0.11.0-SNAPSHOT"
buildConfigField "String", "VERSION", '"' + version + '"' buildConfigField "String", "VERSION", '"' + version + '"'
buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"' buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"'
buildConfigField "String", "HEAD", '"' + generateGitBuild() + '"' buildConfigField "String", "HEAD", '"' + generateGitBuild() + '"'

View file

@ -1124,6 +1124,28 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return null; return null;
} }
public TemporaryBasal findTempBasalByPumpId(Long pumpId) {
try {
QueryBuilder<TemporaryBasal, Long> queryBuilder = null;
queryBuilder = getDaoTemporaryBasal().queryBuilder();
Where where = queryBuilder.where();
where.eq("pumpId", pumpId);
PreparedQuery<TemporaryBasal> preparedQuery = queryBuilder.prepare();
List<TemporaryBasal> list = getDaoTemporaryBasal().query(preparedQuery);
if (list.size() != 1) {
return null;
} else {
return list.get(0);
}
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
return null;
}
// ------------ ExtendedBolus handling --------------- // ------------ ExtendedBolus handling ---------------
public boolean createOrUpdate(ExtendedBolus extendedBolus) { public boolean createOrUpdate(ExtendedBolus extendedBolus) {

View file

@ -7,6 +7,7 @@ package info.nightscout.androidaps.plugins.pump.common.utils;
import android.util.Log; import android.util.Log;
import org.joda.time.LocalDateTime; import org.joda.time.LocalDateTime;
import org.joda.time.Minutes;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -211,4 +212,11 @@ public class DateTimeUtil {
return d.getTime(); return d.getTime();
} }
public static int getATechDateDiferenceAsMinutes(Long date1, Long date2) {
Minutes minutes = Minutes.minutesBetween(toLocalDateTime(date1), toLocalDateTime(date2));
return minutes.getMinutes();
}
} }

View file

@ -10,11 +10,13 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar; import java.util.Calendar;
import java.util.Collections; import java.util.Collections;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
@ -64,7 +66,7 @@ public class MedtronicHistoryData {
private Long lastHistoryRecordTime; private Long lastHistoryRecordTime;
private boolean isInit = false; private boolean isInit = false;
private Gson gsonPretty; private Gson gson;
//private List<PumpHistoryEntry> fakeTBRs; //private List<PumpHistoryEntry> fakeTBRs;
private DatabaseHelper databaseHelper = MainApp.getDbHelper(); private DatabaseHelper databaseHelper = MainApp.getDbHelper();
@ -73,10 +75,10 @@ public class MedtronicHistoryData {
public MedtronicHistoryData() { public MedtronicHistoryData() {
this.allHistory = new ArrayList<>(); this.allHistory = new ArrayList<>();
this.gsonPretty = MedtronicUtil.gsonInstance; this.gson = MedtronicUtil.gsonInstance;
if (this.gsonPretty == null) { if (this.gson == null) {
this.gsonPretty = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create(); this.gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
} }
} }
@ -101,21 +103,22 @@ public class MedtronicHistoryData {
this.newHistory = newEntries; this.newHistory = newEntries;
showLogs("List of history (before filtering): [" + this.newHistory.size() + "]", gsonPretty.toJson(this.newHistory)); showLogs("List of history (before filtering): [" + this.newHistory.size() + "]", gson.toJson(this.newHistory));
} }
public static void showLogs(String header, String data) { private static void showLogs(String header, String data) {
if (!isLogEnabled())
return;
if (header != null) { if (header != null) {
if (isLogEnabled()) LOG.debug(header);
LOG.debug(header);
} }
if (StringUtils.isNotBlank(data)) { if (StringUtils.isNotBlank(data)) {
for (final String token : StringUtil.splitString(data, 3500)) { for (final String token : StringUtil.splitString(data, 3500)) {
if (isLogEnabled()) LOG.debug("{}", token);
LOG.debug("{}", token);
} }
} else { } else {
LOG.debug("No data."); LOG.debug("No data.");
@ -178,7 +181,8 @@ public class MedtronicHistoryData {
if (isLogEnabled()) if (isLogEnabled())
LOG.debug("New History entries found: {}", this.newHistory.size()); LOG.debug("New History entries found: {}", this.newHistory.size());
showLogs("List of history (after filtering): [" + this.newHistory.size() + "]", gsonPretty.toJson(this.newHistory));
showLogs("List of history (after filtering): [" + this.newHistory.size() + "]", gson.toJson(this.newHistory));
} }
@ -369,7 +373,7 @@ public class MedtronicHistoryData {
// TDD // TDD
List<PumpHistoryEntry> tdds = getFilteredItems(PumpHistoryEntryType.EndResultTotals, getTDDType()); List<PumpHistoryEntry> tdds = getFilteredItems(PumpHistoryEntryType.EndResultTotals, getTDDType());
LOG.debug("ProcessHistoryData: TDD [count={}, items={}]", tdds.size(), gsonPretty.toJson(tdds)); LOG.debug("ProcessHistoryData: TDD [count={}, items={}]", tdds.size(), gson.toJson(tdds));
if (!isCollectionEmpty(tdds)) { if (!isCollectionEmpty(tdds)) {
processTDDs(tdds); processTDDs(tdds);
@ -380,7 +384,7 @@ public class MedtronicHistoryData {
// Bolus // Bolus
List<PumpHistoryEntry> treatments = getFilteredItems(PumpHistoryEntryType.Bolus); List<PumpHistoryEntry> treatments = getFilteredItems(PumpHistoryEntryType.Bolus);
LOG.debug("ProcessHistoryData: Bolus [count={}, items={}]", treatments.size(), gsonPretty.toJson(treatments)); LOG.debug("ProcessHistoryData: Bolus [count={}, items={}]", treatments.size(), gson.toJson(treatments));
if (treatments.size() > 0) { if (treatments.size() > 0) {
processEntries(treatments, ProcessHistoryRecord.Bolus); processEntries(treatments, ProcessHistoryRecord.Bolus);
@ -389,20 +393,20 @@ public class MedtronicHistoryData {
// TBR // TBR
List<PumpHistoryEntry> tbrs = getFilteredItems(PumpHistoryEntryType.TempBasalCombined); List<PumpHistoryEntry> tbrs = getFilteredItems(PumpHistoryEntryType.TempBasalCombined);
LOG.debug("ProcessHistoryData: TBRs NOT Processed [count={}, items={}]", tbrs.size(), gsonPretty.toJson(tbrs)); LOG.debug("ProcessHistoryData: TBRs NOT Processed [count={}, items={}]", tbrs.size(), gson.toJson(tbrs));
if (tbrs.size() > 0) { if (tbrs.size() > 0) {
//processEntries(tbrs, ProcessHistoryRecord.TBR); //processEntries(tbrs, ProcessHistoryRecord.TBR);
} }
// Suspends (for suspends/resume, fakeTBR) // 'Delivery Suspend'
List<PumpHistoryEntry> suspends = getSuspends(); List<TempBasalProcessDTO> suspends = getSuspends();
LOG.debug("ProcessHistoryData: FakeTBRs (suspend/resume) NOT Processed [count={}, items={}]", suspends.size(), LOG.debug("ProcessHistoryData: 'Delivery Suspend' Processed [count={}, items={}]", suspends.size(),
gsonPretty.toJson(suspends)); gson.toJson(suspends));
if (suspends.size() > 0) { if (suspends.size() > 0) {
// processSuspends(treatments); processSuspends(suspends);
} }
} }
@ -412,7 +416,7 @@ public class MedtronicHistoryData {
List<PumpHistoryEntry> tdds = filterTDDs(tddsIn); List<PumpHistoryEntry> tdds = filterTDDs(tddsIn);
if (isLogEnabled()) if (isLogEnabled())
LOG.debug(getLogPrefix() + "TDDs found: {}.\n{}", tdds.size(), gsonPretty.toJson(tdds)); LOG.debug(getLogPrefix() + "TDDs found: {}.\n{}", tdds.size(), gson.toJson(tdds));
List<TDD> tddsDb = databaseHelper.getTDDsForLastXDays(3); List<TDD> tddsDb = databaseHelper.getTDDsForLastXDays(3);
@ -601,7 +605,7 @@ public class MedtronicHistoryData {
if (min == 0 && sec == 10 && outList.size() > 1) { if (min == 0 && sec == 10 && outList.size() > 1) {
if (isLogEnabled()) if (isLogEnabled())
LOG.error("Too many entries (with too small diff): (timeDiff=[min={},sec={}],count={},list={})", LOG.error("Too many entries (with too small diff): (timeDiff=[min={},sec={}],count={},list={})",
min, sec, outList.size(), gsonPretty.toJson(outList)); min, sec, outList.size(), gson.toJson(outList));
} }
} }
} }
@ -624,16 +628,14 @@ public class MedtronicHistoryData {
private List<? extends DbObjectBase> getDatabaseEntries(int dateDifference, ProcessHistoryRecord processHistoryRecord) { private List<? extends DbObjectBase> getDatabaseEntries(int dateDifference, ProcessHistoryRecord processHistoryRecord) {
if (processHistoryRecord == ProcessHistoryRecord.Bolus) { if (processHistoryRecord == ProcessHistoryRecord.Bolus) {
List<Treatment> treatmentsFromHistory = TreatmentsPlugin.getPlugin().getTreatmentsFromHistoryXMinutesAgo( return TreatmentsPlugin.getPlugin().getTreatmentsFromHistoryXMinutesAgo(
dateDifference); dateDifference);
return treatmentsFromHistory;
} else { } else {
GregorianCalendar gc = new GregorianCalendar(); GregorianCalendar gc = new GregorianCalendar();
gc.add(Calendar.MINUTE, (-1) * dateDifference); gc.add(Calendar.MINUTE, (-1) * dateDifference);
List<TemporaryBasal> tbrsFromHistory = databaseHelper.getTemporaryBasalsDataFromTime(gc.getTimeInMillis(), true); return databaseHelper.getTemporaryBasalsDataFromTime(gc.getTimeInMillis(), true);
return tbrsFromHistory;
} }
} }
@ -785,22 +787,232 @@ public class MedtronicHistoryData {
LOG.debug(operation + " - [date={},pumpId={}, rate={} {}, duration={}]", // LOG.debug(operation + " - [date={},pumpId={}, rate={} {}, duration={}]", //
temporaryBasalDb.date, // temporaryBasalDb.date, //
temporaryBasalDb.pumpId, // temporaryBasalDb.pumpId, //
temporaryBasalDb.isAbsolute ? String.format("%.2f", temporaryBasalDb.absoluteRate) : temporaryBasalDb.isAbsolute ? String.format(Locale.ENGLISH, "%.2f", temporaryBasalDb.absoluteRate) :
String.format("%d", temporaryBasalDb.percentRate), // String.format(Locale.ENGLISH, "%d", temporaryBasalDb.percentRate), //
temporaryBasalDb.isAbsolute ? "U/h" : "%", // temporaryBasalDb.isAbsolute ? "U/h" : "%", //
temporaryBasalDb.durationInMinutes); temporaryBasalDb.durationInMinutes);
} }
// TODO needs to be implemented public void processSuspends(List<TempBasalProcessDTO> tempBasalProcessList) {
public void processSuspends(List<PumpHistoryEntry> treatments) {
for (TempBasalProcessDTO tempBasalProcess : tempBasalProcessList) {
TemporaryBasal tempBasal = databaseHelper.findTempBasalByPumpId(tempBasalProcess.itemOne.getPumpId());
if (tempBasal == null) {
// add
tempBasal = new TemporaryBasal();
tempBasal.date = tryToGetByLocalTime(tempBasalProcess.itemOne.atechDateTime);
tempBasal.source = Source.PUMP;
tempBasal.pumpId = tempBasalProcess.itemOne.getPumpId();
tempBasal.durationInMinutes = tempBasalProcess.getDuration();
tempBasal.absoluteRate = 0.0d;
tempBasal.isAbsolute = true;
tempBasalProcess.itemOne.setLinkedObject(tempBasal);
tempBasalProcess.itemTwo.setLinkedObject(tempBasal);
databaseHelper.createOrUpdate(tempBasal);
} else {
continue;
}
}
} }
// TODO needs to be implemented private List<TempBasalProcessDTO> getSuspends() {
public List<PumpHistoryEntry> getSuspends() {
return new ArrayList<PumpHistoryEntry>(); List<TempBasalProcessDTO> outList = new ArrayList<>();
// suspend/resume
outList.addAll(getSuspendResumeRecords());
// no_delivery/prime & rewind/prime
outList.addAll(getNoDeliveryRewindPrimeRecords());
return outList;
}
private List<TempBasalProcessDTO> getSuspendResumeRecords() {
List<PumpHistoryEntry> filteredItems = getFilteredItems(this.newHistory, //
PumpHistoryEntryType.Suspend, //
PumpHistoryEntryType.Resume);
List<TempBasalProcessDTO> outList = new ArrayList<>();
if (filteredItems.size() > 0) {
List<PumpHistoryEntry> filtered2Items = new ArrayList<>();
if ((filteredItems.size() % 2 == 0) && (filteredItems.get(0).getEntryType() == PumpHistoryEntryType.Resume)) {
// full resume suspends (S R S R)
filtered2Items.addAll(filteredItems);
} else if ((filteredItems.size() % 2 == 0) && (filteredItems.get(0).getEntryType() == PumpHistoryEntryType.Suspend)) {
// not full suspends, need to retrive one more record and discard first one (R S R S) -> ([S] R S R [xS])
filteredItems.remove(0);
PumpHistoryEntry oneMoreEntryFromHistory = getOneMoreEntryFromHistory();
if (oneMoreEntryFromHistory != null) {
filteredItems.add(getOneMoreEntryFromHistory());
} else {
filteredItems.remove(filteredItems.size() - 1); // remove last (unpaired R)
}
filtered2Items.addAll(filteredItems);
} else {
if (filteredItems.get(0).getEntryType() == PumpHistoryEntryType.Resume) {
// get one more from history (R S R) -> ([S] R S R)
PumpHistoryEntry oneMoreEntryFromHistory = getOneMoreEntryFromHistory();
if (oneMoreEntryFromHistory != null) {
filteredItems.add(getOneMoreEntryFromHistory());
} else {
filteredItems.remove(filteredItems.size() - 1); // remove last (unpaired R)
}
filtered2Items.addAll(filteredItems);
} else {
// remove last and have paired items
filteredItems.remove(0);
filtered2Items.addAll(filteredItems);
}
}
if (filtered2Items.size() > 0) {
sort(filtered2Items);
Collections.reverse(filtered2Items);
for (int i = 0; i < filtered2Items.size(); i += 2) {
TempBasalProcessDTO dto = new TempBasalProcessDTO();
dto.itemOne = filtered2Items.get(i);
dto.itemTwo = filtered2Items.get(i + 1);
dto.processOperation = TempBasalProcessDTO.Operation.Add;
outList.add(dto);
}
}
}
return outList;
}
private List<TempBasalProcessDTO> getNoDeliveryRewindPrimeRecords() {
List<PumpHistoryEntry> primeItems = getFilteredItems(this.newHistory, //
PumpHistoryEntryType.Prime);
List<TempBasalProcessDTO> outList = new ArrayList<>();
if (primeItems.size() == 0)
return outList;
List<PumpHistoryEntry> filteredItems = getFilteredItems(this.newHistory, //
PumpHistoryEntryType.Prime,
PumpHistoryEntryType.Rewind,
PumpHistoryEntryType.NoDeliveryAlarm,
PumpHistoryEntryType.Bolus,
PumpHistoryEntryType.TempBasalCombined
);
List<PumpHistoryEntry> tempData = new ArrayList<>();
boolean startedItems = false;
boolean finishedItems = false;
for (PumpHistoryEntry filteredItem : filteredItems) {
if (filteredItem.getEntryType() == PumpHistoryEntryType.Prime) {
startedItems = true;
}
if (startedItems) {
if (filteredItem.getEntryType() == PumpHistoryEntryType.Bolus ||
filteredItem.getEntryType() == PumpHistoryEntryType.TempBasalCombined) {
finishedItems = true;
}
if (!finishedItems) {
tempData.add(filteredItem);
}
}
}
if (!finishedItems) {
List<PumpHistoryEntry> filteredItemsOld = getFilteredItems(this.allHistory, //
PumpHistoryEntryType.Rewind,
PumpHistoryEntryType.NoDeliveryAlarm,
PumpHistoryEntryType.Bolus,
PumpHistoryEntryType.TempBasalCombined
);
for (PumpHistoryEntry filteredItem : filteredItemsOld) {
if (filteredItem.getEntryType() == PumpHistoryEntryType.Bolus ||
filteredItem.getEntryType() == PumpHistoryEntryType.TempBasalCombined) {
finishedItems = true;
}
if (!finishedItems) {
tempData.add(filteredItem);
}
}
}
if (!finishedItems)
return outList;
showLogs("NoDeliveryRewindPrimeRecords: Records to evaluate: ", gson.toJson(tempData));
List<PumpHistoryEntry> items = getFilteredItems(tempData, //
PumpHistoryEntryType.Prime
);
TempBasalProcessDTO processDTO = new TempBasalProcessDTO();
processDTO.itemTwo = items.get(0);
items = getFilteredItems(tempData, //
PumpHistoryEntryType.NoDeliveryAlarm
);
if (items.size() > 0) {
processDTO.itemOne = items.get(items.size() - 1);
processDTO.processOperation = TempBasalProcessDTO.Operation.Add;
return Arrays.asList(processDTO);
}
items = getFilteredItems(tempData, //
PumpHistoryEntryType.Rewind
);
if (items.size() > 0) {
processDTO.itemOne = items.get(0);
processDTO.processOperation = TempBasalProcessDTO.Operation.Add;
return Arrays.asList(processDTO);
}
return outList;
}
private PumpHistoryEntry getOneMoreEntryFromHistory() {
List<PumpHistoryEntry> filteredItems = getFilteredItems(this.allHistory, PumpHistoryEntryType.Suspend);
return filteredItems.size() == 0 ? null : filteredItems.get(0);
} }

View file

@ -1,5 +1,6 @@
package info.nightscout.androidaps.plugins.pump.medtronic.data.dto; package info.nightscout.androidaps.plugins.pump.medtronic.data.dto;
import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil;
import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntry; import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntry;
public class TempBasalProcessDTO { public class TempBasalProcessDTO {
@ -9,6 +10,11 @@ public class TempBasalProcessDTO {
public Operation processOperation = Operation.None; public Operation processOperation = Operation.None;
public int getDuration() {
int difference = DateTimeUtil.getATechDateDiferenceAsMinutes(itemOne.atechDateTime, itemTwo.atechDateTime);
return difference;
}
public static enum Operation { public static enum Operation {
None, None,

View file

@ -0,0 +1,26 @@
package info.nightscout.androidaps.plugins.pump.common.utils;
import android.util.Log;
import junit.framework.Assert;
import org.junit.Test;
import static org.junit.Assert.*;
public class DateTimeUtilUTest {
@Test
public void getATechDateDiferenceAsMinutes() {
long dt1 = 20191001182301L;
long dt2 = 20191001192805L;
int aTechDateDiferenceAsMinutes = DateTimeUtil.getATechDateDiferenceAsMinutes(dt1, dt2);
Assert.assertEquals(65, aTechDateDiferenceAsMinutes);
Log.d("DateTimeUtilUTest", "Time difference: " + aTechDateDiferenceAsMinutes);
}
}