TDD -> room

This commit is contained in:
Milos Kozak 2021-04-18 13:31:25 +02:00
parent ccef857b41
commit 3928b579a7
25 changed files with 3301 additions and 328 deletions

View file

@ -97,7 +97,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
TableUtils.createTableIfNotExists(connectionSource, TemporaryBasal.class);
TableUtils.createTableIfNotExists(connectionSource, ExtendedBolus.class);
TableUtils.createTableIfNotExists(connectionSource, ProfileSwitch.class);
TableUtils.createTableIfNotExists(connectionSource, TDD.class);
TableUtils.createTableIfNotExists(connectionSource, InsightHistoryOffset.class);
TableUtils.createTableIfNotExists(connectionSource, InsightBolusID.class);
TableUtils.createTableIfNotExists(connectionSource, InsightPumpID.class);
@ -173,14 +172,12 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
TableUtils.dropTable(connectionSource, TemporaryBasal.class, true);
TableUtils.dropTable(connectionSource, ExtendedBolus.class, true);
TableUtils.dropTable(connectionSource, ProfileSwitch.class, true);
TableUtils.dropTable(connectionSource, TDD.class, true);
TableUtils.dropTable(connectionSource, OmnipodHistoryRecord.class, true);
TableUtils.createTableIfNotExists(connectionSource, DanaRHistoryRecord.class);
TableUtils.createTableIfNotExists(connectionSource, DbRequest.class);
TableUtils.createTableIfNotExists(connectionSource, TemporaryBasal.class);
TableUtils.createTableIfNotExists(connectionSource, ExtendedBolus.class);
TableUtils.createTableIfNotExists(connectionSource, ProfileSwitch.class);
TableUtils.createTableIfNotExists(connectionSource, TDD.class);
TableUtils.createTableIfNotExists(connectionSource, OmnipodHistoryRecord.class);
updateEarliestDataChange(0);
} catch (SQLException e) {
@ -209,25 +206,12 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
scheduleProfileSwitchChange();
}
public void resetTDDs() {
try {
TableUtils.dropTable(connectionSource, TDD.class, true);
TableUtils.createTableIfNotExists(connectionSource, TDD.class);
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);
}
}
// ------------------ getDao -------------------------------------------
private Dao<DanaRHistoryRecord, String> getDaoDanaRHistory() throws SQLException {
return getDao(DanaRHistoryRecord.class);
}
private Dao<TDD, String> getDaoTDD() throws SQLException {
return getDao(TDD.class);
}
private Dao<DbRequest, String> getDaoDbRequest() throws SQLException {
return getDao(DbRequest.class);
}
@ -271,60 +255,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return rounded;
}
// ------------------- TDD handling -----------------------
public void createOrUpdateTDD(TDD tdd) {
try {
Dao<TDD, String> dao = getDaoTDD();
dao.createOrUpdate(tdd);
openHumansUploader.enqueueTotalDailyDose(tdd);
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);
}
}
public List<TDD> getTDDs() {
List<TDD> tddList;
try {
QueryBuilder<TDD, String> queryBuilder = getDaoTDD().queryBuilder();
queryBuilder.orderBy("date", false);
queryBuilder.limit(10L);
PreparedQuery<TDD> preparedQuery = queryBuilder.prepare();
tddList = getDaoTDD().query(preparedQuery);
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);
tddList = new ArrayList<>();
}
return tddList;
}
public List<TDD> getAllTDDs() {
try {
return getDaoTDD().queryForAll();
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);
}
return Collections.emptyList();
}
public List<TDD> getTDDsForLastXDays(int days) {
List<TDD> tddList;
GregorianCalendar gc = new GregorianCalendar();
gc.add(Calendar.DAY_OF_YEAR, (-1) * days);
try {
QueryBuilder<TDD, String> queryBuilder = getDaoTDD().queryBuilder();
queryBuilder.orderBy("date", false);
Where<TDD, String> where = queryBuilder.where();
where.ge("date", gc.getTimeInMillis());
PreparedQuery<TDD> preparedQuery = queryBuilder.prepare();
tddList = getDaoTDD().query(preparedQuery);
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);
tddList = new ArrayList<>();
}
return tddList;
}
// ------------- DbRequests handling -------------------
public void create(DbRequest dbr) throws SQLException {
@ -403,12 +333,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public void createOrUpdate(DanaRHistoryRecord record) {
try {
getDaoDanaRHistory().createOrUpdate(record);
//If it is a TDD, store it for stats also.
if (record.recordCode == RecordTypes.RECORD_TYPE_DAILY) {
createOrUpdateTDD(new TDD(record.recordDate, record.recordDailyBolus, record.recordDailyBasal, 0));
}
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);
}
@ -1136,7 +1060,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
try {
return getDaoExtendedBolus().countOf()
+ getDaoProfileSwitch().countOf()
+ getDaoTDD().countOf()
+ getDaoTemporaryBasal().countOf();
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);

View file

@ -35,10 +35,6 @@ public class DatabaseHelperProvider implements DatabaseHelperInterface {
return MainApp.Companion.getDbHelper().getDanaRHistoryRecordsByType(type);
}
@NonNull @Override public List<TDD> getTDDs() {
return MainApp.Companion.getDbHelper().getTDDs();
}
@Override public long size(@NonNull String table) {
return MainApp.Companion.getDbHelper().size(table);
}
@ -71,10 +67,6 @@ public class DatabaseHelperProvider implements DatabaseHelperInterface {
return MainApp.Companion.getDbHelper().roundDateToSec(date);
}
@Override public void createOrUpdateTDD(@NonNull TDD record) {
MainApp.Companion.getDbHelper().createOrUpdateTDD(record);
}
@Override public boolean createOrUpdate(@NonNull TemporaryBasal tempBasal) {
return MainApp.Companion.getDbHelper().createOrUpdate(tempBasal);
}
@ -96,10 +88,6 @@ public class DatabaseHelperProvider implements DatabaseHelperInterface {
return MainApp.Companion.getDbHelper().findOmnipodHistoryRecordByPumpId(pumpId);
}
@NonNull @Override public List<TDD> getTDDsForLastXDays(int days) {
return MainApp.Companion.getDbHelper().getTDDsForLastXDays(days);
}
@NonNull @Override public List<ProfileSwitch> getProfileSwitchData(long from, boolean ascending) {
return MainApp.Companion.getDbHelper().getProfileSwitchData(from, ascending);
}
@ -172,10 +160,6 @@ public class DatabaseHelperProvider implements DatabaseHelperInterface {
return MainApp.Companion.getDbHelper().getAllProfileSwitches();
}
@NonNull @Override public List<TDD> getAllTDDs() {
return MainApp.Companion.getDbHelper().getAllTDDs();
}
@NonNull @Override public List<OHQueueItem> getAllOHQueueItems(long maxEntries) {
return MainApp.Companion.getDbHelper().getAllOHQueueItems(maxEntries);
}

View file

@ -237,12 +237,12 @@ class OpenHumansUploader @Inject constructor(
put("isDeletion", deleted)
}
fun enqueueTotalDailyDose(tdd: TDD) = insertQueueItem("TotalDailyDoses") {
put("double", tdd.date)
put("double", tdd.bolus)
put("double", tdd.basal)
put("double", tdd.total)
}
// fun enqueueTotalDailyDose(tdd: TDD) = insertQueueItem("TotalDailyDoses") {
// put("double", tdd.date)
// put("double", tdd.bolus)
// put("double", tdd.basal)
// put("double", tdd.total)
// }
@JvmOverloads
fun enqueueTemporaryBasal(temporaryBasal: TemporaryBasal?, deleted: Boolean = false) = temporaryBasal?.let {
@ -371,9 +371,9 @@ class OpenHumansUploader @Inject constructor(
.andThen(Observable.defer { Observable.fromIterable(databaseHelper.getAllProfileSwitches()) })
.map { enqueueProfileSwitch(it); increaseCounter() }
.ignoreElements()
.andThen(Observable.defer { Observable.fromIterable(databaseHelper.getAllTDDs()) })
.map { enqueueTotalDailyDose(it); increaseCounter() }
.ignoreElements()
// .andThen(Observable.defer { Observable.fromIterable(databaseHelper.getAllTDDs()) })
// .map { enqueueTotalDailyDose(it); increaseCounter() }
// .ignoreElements()
// .andThen(Observable.defer { Observable.fromIterable(databaseHelper.getAllTemporaryBasals()) })
// .map { enqueueTemporaryBasal(it); increaseCounter() }
// .ignoreElements()

View file

@ -16,13 +16,14 @@ import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.database.entities.TotalDailyDose
import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.database.interfaces.end
import info.nightscout.androidaps.database.transactions.CancelCurrentTemporaryTargetIfAnyTransaction
import info.nightscout.androidaps.database.transactions.InsertTemporaryTargetAndCancelCurrentTransaction
import info.nightscout.androidaps.db.TDD
import info.nightscout.androidaps.extensions.total
import info.nightscout.androidaps.extensions.valueToUnits
import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.logging.AAPSLogger
@ -79,7 +80,6 @@ class ActionStringHandler @Inject constructor(
private val danaPump: DanaPump,
private val dateUtil: DateUtil,
private val config: Config,
private val databaseHelper: DatabaseHelperInterface,
private val repository: AppRepository,
private val uel: UserEntryLogger
) {
@ -274,7 +274,7 @@ class ActionStringHandler @Inject constructor(
} else if ("tddstats" == act[0]) {
val activePump = activePlugin.activePump
// check if DB up to date
val dummies: MutableList<TDD> = LinkedList()
val dummies: MutableList<TotalDailyDose> = LinkedList()
val historyList = getTDDList(dummies)
if (isOldData(historyList)) {
rTitle = "TDD"
@ -287,7 +287,7 @@ class ActionStringHandler @Inject constructor(
rMessage += "trying to fetch data from pump."
commandQueue.loadTDDs(object : Callback() {
override fun run() {
val dummies1: MutableList<TDD> = LinkedList()
val dummies1: MutableList<TotalDailyDose> = LinkedList()
val historyList1 = getTDDList(dummies1)
if (isOldData(historyList1)) {
sendStatusMessage("TDD: Still old data! Cannot load from pump.\n" + generateTDDMessage(historyList1, dummies1))
@ -340,7 +340,7 @@ class ActionStringHandler @Inject constructor(
lastConfirmActionString = rAction
}
private fun generateTDDMessage(historyList: MutableList<TDD>, dummies: MutableList<TDD>): String {
private fun generateTDDMessage(historyList: MutableList<TotalDailyDose>, dummies: MutableList<TotalDailyDose>): String {
val profile = profileFunction.getProfile() ?: return "No profile loaded :("
if (historyList.isEmpty()) {
return "No history data!"
@ -349,8 +349,8 @@ class ActionStringHandler @Inject constructor(
var message = ""
val refTDD = profile.baseBasalSum() * 2
val pump = activePlugin.activePump
if (df.format(Date(historyList[0].date)) == df.format(Date())) {
val tdd = historyList[0].getTotal()
if (df.format(Date(historyList[0].timestamp)) == df.format(Date())) {
val tdd = historyList[0].total
historyList.removeAt(0)
message += "Today: " + DecimalFormatter.to2Decimal(tdd) + "U " + (DecimalFormatter.to0Decimal(100 * tdd / refTDD) + "%") + "\n"
message += "\n"
@ -364,7 +364,7 @@ class ActionStringHandler @Inject constructor(
var weighted07 = 0.0
historyList.reverse()
for ((i, record) in historyList.withIndex()) {
val tdd = record.getTotal()
val tdd = record.total
if (i == 0) {
weighted03 = tdd
weighted05 = tdd
@ -383,40 +383,38 @@ class ActionStringHandler @Inject constructor(
historyList.reverse()
//add TDDs:
for (record in historyList) {
val tdd = record.getTotal()
message += df.format(Date(record.date)) + " " + DecimalFormatter.to2Decimal(tdd) + "U " + (DecimalFormatter.to0Decimal(100 * tdd / refTDD) + "%") + (if (dummies.contains(record)) "x" else "") + "\n"
val tdd = record.total
message += df.format(Date(record.timestamp)) + " " + DecimalFormatter.to2Decimal(tdd) + "U " + (DecimalFormatter.to0Decimal(100 * tdd / refTDD) + "%") + (if (dummies.contains(record)) "x" else "") + "\n"
}
return message
}
private fun isOldData(historyList: List<TDD>): Boolean {
private fun isOldData(historyList: List<TotalDailyDose>): Boolean {
val activePump = activePlugin.activePump
val startsYesterday = activePump === danaRPlugin || activePump === danaRSPlugin || activePump === danaRv2Plugin || activePump === danaRKoreanPlugin || activePump === localInsightPlugin
val df: DateFormat = SimpleDateFormat("dd.MM.", Locale.getDefault())
return historyList.size < 3 || df.format(Date(historyList[0].date)) != df.format(Date(System.currentTimeMillis() - if (startsYesterday) 1000 * 60 * 60 * 24 else 0))
return historyList.size < 3 || df.format(Date(historyList[0].timestamp)) != df.format(Date(System.currentTimeMillis() - if (startsYesterday) 1000 * 60 * 60 * 24 else 0))
}
private fun getTDDList(returnDummies: MutableList<TDD>): MutableList<TDD> {
var historyList = databaseHelper.getTDDs().toMutableList()
private fun getTDDList(returnDummies: MutableList<TotalDailyDose>): MutableList<TotalDailyDose> {
var historyList = repository.getLastTotalDailyDoses(10, false).blockingGet().toMutableList()
//var historyList = databaseHelper.getTDDs().toMutableList()
historyList = historyList.subList(0, min(10, historyList.size))
//fill single gaps - only needed for Dana*R data
val dummies: MutableList<TDD> = returnDummies
val dummies: MutableList<TotalDailyDose> = returnDummies
val df: DateFormat = SimpleDateFormat("dd.MM.", Locale.getDefault())
for (i in 0 until historyList.size - 1) {
val elem1 = historyList[i]
val elem2 = historyList[i + 1]
if (df.format(Date(elem1.date)) != df.format(Date(elem2.date + 25 * 60 * 60 * 1000))) {
val dummy = TDD()
dummy.date = elem1.date - 24 * 60 * 60 * 1000
dummy.basal = elem1.basal / 2
dummy.bolus = elem1.bolus / 2
if (df.format(Date(elem1.timestamp)) != df.format(Date(elem2.timestamp + 25 * 60 * 60 * 1000))) {
val dummy = TotalDailyDose(timestamp = elem1.timestamp - T.hours(24).msecs(), bolusAmount = elem1.bolusAmount / 2, basalAmount = elem1.basalAmount / 2)
dummies.add(dummy)
elem1.basal /= 2.0
elem1.bolus /= 2.0
elem1.basalAmount /= 2.0
elem1.bolusAmount /= 2.0
}
}
historyList.addAll(dummies)
historyList.sortWith { lhs, rhs -> (rhs.date - lhs.date).toInt() }
historyList.sortWith { lhs, rhs -> (rhs.timestamp - lhs.timestamp).toInt() }
return historyList
}

View file

@ -168,34 +168,36 @@ open class IobCobCalculatorPlugin @Inject constructor(
}
override fun calculateFromTreatmentsAndTemps(fromTime: Long, profile: Profile): IobTotal {
val now = System.currentTimeMillis()
val time = ads.roundUpTime(fromTime)
val cacheHit = iobTable[time]
if (time < now && cacheHit != null) {
//og.debug(">>> calculateFromTreatmentsAndTemps Cache hit " + new Date(time).toLocaleString());
return cacheHit
} // else log.debug(">>> calculateFromTreatmentsAndTemps Cache miss " + new Date(time).toLocaleString());
val bolusIob = calculateIobFromBolusToTime(time).round()
val basalIob = calculateIobToTimeFromTempBasalsIncludingConvertedExtended(time).round()
// OpenAPSSMB only
// Add expected zero temp basal for next 240 minutes
val basalIobWithZeroTemp = basalIob.copy()
val t = TemporaryBasal(
timestamp = now + 60 * 1000L,
duration = 240,
rate = 0.0,
isAbsolute = true,
type = TemporaryBasal.Type.NORMAL)
if (t.timestamp < time) {
val calc = t.iobCalc(time, profile, activePlugin.activeInsulin)
basalIobWithZeroTemp.plus(calc)
synchronized(dataLock) {
val now = System.currentTimeMillis()
val time = ads.roundUpTime(fromTime)
val cacheHit = iobTable[time]
if (time < now && cacheHit != null) {
//og.debug(">>> calculateFromTreatmentsAndTemps Cache hit " + new Date(time).toLocaleString());
return cacheHit
} // else log.debug(">>> calculateFromTreatmentsAndTemps Cache miss " + new Date(time).toLocaleString());
val bolusIob = calculateIobFromBolusToTime(time).round()
val basalIob = calculateIobToTimeFromTempBasalsIncludingConvertedExtended(time).round()
// OpenAPSSMB only
// Add expected zero temp basal for next 240 minutes
val basalIobWithZeroTemp = basalIob.copy()
val t = TemporaryBasal(
timestamp = now + 60 * 1000L,
duration = 240,
rate = 0.0,
isAbsolute = true,
type = TemporaryBasal.Type.NORMAL)
if (t.timestamp < time) {
val calc = t.iobCalc(time, profile, activePlugin.activeInsulin)
basalIobWithZeroTemp.plus(calc)
}
basalIob.iobWithZeroTemp = IobTotal.combine(bolusIob, basalIobWithZeroTemp).round()
val iobTotal = IobTotal.combine(bolusIob, basalIob).round()
if (time < System.currentTimeMillis()) {
iobTable.put(time, iobTotal)
}
return iobTotal
}
basalIob.iobWithZeroTemp = IobTotal.combine(bolusIob, basalIobWithZeroTemp).round()
val iobTotal = IobTotal.combine(bolusIob, basalIob).round()
if (time < System.currentTimeMillis()) {
iobTable.put(time, iobTotal)
}
return iobTotal
}
override fun calculateAbsInsulinFromTreatmentsAndTemps(fromTime: Long): IobTotal {

View file

@ -5,7 +5,7 @@ import android.util.LongSparseArray
import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.Bolus
import info.nightscout.androidaps.db.TDD
import info.nightscout.androidaps.database.entities.TotalDailyDose
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.IobCobCalculator
import info.nightscout.androidaps.interfaces.ProfileFunction
@ -16,6 +16,7 @@ import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.MidnightTime
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.extensions.convertedToAbsolute
import info.nightscout.androidaps.extensions.toText
import info.nightscout.androidaps.utils.resources.ResourceHelper
import javax.inject.Inject
@ -29,62 +30,62 @@ class TddCalculator @Inject constructor(
private val repository: AppRepository
) {
fun calculate(days: Long): LongSparseArray<TDD> {
fun calculate(days: Long): LongSparseArray<TotalDailyDose> {
val startTime = MidnightTime.calc(dateUtil.now() - T.days(days).msecs())
val endTime = MidnightTime.calc(dateUtil.now())
val result = LongSparseArray<TDD>()
val result = LongSparseArray<TotalDailyDose>()
repository.getBolusesDataFromTimeToTime(startTime, endTime, true).blockingGet()
.filter { it.type != Bolus.Type.PRIMING }
.forEach { t ->
val midnight = MidnightTime.calc(t.timestamp)
val tdd = result[midnight] ?: TDD(midnight, 0.0, 0.0, 0.0)
tdd.bolus += t.amount
val tdd = result[midnight] ?: TotalDailyDose(timestamp = midnight)
tdd.bolusAmount += t.amount
result.put(midnight, tdd)
}
repository.getCarbsDataFromTimeToTimeExpanded(startTime, endTime, true).blockingGet().forEach { t ->
val midnight = MidnightTime.calc(t.timestamp)
val tdd = result[midnight] ?: TDD(midnight, 0.0, 0.0, 0.0)
val tdd = result[midnight] ?: TotalDailyDose(timestamp = midnight)
tdd.carbs += t.amount
result.put(midnight, tdd)
}
for (t in startTime until endTime step T.mins(5).msecs()) {
val midnight = MidnightTime.calc(t)
val tdd = result[midnight] ?: TDD(midnight, 0.0, 0.0, 0.0)
val tdd = result[midnight] ?: TotalDailyDose(timestamp = midnight)
val tbr = iobCobCalculator.getTempBasalIncludingConvertedExtended(t)
val profile = profileFunction.getProfile(t) ?: continue
val absoluteRate = tbr?.convertedToAbsolute(t, profile) ?: profile.getBasal(t)
tdd.basal += absoluteRate / 60.0 * 5.0
tdd.basalAmount += absoluteRate / 60.0 * 5.0
if (!activePlugin.activePump.isFakingTempsByExtendedBoluses) {
// they are not included in TBRs
val eb = iobCobCalculator.getExtendedBolus(t)
val absoluteEbRate = eb?.rate ?: 0.0
tdd.bolus += absoluteEbRate / 60.0 * 5.0
tdd.bolusAmount += absoluteEbRate / 60.0 * 5.0
}
result.put(midnight, tdd)
}
for (i in 0 until result.size()) {
val tdd = result.valueAt(i)
tdd.total = tdd.bolus + tdd.basal
tdd.totalAmount = tdd.bolusAmount + tdd.basalAmount
}
aapsLogger.debug(LTag.CORE, result.toString())
return result
}
private fun averageTDD(tdds: LongSparseArray<TDD>): TDD {
val totalTdd = TDD()
private fun averageTDD(tdds: LongSparseArray<TotalDailyDose>): TotalDailyDose {
val totalTdd = TotalDailyDose(timestamp = dateUtil.now())
for (i in 0 until tdds.size()) {
val tdd = tdds.valueAt(i)
totalTdd.basal += tdd.basal
totalTdd.bolus += tdd.bolus
totalTdd.total += tdd.total
totalTdd.basalAmount += tdd.basalAmount
totalTdd.bolusAmount += tdd.bolusAmount
totalTdd.totalAmount += tdd.totalAmount
totalTdd.carbs += tdd.carbs
}
totalTdd.basal /= tdds.size().toDouble()
totalTdd.bolus /= tdds.size().toDouble()
totalTdd.total /= tdds.size().toDouble()
totalTdd.basalAmount /= tdds.size().toDouble()
totalTdd.bolusAmount /= tdds.size().toDouble()
totalTdd.totalAmount /= tdds.size().toDouble()
totalTdd.carbs /= tdds.size().toDouble()
return totalTdd
}
@ -101,7 +102,7 @@ class TddCalculator @Inject constructor(
}
@Suppress("SameParameterValue")
private fun toText(tdds: LongSparseArray<TDD>, includeCarbs: Boolean): String {
private fun toText(tdds: LongSparseArray<TotalDailyDose>, includeCarbs: Boolean): String {
var t = ""
for (i in 0 until tdds.size()) {
t += "${tdds.valueAt(i).toText(resourceHelper, dateUtil, includeCarbs)}<br>"

View file

@ -7,6 +7,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import info.nightscout.androidaps.extensions.PumpStateExtensionKt;
import org.joda.time.DateTime;
import org.json.JSONObject;
@ -26,7 +27,6 @@ import info.nightscout.androidaps.combo.R;
import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.TDD;
import info.nightscout.androidaps.events.EventInitializationChanged;
import info.nightscout.androidaps.events.EventRefreshOverview;
import info.nightscout.androidaps.interfaces.CommandQueueProvider;
@ -81,7 +81,6 @@ public class ComboPlugin extends PumpPluginBase implements Pump, Constraints {
private RxBusWrapper rxBus;
private final CommandQueueProvider commandQueue;
private final Context context;
private final DatabaseHelperInterface databaseHelper;
private final PumpSync pumpSync;
private final DateUtil dateUtil;
@ -156,7 +155,6 @@ public class ComboPlugin extends PumpPluginBase implements Pump, Constraints {
this.sp = sp;
this.commandQueue = commandQueue;
this.context = context;
this.databaseHelper = databaseHelper;
this.pumpSync = pumpSync;
this.dateUtil = dateUtil;
@ -1334,24 +1332,32 @@ public class ComboPlugin extends PumpPluginBase implements Pump, Constraints {
if (result.getSuccess()) {
List<Tdd> tdds = pump.tddHistory;
if (tdds != null) {
HashMap<Long, TDD> map = new HashMap<>();
HashMap<Long, Tdd> map = new HashMap<>();
for (int i = 0; i < tdds.size(); i++) {
Tdd currTdd = tdds.get(i);
if (currTdd.total < 1)
continue; //cases where dummy days are introduced (e.g. Battery change with date loss)
if (map.containsKey(currTdd.timestamp)) {
//duplicate days on time changes
TDD existing = map.get(currTdd.timestamp);
Tdd existing = map.get(currTdd.timestamp);
existing.total += currTdd.total;
} else {
map.put(currTdd.timestamp, new TDD(currTdd.timestamp, 0d, 0d, currTdd.total));
map.put(currTdd.timestamp, currTdd);
}
}
Collection<TDD> uniqueColl = map.values();
Collection<Tdd> uniqueColl = map.values();
for (TDD currTdd : uniqueColl) {
databaseHelper.createOrUpdateTDD(currTdd);
for (Tdd currTdd : uniqueColl) {
pumpSync.createOrUpdateTotalDailyDose(
currTdd.timestamp,
0.0,
0.0,
currTdd.total,
null,
PumpType.ACCU_CHEK_COMBO,
serialNumber()
);
}
}
}

View file

@ -1,10 +1,12 @@
package info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.history;
import androidx.annotation.NonNull;
import java.util.Date;
/** Total daily dosage; amount of insulin delivered over a full day. */
public class Tdd extends HistoryRecord {
public final double total;
public double total;
public Tdd(long timestamp, double total) {
super(timestamp);
@ -32,7 +34,7 @@ public class Tdd extends HistoryRecord {
return result;
}
@Override
@NonNull @Override
public String toString() {
return "Tdd{" +
"timestamp=" + timestamp + "(" + new Date(timestamp) + ")" +

View file

@ -17,12 +17,13 @@ import android.widget.TableRow
import android.widget.TextView
import info.nightscout.androidaps.core.R
import info.nightscout.androidaps.core.databinding.ActivityTddStatsBinding
import info.nightscout.androidaps.db.TDD
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.TotalDailyDose
import info.nightscout.androidaps.events.EventDanaRSyncStatus
import info.nightscout.androidaps.events.EventPumpStatusChanged
import info.nightscout.androidaps.extensions.total
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.CommandQueueProvider
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
@ -30,6 +31,7 @@ import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.SafeParse
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.androidaps.utils.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
@ -49,7 +51,7 @@ class TDDStatsActivity : NoSplashAppCompatActivity() {
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var commandQueue: CommandQueueProvider
@Inject lateinit var databaseHelper: DatabaseHelperInterface
@Inject lateinit var repository: AppRepository
@Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var aapsSchedulers: AapsSchedulers
@ -59,8 +61,8 @@ class TDDStatsActivity : NoSplashAppCompatActivity() {
lateinit var tbb: String
private var magicNumber = 0.0
private var decimalFormat: DecimalFormat = DecimalFormat("0.000")
private var historyList: MutableList<TDD> = mutableListOf()
private var dummies: MutableList<TDD> = mutableListOf()
private var historyList: MutableList<TotalDailyDose> = mutableListOf()
private var dummies: MutableList<TotalDailyDose> = mutableListOf()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -230,7 +232,7 @@ class TDDStatsActivity : NoSplashAppCompatActivity() {
@SuppressLint("SetTextI18n")
private fun loadDataFromDB() {
historyList.clear()
historyList.addAll(databaseHelper.getTDDs())
historyList.addAll(repository.getLastTotalDailyDoses(10, false).blockingGet())
//only use newest 10
historyList = historyList.subList(0, min(10, historyList.size))
@ -240,18 +242,19 @@ class TDDStatsActivity : NoSplashAppCompatActivity() {
for (i in 0 until historyList.size - 1) {
val elem1 = historyList[i]
val elem2 = historyList[i + 1]
if (df.format(Date(elem1.date)) != df.format(Date(elem2.date + 25 * 60 * 60 * 1000))) {
val dummy = TDD()
dummy.date = elem1.date - 24 * 60 * 60 * 1000
dummy.basal = elem1.basal / 2
dummy.bolus = elem1.bolus / 2
if (df.format(Date(elem1.timestamp)) != df.format(Date(elem2.timestamp + 25 * 60 * 60 * 1000))) {
val dummy = TotalDailyDose(
timestamp = elem1.timestamp - T.hours(24).msecs(),
basalAmount = elem1.basalAmount / 2.0,
bolusAmount = elem1.bolusAmount / 2.0
)
dummies.add(dummy)
elem1.basal /= 2.0
elem1.bolus /= 2.0
elem1.basalAmount /= 2.0
elem1.bolusAmount /= 2.0
}
}
historyList.addAll(dummies)
historyList.sortWith { lhs: TDD, rhs: TDD -> (rhs.date - lhs.date).toInt() }
historyList.sortWith { lhs: TotalDailyDose, rhs: TotalDailyDose -> (rhs.timestamp - lhs.timestamp).toInt() }
runOnUiThread {
cleanTable(binding.mainTable)
cleanTable(binding.cumulativeTable)
@ -273,7 +276,7 @@ class TDDStatsActivity : NoSplashAppCompatActivity() {
//TDD table
for (record in historyList) {
val tdd = record.getTotal()
val tdd = record.total
// Create the table row
binding.mainTable.addView(
@ -290,17 +293,17 @@ class TDDStatsActivity : NoSplashAppCompatActivity() {
// Here create the TextView dynamically
tr.addView(TextView(this@TDDStatsActivity).also { labelDATE ->
labelDATE.id = 200 + i
labelDATE.text = df1.format(Date(record.date))
labelDATE.text = df1.format(Date(record.timestamp))
labelDATE.setTextColor(Color.WHITE)
})
tr.addView(TextView(this@TDDStatsActivity).also { labelBASAL ->
labelBASAL.id = 300 + i
labelBASAL.text = resourceHelper.gs(R.string.formatinsulinunits, record.basal)
labelBASAL.text = resourceHelper.gs(R.string.formatinsulinunits, record.basalAmount)
labelBASAL.setTextColor(Color.WHITE)
})
tr.addView(TextView(this@TDDStatsActivity).also { labelBOLUS ->
labelBOLUS.id = 400 + i
labelBOLUS.text = resourceHelper.gs(R.string.formatinsulinunits, record.bolus)
labelBOLUS.text = resourceHelper.gs(R.string.formatinsulinunits, record.bolusAmount)
labelBOLUS.setTextColor(Color.WHITE)
})
tr.addView(TextView(this@TDDStatsActivity).also { labelTDD ->
@ -320,11 +323,11 @@ class TDDStatsActivity : NoSplashAppCompatActivity() {
//cumulative TDDs
for (record in historyList) {
if (historyList.isNotEmpty() && df1.format(Date(record.date)) == df1.format(Date()))
if (historyList.isNotEmpty() && df1.format(Date(record.timestamp)) == df1.format(Date()))
//Today should not be included
continue
i++
sum += record.getTotal()
sum += record.total
// Create the cumulative table row
binding.cumulativeTable.addView(
@ -358,14 +361,14 @@ class TDDStatsActivity : NoSplashAppCompatActivity() {
binding.message.visibility = View.VISIBLE
binding.message.text = resourceHelper.gs(R.string.olddata_Message)
} else binding.mainTable.setBackgroundColor(Color.TRANSPARENT)
if (historyList.isNotEmpty() && df1.format(Date(historyList[0].date)) == df1.format(Date())) {
if (historyList.isNotEmpty() && df1.format(Date(historyList[0].timestamp)) == df1.format(Date())) {
//Today should not be included
historyList.removeAt(0)
}
historyList.reverse()
i = 0
for (record in historyList) {
val tdd = record.getTotal()
val tdd = record.total
if (i == 0) {
weighted03 = tdd
weighted05 = tdd
@ -420,10 +423,10 @@ class TDDStatsActivity : NoSplashAppCompatActivity() {
if (childCount > 1) table.removeViews(1, childCount - 1)
}
private fun isOldData(historyList: List<TDD>): Boolean {
private fun isOldData(historyList: List<TotalDailyDose>): Boolean {
val type = activePlugin.activePump.pumpDescription.pumpType
val startsYesterday = type == PumpType.DANA_R || type == PumpType.DANA_RS || type == PumpType.DANA_RV2 || type == PumpType.DANA_R_KOREAN || type == PumpType.ACCU_CHEK_INSIGHT
val df: DateFormat = SimpleDateFormat("dd.MM.", Locale.getDefault())
return historyList.size < 3 || df.format(Date(historyList[0].date)) != df.format(Date(System.currentTimeMillis() - if (startsYesterday) 1000 * 60 * 60 * 24 else 0))
return historyList.size < 3 || df.format(Date(historyList[0].timestamp)) != df.format(Date(System.currentTimeMillis() - if (startsYesterday) 1000 * 60 * 60 * 24 else 0))
}
}

View file

@ -1,73 +0,0 @@
package info.nightscout.androidaps.db;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
import java.util.Locale;
import info.nightscout.androidaps.core.R;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
/**
* Created by mike on 20.09.2017.
*/
@DatabaseTable(tableName = "TDDs")
public class TDD {
@DatabaseField(id = true)
public long date;
@DatabaseField
public double bolus;
@DatabaseField
public double basal;
@DatabaseField
public double total;
public double carbs;
public double getTotal() {
return (total > 0d) ? total : (bolus + basal);
}
public TDD() {
}
public TDD(long date, double bolus, double basal, double total) {
this.date = date;
this.bolus = bolus;
this.basal = basal;
this.total = total;
}
public String toString(DateUtil dateUtil) {
return "TDD [" +
"date=" + date +
"date(str)=" + dateUtil.dateAndTimeString(date) +
", bolus=" + bolus +
", basal=" + basal +
", total=" + total +
']';
}
public String toText(ResourceHelper resourceHelper, DateUtil dateUtil, boolean includeCarbs) {
if (includeCarbs)
return resourceHelper.gs(R.string.tddwithcarbsformat, dateUtil.dateStringShort(date), total, bolus, basal, basal / total * 100, carbs);
else
return resourceHelper.gs(R.string.tddformat, dateUtil.dateStringShort(date), total, bolus, basal, basal / total * 100);
}
public String toText(ResourceHelper resourceHelper, int days, boolean includeCarbs) {
if (includeCarbs)
return resourceHelper.gs(R.string.tddwithcarbsformat, String.format(Locale.getDefault(), "%d ", days) + resourceHelper.gs(R.string.days), total, bolus, basal, basal / total * 100, carbs);
else
return resourceHelper.gs(R.string.tddformat, String.format(Locale.getDefault(), "%d ", days) + resourceHelper.gs(R.string.days), total, bolus, basal, basal / total * 100);
}
}

View file

@ -0,0 +1,18 @@
package info.nightscout.androidaps.extensions
import info.nightscout.androidaps.core.R
import info.nightscout.androidaps.database.entities.TotalDailyDose
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.resources.ResourceHelper
import java.util.*
val TotalDailyDose.total
get() = if (totalAmount > 0) totalAmount else basalAmount + bolusAmount
fun TotalDailyDose.toText(resourceHelper: ResourceHelper, dateUtil: DateUtil, includeCarbs: Boolean): String =
if (includeCarbs) resourceHelper.gs(R.string.tddwithcarbsformat, dateUtil.dateStringShort(timestamp), total, bolusAmount, basalAmount, basalAmount / total * 100, carbs)
else resourceHelper.gs(R.string.tddformat, dateUtil.dateStringShort(timestamp), total, bolusAmount, basalAmount, basalAmount / total * 100)
fun TotalDailyDose.toText(resourceHelper: ResourceHelper, days: Int, includeCarbs: Boolean): String =
if (includeCarbs) resourceHelper.gs(R.string.tddwithcarbsformat, String.format(Locale.getDefault(), "%d ", days) + resourceHelper.gs(R.string.days), total, bolusAmount, basalAmount, basalAmount / total * 100, carbs)
else resourceHelper.gs(R.string.tddformat, String.format(Locale.getDefault(), "%d ", days) + resourceHelper.gs(R.string.days), total, bolusAmount, basalAmount, basalAmount / total * 100)

View file

@ -17,7 +17,6 @@ interface DatabaseHelperInterface {
fun createOrUpdate(record: OHQueueItem)
fun create(record: DbRequest)
fun getDanaRHistoryRecordsByType(type: Byte): List<DanaRHistoryRecord>
fun getTDDs(): List<TDD>
fun size(table: String): Long
fun deleteAllDbRequests()
fun deleteDbRequest(id: String): Int
@ -26,7 +25,6 @@ interface DatabaseHelperInterface {
fun deleteDbRequestbyMongoId(action: String, _id: String)
fun getDbRequestIterator(): CloseableIterator<DbRequest>
fun roundDateToSec(date: Long): Long
fun createOrUpdateTDD(record: TDD)
fun createOrUpdate(tempBasal: TemporaryBasal): Boolean
@Deprecated("Use new DB")
fun findTempBasalByPumpId(id: Long): TemporaryBasal?
@ -36,12 +34,10 @@ interface DatabaseHelperInterface {
fun getProfileSwitchEventsFromTime(mills: Long, ascending: Boolean): List<ProfileSwitch>
fun getAllOmnipodHistoryRecordsFromTimestamp(timestamp: Long, ascending: Boolean): List<OmnipodHistoryRecord>
fun findOmnipodHistoryRecordByPumpId(pumpId: Long): OmnipodHistoryRecord?
fun getTDDsForLastXDays(days: Int): List<TDD>
fun getProfileSwitchData(from: Long, ascending: Boolean): List<ProfileSwitch>
@Deprecated("Use new DB")
fun getExtendedBolusByPumpId(pumpId: Long): ExtendedBolus?
fun getAllProfileSwitches(): List<ProfileSwitch>
fun getAllTDDs(): List<TDD>
fun getAllOHQueueItems(maxEntries: Long): List<OHQueueItem>
fun resetProfileSwitch()

View file

@ -55,10 +55,12 @@ interface PumpSync {
* bolus is null when there is no record in database
*/
data class PumpState(val temporaryBasal: TemporaryBasal?, val extendedBolus: ExtendedBolus?, val bolus: Bolus?, val profile: Profile?) {
data class TemporaryBasal(val timestamp: Long, val duration: Long, val rate: Double, val isAbsolute: Boolean, val type: TemporaryBasalType, val id: Long, val pumpId: Long?)
data class ExtendedBolus(val timestamp: Long, val duration: Long, val amount: Double, val rate: Double)
data class Bolus(val timestamp: Long, val amount: Double)
}
fun expectedPumpState(): PumpState
/*
@ -171,7 +173,7 @@ interface PumpSync {
* @param pumpSerial pump serial number
* @return true if new record is created
**/
fun insertTherapyEventIfNewWithTimestamp(timestamp: Long, type: DetailedBolusInfo.EventType, note: String? = null, pumpId: Long? = null, pumpType: PumpType, pumpSerial: String) : Boolean
fun insertTherapyEventIfNewWithTimestamp(timestamp: Long, type: DetailedBolusInfo.EventType, note: String? = null, pumpId: Long? = null, pumpType: PumpType, pumpSerial: String): Boolean
/**
* Create an announcement
@ -210,7 +212,8 @@ interface PumpSync {
companion object {
fun fromDbType(dbType: TemporaryBasal.Type) = values().firstOrNull { it.name == dbType.name } ?: NORMAL
fun fromDbType(dbType: TemporaryBasal.Type) = values().firstOrNull { it.name == dbType.name }
?: NORMAL
}
}
@ -274,7 +277,7 @@ interface PumpSync {
**/
fun syncStopTemporaryBasalWithPumpId(timestamp: Long, endPumpId: Long, pumpType: PumpType, pumpSerial: String): Boolean
/**
/**
* Invalidate of temporary basals that failed to start
* EROS specific, replace by setting duration to zero ????
*
@ -336,4 +339,34 @@ interface PumpSync {
* @return true if running record is found and ended by changing duration
**/
fun syncStopExtendedBolusWithPumpId(timestamp: Long, endPumpId: Long, pumpType: PumpType, pumpSerial: String): Boolean
/*
* TOTAL DAILY DOSE
*/
/**
* Synchronization of TDD
*
* Search for existing record following way
* 1. pumpId, pumpType, pumpSerial (only if pumpId is provided)
* 2. timestamp, pumpType, pumpSerial
*
* If record is found data is updated
* isValid field is preserved
* If db record doesn't exist, new record is created.
*
* see [info.nightscout.androidaps.database.transactions.SyncPumpTotalDailyDoseTransaction]
*
* @param timestamp timestamp of event from pump history
* @param bolusAmount bolus part
* @param basalAmount basal part
* @param totalAmount if > 0, this value is used as total. Otherwise it's calculated as basal + bolus
* @param pumpId pump id from history
* @param pumpType pump type like PumpType.ACCU_CHEK_COMBO
* @param pumpSerial pump serial number
* @return true if new record is created
**/
fun createOrUpdateTotalDailyDose(timestamp: Long, bolusAmount: Double, basalAmount: Double, totalAmount: Double, pumpId: Long?, pumpType: PumpType, pumpSerial: String): Boolean
}

View file

@ -5,11 +5,7 @@ import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.database.embedments.InterfaceIDs
import info.nightscout.androidaps.database.entities.Bolus
import info.nightscout.androidaps.database.entities.Carbs
import info.nightscout.androidaps.database.entities.ExtendedBolus
import info.nightscout.androidaps.database.entities.TemporaryBasal
import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.database.entities.*
import info.nightscout.androidaps.database.transactions.*
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.interfaces.PumpSync
@ -53,7 +49,7 @@ class PumpSyncImplementation @Inject constructor(
* @param serialNumber serial number of of pump
* @return true if data is allowed
*/
private fun confirmActivePump(timestamp: Long, type: PumpType, serialNumber: String) : Boolean {
private fun confirmActivePump(timestamp: Long, type: PumpType, serialNumber: String): Boolean {
val storedType = sp.getString(R.string.key_active_pump_type, "")
val storedSerial = sp.getString(R.string.key_active_pump_serial_number, "")
val storedTimestamp = sp.getLong(R.string.key_active_pump_change_timestamp, 0L)
@ -74,7 +70,7 @@ class PumpSyncImplementation @Inject constructor(
if (type.description != storedType || serialNumber != storedSerial)
rxBus.send(EventNewNotification(Notification(Notification.WRONG_PUMP_DATA, resourceHelper.gs(R.string.wrong_pump_data), Notification.URGENT)))
aapsLogger.error(LTag.PUMP, "Ignoring pump history record $timestamp ${type.description} $serialNumber. Registered pump: $storedType $storedSerial")
aapsLogger.error(LTag.PUMP, "Ignoring pump history record Allowed: ${dateUtil.dateAndTimeAndSecondsString(storedTimestamp)} $storedType $storedSerial Received: $timestamp ${dateUtil.dateAndTimeAndSecondsString(timestamp)}${type.description} $serialNumber")
return false
}
@ -323,4 +319,27 @@ class PumpSyncImplementation @Inject constructor(
}
}
override fun createOrUpdateTotalDailyDose(timestamp: Long, bolusAmount: Double, basalAmount: Double, totalAmount: Double, pumpId: Long?, pumpType: PumpType, pumpSerial: String): Boolean {
if (!confirmActivePump(timestamp, pumpType, pumpSerial)) return false
val tdd = TotalDailyDose(
timestamp = timestamp,
bolusAmount = bolusAmount,
basalAmount = basalAmount,
totalAmount = totalAmount,
interfaceIDs_backing = InterfaceIDs(
pumpId = pumpId,
pumpType = pumpType.toDbPumpType(),
pumpSerial = pumpSerial
)
)
repository.runTransactionForResult(SyncPumpTotalDailyDoseTransaction(tdd))
.doOnError { aapsLogger.error(LTag.DATABASE, "Error while saving TotalDailyDose", it) }
.blockingGet()
.also { result ->
result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted TotalDailyDose $it") }
result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated TotalDailyDose $it") }
return result.inserted.size > 0
}
}
}

View file

@ -106,7 +106,11 @@ class DanaRSPlugin @Inject constructor(
disposable.add(rxBus
.toObservable(EventDanaRSDeviceChange::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ changePump() }, fabricPrivacy::logException)
.subscribe({
pumpSync.connectNewPump()
changePump()
}, fabricPrivacy::logException)
)
changePump() // load device name
}
@ -134,7 +138,6 @@ class DanaRSPlugin @Inject constructor(
mDeviceAddress = sp.getString(R.string.key_danars_address, "")
mDeviceName = sp.getString(R.string.key_danars_name, "")
danaPump.reset()
pumpSync.connectNewPump()
commandQueue.readStatus("DeviceChanged", null)
}

View file

@ -1,12 +1,15 @@
package info.nightscout.androidaps.danars.comm
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.dana.DanaPump
import info.nightscout.androidaps.dana.comm.RecordTypes
import info.nightscout.androidaps.db.DanaRHistoryRecord
import info.nightscout.androidaps.events.EventDanaRSyncStatus
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface
import info.nightscout.androidaps.interfaces.PumpSync
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
import org.joda.time.DateTime
import java.util.*
import javax.inject.Inject
@ -18,6 +21,8 @@ abstract class DanaRS_Packet_History_(
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var databaseHelper: DatabaseHelperInterface
@Inject lateinit var pumpSync: PumpSync
@Inject lateinit var danaPump: DanaPump
protected var year = 0
protected var month = 0
@ -220,6 +225,18 @@ abstract class DanaRS_Packet_History_(
}
}
databaseHelper.createOrUpdate(danaRHistoryRecord)
//If it is a TDD, store it for stats also.
if (danaRHistoryRecord.recordCode == RecordTypes.RECORD_TYPE_DAILY) {
pumpSync.createOrUpdateTotalDailyDose(
timestamp = danaRHistoryRecord.recordDate,
bolusAmount = danaRHistoryRecord.recordDailyBolus,
basalAmount = danaRHistoryRecord.recordDailyBasal,
totalAmount = 0.0,
pumpId = null,
pumpType = PumpType.DANA_RS,
danaPump.serialNumber
)
}
rxBus.send(EventDanaRSyncStatus(dateUtil.dateAndTimeString(danaRHistoryRecord.recordDate) + " " + messageType))
}
}

File diff suppressed because it is too large Load diff

View file

@ -6,7 +6,7 @@ import androidx.room.TypeConverters
import info.nightscout.androidaps.database.daos.*
import info.nightscout.androidaps.database.entities.*
const val DATABASE_VERSION = 14
const val DATABASE_VERSION = 15
@Database(version = DATABASE_VERSION,
entities = [APSResult::class, Bolus::class, BolusCalculatorResult::class, Carbs::class,

View file

@ -598,6 +598,18 @@ open class AppRepository @Inject internal constructor(
fun getOldestExtendedBolusRecord(): ExtendedBolus? =
database.extendedBolusDao.getOldestRecord()
// TotalDailyDose
fun getAllTotalDailyDoses(ascending: Boolean): Single<List<TotalDailyDose>> =
database.totalDailyDoseDao.getAllTotalDailyDoses()
.map { if (!ascending) it.reversed() else it }
.subscribeOn(Schedulers.io())
fun getLastTotalDailyDoses(count: Int, ascending: Boolean): Single<List<TotalDailyDose>> =
database.totalDailyDoseDao.getLastTotalDailyDoses(count)
.map { if (!ascending) it.reversed() else it }
.subscribeOn(Schedulers.io())
}
@Suppress("USELESS_CAST")

View file

@ -3,6 +3,7 @@ package info.nightscout.androidaps.database.daos
import androidx.room.Dao
import androidx.room.Query
import info.nightscout.androidaps.database.TABLE_TOTAL_DAILY_DOSES
import info.nightscout.androidaps.database.embedments.InterfaceIDs
import info.nightscout.androidaps.database.entities.TotalDailyDose
import io.reactivex.Single
@ -15,4 +16,17 @@ internal interface TotalDailyDoseDao : TraceableDao<TotalDailyDose> {
@Query("DELETE FROM $TABLE_TOTAL_DAILY_DOSES")
override fun deleteAllEntries()
@Query("SELECT * FROM $TABLE_TOTAL_DAILY_DOSES WHERE pumpId = :pumpId AND pumpType = :pumpType AND pumpSerial = :pumpSerial AND referenceId IS NULL")
fun findByPumpIds(pumpId: Long, pumpType: InterfaceIDs.PumpType, pumpSerial: String): TotalDailyDose?
@Query("SELECT * FROM $TABLE_TOTAL_DAILY_DOSES WHERE timestamp = :timestamp AND pumpType = :pumpType AND pumpSerial = :pumpSerial AND referenceId IS NULL")
fun findByPumpTimestamp(timestamp: Long, pumpType: InterfaceIDs.PumpType, pumpSerial: String): TotalDailyDose?
@Query("SELECT * FROM $TABLE_TOTAL_DAILY_DOSES WHERE isValid = 1 AND referenceId IS NULL ORDER BY timestamp ASC")
fun getAllTotalDailyDoses(): Single<List<TotalDailyDose>>
@Query("SELECT * FROM $TABLE_TOTAL_DAILY_DOSES WHERE isValid = 1 AND referenceId IS NULL ORDER BY timestamp DESC LIMIT :count")
fun getLastTotalDailyDoses(count: Int): Single<List<TotalDailyDose>>
}

View file

@ -1,30 +1,35 @@
package info.nightscout.androidaps.database.entities
import androidx.room.*
import androidx.room.Embedded
import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.Index
import androidx.room.PrimaryKey
import info.nightscout.androidaps.database.TABLE_TOTAL_DAILY_DOSES
import info.nightscout.androidaps.database.embedments.InterfaceIDs
import info.nightscout.androidaps.database.interfaces.DBEntryWithTime
import info.nightscout.androidaps.database.interfaces.TraceableDBEntry
import java.util.TimeZone
import java.util.*
@Entity(tableName = TABLE_TOTAL_DAILY_DOSES,
foreignKeys = [ForeignKey(
entity = TotalDailyDose::class,
parentColumns = ["id"],
childColumns = ["referenceId"])],
indices = [Index("referenceId"), Index("timestamp")])
foreignKeys = [ForeignKey(
entity = TotalDailyDose::class,
parentColumns = ["id"],
childColumns = ["referenceId"])],
indices = [Index("referenceId"), Index("timestamp")])
data class TotalDailyDose(
@PrimaryKey(autoGenerate = true)
override var id: Long = 0,
override var id: Long = 0,
override var version: Int = 0,
override var dateCreated: Long = -1,
override var isValid: Boolean = true,
override var referenceId: Long? = null,
@Embedded
override var interfaceIDs_backing: InterfaceIDs? = InterfaceIDs(),
override var interfaceIDs_backing: InterfaceIDs? = InterfaceIDs(),
override var timestamp: Long,
override var utcOffset: Long = TimeZone.getDefault().getOffset(timestamp).toLong(),
var basalAmount: Double?,
var bolusAmount: Double?,
var totalAmount: Double?
var basalAmount: Double = 0.0,
var bolusAmount: Double = 0.0,
var totalAmount: Double = 0.0, // if zero it's calculated as basalAmount + bolusAmount
var carbs: Double = 0.0
) : TraceableDBEntry, DBEntryWithTime

View file

@ -0,0 +1,46 @@
package info.nightscout.androidaps.database.transactions
import info.nightscout.androidaps.database.entities.TotalDailyDose
/**
* Creates or updates the TotalDailyDose from pump synchronization
*/
class SyncPumpTotalDailyDoseTransaction(private val tdd: TotalDailyDose
) : Transaction<SyncPumpTotalDailyDoseTransaction.TransactionResult>() {
override fun run(): TransactionResult {
tdd.interfaceIDs.pumpType ?: tdd.interfaceIDs.pumpSerial
?: throw IllegalStateException("Some pump ID is null")
val result = TransactionResult()
var current: TotalDailyDose? = null
// search by pumpId
if (tdd.interfaceIDs.pumpId != null) {
current = database.totalDailyDoseDao.findByPumpIds(tdd.interfaceIDs.pumpId!!, tdd.interfaceIDs.pumpType!!, tdd.interfaceIDs.pumpSerial!!)
}
// search by timestamp
if (current == null) {
current = database.totalDailyDoseDao.findByPumpTimestamp(tdd.timestamp, tdd.interfaceIDs.pumpType!!, tdd.interfaceIDs.pumpSerial!!)
}
if (current == null) {
database.totalDailyDoseDao.insertNewEntry(tdd)
result.inserted.add(tdd)
} else {
current.basalAmount = tdd.basalAmount
current.bolusAmount = tdd.bolusAmount
current.totalAmount = tdd.totalAmount
current.carbs = tdd.carbs
current.interfaceIDs.pumpId = tdd.interfaceIDs.pumpId
database.totalDailyDoseDao.updateExistingEntry(current)
result.updated.add(current)
}
return result
}
class TransactionResult {
val inserted = mutableListOf<TotalDailyDose>()
val updated = mutableListOf<TotalDailyDose>()
}
}

View file

@ -38,7 +38,6 @@ import info.nightscout.androidaps.db.InsightBolusID;
import info.nightscout.androidaps.db.InsightHistoryOffset;
import info.nightscout.androidaps.db.InsightPumpID;
import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TDD;
import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.events.EventInitializationChanged;
import info.nightscout.androidaps.events.EventRefreshOverview;
@ -51,8 +50,8 @@ import info.nightscout.androidaps.interfaces.DatabaseHelperInterface;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.interfaces.ProfileFunction;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.Pump;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpPluginBase;
import info.nightscout.androidaps.interfaces.PumpSync;
import info.nightscout.androidaps.interfaces.TreatmentsInterface;
@ -1275,12 +1274,15 @@ public class LocalInsightPlugin extends PumpPluginBase implements Pump, Constrai
calendar.set(Calendar.YEAR, event.getTotalYear());
calendar.set(Calendar.MONTH, event.getTotalMonth() - 1);
calendar.set(Calendar.DAY_OF_MONTH, event.getTotalDay());
TDD tdd = new TDD();
tdd.basal = event.getBasalTotal();
tdd.bolus = event.getBolusTotal();
tdd.total = tdd.basal + tdd.bolus;
tdd.date = calendar.getTimeInMillis();
databaseHelper.createOrUpdateTDD(tdd);
pumpSync.createOrUpdateTotalDailyDose(
calendar.getTimeInMillis(),
event.getBolusTotal(),
event.getBasalTotal(),
0.0, // will be calculated automatically
null,
PumpType.ACCU_CHEK_INSIGHT,
serialNumber()
);
}
private void processTubeFilledEvent(TubeFilledEvent event) {

View file

@ -24,7 +24,6 @@ import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.db.DbObjectBase;
import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TDD;
import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.interfaces.ActivePlugin;
@ -589,6 +588,21 @@ public class MedtronicHistoryData {
aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, getLogPrefix() + "TDDs found: %d.\n%s", tdds.size(), gson().toJson(tdds)));
for (PumpHistoryEntry tdd : tdds) {
DailyTotalsDTO totalsDTO = (DailyTotalsDTO) tdd.getDecodedData().get("Object");
Boolean result = pumpSync.createOrUpdateTotalDailyDose(
totalsDTO.timestamp(),
totalsDTO.insulinBasal(),
totalsDTO.insulinBolus(),
totalsDTO.insulinTotal(),
null,
medtronicPumpStatus.pumpType,
medtronicPumpStatus.serialNumber
);
if (result) aapsLogger.debug(LTag.PUMP, "TDD Added/Updated: " + totalsDTO);
}
/*
List<TDD> tddsDb = databaseHelper.getTDDsForLastXDays(3);
for (PumpHistoryEntry tdd : tdds) {
@ -618,6 +632,8 @@ public class MedtronicHistoryData {
}
}
}
*/
}
@ -1317,7 +1333,7 @@ public class MedtronicHistoryData {
return tddsOut.size() == 0 ? tdds : tddsOut;
}
/*
private TDD findTDD(long atechDateTime, List<TDD> tddsDb) {
for (TDD tdd : tddsDb) {
@ -1329,7 +1345,7 @@ public class MedtronicHistoryData {
return null;
}
*/
private long tryToGetByLocalTime(long atechDateTime) {
return DateTimeUtil.toMillisFromATD(atechDateTime);
}

View file

@ -8,7 +8,6 @@ import org.apache.commons.lang3.builder.ToStringBuilder;
import java.util.Locale;
import info.nightscout.androidaps.db.TDD;
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil;
import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil;
@ -240,16 +239,20 @@ public class DailyTotalsDTO {
.toString();
}
public void setTDD(TDD tdd) {
tdd.date = DateTimeUtil.toMillisFromATD(this.entry.atechDateTime);
tdd.basal = insulinBasal;
tdd.bolus = insulinBolus;
tdd.total = insulinTotal;
public long timestamp() {
return DateTimeUtil.toMillisFromATD(this.entry.atechDateTime);
}
public boolean doesEqual(TDD tdd) {
return tdd.total == this.insulinTotal && tdd.bolus == this.insulinBolus && tdd.basal == this.insulinBasal;
public double insulinBasal() {
return insulinBasal;
}
public double insulinBolus() {
return insulinBolus;
}
public double insulinTotal() {
return insulinTotal;
}
}