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, TemporaryBasal.class);
TableUtils.createTableIfNotExists(connectionSource, ExtendedBolus.class); TableUtils.createTableIfNotExists(connectionSource, ExtendedBolus.class);
TableUtils.createTableIfNotExists(connectionSource, ProfileSwitch.class); TableUtils.createTableIfNotExists(connectionSource, ProfileSwitch.class);
TableUtils.createTableIfNotExists(connectionSource, TDD.class);
TableUtils.createTableIfNotExists(connectionSource, InsightHistoryOffset.class); TableUtils.createTableIfNotExists(connectionSource, InsightHistoryOffset.class);
TableUtils.createTableIfNotExists(connectionSource, InsightBolusID.class); TableUtils.createTableIfNotExists(connectionSource, InsightBolusID.class);
TableUtils.createTableIfNotExists(connectionSource, InsightPumpID.class); TableUtils.createTableIfNotExists(connectionSource, InsightPumpID.class);
@ -173,14 +172,12 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
TableUtils.dropTable(connectionSource, TemporaryBasal.class, true); TableUtils.dropTable(connectionSource, TemporaryBasal.class, true);
TableUtils.dropTable(connectionSource, ExtendedBolus.class, true); TableUtils.dropTable(connectionSource, ExtendedBolus.class, true);
TableUtils.dropTable(connectionSource, ProfileSwitch.class, true); TableUtils.dropTable(connectionSource, ProfileSwitch.class, true);
TableUtils.dropTable(connectionSource, TDD.class, true);
TableUtils.dropTable(connectionSource, OmnipodHistoryRecord.class, true); TableUtils.dropTable(connectionSource, OmnipodHistoryRecord.class, true);
TableUtils.createTableIfNotExists(connectionSource, DanaRHistoryRecord.class); TableUtils.createTableIfNotExists(connectionSource, DanaRHistoryRecord.class);
TableUtils.createTableIfNotExists(connectionSource, DbRequest.class); TableUtils.createTableIfNotExists(connectionSource, DbRequest.class);
TableUtils.createTableIfNotExists(connectionSource, TemporaryBasal.class); TableUtils.createTableIfNotExists(connectionSource, TemporaryBasal.class);
TableUtils.createTableIfNotExists(connectionSource, ExtendedBolus.class); TableUtils.createTableIfNotExists(connectionSource, ExtendedBolus.class);
TableUtils.createTableIfNotExists(connectionSource, ProfileSwitch.class); TableUtils.createTableIfNotExists(connectionSource, ProfileSwitch.class);
TableUtils.createTableIfNotExists(connectionSource, TDD.class);
TableUtils.createTableIfNotExists(connectionSource, OmnipodHistoryRecord.class); TableUtils.createTableIfNotExists(connectionSource, OmnipodHistoryRecord.class);
updateEarliestDataChange(0); updateEarliestDataChange(0);
} catch (SQLException e) { } catch (SQLException e) {
@ -209,25 +206,12 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
scheduleProfileSwitchChange(); 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 ------------------------------------------- // ------------------ getDao -------------------------------------------
private Dao<DanaRHistoryRecord, String> getDaoDanaRHistory() throws SQLException { private Dao<DanaRHistoryRecord, String> getDaoDanaRHistory() throws SQLException {
return getDao(DanaRHistoryRecord.class); return getDao(DanaRHistoryRecord.class);
} }
private Dao<TDD, String> getDaoTDD() throws SQLException {
return getDao(TDD.class);
}
private Dao<DbRequest, String> getDaoDbRequest() throws SQLException { private Dao<DbRequest, String> getDaoDbRequest() throws SQLException {
return getDao(DbRequest.class); return getDao(DbRequest.class);
} }
@ -271,60 +255,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return rounded; 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 ------------------- // ------------- DbRequests handling -------------------
public void create(DbRequest dbr) throws SQLException { public void create(DbRequest dbr) throws SQLException {
@ -403,12 +333,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public void createOrUpdate(DanaRHistoryRecord record) { public void createOrUpdate(DanaRHistoryRecord record) {
try { try {
getDaoDanaRHistory().createOrUpdate(record); 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) { } catch (SQLException e) {
aapsLogger.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
} }
@ -1136,7 +1060,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
try { try {
return getDaoExtendedBolus().countOf() return getDaoExtendedBolus().countOf()
+ getDaoProfileSwitch().countOf() + getDaoProfileSwitch().countOf()
+ getDaoTDD().countOf()
+ getDaoTemporaryBasal().countOf(); + getDaoTemporaryBasal().countOf();
} catch (SQLException e) { } catch (SQLException e) {
aapsLogger.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);

View file

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

View file

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

View file

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

View file

@ -168,34 +168,36 @@ open class IobCobCalculatorPlugin @Inject constructor(
} }
override fun calculateFromTreatmentsAndTemps(fromTime: Long, profile: Profile): IobTotal { override fun calculateFromTreatmentsAndTemps(fromTime: Long, profile: Profile): IobTotal {
val now = System.currentTimeMillis() synchronized(dataLock) {
val time = ads.roundUpTime(fromTime) val now = System.currentTimeMillis()
val cacheHit = iobTable[time] val time = ads.roundUpTime(fromTime)
if (time < now && cacheHit != null) { val cacheHit = iobTable[time]
//og.debug(">>> calculateFromTreatmentsAndTemps Cache hit " + new Date(time).toLocaleString()); if (time < now && cacheHit != null) {
return cacheHit //og.debug(">>> calculateFromTreatmentsAndTemps Cache hit " + new Date(time).toLocaleString());
} // else log.debug(">>> calculateFromTreatmentsAndTemps Cache miss " + new Date(time).toLocaleString()); return cacheHit
val bolusIob = calculateIobFromBolusToTime(time).round() } // else log.debug(">>> calculateFromTreatmentsAndTemps Cache miss " + new Date(time).toLocaleString());
val basalIob = calculateIobToTimeFromTempBasalsIncludingConvertedExtended(time).round() val bolusIob = calculateIobFromBolusToTime(time).round()
// OpenAPSSMB only val basalIob = calculateIobToTimeFromTempBasalsIncludingConvertedExtended(time).round()
// Add expected zero temp basal for next 240 minutes // OpenAPSSMB only
val basalIobWithZeroTemp = basalIob.copy() // Add expected zero temp basal for next 240 minutes
val t = TemporaryBasal( val basalIobWithZeroTemp = basalIob.copy()
timestamp = now + 60 * 1000L, val t = TemporaryBasal(
duration = 240, timestamp = now + 60 * 1000L,
rate = 0.0, duration = 240,
isAbsolute = true, rate = 0.0,
type = TemporaryBasal.Type.NORMAL) isAbsolute = true,
if (t.timestamp < time) { type = TemporaryBasal.Type.NORMAL)
val calc = t.iobCalc(time, profile, activePlugin.activeInsulin) if (t.timestamp < time) {
basalIobWithZeroTemp.plus(calc) 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 { 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.R
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.Bolus 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.ActivePlugin
import info.nightscout.androidaps.interfaces.IobCobCalculator import info.nightscout.androidaps.interfaces.IobCobCalculator
import info.nightscout.androidaps.interfaces.ProfileFunction 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.MidnightTime
import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.extensions.convertedToAbsolute import info.nightscout.androidaps.extensions.convertedToAbsolute
import info.nightscout.androidaps.extensions.toText
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import javax.inject.Inject import javax.inject.Inject
@ -29,62 +30,62 @@ class TddCalculator @Inject constructor(
private val repository: AppRepository 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 startTime = MidnightTime.calc(dateUtil.now() - T.days(days).msecs())
val endTime = MidnightTime.calc(dateUtil.now()) val endTime = MidnightTime.calc(dateUtil.now())
val result = LongSparseArray<TDD>() val result = LongSparseArray<TotalDailyDose>()
repository.getBolusesDataFromTimeToTime(startTime, endTime, true).blockingGet() repository.getBolusesDataFromTimeToTime(startTime, endTime, true).blockingGet()
.filter { it.type != Bolus.Type.PRIMING } .filter { it.type != Bolus.Type.PRIMING }
.forEach { t -> .forEach { t ->
val midnight = MidnightTime.calc(t.timestamp) 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.bolus += t.amount tdd.bolusAmount += t.amount
result.put(midnight, tdd) result.put(midnight, tdd)
} }
repository.getCarbsDataFromTimeToTimeExpanded(startTime, endTime, true).blockingGet().forEach { t -> repository.getCarbsDataFromTimeToTimeExpanded(startTime, endTime, true).blockingGet().forEach { t ->
val midnight = MidnightTime.calc(t.timestamp) 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 tdd.carbs += t.amount
result.put(midnight, tdd) result.put(midnight, tdd)
} }
for (t in startTime until endTime step T.mins(5).msecs()) { for (t in startTime until endTime step T.mins(5).msecs()) {
val midnight = MidnightTime.calc(t) 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 tbr = iobCobCalculator.getTempBasalIncludingConvertedExtended(t)
val profile = profileFunction.getProfile(t) ?: continue val profile = profileFunction.getProfile(t) ?: continue
val absoluteRate = tbr?.convertedToAbsolute(t, profile) ?: profile.getBasal(t) 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) { if (!activePlugin.activePump.isFakingTempsByExtendedBoluses) {
// they are not included in TBRs // they are not included in TBRs
val eb = iobCobCalculator.getExtendedBolus(t) val eb = iobCobCalculator.getExtendedBolus(t)
val absoluteEbRate = eb?.rate ?: 0.0 val absoluteEbRate = eb?.rate ?: 0.0
tdd.bolus += absoluteEbRate / 60.0 * 5.0 tdd.bolusAmount += absoluteEbRate / 60.0 * 5.0
} }
result.put(midnight, tdd) result.put(midnight, tdd)
} }
for (i in 0 until result.size()) { for (i in 0 until result.size()) {
val tdd = result.valueAt(i) val tdd = result.valueAt(i)
tdd.total = tdd.bolus + tdd.basal tdd.totalAmount = tdd.bolusAmount + tdd.basalAmount
} }
aapsLogger.debug(LTag.CORE, result.toString()) aapsLogger.debug(LTag.CORE, result.toString())
return result return result
} }
private fun averageTDD(tdds: LongSparseArray<TDD>): TDD { private fun averageTDD(tdds: LongSparseArray<TotalDailyDose>): TotalDailyDose {
val totalTdd = TDD() val totalTdd = TotalDailyDose(timestamp = dateUtil.now())
for (i in 0 until tdds.size()) { for (i in 0 until tdds.size()) {
val tdd = tdds.valueAt(i) val tdd = tdds.valueAt(i)
totalTdd.basal += tdd.basal totalTdd.basalAmount += tdd.basalAmount
totalTdd.bolus += tdd.bolus totalTdd.bolusAmount += tdd.bolusAmount
totalTdd.total += tdd.total totalTdd.totalAmount += tdd.totalAmount
totalTdd.carbs += tdd.carbs totalTdd.carbs += tdd.carbs
} }
totalTdd.basal /= tdds.size().toDouble() totalTdd.basalAmount /= tdds.size().toDouble()
totalTdd.bolus /= tdds.size().toDouble() totalTdd.bolusAmount /= tdds.size().toDouble()
totalTdd.total /= tdds.size().toDouble() totalTdd.totalAmount /= tdds.size().toDouble()
totalTdd.carbs /= tdds.size().toDouble() totalTdd.carbs /= tdds.size().toDouble()
return totalTdd return totalTdd
} }
@ -101,7 +102,7 @@ class TddCalculator @Inject constructor(
} }
@Suppress("SameParameterValue") @Suppress("SameParameterValue")
private fun toText(tdds: LongSparseArray<TDD>, includeCarbs: Boolean): String { private fun toText(tdds: LongSparseArray<TotalDailyDose>, includeCarbs: Boolean): String {
var t = "" var t = ""
for (i in 0 until tdds.size()) { for (i in 0 until tdds.size()) {
t += "${tdds.valueAt(i).toText(resourceHelper, dateUtil, includeCarbs)}<br>" t += "${tdds.valueAt(i).toText(resourceHelper, dateUtil, includeCarbs)}<br>"

View file

@ -7,6 +7,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import info.nightscout.androidaps.extensions.PumpStateExtensionKt; import info.nightscout.androidaps.extensions.PumpStateExtensionKt;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.json.JSONObject; 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.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.TDD;
import info.nightscout.androidaps.events.EventInitializationChanged; import info.nightscout.androidaps.events.EventInitializationChanged;
import info.nightscout.androidaps.events.EventRefreshOverview; import info.nightscout.androidaps.events.EventRefreshOverview;
import info.nightscout.androidaps.interfaces.CommandQueueProvider; import info.nightscout.androidaps.interfaces.CommandQueueProvider;
@ -81,7 +81,6 @@ public class ComboPlugin extends PumpPluginBase implements Pump, Constraints {
private RxBusWrapper rxBus; private RxBusWrapper rxBus;
private final CommandQueueProvider commandQueue; private final CommandQueueProvider commandQueue;
private final Context context; private final Context context;
private final DatabaseHelperInterface databaseHelper;
private final PumpSync pumpSync; private final PumpSync pumpSync;
private final DateUtil dateUtil; private final DateUtil dateUtil;
@ -156,7 +155,6 @@ public class ComboPlugin extends PumpPluginBase implements Pump, Constraints {
this.sp = sp; this.sp = sp;
this.commandQueue = commandQueue; this.commandQueue = commandQueue;
this.context = context; this.context = context;
this.databaseHelper = databaseHelper;
this.pumpSync = pumpSync; this.pumpSync = pumpSync;
this.dateUtil = dateUtil; this.dateUtil = dateUtil;
@ -1334,24 +1332,32 @@ public class ComboPlugin extends PumpPluginBase implements Pump, Constraints {
if (result.getSuccess()) { if (result.getSuccess()) {
List<Tdd> tdds = pump.tddHistory; List<Tdd> tdds = pump.tddHistory;
if (tdds != null) { if (tdds != null) {
HashMap<Long, TDD> map = new HashMap<>(); HashMap<Long, Tdd> map = new HashMap<>();
for (int i = 0; i < tdds.size(); i++) { for (int i = 0; i < tdds.size(); i++) {
Tdd currTdd = tdds.get(i); Tdd currTdd = tdds.get(i);
if (currTdd.total < 1) if (currTdd.total < 1)
continue; //cases where dummy days are introduced (e.g. Battery change with date loss) continue; //cases where dummy days are introduced (e.g. Battery change with date loss)
if (map.containsKey(currTdd.timestamp)) { if (map.containsKey(currTdd.timestamp)) {
//duplicate days on time changes //duplicate days on time changes
TDD existing = map.get(currTdd.timestamp); Tdd existing = map.get(currTdd.timestamp);
existing.total += currTdd.total; existing.total += currTdd.total;
} else { } 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) { for (Tdd currTdd : uniqueColl) {
databaseHelper.createOrUpdateTDD(currTdd); 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; package info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.history;
import androidx.annotation.NonNull;
import java.util.Date; import java.util.Date;
/** Total daily dosage; amount of insulin delivered over a full day. */ /** Total daily dosage; amount of insulin delivered over a full day. */
public class Tdd extends HistoryRecord { public class Tdd extends HistoryRecord {
public final double total; public double total;
public Tdd(long timestamp, double total) { public Tdd(long timestamp, double total) {
super(timestamp); super(timestamp);
@ -32,7 +34,7 @@ public class Tdd extends HistoryRecord {
return result; return result;
} }
@Override @NonNull @Override
public String toString() { public String toString() {
return "Tdd{" + return "Tdd{" +
"timestamp=" + timestamp + "(" + new Date(timestamp) + ")" + "timestamp=" + timestamp + "(" + new Date(timestamp) + ")" +

View file

@ -17,12 +17,13 @@ import android.widget.TableRow
import android.widget.TextView import android.widget.TextView
import info.nightscout.androidaps.core.R import info.nightscout.androidaps.core.R
import info.nightscout.androidaps.core.databinding.ActivityTddStatsBinding 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.EventDanaRSyncStatus
import info.nightscout.androidaps.events.EventPumpStatusChanged import info.nightscout.androidaps.events.EventPumpStatusChanged
import info.nightscout.androidaps.extensions.total
import info.nightscout.androidaps.interfaces.ActivePlugin import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.CommandQueueProvider import info.nightscout.androidaps.interfaces.CommandQueueProvider
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.plugins.bus.RxBusWrapper 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.queue.Callback
import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.SafeParse import info.nightscout.androidaps.utils.SafeParse
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
@ -49,7 +51,7 @@ class TDDStatsActivity : NoSplashAppCompatActivity() {
@Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var activePlugin: ActivePlugin @Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var commandQueue: CommandQueueProvider @Inject lateinit var commandQueue: CommandQueueProvider
@Inject lateinit var databaseHelper: DatabaseHelperInterface @Inject lateinit var repository: AppRepository
@Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var aapsSchedulers: AapsSchedulers @Inject lateinit var aapsSchedulers: AapsSchedulers
@ -59,8 +61,8 @@ class TDDStatsActivity : NoSplashAppCompatActivity() {
lateinit var tbb: String lateinit var tbb: String
private var magicNumber = 0.0 private var magicNumber = 0.0
private var decimalFormat: DecimalFormat = DecimalFormat("0.000") private var decimalFormat: DecimalFormat = DecimalFormat("0.000")
private var historyList: MutableList<TDD> = mutableListOf() private var historyList: MutableList<TotalDailyDose> = mutableListOf()
private var dummies: MutableList<TDD> = mutableListOf() private var dummies: MutableList<TotalDailyDose> = mutableListOf()
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -230,7 +232,7 @@ class TDDStatsActivity : NoSplashAppCompatActivity() {
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
private fun loadDataFromDB() { private fun loadDataFromDB() {
historyList.clear() historyList.clear()
historyList.addAll(databaseHelper.getTDDs()) historyList.addAll(repository.getLastTotalDailyDoses(10, false).blockingGet())
//only use newest 10 //only use newest 10
historyList = historyList.subList(0, min(10, historyList.size)) historyList = historyList.subList(0, min(10, historyList.size))
@ -240,18 +242,19 @@ class TDDStatsActivity : NoSplashAppCompatActivity() {
for (i in 0 until historyList.size - 1) { for (i in 0 until historyList.size - 1) {
val elem1 = historyList[i] val elem1 = historyList[i]
val elem2 = historyList[i + 1] val elem2 = historyList[i + 1]
if (df.format(Date(elem1.date)) != df.format(Date(elem2.date + 25 * 60 * 60 * 1000))) { if (df.format(Date(elem1.timestamp)) != df.format(Date(elem2.timestamp + 25 * 60 * 60 * 1000))) {
val dummy = TDD() val dummy = TotalDailyDose(
dummy.date = elem1.date - 24 * 60 * 60 * 1000 timestamp = elem1.timestamp - T.hours(24).msecs(),
dummy.basal = elem1.basal / 2 basalAmount = elem1.basalAmount / 2.0,
dummy.bolus = elem1.bolus / 2 bolusAmount = elem1.bolusAmount / 2.0
)
dummies.add(dummy) dummies.add(dummy)
elem1.basal /= 2.0 elem1.basalAmount /= 2.0
elem1.bolus /= 2.0 elem1.bolusAmount /= 2.0
} }
} }
historyList.addAll(dummies) 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 { runOnUiThread {
cleanTable(binding.mainTable) cleanTable(binding.mainTable)
cleanTable(binding.cumulativeTable) cleanTable(binding.cumulativeTable)
@ -273,7 +276,7 @@ class TDDStatsActivity : NoSplashAppCompatActivity() {
//TDD table //TDD table
for (record in historyList) { for (record in historyList) {
val tdd = record.getTotal() val tdd = record.total
// Create the table row // Create the table row
binding.mainTable.addView( binding.mainTable.addView(
@ -290,17 +293,17 @@ class TDDStatsActivity : NoSplashAppCompatActivity() {
// Here create the TextView dynamically // Here create the TextView dynamically
tr.addView(TextView(this@TDDStatsActivity).also { labelDATE -> tr.addView(TextView(this@TDDStatsActivity).also { labelDATE ->
labelDATE.id = 200 + i labelDATE.id = 200 + i
labelDATE.text = df1.format(Date(record.date)) labelDATE.text = df1.format(Date(record.timestamp))
labelDATE.setTextColor(Color.WHITE) labelDATE.setTextColor(Color.WHITE)
}) })
tr.addView(TextView(this@TDDStatsActivity).also { labelBASAL -> tr.addView(TextView(this@TDDStatsActivity).also { labelBASAL ->
labelBASAL.id = 300 + i 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) labelBASAL.setTextColor(Color.WHITE)
}) })
tr.addView(TextView(this@TDDStatsActivity).also { labelBOLUS -> tr.addView(TextView(this@TDDStatsActivity).also { labelBOLUS ->
labelBOLUS.id = 400 + i 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) labelBOLUS.setTextColor(Color.WHITE)
}) })
tr.addView(TextView(this@TDDStatsActivity).also { labelTDD -> tr.addView(TextView(this@TDDStatsActivity).also { labelTDD ->
@ -320,11 +323,11 @@ class TDDStatsActivity : NoSplashAppCompatActivity() {
//cumulative TDDs //cumulative TDDs
for (record in historyList) { 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 //Today should not be included
continue continue
i++ i++
sum += record.getTotal() sum += record.total
// Create the cumulative table row // Create the cumulative table row
binding.cumulativeTable.addView( binding.cumulativeTable.addView(
@ -358,14 +361,14 @@ class TDDStatsActivity : NoSplashAppCompatActivity() {
binding.message.visibility = View.VISIBLE binding.message.visibility = View.VISIBLE
binding.message.text = resourceHelper.gs(R.string.olddata_Message) binding.message.text = resourceHelper.gs(R.string.olddata_Message)
} else binding.mainTable.setBackgroundColor(Color.TRANSPARENT) } 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 //Today should not be included
historyList.removeAt(0) historyList.removeAt(0)
} }
historyList.reverse() historyList.reverse()
i = 0 i = 0
for (record in historyList) { for (record in historyList) {
val tdd = record.getTotal() val tdd = record.total
if (i == 0) { if (i == 0) {
weighted03 = tdd weighted03 = tdd
weighted05 = tdd weighted05 = tdd
@ -420,10 +423,10 @@ class TDDStatsActivity : NoSplashAppCompatActivity() {
if (childCount > 1) table.removeViews(1, childCount - 1) 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 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 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()) 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 createOrUpdate(record: OHQueueItem)
fun create(record: DbRequest) fun create(record: DbRequest)
fun getDanaRHistoryRecordsByType(type: Byte): List<DanaRHistoryRecord> fun getDanaRHistoryRecordsByType(type: Byte): List<DanaRHistoryRecord>
fun getTDDs(): List<TDD>
fun size(table: String): Long fun size(table: String): Long
fun deleteAllDbRequests() fun deleteAllDbRequests()
fun deleteDbRequest(id: String): Int fun deleteDbRequest(id: String): Int
@ -26,7 +25,6 @@ interface DatabaseHelperInterface {
fun deleteDbRequestbyMongoId(action: String, _id: String) fun deleteDbRequestbyMongoId(action: String, _id: String)
fun getDbRequestIterator(): CloseableIterator<DbRequest> fun getDbRequestIterator(): CloseableIterator<DbRequest>
fun roundDateToSec(date: Long): Long fun roundDateToSec(date: Long): Long
fun createOrUpdateTDD(record: TDD)
fun createOrUpdate(tempBasal: TemporaryBasal): Boolean fun createOrUpdate(tempBasal: TemporaryBasal): Boolean
@Deprecated("Use new DB") @Deprecated("Use new DB")
fun findTempBasalByPumpId(id: Long): TemporaryBasal? fun findTempBasalByPumpId(id: Long): TemporaryBasal?
@ -36,12 +34,10 @@ interface DatabaseHelperInterface {
fun getProfileSwitchEventsFromTime(mills: Long, ascending: Boolean): List<ProfileSwitch> fun getProfileSwitchEventsFromTime(mills: Long, ascending: Boolean): List<ProfileSwitch>
fun getAllOmnipodHistoryRecordsFromTimestamp(timestamp: Long, ascending: Boolean): List<OmnipodHistoryRecord> fun getAllOmnipodHistoryRecordsFromTimestamp(timestamp: Long, ascending: Boolean): List<OmnipodHistoryRecord>
fun findOmnipodHistoryRecordByPumpId(pumpId: Long): OmnipodHistoryRecord? fun findOmnipodHistoryRecordByPumpId(pumpId: Long): OmnipodHistoryRecord?
fun getTDDsForLastXDays(days: Int): List<TDD>
fun getProfileSwitchData(from: Long, ascending: Boolean): List<ProfileSwitch> fun getProfileSwitchData(from: Long, ascending: Boolean): List<ProfileSwitch>
@Deprecated("Use new DB") @Deprecated("Use new DB")
fun getExtendedBolusByPumpId(pumpId: Long): ExtendedBolus? fun getExtendedBolusByPumpId(pumpId: Long): ExtendedBolus?
fun getAllProfileSwitches(): List<ProfileSwitch> fun getAllProfileSwitches(): List<ProfileSwitch>
fun getAllTDDs(): List<TDD>
fun getAllOHQueueItems(maxEntries: Long): List<OHQueueItem> fun getAllOHQueueItems(maxEntries: Long): List<OHQueueItem>
fun resetProfileSwitch() fun resetProfileSwitch()

View file

@ -55,10 +55,12 @@ interface PumpSync {
* bolus is null when there is no record in database * 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 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 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 ExtendedBolus(val timestamp: Long, val duration: Long, val amount: Double, val rate: Double)
data class Bolus(val timestamp: Long, val amount: Double) data class Bolus(val timestamp: Long, val amount: Double)
} }
fun expectedPumpState(): PumpState fun expectedPumpState(): PumpState
/* /*
@ -171,7 +173,7 @@ interface PumpSync {
* @param pumpSerial pump serial number * @param pumpSerial pump serial number
* @return true if new record is created * @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 * Create an announcement
@ -210,7 +212,8 @@ interface PumpSync {
companion object { 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 fun syncStopTemporaryBasalWithPumpId(timestamp: Long, endPumpId: Long, pumpType: PumpType, pumpSerial: String): Boolean
/** /**
* Invalidate of temporary basals that failed to start * Invalidate of temporary basals that failed to start
* EROS specific, replace by setting duration to zero ???? * 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 * @return true if running record is found and ended by changing duration
**/ **/
fun syncStopExtendedBolusWithPumpId(timestamp: Long, endPumpId: Long, pumpType: PumpType, pumpSerial: String): Boolean 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.AppRepository
import info.nightscout.androidaps.database.ValueWrapper import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.database.embedments.InterfaceIDs import info.nightscout.androidaps.database.embedments.InterfaceIDs
import info.nightscout.androidaps.database.entities.Bolus import info.nightscout.androidaps.database.entities.*
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.transactions.* import info.nightscout.androidaps.database.transactions.*
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.interfaces.PumpSync import info.nightscout.androidaps.interfaces.PumpSync
@ -53,7 +49,7 @@ class PumpSyncImplementation @Inject constructor(
* @param serialNumber serial number of of pump * @param serialNumber serial number of of pump
* @return true if data is allowed * @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 storedType = sp.getString(R.string.key_active_pump_type, "")
val storedSerial = sp.getString(R.string.key_active_pump_serial_number, "") val storedSerial = sp.getString(R.string.key_active_pump_serial_number, "")
val storedTimestamp = sp.getLong(R.string.key_active_pump_change_timestamp, 0L) 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) if (type.description != storedType || serialNumber != storedSerial)
rxBus.send(EventNewNotification(Notification(Notification.WRONG_PUMP_DATA, resourceHelper.gs(R.string.wrong_pump_data), Notification.URGENT))) 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 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 disposable.add(rxBus
.toObservable(EventDanaRSDeviceChange::class.java) .toObservable(EventDanaRSDeviceChange::class.java)
.observeOn(aapsSchedulers.io) .observeOn(aapsSchedulers.io)
.subscribe({ changePump() }, fabricPrivacy::logException) .subscribe({
pumpSync.connectNewPump()
changePump()
}, fabricPrivacy::logException)
) )
changePump() // load device name changePump() // load device name
} }
@ -134,7 +138,6 @@ class DanaRSPlugin @Inject constructor(
mDeviceAddress = sp.getString(R.string.key_danars_address, "") mDeviceAddress = sp.getString(R.string.key_danars_address, "")
mDeviceName = sp.getString(R.string.key_danars_name, "") mDeviceName = sp.getString(R.string.key_danars_name, "")
danaPump.reset() danaPump.reset()
pumpSync.connectNewPump()
commandQueue.readStatus("DeviceChanged", null) commandQueue.readStatus("DeviceChanged", null)
} }

View file

@ -1,12 +1,15 @@
package info.nightscout.androidaps.danars.comm package info.nightscout.androidaps.danars.comm
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.dana.DanaPump
import info.nightscout.androidaps.dana.comm.RecordTypes import info.nightscout.androidaps.dana.comm.RecordTypes
import info.nightscout.androidaps.db.DanaRHistoryRecord import info.nightscout.androidaps.db.DanaRHistoryRecord
import info.nightscout.androidaps.events.EventDanaRSyncStatus import info.nightscout.androidaps.events.EventDanaRSyncStatus
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface import info.nightscout.androidaps.interfaces.DatabaseHelperInterface
import info.nightscout.androidaps.interfaces.PumpSync
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
import org.joda.time.DateTime import org.joda.time.DateTime
import java.util.* import java.util.*
import javax.inject.Inject import javax.inject.Inject
@ -18,6 +21,8 @@ abstract class DanaRS_Packet_History_(
@Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var databaseHelper: DatabaseHelperInterface @Inject lateinit var databaseHelper: DatabaseHelperInterface
@Inject lateinit var pumpSync: PumpSync
@Inject lateinit var danaPump: DanaPump
protected var year = 0 protected var year = 0
protected var month = 0 protected var month = 0
@ -220,6 +225,18 @@ abstract class DanaRS_Packet_History_(
} }
} }
databaseHelper.createOrUpdate(danaRHistoryRecord) 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)) 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.daos.*
import info.nightscout.androidaps.database.entities.* import info.nightscout.androidaps.database.entities.*
const val DATABASE_VERSION = 14 const val DATABASE_VERSION = 15
@Database(version = DATABASE_VERSION, @Database(version = DATABASE_VERSION,
entities = [APSResult::class, Bolus::class, BolusCalculatorResult::class, Carbs::class, entities = [APSResult::class, Bolus::class, BolusCalculatorResult::class, Carbs::class,

View file

@ -598,6 +598,18 @@ open class AppRepository @Inject internal constructor(
fun getOldestExtendedBolusRecord(): ExtendedBolus? = fun getOldestExtendedBolusRecord(): ExtendedBolus? =
database.extendedBolusDao.getOldestRecord() 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") @Suppress("USELESS_CAST")

View file

@ -3,6 +3,7 @@ package info.nightscout.androidaps.database.daos
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Query import androidx.room.Query
import info.nightscout.androidaps.database.TABLE_TOTAL_DAILY_DOSES import info.nightscout.androidaps.database.TABLE_TOTAL_DAILY_DOSES
import info.nightscout.androidaps.database.embedments.InterfaceIDs
import info.nightscout.androidaps.database.entities.TotalDailyDose import info.nightscout.androidaps.database.entities.TotalDailyDose
import io.reactivex.Single import io.reactivex.Single
@ -15,4 +16,17 @@ internal interface TotalDailyDoseDao : TraceableDao<TotalDailyDose> {
@Query("DELETE FROM $TABLE_TOTAL_DAILY_DOSES") @Query("DELETE FROM $TABLE_TOTAL_DAILY_DOSES")
override fun deleteAllEntries() 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 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.TABLE_TOTAL_DAILY_DOSES
import info.nightscout.androidaps.database.embedments.InterfaceIDs import info.nightscout.androidaps.database.embedments.InterfaceIDs
import info.nightscout.androidaps.database.interfaces.DBEntryWithTime import info.nightscout.androidaps.database.interfaces.DBEntryWithTime
import info.nightscout.androidaps.database.interfaces.TraceableDBEntry import info.nightscout.androidaps.database.interfaces.TraceableDBEntry
import java.util.TimeZone import java.util.*
@Entity(tableName = TABLE_TOTAL_DAILY_DOSES, @Entity(tableName = TABLE_TOTAL_DAILY_DOSES,
foreignKeys = [ForeignKey( foreignKeys = [ForeignKey(
entity = TotalDailyDose::class, entity = TotalDailyDose::class,
parentColumns = ["id"], parentColumns = ["id"],
childColumns = ["referenceId"])], childColumns = ["referenceId"])],
indices = [Index("referenceId"), Index("timestamp")]) indices = [Index("referenceId"), Index("timestamp")])
data class TotalDailyDose( data class TotalDailyDose(
@PrimaryKey(autoGenerate = true) @PrimaryKey(autoGenerate = true)
override var id: Long = 0, override var id: Long = 0,
override var version: Int = 0, override var version: Int = 0,
override var dateCreated: Long = -1, override var dateCreated: Long = -1,
override var isValid: Boolean = true, override var isValid: Boolean = true,
override var referenceId: Long? = null, override var referenceId: Long? = null,
@Embedded @Embedded
override var interfaceIDs_backing: InterfaceIDs? = InterfaceIDs(), override var interfaceIDs_backing: InterfaceIDs? = InterfaceIDs(),
override var timestamp: Long, override var timestamp: Long,
override var utcOffset: Long = TimeZone.getDefault().getOffset(timestamp).toLong(), override var utcOffset: Long = TimeZone.getDefault().getOffset(timestamp).toLong(),
var basalAmount: Double?, var basalAmount: Double = 0.0,
var bolusAmount: Double?, var bolusAmount: Double = 0.0,
var totalAmount: Double? var totalAmount: Double = 0.0, // if zero it's calculated as basalAmount + bolusAmount
var carbs: Double = 0.0
) : TraceableDBEntry, DBEntryWithTime ) : 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.InsightHistoryOffset;
import info.nightscout.androidaps.db.InsightPumpID; import info.nightscout.androidaps.db.InsightPumpID;
import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TDD;
import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.events.EventInitializationChanged; import info.nightscout.androidaps.events.EventInitializationChanged;
import info.nightscout.androidaps.events.EventRefreshOverview; 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.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.interfaces.ProfileFunction; import info.nightscout.androidaps.interfaces.ProfileFunction;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.Pump; import info.nightscout.androidaps.interfaces.Pump;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpPluginBase; import info.nightscout.androidaps.interfaces.PumpPluginBase;
import info.nightscout.androidaps.interfaces.PumpSync; import info.nightscout.androidaps.interfaces.PumpSync;
import info.nightscout.androidaps.interfaces.TreatmentsInterface; 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.YEAR, event.getTotalYear());
calendar.set(Calendar.MONTH, event.getTotalMonth() - 1); calendar.set(Calendar.MONTH, event.getTotalMonth() - 1);
calendar.set(Calendar.DAY_OF_MONTH, event.getTotalDay()); calendar.set(Calendar.DAY_OF_MONTH, event.getTotalDay());
TDD tdd = new TDD(); pumpSync.createOrUpdateTotalDailyDose(
tdd.basal = event.getBasalTotal(); calendar.getTimeInMillis(),
tdd.bolus = event.getBolusTotal(); event.getBolusTotal(),
tdd.total = tdd.basal + tdd.bolus; event.getBasalTotal(),
tdd.date = calendar.getTimeInMillis(); 0.0, // will be calculated automatically
databaseHelper.createOrUpdateTDD(tdd); null,
PumpType.ACCU_CHEK_INSIGHT,
serialNumber()
);
} }
private void processTubeFilledEvent(TubeFilledEvent event) { 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.DbObjectBase;
import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TDD;
import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.interfaces.ActivePlugin; 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))); 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); List<TDD> tddsDb = databaseHelper.getTDDsForLastXDays(3);
for (PumpHistoryEntry tdd : tdds) { for (PumpHistoryEntry tdd : tdds) {
@ -618,6 +632,8 @@ public class MedtronicHistoryData {
} }
} }
} }
*/
} }
@ -1317,7 +1333,7 @@ public class MedtronicHistoryData {
return tddsOut.size() == 0 ? tdds : tddsOut; return tddsOut.size() == 0 ? tdds : tddsOut;
} }
/*
private TDD findTDD(long atechDateTime, List<TDD> tddsDb) { private TDD findTDD(long atechDateTime, List<TDD> tddsDb) {
for (TDD tdd : tddsDb) { for (TDD tdd : tddsDb) {
@ -1329,7 +1345,7 @@ public class MedtronicHistoryData {
return null; return null;
} }
*/
private long tryToGetByLocalTime(long atechDateTime) { private long tryToGetByLocalTime(long atechDateTime) {
return DateTimeUtil.toMillisFromATD(atechDateTime); return DateTimeUtil.toMillisFromATD(atechDateTime);
} }

View file

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