Merge remote-tracking branch 'Nightscout/dev' into User_Entry_VWU

# Conflicts:
#	app/src/main/java/info/nightscout/androidaps/dialogs/CarbsDialog.kt
#	app/src/main/java/info/nightscout/androidaps/dialogs/CareDialog.kt
#	app/src/main/java/info/nightscout/androidaps/dialogs/InsulinDialog.kt
#	app/src/main/java/info/nightscout/androidaps/dialogs/TempTargetDialog.kt
#	app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.kt
#	app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.kt
#	app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.kt
#	app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsTempTargetFragment.kt
#	app/src/main/java/info/nightscout/androidaps/utils/wizard/BolusWizard.kt
This commit is contained in:
Philoul 2021-03-03 22:49:31 +01:00
commit 4ce59b929a
108 changed files with 1850 additions and 1057 deletions

1
.gitignore vendored
View file

@ -7,6 +7,7 @@
/captures /captures
*.apk *.apk
build/ build/
!.idea/dictionaries/project-dictionary.xml
.idea/* .idea/*
!.idea/codeStyles/ !.idea/codeStyles/
full/ full/

View file

@ -2,22 +2,6 @@
<code_scheme name="Project" version="173"> <code_scheme name="Project" version="173">
<option name="AUTODETECT_INDENTS" value="false" /> <option name="AUTODETECT_INDENTS" value="false" />
<JetCodeStyleSettings> <JetCodeStyleSettings>
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
<value>
<package name="java.util" alias="false" withSubpackages="false" />
<package name="kotlinx.android.synthetic" alias="false" withSubpackages="true" />
<package name="io.ktor" alias="false" withSubpackages="true" />
</value>
</option>
<option name="PACKAGES_IMPORT_LAYOUT">
<value>
<package name="" alias="false" withSubpackages="true" />
<package name="java" alias="false" withSubpackages="true" />
<package name="javax" alias="false" withSubpackages="true" />
<package name="kotlin" alias="false" withSubpackages="true" />
<package name="" alias="true" withSubpackages="true" />
</value>
</option>
<option name="ALIGN_IN_COLUMNS_CASE_BRANCH" value="true" /> <option name="ALIGN_IN_COLUMNS_CASE_BRANCH" value="true" />
<option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="6" /> <option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="6" />
<option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="6" /> <option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="6" />

View file

@ -0,0 +1,78 @@
<component name="ProjectDictionaryState">
<dictionary name="project-dictionary">
<words>
<w>aaps</w>
<w>actionstring</w>
<w>allowednumbers</w>
<w>androidaps</w>
<w>autosens</w>
<w>autosensdata</w>
<w>bage</w>
<w>basals</w>
<w>bgcheck</w>
<w>bolusing</w>
<w>carb</w>
<w>carbs</w>
<w>carbsreq</w>
<w>careportal</w>
<w>crashlytics</w>
<w>danar</w>
<w>danars</w>
<w>dataset</w>
<w>datasets</w>
<w>dexcom</w>
<w>dexdrip</w>
<w>enteredby</w>
<w>eveningoutpost</w>
<w>eversense</w>
<w>extendedbolus</w>
<w>fileprovider</w>
<w>firebase</w>
<w>glimp</w>
<w>gson</w>
<w>hmac</w>
<w>iage</w>
<w>iobtotal</w>
<w>listdelimiter</w>
<w>localprofile</w>
<w>medtronic</w>
<w>mgdl</w>
<w>mmol</w>
<w>netinsulin</w>
<w>netratio</w>
<w>nightscout</w>
<w>notif</w>
<w>nsclient</w>
<w>okcancel</w>
<w>omnipod</w>
<w>oref</w>
<w>passcode</w>
<w>poctech</w>
<w>profileswitch</w>
<w>pumpbtcomm</w>
<w>quickwizard</w>
<w>readstatus</w>
<w>realduration</w>
<w>refresheventsfromnightscout</w>
<w>rileylink</w>
<w>roboelectric</w>
<w>smscommunicator</w>
<w>soundid</w>
<w>splitted</w>
<w>superbolus</w>
<w>targethigh</w>
<w>targetlow</w>
<w>tdds</w>
<w>tempbasal</w>
<w>tempbasals</w>
<w>temptarget</w>
<w>textl</w>
<w>tidepool</w>
<w>timeshift</w>
<w>tirs</w>
<w>uart</w>
<w>wizzardpage</w>
<w>xdrip</w>
</words>
</dictionary>
</component>

View file

@ -110,7 +110,7 @@ android {
defaultConfig { defaultConfig {
multiDexEnabled true multiDexEnabled true
versionCode 1500 versionCode 1500
version "2.8.2.1-dev-b" version "2.8.2.1-dev-c"
buildConfigField "String", "VERSION", '"' + version + '"' buildConfigField "String", "VERSION", '"' + version + '"'
buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"' buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"'
buildConfigField "String", "REMOTE", '"' + generateGitRemote() + '"' buildConfigField "String", "REMOTE", '"' + generateGitRemote() + '"'

View file

@ -140,7 +140,10 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
else defaultProfileDPV.profile(age, tdd, pct / 100.0, profileFunction.getUnits()) else defaultProfileDPV.profile(age, tdd, pct / 100.0, profileFunction.getUnits())
profile?.let { profile?.let {
OKDialog.showConfirmation(this, resourceHelper.gs(R.string.careportal_profileswitch), resourceHelper.gs(R.string.copytolocalprofile), Runnable { OKDialog.showConfirmation(this, resourceHelper.gs(R.string.careportal_profileswitch), resourceHelper.gs(R.string.copytolocalprofile), Runnable {
localProfilePlugin.addProfile(localProfilePlugin.copyFrom(it, "DefaultProfile" + dateUtil.dateAndTimeAndSecondsString(dateUtil._now()))) localProfilePlugin.addProfile(localProfilePlugin.copyFrom(it, "DefaultProfile " +
dateUtil.dateAndTimeAndSecondsString(dateUtil._now())
.replace(".", "/")
))
rxBus.send(EventLocalProfileChanged()) rxBus.send(EventLocalProfileChanged())
}) })
} }

View file

@ -74,9 +74,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
@Inject OpenHumansUploader openHumansUploader; @Inject OpenHumansUploader openHumansUploader;
public static final String DATABASE_NAME = "AndroidAPSDb"; public static final String DATABASE_NAME = "AndroidAPSDb";
public static final String DATABASE_TEMPORARYBASALS = "TemporaryBasals";
public static final String DATABASE_EXTENDEDBOLUSES = "ExtendedBoluses"; public static final String DATABASE_EXTENDEDBOLUSES = "ExtendedBoluses";
public static final String DATABASE_TEMPTARGETS = "TempTargets";
public static final String DATABASE_DANARHISTORY = "DanaRHistory"; public static final String DATABASE_DANARHISTORY = "DanaRHistory";
public static final String DATABASE_DBREQUESTS = "DBRequests"; public static final String DATABASE_DBREQUESTS = "DBRequests";
public static final String DATABASE_CAREPORTALEVENTS = "CareportalEvents"; public static final String DATABASE_CAREPORTALEVENTS = "CareportalEvents";
@ -87,15 +85,9 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public static Long earliestDataChange = null; public static Long earliestDataChange = null;
private static final ScheduledExecutorService bgWorker = Executors.newSingleThreadScheduledExecutor();
private static ScheduledFuture<?> scheduledBgPost = null;
private static final ScheduledExecutorService tempBasalsWorker = Executors.newSingleThreadScheduledExecutor(); private static final ScheduledExecutorService tempBasalsWorker = Executors.newSingleThreadScheduledExecutor();
private static ScheduledFuture<?> scheduledTemBasalsPost = null; private static ScheduledFuture<?> scheduledTemBasalsPost = null;
private static final ScheduledExecutorService tempTargetWorker = Executors.newSingleThreadScheduledExecutor();
private static ScheduledFuture<?> scheduledTemTargetPost = null;
private static final ScheduledExecutorService extendedBolusWorker = Executors.newSingleThreadScheduledExecutor(); private static final ScheduledExecutorService extendedBolusWorker = Executors.newSingleThreadScheduledExecutor();
private static ScheduledFuture<?> scheduledExtendedBolusPost = null; private static ScheduledFuture<?> scheduledExtendedBolusPost = null;
@ -119,8 +111,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public void onCreate(SQLiteDatabase database, ConnectionSource connectionSource) { public void onCreate(SQLiteDatabase database, ConnectionSource connectionSource) {
try { try {
aapsLogger.info(LTag.DATABASE, "onCreate"); aapsLogger.info(LTag.DATABASE, "onCreate");
TableUtils.createTableIfNotExists(connectionSource, TempTarget.class);
//TableUtils.createTableIfNotExists(connectionSource, BgReading.class);
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);
@ -151,8 +141,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
if (oldVersion < 7) { if (oldVersion < 7) {
aapsLogger.info(LTag.DATABASE, "onUpgrade"); aapsLogger.info(LTag.DATABASE, "onUpgrade");
TableUtils.dropTable(connectionSource, TempTarget.class, true);
//TableUtils.dropTable(connectionSource, BgReading.class, true);
TableUtils.dropTable(connectionSource, DanaRHistoryRecord.class, true); TableUtils.dropTable(connectionSource, DanaRHistoryRecord.class, true);
TableUtils.dropTable(connectionSource, DbRequest.class, true); TableUtils.dropTable(connectionSource, DbRequest.class, true);
TableUtils.dropTable(connectionSource, TemporaryBasal.class, true); TableUtils.dropTable(connectionSource, TemporaryBasal.class, true);
@ -201,8 +189,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public void resetDatabases() { public void resetDatabases() {
try { try {
TableUtils.dropTable(connectionSource, TempTarget.class, true);
//TableUtils.dropTable(connectionSource, BgReading.class, true);
TableUtils.dropTable(connectionSource, DanaRHistoryRecord.class, true); TableUtils.dropTable(connectionSource, DanaRHistoryRecord.class, true);
TableUtils.dropTable(connectionSource, DbRequest.class, true); TableUtils.dropTable(connectionSource, DbRequest.class, true);
TableUtils.dropTable(connectionSource, TemporaryBasal.class, true); TableUtils.dropTable(connectionSource, TemporaryBasal.class, true);
@ -211,8 +197,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
TableUtils.dropTable(connectionSource, ProfileSwitch.class, true); TableUtils.dropTable(connectionSource, ProfileSwitch.class, true);
TableUtils.dropTable(connectionSource, TDD.class, true); TableUtils.dropTable(connectionSource, TDD.class, true);
TableUtils.dropTable(connectionSource, OmnipodHistoryRecord.class, true); TableUtils.dropTable(connectionSource, OmnipodHistoryRecord.class, true);
TableUtils.createTableIfNotExists(connectionSource, TempTarget.class);
//TableUtils.createTableIfNotExists(connectionSource, BgReading.class);
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);
@ -228,7 +212,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
virtualPumpPlugin.setFakingStatus(true); virtualPumpPlugin.setFakingStatus(true);
scheduleTemporaryBasalChange(); scheduleTemporaryBasalChange();
scheduleExtendedBolusChange(); scheduleExtendedBolusChange();
scheduleTemporaryTargetChange();
scheduleCareportalEventChange(); scheduleCareportalEventChange();
scheduleProfileSwitchChange(); scheduleProfileSwitchChange();
new java.util.Timer().schedule( new java.util.Timer().schedule(
@ -242,16 +225,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
); );
} }
public void resetTempTargets() {
try {
TableUtils.dropTable(connectionSource, TempTarget.class, true);
TableUtils.createTableIfNotExists(connectionSource, TempTarget.class);
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);
}
scheduleTemporaryTargetChange();
}
public void resetTemporaryBasals() { public void resetTemporaryBasals() {
try { try {
TableUtils.dropTable(connectionSource, TemporaryBasal.class, true); TableUtils.dropTable(connectionSource, TemporaryBasal.class, true);
@ -306,10 +279,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
// ------------------ getDao ------------------------------------------- // ------------------ getDao -------------------------------------------
private Dao<TempTarget, Long> getDaoTempTargets() throws SQLException {
return getDao(TempTarget.class);
}
private Dao<DanaRHistoryRecord, String> getDaoDanaRHistory() throws SQLException { private Dao<DanaRHistoryRecord, String> getDaoDanaRHistory() throws SQLException {
return getDao(DanaRHistoryRecord.class); return getDao(DanaRHistoryRecord.class);
} }
@ -476,8 +445,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
} }
} }
// -------------------- TEMPTARGET HANDLING -------------------
public static void updateEarliestDataChange(long newDate) { public static void updateEarliestDataChange(long newDate) {
if (earliestDataChange == null) { if (earliestDataChange == null) {
earliestDataChange = newDate; earliestDataChange = newDate;
@ -488,196 +455,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
} }
} }
// ---------------- TempTargets handling ---------------
public List<TempTarget> getTemptargetsDataFromTime(long mills, boolean ascending) {
try {
Dao<TempTarget, Long> daoTempTargets = getDaoTempTargets();
List<TempTarget> tempTargets;
QueryBuilder<TempTarget, Long> queryBuilder = daoTempTargets.queryBuilder();
queryBuilder.orderBy("date", ascending);
Where where = queryBuilder.where();
where.ge("date", mills);
PreparedQuery<TempTarget> preparedQuery = queryBuilder.prepare();
tempTargets = daoTempTargets.query(preparedQuery);
return tempTargets;
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);
}
return new ArrayList<TempTarget>();
}
public List<TempTarget> getAllTempTargets() {
try {
return getDaoTempTargets().queryForAll();
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);
}
return Collections.emptyList();
}
public List<TempTarget> getTemptargetsDataFromTime(long from, long to, boolean ascending) {
try {
Dao<TempTarget, Long> daoTempTargets = getDaoTempTargets();
List<TempTarget> tempTargets;
QueryBuilder<TempTarget, Long> queryBuilder = daoTempTargets.queryBuilder();
queryBuilder.orderBy("date", ascending);
Where where = queryBuilder.where();
where.between("date", from, to);
PreparedQuery<TempTarget> preparedQuery = queryBuilder.prepare();
tempTargets = daoTempTargets.query(preparedQuery);
return tempTargets;
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);
}
return new ArrayList<TempTarget>();
}
public boolean createOrUpdate(TempTarget tempTarget) {
try {
TempTarget old;
tempTarget.date = roundDateToSec(tempTarget.date);
if (tempTarget.source == Source.NIGHTSCOUT) {
old = getDaoTempTargets().queryForId(tempTarget.date);
if (old != null) {
if (!old.isEqual(tempTarget)) {
getDaoTempTargets().delete(old); // need to delete/create because date may change too
old.copyFrom(tempTarget);
getDaoTempTargets().create(old);
openHumansUploader.enqueueTempTarget(old);
aapsLogger.debug(LTag.DATABASE, "TEMPTARGET: Updating record by date from: " + Source.getString(tempTarget.source) + " " + old.toString());
scheduleTemporaryTargetChange();
return true;
}
return false;
}
// find by NS _id
if (tempTarget._id != null) {
QueryBuilder<TempTarget, Long> queryBuilder = getDaoTempTargets().queryBuilder();
Where where = queryBuilder.where();
where.eq("_id", tempTarget._id);
PreparedQuery<TempTarget> preparedQuery = queryBuilder.prepare();
List<TempTarget> trList = getDaoTempTargets().query(preparedQuery);
if (trList.size() > 0) {
old = trList.get(0);
if (!old.isEqual(tempTarget)) {
getDaoTempTargets().delete(old); // need to delete/create because date may change too
old.copyFrom(tempTarget);
getDaoTempTargets().create(old);
openHumansUploader.enqueueTempTarget(old);
aapsLogger.debug(LTag.DATABASE, "TEMPTARGET: Updating record by _id from: " + Source.getString(tempTarget.source) + " " + old.toString());
scheduleTemporaryTargetChange();
return true;
}
}
}
getDaoTempTargets().create(tempTarget);
aapsLogger.debug(LTag.DATABASE, "TEMPTARGET: New record from: " + Source.getString(tempTarget.source) + " " + tempTarget.toString());
scheduleTemporaryTargetChange();
return true;
}
if (tempTarget.source == Source.USER) {
getDaoTempTargets().create(tempTarget);
openHumansUploader.enqueueTempTarget(tempTarget);
aapsLogger.debug(LTag.DATABASE, "TEMPTARGET: New record from: " + Source.getString(tempTarget.source) + " " + tempTarget.toString());
scheduleTemporaryTargetChange();
return true;
}
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);
}
return false;
}
public void delete(TempTarget tempTarget) {
try {
getDaoTempTargets().delete(tempTarget);
openHumansUploader.enqueueTempTarget(tempTarget, true);
scheduleTemporaryTargetChange();
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);
}
}
private void scheduleTemporaryTargetChange() {
class PostRunnable implements Runnable {
public void run() {
aapsLogger.debug(LTag.DATABASE, "Firing EventTempTargetChange");
rxBus.send(new EventTempTargetChange());
scheduledTemTargetPost = null;
}
}
// prepare task for execution in 1 sec
// cancel waiting task to prevent sending multiple posts
if (scheduledTemTargetPost != null)
scheduledTemTargetPost.cancel(false);
Runnable task = new PostRunnable();
final int sec = 1;
scheduledTemTargetPost = tempTargetWorker.schedule(task, sec, TimeUnit.SECONDS);
}
/*
{
"_id": "58795998aa86647ba4d68ce7",
"enteredBy": "",
"eventType": "Temporary Target",
"reason": "Eating Soon",
"targetTop": 80,
"targetBottom": 80,
"duration": 120,
"created_at": "2017-01-13T22:50:00.782Z",
"carbs": null,
"insulin": null
}
*/
public void createTemptargetFromJsonIfNotExists(JSONObject trJson) {
try {
String units = JsonHelper.safeGetString(trJson, "units", Constants.MGDL);
TempTarget tempTarget = new TempTarget()
.date(trJson.getLong("mills"))
.duration(JsonHelper.safeGetInt(trJson, "duration"))
.low(Profile.toMgdl(JsonHelper.safeGetDouble(trJson, "targetBottom"), units))
.high(Profile.toMgdl(JsonHelper.safeGetDouble(trJson, "targetTop"), units))
.reason(JsonHelper.safeGetString(trJson, "reason", ""))
._id(trJson.getString("_id"))
.source(Source.NIGHTSCOUT);
createOrUpdate(tempTarget);
} catch (JSONException e) {
aapsLogger.error("Unhandled exception: " + trJson.toString(), e);
}
}
public void deleteTempTargetById(String _id) {
TempTarget stored = findTempTargetById(_id);
if (stored != null) {
aapsLogger.debug(LTag.DATABASE, "TEMPTARGET: Removing TempTarget record from database: " + stored.toString());
delete(stored);
scheduleTemporaryTargetChange();
}
}
public TempTarget findTempTargetById(String _id) {
try {
QueryBuilder<TempTarget, Long> queryBuilder = getDaoTempTargets().queryBuilder();
Where where = queryBuilder.where();
where.eq("_id", _id);
PreparedQuery<TempTarget> preparedQuery = queryBuilder.prepare();
List<TempTarget> list = getDaoTempTargets().query(preparedQuery);
if (list.size() == 1) {
return list.get(0);
} else {
return null;
}
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);
}
return null;
}
// ----------------- DanaRHistory handling -------------------- // ----------------- DanaRHistory handling --------------------
public void createOrUpdate(DanaRHistoryRecord record) { public void createOrUpdate(DanaRHistoryRecord record) {
@ -1723,7 +1500,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
if (stored != null) { if (stored != null) {
aapsLogger.debug(LTag.DATABASE, "PROFILESWITCH: Removing ProfileSwitch record from database: " + stored.toString()); aapsLogger.debug(LTag.DATABASE, "PROFILESWITCH: Removing ProfileSwitch record from database: " + stored.toString());
delete(stored); delete(stored);
scheduleTemporaryTargetChange(); scheduleProfileSwitchChange();
} }
} }
@ -1958,8 +1735,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
+ getDaoCareportalEvents().countOf() + getDaoCareportalEvents().countOf()
+ getDaoProfileSwitch().countOf() + getDaoProfileSwitch().countOf()
+ getDaoTDD().countOf() + getDaoTDD().countOf()
+ getDaoTemporaryBasal().countOf() + getDaoTemporaryBasal().countOf();
+ getDaoTempTargets().countOf();
} catch (SQLException e) { } catch (SQLException e) {
aapsLogger.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
} }

View file

@ -5,6 +5,7 @@ import androidx.annotation.NonNull;
import com.j256.ormlite.dao.CloseableIterator; import com.j256.ormlite.dao.CloseableIterator;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.json.JSONObject;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.List; import java.util.List;
@ -13,7 +14,9 @@ import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface; import info.nightscout.androidaps.interfaces.DatabaseHelperInterface;
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
@Singleton @Singleton
public class DatabaseHelperProvider implements DatabaseHelperInterface { public class DatabaseHelperProvider implements DatabaseHelperInterface {
@ -77,8 +80,8 @@ public class DatabaseHelperProvider implements DatabaseHelperInterface {
MainApp.getDbHelper().createOrUpdateTDD(record); MainApp.getDbHelper().createOrUpdateTDD(record);
} }
@Override public void createOrUpdate(@NonNull TemporaryBasal tempBasal) { @Override public boolean createOrUpdate(@NonNull TemporaryBasal tempBasal) {
MainApp.getDbHelper().createOrUpdate(tempBasal); return MainApp.getDbHelper().createOrUpdate(tempBasal);
} }
@NonNull @Override public TemporaryBasal findTempBasalByPumpId(long id) { @NonNull @Override public TemporaryBasal findTempBasalByPumpId(long id) {
@ -140,4 +143,56 @@ public class DatabaseHelperProvider implements DatabaseHelperInterface {
@Nullable @Override public InsightPumpID getPumpStoppedEvent(@NonNull String pumpSerial, long before) { @Nullable @Override public InsightPumpID getPumpStoppedEvent(@NonNull String pumpSerial, long before) {
return MainApp.getDbHelper().getPumpStoppedEvent(pumpSerial, before); return MainApp.getDbHelper().getPumpStoppedEvent(pumpSerial, before);
} }
@Override public boolean createOrUpdate(@NonNull ExtendedBolus extendedBolus) {
return MainApp.getDbHelper().createOrUpdate(extendedBolus);
}
@Override public void createOrUpdate(@NonNull ProfileSwitch profileSwitch) {
MainApp.getDbHelper().createOrUpdate(profileSwitch);
}
@Override public void delete(@NonNull TemporaryBasal tempBasal) {
MainApp.getDbHelper().delete(tempBasal);
}
@NonNull @Override public List<ExtendedBolus> getExtendedBolusDataFromTime(long mills, boolean ascending) {
return MainApp.getDbHelper().getExtendedBolusDataFromTime(mills, ascending);
}
@Override public void deleteTempBasalById(@NonNull String _id) {
MainApp.getDbHelper().deleteTempBasalById(_id);
}
@Override public void deleteExtendedBolusById(@NonNull String _id) {
MainApp.getDbHelper().deleteExtendedBolusById(_id);
}
@Override public void deleteCareportalEventById(@NonNull String _id) {
MainApp.getDbHelper().deleteCareportalEventById(_id);
}
@Override public void deleteProfileSwitchById(@NonNull String _id) {
MainApp.getDbHelper().deleteProfileSwitchById(_id);
}
@Override public void createTempBasalFromJsonIfNotExists(@NonNull JSONObject json) {
MainApp.getDbHelper().createTempBasalFromJsonIfNotExists(json);
}
@Override public void createExtendedBolusFromJsonIfNotExists(@NonNull JSONObject json) {
MainApp.getDbHelper().createExtendedBolusFromJsonIfNotExists(json);
}
@Override public void createCareportalEventFromJsonIfNotExists(@NonNull JSONObject json) {
MainApp.getDbHelper().createCareportalEventFromJsonIfNotExists(json);
}
@Override public void createProfileSwitchFromJsonIfNotExists(@NonNull ActivePluginProvider activePluginProvider, @NonNull NSUpload nsUpload, @NonNull JSONObject trJson) {
MainApp.getDbHelper().createProfileSwitchFromJsonIfNotExists(activePluginProvider, nsUpload, trJson);
}
@Override public void resetDatabases() {
MainApp.getDbHelper().resetDatabases();
}
} }

View file

@ -11,13 +11,15 @@ import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.database.entities.UserEntry.* import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.database.transactions.InsertTemporaryTargetAndCancelCurrentTransaction
import info.nightscout.androidaps.databinding.DialogCarbsBinding import info.nightscout.androidaps.databinding.DialogCarbsBinding
import info.nightscout.androidaps.db.CareportalEvent import info.nightscout.androidaps.db.CareportalEvent
import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.db.TempTarget
import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
@ -28,8 +30,11 @@ import info.nightscout.androidaps.utils.*
import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.extensions.formatColor import info.nightscout.androidaps.utils.extensions.formatColor
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import java.text.DecimalFormat import java.text.DecimalFormat
import java.util.* import java.util.*
import java.util.concurrent.TimeUnit
import javax.inject.Inject import javax.inject.Inject
import kotlin.math.max import kotlin.math.max
@ -46,6 +51,7 @@ class CarbsDialog : DialogFragmentWithDate() {
@Inject lateinit var carbsGenerator: CarbsGenerator @Inject lateinit var carbsGenerator: CarbsGenerator
@Inject lateinit var uel: UserEntryLogger @Inject lateinit var uel: UserEntryLogger
@Inject lateinit var carbTimer: CarbTimer @Inject lateinit var carbTimer: CarbTimer
@Inject lateinit var repository: AppRepository
companion object { companion object {
@ -54,6 +60,8 @@ class CarbsDialog : DialogFragmentWithDate() {
private const val FAV3_DEFAULT = 20 private const val FAV3_DEFAULT = 20
} }
private val disposable = CompositeDisposable()
private val textWatcher: TextWatcher = object : TextWatcher { private val textWatcher: TextWatcher = object : TextWatcher {
override fun afterTextChanged(s: Editable) { override fun afterTextChanged(s: Editable) {
validateInputs() validateInputs()
@ -154,6 +162,7 @@ class CarbsDialog : DialogFragmentWithDate() {
override fun onDestroyView() { override fun onDestroyView() {
super.onDestroyView() super.onDestroyView()
disposable.clear()
_binding = null _binding = null
} }
@ -214,38 +223,50 @@ class CarbsDialog : DialogFragmentWithDate() {
when { when {
activitySelected -> { activitySelected -> {
uel.log(Action.TT_ACTIVITY, ValueWithUnit(activityTT, units) , ValueWithUnit(activityTTDuration, Units.M)) uel.log(Action.TT_ACTIVITY, ValueWithUnit(activityTT, units) , ValueWithUnit(activityTTDuration, Units.M))
val tempTarget = TempTarget() disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction(
.date(System.currentTimeMillis()) timestamp = System.currentTimeMillis(),
.duration(activityTTDuration) duration = TimeUnit.MINUTES.toMillis(activityTTDuration.toLong()),
.reason(resourceHelper.gs(R.string.activity)) reason = TemporaryTarget.Reason.ACTIVITY,
.source(Source.USER) lowTarget = Profile.toMgdl(activityTT, profileFunction.getUnits()),
.low(Profile.toMgdl(activityTT, profileFunction.getUnits())) highTarget = Profile.toMgdl(activityTT, profileFunction.getUnits())
.high(Profile.toMgdl(activityTT, profileFunction.getUnits())) )).subscribe({ result ->
treatmentsPlugin.addToHistoryTempTarget(tempTarget) result.inserted.forEach { nsUpload.uploadTempTarget(it) }
result.updated.forEach { nsUpload.updateTempTarget(it) }
}, {
aapsLogger.error(LTag.BGSOURCE, "Error while saving temporary target", it)
})
} }
eatingSoonSelected -> { eatingSoonSelected -> {
uel.log(Action.TT_EATING_SOON, ValueWithUnit(eatingSoonTT, units) , ValueWithUnit(eatingSoonTTDuration, Units.M)) uel.log(Action.TT_EATING_SOON, ValueWithUnit(eatingSoonTT, units) , ValueWithUnit(eatingSoonTTDuration, Units.M))
val tempTarget = TempTarget() disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction(
.date(System.currentTimeMillis()) timestamp = System.currentTimeMillis(),
.duration(eatingSoonTTDuration) duration = TimeUnit.MINUTES.toMillis(eatingSoonTTDuration.toLong()),
.reason(resourceHelper.gs(R.string.eatingsoon)) reason = TemporaryTarget.Reason.EATING_SOON,
.source(Source.USER) lowTarget = Profile.toMgdl(eatingSoonTT, profileFunction.getUnits()),
.low(Profile.toMgdl(eatingSoonTT, profileFunction.getUnits())) highTarget = Profile.toMgdl(eatingSoonTT, profileFunction.getUnits())
.high(Profile.toMgdl(eatingSoonTT, profileFunction.getUnits())) )).subscribe({ result ->
treatmentsPlugin.addToHistoryTempTarget(tempTarget) result.inserted.forEach { nsUpload.uploadTempTarget(it) }
result.updated.forEach { nsUpload.updateTempTarget(it) }
}, {
aapsLogger.error(LTag.BGSOURCE, "Error while saving temporary target", it)
})
} }
hypoSelected -> { hypoSelected -> {
uel.log(Action.TT_HYPO, ValueWithUnit(hypoTT, units) , ValueWithUnit(hypoTTDuration, Units.M)) uel.log(Action.TT_HYPO, ValueWithUnit(hypoTT, units) , ValueWithUnit(hypoTTDuration, Units.M))
val tempTarget = TempTarget() disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction(
.date(System.currentTimeMillis()) timestamp = System.currentTimeMillis(),
.duration(hypoTTDuration) duration = TimeUnit.MINUTES.toMillis(hypoTTDuration.toLong()),
.reason(resourceHelper.gs(R.string.hypo)) reason = TemporaryTarget.Reason.HYPOGLYCEMIA,
.source(Source.USER) lowTarget = Profile.toMgdl(hypoTT, profileFunction.getUnits()),
.low(Profile.toMgdl(hypoTT, profileFunction.getUnits())) highTarget = Profile.toMgdl(hypoTT, profileFunction.getUnits())
.high(Profile.toMgdl(hypoTT, profileFunction.getUnits())) )).subscribe({ result ->
treatmentsPlugin.addToHistoryTempTarget(tempTarget) result.inserted.forEach { nsUpload.uploadTempTarget(it) }
result.updated.forEach { nsUpload.updateTempTarget(it) }
}, {
aapsLogger.error(LTag.BGSOURCE, "Error while saving temporary target", it)
})
} }
} }
if (carbsAfterConstraints > 0) { if (carbsAfterConstraints > 0) {

View file

@ -17,6 +17,7 @@ import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.databinding.DialogCareBinding import info.nightscout.androidaps.databinding.DialogCareBinding
import info.nightscout.androidaps.db.CareportalEvent import info.nightscout.androidaps.db.CareportalEvent
import info.nightscout.androidaps.db.Source import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
@ -40,6 +41,7 @@ class CareDialog : DialogFragmentWithDate() {
@Inject lateinit var nsUpload: NSUpload @Inject lateinit var nsUpload: NSUpload
@Inject lateinit var translator: Translator @Inject lateinit var translator: Translator
@Inject lateinit var uel: UserEntryLogger @Inject lateinit var uel: UserEntryLogger
@Inject lateinit var databaseHelper: DatabaseHelperInterface
enum class EventType { enum class EventType {
BGCHECK, BGCHECK,
@ -227,8 +229,8 @@ class CareDialog : DialogFragmentWithDate() {
uel.log(Action.CAREPORTAL, notes, ValueWithUnit(eventTime, Units.Timestamp), ValueWithUnit(careportalEvent.eventType, Units.CPEvent)) uel.log(Action.CAREPORTAL, notes, ValueWithUnit(eventTime, Units.Timestamp), ValueWithUnit(careportalEvent.eventType, Units.CPEvent))
else else
uel.log(Action.CAREPORTAL, notes, ValueWithUnit(careportalEvent.eventType, Units.CPEvent)) uel.log(Action.CAREPORTAL, notes, ValueWithUnit(careportalEvent.eventType, Units.CPEvent))
MainApp.getDbHelper().createOrUpdate(careportalEvent) databaseHelper.createOrUpdate(careportalEvent)
nsUpload.uploadCareportalEntryToNS(json) nsUpload.uploadCareportalEntryToNS(json, eventTime)
}, null) }, null)
} }
return true return true

View file

@ -15,17 +15,20 @@ import info.nightscout.androidaps.activities.ErrorHelperActivity
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.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.database.entities.UserEntry.* import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.database.transactions.InsertTemporaryTargetAndCancelCurrentTransaction
import info.nightscout.androidaps.databinding.DialogInsulinBinding import info.nightscout.androidaps.databinding.DialogInsulinBinding
import info.nightscout.androidaps.db.CareportalEvent import info.nightscout.androidaps.db.CareportalEvent
import info.nightscout.androidaps.db.Source import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.db.TempTarget
import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.CommandQueueProvider import info.nightscout.androidaps.interfaces.CommandQueueProvider
import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.* import info.nightscout.androidaps.utils.*
import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
@ -33,8 +36,11 @@ import info.nightscout.androidaps.utils.extensions.formatColor
import info.nightscout.androidaps.utils.extensions.toSignedString import info.nightscout.androidaps.utils.extensions.toSignedString
import info.nightscout.androidaps.utils.extensions.toVisibility import info.nightscout.androidaps.utils.extensions.toVisibility
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import java.text.DecimalFormat import java.text.DecimalFormat
import java.util.* import java.util.*
import java.util.concurrent.TimeUnit
import javax.inject.Inject import javax.inject.Inject
import kotlin.math.abs import kotlin.math.abs
import kotlin.math.max import kotlin.math.max
@ -51,6 +57,7 @@ class InsulinDialog : DialogFragmentWithDate() {
@Inject lateinit var repository: AppRepository @Inject lateinit var repository: AppRepository
@Inject lateinit var config: Config @Inject lateinit var config: Config
@Inject lateinit var uel: UserEntryLogger @Inject lateinit var uel: UserEntryLogger
@Inject lateinit var nsUpload: NSUpload
companion object { companion object {
@ -59,6 +66,8 @@ class InsulinDialog : DialogFragmentWithDate() {
private const val PLUS3_DEFAULT = 2.0 private const val PLUS3_DEFAULT = 2.0
} }
private val disposable = CompositeDisposable()
private val textWatcher: TextWatcher = object : TextWatcher { private val textWatcher: TextWatcher = object : TextWatcher {
override fun afterTextChanged(s: Editable) { override fun afterTextChanged(s: Editable) {
validateInputs() validateInputs()
@ -140,6 +149,7 @@ class InsulinDialog : DialogFragmentWithDate() {
override fun onDestroyView() { override fun onDestroyView() {
super.onDestroyView() super.onDestroyView()
disposable.clear()
_binding = null _binding = null
} }
@ -180,14 +190,18 @@ class InsulinDialog : DialogFragmentWithDate() {
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.bolus), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), { OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.bolus), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
if (eatingSoonChecked) { if (eatingSoonChecked) {
uel.log(Action.TT_EATING_SOON, notes, ValueWithUnit(eatingSoonTT, units), ValueWithUnit(eatingSoonTTDuration, Units.M)) uel.log(Action.TT_EATING_SOON, notes, ValueWithUnit(eatingSoonTT, units), ValueWithUnit(eatingSoonTTDuration, Units.M))
val tempTarget = TempTarget() disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction(
.date(System.currentTimeMillis()) timestamp = System.currentTimeMillis(),
.duration(eatingSoonTTDuration) duration = TimeUnit.MINUTES.toMillis(eatingSoonTTDuration.toLong()),
.reason(resourceHelper.gs(R.string.eatingsoon)) reason = TemporaryTarget.Reason.EATING_SOON,
.source(Source.USER) lowTarget = Profile.toMgdl(eatingSoonTT, profileFunction.getUnits()),
.low(Profile.toMgdl(eatingSoonTT, profileFunction.getUnits())) highTarget = Profile.toMgdl(eatingSoonTT, profileFunction.getUnits())
.high(Profile.toMgdl(eatingSoonTT, profileFunction.getUnits())) )).subscribe({ result ->
activePlugin.activeTreatments.addToHistoryTempTarget(tempTarget) result.inserted.forEach { nsUpload.uploadTempTarget(it) }
result.updated.forEach { nsUpload.updateTempTarget(it) }
}, {
aapsLogger.error(LTag.BGSOURCE, "Error while saving temporary target", it)
})
} }
if (insulinAfterConstraints > 0) { if (insulinAfterConstraints > 0) {
val detailedBolusInfo = DetailedBolusInfo() val detailedBolusInfo = DetailedBolusInfo()

View file

@ -10,21 +10,27 @@ import com.google.common.collect.Lists
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile 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.UserEntry.* import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.database.transactions.CancelCurrentTemporaryTargetIfAnyTransaction
import info.nightscout.androidaps.database.transactions.InsertTemporaryTargetAndCancelCurrentTransaction
import info.nightscout.androidaps.databinding.DialogTemptargetBinding import info.nightscout.androidaps.databinding.DialogTemptargetBinding
import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.db.TempTarget
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.utils.DefaultValueHelper import info.nightscout.androidaps.utils.DefaultValueHelper
import info.nightscout.androidaps.utils.HtmlHelper import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import java.text.DecimalFormat import java.text.DecimalFormat
import java.util.* import java.util.*
import java.util.concurrent.TimeUnit
import javax.inject.Inject import javax.inject.Inject
class TempTargetDialog : DialogFragmentWithDate() { class TempTargetDialog : DialogFragmentWithDate() {
@ -33,12 +39,14 @@ class TempTargetDialog : DialogFragmentWithDate() {
@Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var defaultValueHelper: DefaultValueHelper @Inject lateinit var defaultValueHelper: DefaultValueHelper
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin
@Inject lateinit var activePlugin: ActivePluginProvider
@Inject lateinit var uel: UserEntryLogger @Inject lateinit var uel: UserEntryLogger
@Inject lateinit var repository: AppRepository
@Inject lateinit var nsUpload: NSUpload
private lateinit var reasonList: List<String> private lateinit var reasonList: List<String>
private val disposable = CompositeDisposable()
private var _binding: DialogTemptargetBinding? = null private var _binding: DialogTemptargetBinding? = null
// This property is only valid between onCreateView and // This property is only valid between onCreateView and
@ -48,7 +56,7 @@ class TempTargetDialog : DialogFragmentWithDate() {
override fun onSaveInstanceState(savedInstanceState: Bundle) { override fun onSaveInstanceState(savedInstanceState: Bundle) {
super.onSaveInstanceState(savedInstanceState) super.onSaveInstanceState(savedInstanceState)
savedInstanceState.putDouble("duration", binding.duration.value) savedInstanceState.putDouble("duration", binding.duration.value)
savedInstanceState.putDouble("temptarget", binding.temptarget.value) savedInstanceState.putDouble("tempTarget", binding.temptarget.value)
} }
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
@ -66,12 +74,12 @@ class TempTargetDialog : DialogFragmentWithDate() {
if (profileFunction.getUnits() == Constants.MMOL) if (profileFunction.getUnits() == Constants.MMOL)
binding.temptarget.setParams( binding.temptarget.setParams(
savedInstanceState?.getDouble("temptarget") savedInstanceState?.getDouble("tempTarget")
?: 8.0, ?: 8.0,
Constants.MIN_TT_MMOL, Constants.MAX_TT_MMOL, 0.1, DecimalFormat("0.0"), false, binding.okcancel.ok) Constants.MIN_TT_MMOL, Constants.MAX_TT_MMOL, 0.1, DecimalFormat("0.0"), false, binding.okcancel.ok)
else else
binding.temptarget.setParams( binding.temptarget.setParams(
savedInstanceState?.getDouble("temptarget") savedInstanceState?.getDouble("tempTarget")
?: 144.0, ?: 144.0,
Constants.MIN_TT_MGDL, Constants.MAX_TT_MGDL, 1.0, DecimalFormat("0"), false, binding.okcancel.ok) Constants.MIN_TT_MGDL, Constants.MAX_TT_MGDL, 1.0, DecimalFormat("0"), false, binding.okcancel.ok)
@ -80,7 +88,7 @@ class TempTargetDialog : DialogFragmentWithDate() {
// temp target // temp target
context?.let { context -> context?.let { context ->
if (activePlugin.activeTreatments.tempTargetFromHistory != null) if (repository.getTemporaryTargetActiveAt(dateUtil._now()).blockingGet() is ValueWrapper.Existing)
binding.targetCancel.visibility = View.VISIBLE binding.targetCancel.visibility = View.VISIBLE
else else
binding.targetCancel.visibility = View.GONE binding.targetCancel.visibility = View.GONE
@ -126,16 +134,19 @@ class TempTargetDialog : DialogFragmentWithDate() {
binding.duration.value = defaultValueHelper.determineEatingSoonTTDuration().toDouble() binding.duration.value = defaultValueHelper.determineEatingSoonTTDuration().toDouble()
binding.reason.setSelection(reasonList.indexOf(resourceHelper.gs(R.string.eatingsoon))) binding.reason.setSelection(reasonList.indexOf(resourceHelper.gs(R.string.eatingsoon)))
} }
R.id.activity -> { R.id.activity -> {
binding.temptarget.value = defaultValueHelper.determineActivityTT() binding.temptarget.value = defaultValueHelper.determineActivityTT()
binding.duration.value = defaultValueHelper.determineActivityTTDuration().toDouble() binding.duration.value = defaultValueHelper.determineActivityTTDuration().toDouble()
binding.reason.setSelection(reasonList.indexOf(resourceHelper.gs(R.string.activity))) binding.reason.setSelection(reasonList.indexOf(resourceHelper.gs(R.string.activity)))
} }
R.id.hypo -> { R.id.hypo -> {
binding.temptarget.value = defaultValueHelper.determineHypoTT() binding.temptarget.value = defaultValueHelper.determineHypoTT()
binding.duration.value = defaultValueHelper.determineHypoTTDuration().toDouble() binding.duration.value = defaultValueHelper.determineHypoTTDuration().toDouble()
binding.reason.setSelection(reasonList.indexOf(resourceHelper.gs(R.string.hypo))) binding.reason.setSelection(reasonList.indexOf(resourceHelper.gs(R.string.hypo)))
} }
R.id.cancel -> { R.id.cancel -> {
binding.duration.value = 0.0 binding.duration.value = 0.0
} }
@ -144,6 +155,7 @@ class TempTargetDialog : DialogFragmentWithDate() {
override fun onDestroyView() { override fun onDestroyView() {
super.onDestroyView() super.onDestroyView()
disposable.clear()
_binding = null _binding = null
} }
@ -185,21 +197,30 @@ class TempTargetDialog : DialogFragmentWithDate() {
resourceHelper.gs(R.string.stoptemptarget) -> uel.log(Action.CANCEL_TT) resourceHelper.gs(R.string.stoptemptarget) -> uel.log(Action.CANCEL_TT)
} }
if (target == 0.0 || duration == 0) { if (target == 0.0 || duration == 0) {
val tempTarget = TempTarget() disposable += repository.runTransactionForResult(CancelCurrentTemporaryTargetIfAnyTransaction(eventTime))
.date(eventTime) .subscribe({ result ->
.duration(0) result.updated.forEach { nsUpload.updateTempTarget(it) }
.low(0.0).high(0.0) }, {
.source(Source.USER) aapsLogger.error(LTag.BGSOURCE, "Error while saving temporary target", it)
treatmentsPlugin.addToHistoryTempTarget(tempTarget) })
} else { } else {
val tempTarget = TempTarget() disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction(
.date(eventTime) timestamp = eventTime,
.duration(duration) duration = TimeUnit.MINUTES.toMillis(duration.toLong()),
.reason(reason) reason = when (reason) {
.source(Source.USER) "Eating Soon" -> TemporaryTarget.Reason.EATING_SOON
.low(Profile.toMgdl(target, profileFunction.getUnits())) "Activity" -> TemporaryTarget.Reason.ACTIVITY
.high(Profile.toMgdl(target, profileFunction.getUnits())) "Hypo" -> TemporaryTarget.Reason.HYPOGLYCEMIA
treatmentsPlugin.addToHistoryTempTarget(tempTarget) else -> TemporaryTarget.Reason.CUSTOM
},
lowTarget = Profile.toMgdl(target, profileFunction.getUnits()),
highTarget = Profile.toMgdl(target, profileFunction.getUnits())
)).subscribe({ result ->
result.inserted.forEach { nsUpload.uploadTempTarget(it) }
result.updated.forEach { nsUpload.updateTempTarget(it) }
}, {
aapsLogger.error(LTag.BGSOURCE, "Error while saving temporary target", it)
})
} }
if (duration == 10) sp.putBoolean(R.string.key_objectiveusetemptarget, true) if (duration == 10) sp.putBoolean(R.string.key_objectiveusetemptarget, true)
}) })

View file

@ -19,26 +19,24 @@ import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.databinding.DialogWizardBinding import info.nightscout.androidaps.databinding.DialogWizardBinding
import info.nightscout.androidaps.events.EventAutosensCalculationFinished
import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.interfaces.TreatmentsInterface
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
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.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
import info.nightscout.androidaps.events.EventAutosensCalculationFinished import info.nightscout.androidaps.utils.*
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.SafeParse
import info.nightscout.androidaps.utils.ToastUtils
import info.nightscout.androidaps.utils.extensions.toVisibility import info.nightscout.androidaps.utils.extensions.toVisibility
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
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 info.nightscout.androidaps.utils.valueToUnits
import info.nightscout.androidaps.utils.wizard.BolusWizard import info.nightscout.androidaps.utils.wizard.BolusWizard
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
import java.text.DecimalFormat import java.text.DecimalFormat
@ -58,9 +56,11 @@ class WizardDialog : DaggerDialogFragment() {
@Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin
@Inject lateinit var activePlugin: ActivePluginProvider @Inject lateinit var activePlugin: ActivePluginProvider
@Inject lateinit var iobCobCalculatorPlugin: IobCobCalculatorPlugin @Inject lateinit var iobCobCalculatorPlugin: IobCobCalculatorPlugin
@Inject lateinit var repository: AppRepository
@Inject lateinit var treatmentsPlugin: TreatmentsInterface
@Inject lateinit var dateUtil: DateUtil
private var wizard: BolusWizard? = null private var wizard: BolusWizard? = null
@ -207,7 +207,7 @@ class WizardDialog : DaggerDialogFragment() {
private fun onCheckedChanged(buttonView: CompoundButton, @Suppress("UNUSED_PARAMETER") state: Boolean) { private fun onCheckedChanged(buttonView: CompoundButton, @Suppress("UNUSED_PARAMETER") state: Boolean) {
saveCheckedStates() saveCheckedStates()
binding.ttcheckbox.isEnabled = binding.bgcheckbox.isChecked && treatmentsPlugin.tempTargetFromHistory != null binding.ttcheckbox.isEnabled = binding.bgcheckbox.isChecked && repository.getTemporaryTargetActiveAt(dateUtil._now()).blockingGet() is ValueWrapper.Existing
if (buttonView.id == binding.cobcheckbox.id) if (buttonView.id == binding.cobcheckbox.id)
processCobCheckBox() processCobCheckBox()
calculateInsulin() calculateInsulin()
@ -271,7 +271,7 @@ class WizardDialog : DaggerDialogFragment() {
} else { } else {
binding.bgInput.value = 0.0 binding.bgInput.value = 0.0
} }
binding.ttcheckbox.isEnabled = treatmentsPlugin.tempTargetFromHistory != null binding.ttcheckbox.isEnabled = repository.getTemporaryTargetActiveAt(dateUtil._now()).blockingGet() is ValueWrapper.Existing
// IOB calculation // IOB calculation
treatmentsPlugin.updateTotalIOBTreatments() treatmentsPlugin.updateTotalIOBTreatments()
@ -313,7 +313,8 @@ class WizardDialog : DaggerDialogFragment() {
} }
bg = if (binding.bgcheckbox.isChecked) bg else 0.0 bg = if (binding.bgcheckbox.isChecked) bg else 0.0
val tempTarget = if (binding.ttcheckbox.isChecked) treatmentsPlugin.tempTargetFromHistory else null val dbRecord = repository.getTemporaryTargetActiveAt(dateUtil._now()).blockingGet()
val tempTarget = if (binding.ttcheckbox.isChecked && dbRecord is ValueWrapper.Existing) dbRecord.value else null
// COB // COB
var cob = 0.0 var cob = 0.0

View file

@ -2,7 +2,9 @@ package info.nightscout.androidaps.historyBrowser
import android.content.Context import android.content.Context
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.ActivePluginProvider
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
@ -32,8 +34,10 @@ class TreatmentsPluginHistory @Inject constructor(
nsUpload: NSUpload, nsUpload: NSUpload,
fabricPrivacy: FabricPrivacy, fabricPrivacy: FabricPrivacy,
dateUtil: DateUtil, dateUtil: DateUtil,
uploadQueue: UploadQueue uploadQueue: UploadQueue,
) : TreatmentsPlugin(injector, aapsLogger, rxBus, aapsSchedulers, resourceHelper, context, sp, profileFunction, activePlugin, nsUpload, fabricPrivacy, dateUtil, uploadQueue) { databaseHelper: DatabaseHelperInterface,
repository: AppRepository
) : TreatmentsPlugin(injector, aapsLogger, rxBus, aapsSchedulers, resourceHelper, context, sp, profileFunction, activePlugin, nsUpload, fabricPrivacy, dateUtil, uploadQueue, databaseHelper, repository) {
init { init {
onStart() onStart()

View file

@ -33,9 +33,10 @@ import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
import info.nightscout.androidaps.plugins.general.wear.events.EventWearDoAction import info.nightscout.androidaps.plugins.general.wear.events.EventWearInitiateAction
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
import info.nightscout.androidaps.events.EventAutosensCalculationFinished import info.nightscout.androidaps.events.EventAutosensCalculationFinished
import info.nightscout.androidaps.plugins.general.wear.events.EventWearConfirmAction
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.queue.Callback
@ -75,6 +76,7 @@ open class LoopPlugin @Inject constructor(
private val receiverStatusStore: ReceiverStatusStore, private val receiverStatusStore: ReceiverStatusStore,
private val fabricPrivacy: FabricPrivacy, private val fabricPrivacy: FabricPrivacy,
private val nsUpload: NSUpload, private val nsUpload: NSUpload,
private val databaseHelper: DatabaseHelperInterface,
private val hardLimits: HardLimits private val hardLimits: HardLimits
) : PluginBase(PluginDescription() ) : PluginBase(PluginDescription()
.mainType(PluginType.LOOP) .mainType(PluginType.LOOP)
@ -368,7 +370,7 @@ open class LoopPlugin @Inject constructor(
//only send to wear if Native notifications are turned off //only send to wear if Native notifications are turned off
if (!sp.getBoolean(R.string.key_raise_notifications_as_android_notifications, true)) { if (!sp.getBoolean(R.string.key_raise_notifications_as_android_notifications, true)) {
// Send to Wear // Send to Wear
rxBus.send(EventWearDoAction("changeRequest")) rxBus.send(EventWearInitiateAction("changeRequest"))
} }
} }
} else { } else {
@ -472,14 +474,14 @@ open class LoopPlugin @Inject constructor(
rxBus.send(EventNewOpenLoopNotification()) rxBus.send(EventNewOpenLoopNotification())
// Send to Wear // Send to Wear
rxBus.send(EventWearDoAction("changeRequest")) rxBus.send(EventWearInitiateAction("changeRequest"))
} }
private fun dismissSuggestion() { private fun dismissSuggestion() {
// dismiss notifications // dismiss notifications
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.cancel(Constants.notificationID) notificationManager.cancel(Constants.notificationID)
rxBus.send(EventWearDoAction("cancelChangeRequest")) rxBus.send(EventWearConfirmAction("cancelChangeRequest"))
} }
fun acceptChangeRequest() { fun acceptChangeRequest() {
@ -626,7 +628,7 @@ open class LoopPlugin @Inject constructor(
} }
}) })
} }
if (pump.pumpDescription.isExtendedBolusCapable && treatmentsPlugin.isInHistoryExtendedBoluslInProgress) { if (pump.pumpDescription.isExtendedBolusCapable && treatmentsPlugin.isInHistoryExtendedBolusInProgress) {
commandQueue.cancelExtended(object : Callback() { commandQueue.cancelExtended(object : Callback() {
override fun run() { override fun run() {
if (!result.success) { if (!result.success) {
@ -663,7 +665,7 @@ open class LoopPlugin @Inject constructor(
event.source = Source.USER event.source = Source.USER
event.eventType = CareportalEvent.OPENAPSOFFLINE event.eventType = CareportalEvent.OPENAPSOFFLINE
event.json = data.toString() event.json = data.toString()
MainApp.getDbHelper().createOrUpdate(event) databaseHelper.createOrUpdate(event)
nsUpload.uploadOpenAPSOffline(event) nsUpload.uploadOpenAPSOffline(event)
} }

View file

@ -4,6 +4,8 @@ import android.content.Context
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
@ -20,6 +22,7 @@ import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.HardLimits import info.nightscout.androidaps.utils.HardLimits
import info.nightscout.androidaps.utils.Profiler import info.nightscout.androidaps.utils.Profiler
import info.nightscout.androidaps.utils.Round import info.nightscout.androidaps.utils.Round
import info.nightscout.androidaps.utils.extensions.target
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import org.json.JSONException import org.json.JSONException
import javax.inject.Inject import javax.inject.Inject
@ -39,7 +42,9 @@ open class OpenAPSAMAPlugin @Inject constructor(
private val iobCobCalculatorPlugin: IobCobCalculatorPlugin, private val iobCobCalculatorPlugin: IobCobCalculatorPlugin,
private val hardLimits: HardLimits, private val hardLimits: HardLimits,
private val profiler: Profiler, private val profiler: Profiler,
private val fabricPrivacy: FabricPrivacy private val fabricPrivacy: FabricPrivacy,
private val dateUtil: DateUtil,
private val repository: AppRepository
) : PluginBase(PluginDescription() ) : PluginBase(PluginDescription()
.mainType(PluginType.APS) .mainType(PluginType.APS)
.fragmentClass(OpenAPSAMAFragment::class.java.name) .fragmentClass(OpenAPSAMAFragment::class.java.name)
@ -108,21 +113,22 @@ open class OpenAPSAMAPlugin @Inject constructor(
val maxIob = constraintChecker.getMaxIOBAllowed().also { maxIOBAllowedConstraint -> val maxIob = constraintChecker.getMaxIOBAllowed().also { maxIOBAllowedConstraint ->
inputConstraints.copyReasons(maxIOBAllowedConstraint) inputConstraints.copyReasons(maxIOBAllowedConstraint)
}.value() }.value()
var minBg = hardLimits.verifyHardLimits(Round.roundTo(profile.targetLowMgdl, 0.1), "minBg", hardLimits.VERY_HARD_LIMIT_MIN_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_MIN_BG[1].toDouble()) var minBg = hardLimits.verifyHardLimits(Round.roundTo(profile.targetLowMgdl, 0.1), R.string.profile_low_target, hardLimits.VERY_HARD_LIMIT_MIN_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_MIN_BG[1].toDouble())
var maxBg = hardLimits.verifyHardLimits(Round.roundTo(profile.targetHighMgdl, 0.1), "maxBg", hardLimits.VERY_HARD_LIMIT_MAX_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_MAX_BG[1].toDouble()) var maxBg = hardLimits.verifyHardLimits(Round.roundTo(profile.targetHighMgdl, 0.1), R.string.profile_high_target, hardLimits.VERY_HARD_LIMIT_MAX_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_MAX_BG[1].toDouble())
var targetBg = hardLimits.verifyHardLimits(profile.targetMgdl, "targetBg", hardLimits.VERY_HARD_LIMIT_TARGET_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_TARGET_BG[1].toDouble()) var targetBg = hardLimits.verifyHardLimits(profile.targetMgdl, R.string.temp_target_value, hardLimits.VERY_HARD_LIMIT_TARGET_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_TARGET_BG[1].toDouble())
var isTempTarget = false var isTempTarget = false
treatmentsPlugin.getTempTargetFromHistory(System.currentTimeMillis())?.let { tempTarget -> val tempTarget = repository.getTemporaryTargetActiveAt(dateUtil._now()).blockingGet()
isTempTarget = true if (tempTarget is ValueWrapper.Existing) {
minBg = hardLimits.verifyHardLimits(tempTarget.low, "minBg", hardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[1].toDouble()) isTempTarget = true
maxBg = hardLimits.verifyHardLimits(tempTarget.high, "maxBg", hardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[1].toDouble()) minBg = hardLimits.verifyHardLimits(tempTarget.value.lowTarget, R.string.temp_target_low_target, hardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[1].toDouble())
targetBg = hardLimits.verifyHardLimits(tempTarget.target(), "targetBg", hardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[1].toDouble()) maxBg = hardLimits.verifyHardLimits(tempTarget.value.highTarget, R.string.temp_target_high_target, hardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[1].toDouble())
targetBg = hardLimits.verifyHardLimits(tempTarget.value.target(), R.string.temp_target_value, hardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[1].toDouble())
} }
if (!hardLimits.checkOnlyHardLimits(profile.dia, "dia", hardLimits.minDia(), hardLimits.maxDia())) return if (!hardLimits.checkOnlyHardLimits(profile.dia, R.string.profile_dia, hardLimits.minDia(), hardLimits.maxDia())) return
if (!hardLimits.checkOnlyHardLimits(profile.getIcTimeFromMidnight(Profile.secondsFromMidnight()), "carbratio", hardLimits.minIC(), hardLimits.maxIC())) return if (!hardLimits.checkOnlyHardLimits(profile.getIcTimeFromMidnight(Profile.secondsFromMidnight()), R.string.profile_carbs_ratio_value, hardLimits.minIC(), hardLimits.maxIC())) return
if (!hardLimits.checkOnlyHardLimits(profile.isfMgdl, "sens", hardLimits.MINISF, hardLimits.MAXISF)) return if (!hardLimits.checkOnlyHardLimits(profile.isfMgdl, R.string.profile_sensitivity_value, hardLimits.MINISF, hardLimits.MAXISF)) return
if (!hardLimits.checkOnlyHardLimits(profile.maxDailyBasal, "max_daily_basal", 0.02, hardLimits.maxBasal())) return if (!hardLimits.checkOnlyHardLimits(profile.maxDailyBasal, R.string.profile_max_daily_basal_value, 0.02, hardLimits.maxBasal())) return
if (!hardLimits.checkOnlyHardLimits(pump.baseBasalRate, "current_basal", 0.01, hardLimits.maxBasal())) return if (!hardLimits.checkOnlyHardLimits(pump.baseBasalRate, R.string.current_basal_value, 0.01, hardLimits.maxBasal())) return
startPart = System.currentTimeMillis() startPart = System.currentTimeMillis()
if (constraintChecker.isAutosensModeEnabled().value()) { if (constraintChecker.isAutosensModeEnabled().value()) {
val autosensData = iobCobCalculatorPlugin.getLastAutosensDataSynchronized("OpenAPSPlugin") val autosensData = iobCobCalculatorPlugin.getLastAutosensDataSynchronized("OpenAPSPlugin")

View file

@ -6,6 +6,8 @@ import androidx.preference.SwitchPreference
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
@ -21,6 +23,7 @@ import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.HardLimits import info.nightscout.androidaps.utils.HardLimits
import info.nightscout.androidaps.utils.Profiler import info.nightscout.androidaps.utils.Profiler
import info.nightscout.androidaps.utils.Round import info.nightscout.androidaps.utils.Round
import info.nightscout.androidaps.utils.extensions.target
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import javax.inject.Inject import javax.inject.Inject
@ -40,7 +43,9 @@ open class OpenAPSSMBPlugin @Inject constructor(
private val iobCobCalculatorPlugin: IobCobCalculatorPlugin, private val iobCobCalculatorPlugin: IobCobCalculatorPlugin,
private val hardLimits: HardLimits, private val hardLimits: HardLimits,
private val profiler: Profiler, private val profiler: Profiler,
private val sp: SP private val sp: SP,
private val dateUtil: DateUtil,
private val repository: AppRepository
) : PluginBase(PluginDescription() ) : PluginBase(PluginDescription()
.mainType(PluginType.APS) .mainType(PluginType.APS)
.fragmentClass(OpenAPSSMBFragment::class.java.name) .fragmentClass(OpenAPSSMBFragment::class.java.name)
@ -114,21 +119,22 @@ open class OpenAPSSMBPlugin @Inject constructor(
inputConstraints.copyReasons(maxIOBAllowedConstraint) inputConstraints.copyReasons(maxIOBAllowedConstraint)
}.value() }.value()
var minBg = hardLimits.verifyHardLimits(Round.roundTo(profile.targetLowMgdl, 0.1), "minBg", hardLimits.VERY_HARD_LIMIT_MIN_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_MIN_BG[1].toDouble()) var minBg = hardLimits.verifyHardLimits(Round.roundTo(profile.targetLowMgdl, 0.1), R.string.profile_low_target, hardLimits.VERY_HARD_LIMIT_MIN_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_MIN_BG[1].toDouble())
var maxBg = hardLimits.verifyHardLimits(Round.roundTo(profile.targetHighMgdl, 0.1), "maxBg", hardLimits.VERY_HARD_LIMIT_MAX_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_MAX_BG[1].toDouble()) var maxBg = hardLimits.verifyHardLimits(Round.roundTo(profile.targetHighMgdl, 0.1), R.string.profile_high_target, hardLimits.VERY_HARD_LIMIT_MAX_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_MAX_BG[1].toDouble())
var targetBg = hardLimits.verifyHardLimits(profile.targetMgdl, "targetBg", hardLimits.VERY_HARD_LIMIT_TARGET_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_TARGET_BG[1].toDouble()) var targetBg = hardLimits.verifyHardLimits(profile.targetMgdl, R.string.temp_target_value, hardLimits.VERY_HARD_LIMIT_TARGET_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_TARGET_BG[1].toDouble())
var isTempTarget = false var isTempTarget = false
treatmentsPlugin.getTempTargetFromHistory(System.currentTimeMillis())?.let { tempTarget -> val tempTarget = repository.getTemporaryTargetActiveAt(dateUtil._now()).blockingGet()
if (tempTarget is ValueWrapper.Existing) {
isTempTarget = true isTempTarget = true
minBg = hardLimits.verifyHardLimits(tempTarget.low, "minBg", hardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[1].toDouble()) minBg = hardLimits.verifyHardLimits(tempTarget.value.lowTarget, R.string.temp_target_low_target, hardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[1].toDouble())
maxBg = hardLimits.verifyHardLimits(tempTarget.high, "maxBg", hardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[1].toDouble()) maxBg = hardLimits.verifyHardLimits(tempTarget.value.highTarget, R.string.temp_target_high_target, hardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[1].toDouble())
targetBg = hardLimits.verifyHardLimits(tempTarget.target(), "targetBg", hardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[1].toDouble()) targetBg = hardLimits.verifyHardLimits(tempTarget.value.target(), R.string.temp_target_value, hardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[1].toDouble())
} }
if (!hardLimits.checkOnlyHardLimits(profile.dia, "dia", hardLimits.minDia(), hardLimits.maxDia())) return if (!hardLimits.checkOnlyHardLimits(profile.dia, R.string.profile_dia, hardLimits.minDia(), hardLimits.maxDia())) return
if (!hardLimits.checkOnlyHardLimits(profile.getIcTimeFromMidnight(Profile.secondsFromMidnight()), "carbratio", hardLimits.minIC(), hardLimits.maxIC())) return if (!hardLimits.checkOnlyHardLimits(profile.getIcTimeFromMidnight(Profile.secondsFromMidnight()), R.string.profile_carbs_ratio_value, hardLimits.minIC(), hardLimits.maxIC())) return
if (!hardLimits.checkOnlyHardLimits(profile.isfMgdl, "sens", hardLimits.MINISF, hardLimits.MAXISF)) return if (!hardLimits.checkOnlyHardLimits(profile.isfMgdl, R.string.profile_sensitivity_value, hardLimits.MINISF, hardLimits.MAXISF)) return
if (!hardLimits.checkOnlyHardLimits(profile.maxDailyBasal, "max_daily_basal", 0.02, hardLimits.maxBasal())) return if (!hardLimits.checkOnlyHardLimits(profile.maxDailyBasal, R.string.profile_max_daily_basal_value, 0.02, hardLimits.maxBasal())) return
if (!hardLimits.checkOnlyHardLimits(pump.baseBasalRate, "current_basal", 0.01, hardLimits.maxBasal())) return if (!hardLimits.checkOnlyHardLimits(pump.baseBasalRate, R.string.current_basal_value, 0.01, hardLimits.maxBasal())) return
startPart = System.currentTimeMillis() startPart = System.currentTimeMillis()
if (constraintChecker.isAutosensModeEnabled().value()) { if (constraintChecker.isAutosensModeEnabled().value()) {
val autosensData = iobCobCalculatorPlugin.getLastAutosensDataSynchronized("OpenAPSPlugin") val autosensData = iobCobCalculatorPlugin.getLastAutosensDataSynchronized("OpenAPSPlugin")

View file

@ -68,7 +68,7 @@ class SafetyPlugin @Inject constructor(
value[aapsLogger, false, resourceHelper.gs(R.string.closed_loop_disabled_on_dev_branch)] = this value[aapsLogger, false, resourceHelper.gs(R.string.closed_loop_disabled_on_dev_branch)] = this
} }
val pump = activePlugin.activePump val pump = activePlugin.activePump
if (!pump.isFakingTempsByExtendedBoluses && treatmentsPlugin.isInHistoryExtendedBoluslInProgress) { if (!pump.isFakingTempsByExtendedBoluses && treatmentsPlugin.isInHistoryExtendedBolusInProgress) {
value[aapsLogger, false, resourceHelper.gs(R.string.closed_loop_disabled_with_eb)] = this value[aapsLogger, false, resourceHelper.gs(R.string.closed_loop_disabled_with_eb)] = this
} }
return value return value

View file

@ -6,12 +6,12 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import dagger.android.support.DaggerFragment import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.MainApp
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.UserEntry.* import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.databinding.MaintenanceFragmentBinding import info.nightscout.androidaps.databinding.MaintenanceFragmentBinding
import info.nightscout.androidaps.events.EventNewBG import info.nightscout.androidaps.events.EventNewBG
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface
import info.nightscout.androidaps.interfaces.ImportExportPrefsInterface import info.nightscout.androidaps.interfaces.ImportExportPrefsInterface
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
@ -38,6 +38,7 @@ class MaintenanceFragment : DaggerFragment() {
@Inject lateinit var importExportPrefs: ImportExportPrefsInterface @Inject lateinit var importExportPrefs: ImportExportPrefsInterface
@Inject lateinit var aapsSchedulers: AapsSchedulers @Inject lateinit var aapsSchedulers: AapsSchedulers
@Inject lateinit var repository: AppRepository @Inject lateinit var repository: AppRepository
@Inject lateinit var databaseHelper: DatabaseHelperInterface
@Inject lateinit var uel: UserEntryLogger @Inject lateinit var uel: UserEntryLogger
private val compositeDisposable = CompositeDisposable() private val compositeDisposable = CompositeDisposable()
@ -66,7 +67,7 @@ class MaintenanceFragment : DaggerFragment() {
uel.log(Action.RESET_DATABASES) uel.log(Action.RESET_DATABASES)
compositeDisposable.add( compositeDisposable.add(
fromAction { fromAction {
MainApp.getDbHelper().resetDatabases() databaseHelper.resetDatabases()
// should be handled by Plugin-Interface and // should be handled by Plugin-Interface and
// additional service interface and plugin registry // additional service interface and plugin registry
foodPlugin.service?.resetFood() foodPlugin.service?.resetFood()

View file

@ -10,10 +10,10 @@ import android.os.HandlerThread;
import android.os.IBinder; import android.os.IBinder;
import android.text.Spanned; import android.text.Spanned;
import androidx.annotation.NonNull;
import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.SwitchPreference; import androidx.preference.SwitchPreference;
import androidx.annotation.NonNull;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
@ -27,8 +27,10 @@ import javax.inject.Singleton;
import dagger.android.HasAndroidInjector; import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.database.AppRepository;
import info.nightscout.androidaps.database.entities.TemporaryTarget;
import info.nightscout.androidaps.database.transactions.SyncTemporaryTargetTransaction;
import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.events.EventAppExit;
import info.nightscout.androidaps.events.EventChargingState; import info.nightscout.androidaps.events.EventChargingState;
@ -36,11 +38,13 @@ import info.nightscout.androidaps.events.EventNetworkChange;
import info.nightscout.androidaps.events.EventNsTreatment; import info.nightscout.androidaps.events.EventNsTreatment;
import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.interfaces.ActivePluginProvider; import info.nightscout.androidaps.interfaces.ActivePluginProvider;
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
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.logging.AAPSLogger; import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag; import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.logging.UserEntryLogger;
import info.nightscout.androidaps.plugins.bus.RxBusWrapper; import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
import info.nightscout.androidaps.plugins.general.nsclient.data.AlarmAck; import info.nightscout.androidaps.plugins.general.nsclient.data.AlarmAck;
import info.nightscout.androidaps.plugins.general.nsclient.data.NSAlarm; import info.nightscout.androidaps.plugins.general.nsclient.data.NSAlarm;
@ -63,6 +67,9 @@ 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;
import static info.nightscout.androidaps.utils.extensions.TemporaryTargetExtensionKt.temporaryTargetFromJson;
import static info.nightscout.androidaps.utils.extensions.TemporaryTargetExtensionKt.temporaryTargetFromNsIdForInvalidating;
@Singleton @Singleton
public class NSClientPlugin extends PluginBase { public class NSClientPlugin extends PluginBase {
private final CompositeDisposable disposable = new CompositeDisposable(); private final CompositeDisposable disposable = new CompositeDisposable();
@ -78,6 +85,9 @@ public class NSClientPlugin extends PluginBase {
private final BuildHelper buildHelper; private final BuildHelper buildHelper;
private final ActivePluginProvider activePlugin; private final ActivePluginProvider activePlugin;
private final NSUpload nsUpload; private final NSUpload nsUpload;
private final AppRepository repository;
private final DatabaseHelperInterface databaseHelper;
private final UserEntryLogger uel;
public Handler handler; public Handler handler;
@ -107,7 +117,10 @@ public class NSClientPlugin extends PluginBase {
Config config, Config config,
BuildHelper buildHelper, BuildHelper buildHelper,
ActivePluginProvider activePlugin, ActivePluginProvider activePlugin,
NSUpload nsUpload NSUpload nsUpload,
DatabaseHelperInterface databaseHelper,
AppRepository repository,
UserEntryLogger uel
) { ) {
super(new PluginDescription() super(new PluginDescription()
.mainType(PluginType.GENERAL) .mainType(PluginType.GENERAL)
@ -132,6 +145,9 @@ public class NSClientPlugin extends PluginBase {
this.buildHelper = buildHelper; this.buildHelper = buildHelper;
this.activePlugin = activePlugin; this.activePlugin = activePlugin;
this.nsUpload = nsUpload; this.nsUpload = nsUpload;
this.databaseHelper = databaseHelper;
this.repository = repository;
this.uel = uel;
if (config.getNSCLIENT()) { if (config.getNSCLIENT()) {
getPluginDescription().alwaysEnabled(true).visibleByDefault(true); getPluginDescription().alwaysEnabled(true).visibleByDefault(true);
@ -170,12 +186,12 @@ public class NSClientPlugin extends PluginBase {
disposable.add(rxBus disposable.add(rxBus
.toObservable(EventNetworkChange.class) .toObservable(EventNetworkChange.class)
.observeOn(aapsSchedulers.getIo()) .observeOn(aapsSchedulers.getIo())
.subscribe(event -> nsClientReceiverDelegate.onStatusEvent(event), fabricPrivacy::logException) .subscribe(nsClientReceiverDelegate::onStatusEvent, fabricPrivacy::logException)
); );
disposable.add(rxBus disposable.add(rxBus
.toObservable(EventPreferenceChange.class) .toObservable(EventPreferenceChange.class)
.observeOn(aapsSchedulers.getIo()) .observeOn(aapsSchedulers.getIo())
.subscribe(event -> nsClientReceiverDelegate.onStatusEvent(event), fabricPrivacy::logException) .subscribe(nsClientReceiverDelegate::onStatusEvent, fabricPrivacy::logException)
); );
disposable.add(rxBus disposable.add(rxBus
.toObservable(EventAppExit.class) .toObservable(EventAppExit.class)
@ -197,7 +213,7 @@ public class NSClientPlugin extends PluginBase {
disposable.add(rxBus disposable.add(rxBus
.toObservable(EventChargingState.class) .toObservable(EventChargingState.class)
.observeOn(aapsSchedulers.getIo()) .observeOn(aapsSchedulers.getIo())
.subscribe(event -> nsClientReceiverDelegate.onStatusEvent(event), fabricPrivacy::logException) .subscribe(nsClientReceiverDelegate::onStatusEvent, fabricPrivacy::logException)
); );
disposable.add(rxBus disposable.add(rxBus
.toObservable(EventNSClientResend.class) .toObservable(EventNSClientResend.class)
@ -402,16 +418,21 @@ public class NSClientPlugin extends PluginBase {
} }
private void handleRemovedTreatmentFromNS(JSONObject json) { private void handleRemovedTreatmentFromNS(JSONObject json) {
String _id = JsonHelper.safeGetString(json, "_id");
if (_id == null) return;
// room Temporary target
TemporaryTarget temporaryTarget = temporaryTargetFromNsIdForInvalidating(_id);
disposable.add(repository.runTransactionForResult(new SyncTemporaryTargetTransaction(temporaryTarget)).subscribe(
result -> result.getInvalidated().forEach(record -> uel.log("TT DELETED FROM NS", record.getReason().getText(), record.getLowTarget(), record.getHighTarget(), (int) record.getDuration(), 0)),
error -> aapsLogger.error(LTag.BGSOURCE, "Error while saving temporary target", error)));
// new DB model // new DB model
EventNsTreatment evtTreatment = new EventNsTreatment(EventNsTreatment.Companion.getREMOVE(), json); EventNsTreatment evtTreatment = new EventNsTreatment(EventNsTreatment.Companion.getREMOVE(), json);
rxBus.send(evtTreatment); rxBus.send(evtTreatment);
// old DB model // old DB model
String _id = JsonHelper.safeGetString(json, "_id"); databaseHelper.deleteTempBasalById(_id);
MainApp.getDbHelper().deleteTempTargetById(_id); databaseHelper.deleteExtendedBolusById(_id);
MainApp.getDbHelper().deleteTempBasalById(_id); databaseHelper.deleteCareportalEventById(_id);
MainApp.getDbHelper().deleteExtendedBolusById(_id); databaseHelper.deleteProfileSwitchById(_id);
MainApp.getDbHelper().deleteCareportalEventById(_id);
MainApp.getDbHelper().deleteProfileSwitchById(_id);
} }
private void handleTreatmentFromNS(JSONObject json, String action) { private void handleTreatmentFromNS(JSONObject json, String action) {
@ -428,13 +449,24 @@ public class NSClientPlugin extends PluginBase {
EventNsTreatment evtTreatment = new EventNsTreatment(mode, json); EventNsTreatment evtTreatment = new EventNsTreatment(mode, json);
rxBus.send(evtTreatment); rxBus.send(evtTreatment);
} else if (eventType.equals(CareportalEvent.TEMPORARYTARGET)) { } else if (eventType.equals(CareportalEvent.TEMPORARYTARGET)) {
MainApp.getDbHelper().createTemptargetFromJsonIfNotExists(json); TemporaryTarget temporaryTarget = temporaryTargetFromJson(json);
if (temporaryTarget != null) {
disposable.add(repository.runTransactionForResult(new SyncTemporaryTargetTransaction(temporaryTarget)).subscribe(
result -> {
result.getInserted().forEach(record -> uel.log("TT FROM NS", record.getReason().getText(), record.getLowTarget(), record.getHighTarget(), (int) record.getDuration(), 0));
result.getInvalidated().forEach(record -> uel.log("TT DELETED FROM NS", record.getReason().getText(), record.getLowTarget(), record.getHighTarget(), (int) record.getDuration(), 0));
result.getEnded().forEach(record -> uel.log("TT CANCELED FROM NS", record.getReason().getText(), record.getLowTarget(), record.getHighTarget(), (int) record.getDuration(), 0));
},
error -> aapsLogger.error(LTag.BGSOURCE, "Error while saving temporary target", error)));
} else {
aapsLogger.error("Error parsing TT json " + json.toString());
}
} else if (eventType.equals(CareportalEvent.TEMPBASAL)) { } else if (eventType.equals(CareportalEvent.TEMPBASAL)) {
MainApp.getDbHelper().createTempBasalFromJsonIfNotExists(json); databaseHelper.createTempBasalFromJsonIfNotExists(json);
} else if (eventType.equals(CareportalEvent.COMBOBOLUS)) { } else if (eventType.equals(CareportalEvent.COMBOBOLUS)) {
MainApp.getDbHelper().createExtendedBolusFromJsonIfNotExists(json); databaseHelper.createExtendedBolusFromJsonIfNotExists(json);
} else if (eventType.equals(CareportalEvent.PROFILESWITCH)) { } else if (eventType.equals(CareportalEvent.PROFILESWITCH)) {
MainApp.getDbHelper().createProfileSwitchFromJsonIfNotExists(activePlugin, nsUpload, json); databaseHelper.createProfileSwitchFromJsonIfNotExists(activePlugin, nsUpload, json);
} else if (eventType.equals(CareportalEvent.SITECHANGE) || } else if (eventType.equals(CareportalEvent.SITECHANGE) ||
eventType.equals(CareportalEvent.INSULINCHANGE) || eventType.equals(CareportalEvent.INSULINCHANGE) ||
eventType.equals(CareportalEvent.SENSORCHANGE) || eventType.equals(CareportalEvent.SENSORCHANGE) ||
@ -446,7 +478,7 @@ public class NSClientPlugin extends PluginBase {
eventType.equals(CareportalEvent.EXERCISE) || eventType.equals(CareportalEvent.EXERCISE) ||
eventType.equals(CareportalEvent.OPENAPSOFFLINE) || eventType.equals(CareportalEvent.OPENAPSOFFLINE) ||
eventType.equals(CareportalEvent.PUMPBATTERYCHANGE)) { eventType.equals(CareportalEvent.PUMPBATTERYCHANGE)) {
MainApp.getDbHelper().createCareportalEventFromJsonIfNotExists(json); databaseHelper.createCareportalEventFromJsonIfNotExists(json);
} }
if (eventType.equals(CareportalEvent.ANNOUNCEMENT)) { if (eventType.equals(CareportalEvent.ANNOUNCEMENT)) {
@ -468,7 +500,7 @@ public class NSClientPlugin extends PluginBase {
private void storeMbg(JSONObject mbgJson) { private void storeMbg(JSONObject mbgJson) {
NSMbg nsMbg = new NSMbg(mbgJson); NSMbg nsMbg = new NSMbg(mbgJson);
CareportalEvent careportalEvent = new CareportalEvent(nsMbg); CareportalEvent careportalEvent = new CareportalEvent(nsMbg);
MainApp.getDbHelper().createOrUpdate(careportalEvent); databaseHelper.createOrUpdate(careportalEvent);
aapsLogger.debug(LTag.DATASERVICE, "Adding/Updating new MBG: " + careportalEvent.toString()); aapsLogger.debug(LTag.DATASERVICE, "Adding/Updating new MBG: " + careportalEvent.toString());
} }
} }

View file

@ -18,6 +18,7 @@ import info.nightscout.androidaps.MainApp
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.GlucoseValue import info.nightscout.androidaps.database.entities.GlucoseValue
import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.db.* import info.nightscout.androidaps.db.*
import info.nightscout.androidaps.events.EventPreferenceChange import info.nightscout.androidaps.events.EventPreferenceChange
import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.interfaces.PluginBase
@ -27,7 +28,6 @@ import info.nightscout.androidaps.logging.AAPSLogger
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.treatments.TreatmentsPlugin import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import io.reactivex.rxkotlin.plusAssign
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
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
@ -36,6 +36,7 @@ import io.reactivex.Observable
import io.reactivex.Single import io.reactivex.Single
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable import io.reactivex.disposables.Disposable
import io.reactivex.rxkotlin.plusAssign
import org.json.JSONArray import org.json.JSONArray
import org.json.JSONException import org.json.JSONException
import org.json.JSONObject import org.json.JSONObject
@ -268,16 +269,15 @@ class OpenHumansUploader @Inject constructor(
} }
@JvmOverloads @JvmOverloads
fun enqueueTempTarget(tempTarget: TempTarget?, deleted: Boolean = false) = tempTarget?.let { fun enqueueTempTarget(tempTarget: TemporaryTarget?, deleted: Boolean = false) = tempTarget?.let {
insertQueueItem("TempTargets") { insertQueueItem("TempTargets") {
put("date", tempTarget.date) put("date", tempTarget.timestamp)
put("isValid", tempTarget.isValid) put("isValid", tempTarget.isValid)
put("source", tempTarget.source) put("nsId", tempTarget.interfaceIDs_backing?.nightscoutId)
put("nsId", tempTarget._id) put("low", tempTarget.lowTarget)
put("low", tempTarget.low) put("high", tempTarget.highTarget)
put("high", tempTarget.high)
put("reason", tempTarget.reason) put("reason", tempTarget.reason)
put("durationInMinutes", tempTarget.durationInMinutes) put("durationInMinutes", tempTarget.duration)
put("isDeletion", deleted) put("isDeletion", deleted)
} }
} }
@ -384,7 +384,7 @@ class OpenHumansUploader @Inject constructor(
.andThen(Observable.defer { Observable.fromIterable(MainApp.getDbHelper().allTemporaryBasals) }) .andThen(Observable.defer { Observable.fromIterable(MainApp.getDbHelper().allTemporaryBasals) })
.map { enqueueTemporaryBasal(it); increaseCounter() } .map { enqueueTemporaryBasal(it); increaseCounter() }
.ignoreElements() .ignoreElements()
.andThen(Observable.defer { Observable.fromIterable(MainApp.getDbHelper().allTempTargets) }) .andThen(Observable.defer { Observable.fromIterable(repository.compatGetTemporaryTargetData().blockingGet()) })
.map { enqueueTempTarget(it); increaseCounter() } .map { enqueueTempTarget(it); increaseCounter() }
.ignoreElements() .ignoreElements()
.doOnSubscribe { .doOnSubscribe {

View file

@ -28,7 +28,11 @@ import info.nightscout.androidaps.Config
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile 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.UserEntry.* import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.database.interfaces.end
import info.nightscout.androidaps.databinding.OverviewFragmentBinding import info.nightscout.androidaps.databinding.OverviewFragmentBinding
import info.nightscout.androidaps.dialogs.* import info.nightscout.androidaps.dialogs.*
import info.nightscout.androidaps.events.* import info.nightscout.androidaps.events.*
@ -44,10 +48,9 @@ import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus
import info.nightscout.androidaps.plugins.general.overview.activities.QuickWizardListActivity import info.nightscout.androidaps.plugins.general.overview.activities.QuickWizardListActivity
import info.nightscout.androidaps.plugins.general.overview.graphData.GraphData import info.nightscout.androidaps.plugins.general.overview.graphData.GraphData
import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationStore import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationStore
import info.nightscout.androidaps.plugins.general.wear.events.EventWearDoAction import info.nightscout.androidaps.plugins.general.wear.events.EventWearInitiateAction
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
import info.nightscout.androidaps.events.EventAutosensCalculationFinished
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
import info.nightscout.androidaps.plugins.source.DexcomPlugin import info.nightscout.androidaps.plugins.source.DexcomPlugin
@ -111,6 +114,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
@Inject lateinit var dateUtil: DateUtil @Inject lateinit var dateUtil: DateUtil
@Inject lateinit var databaseHelper: DatabaseHelperInterface @Inject lateinit var databaseHelper: DatabaseHelperInterface
@Inject lateinit var uel: UserEntryLogger @Inject lateinit var uel: UserEntryLogger
@Inject lateinit var repository: AppRepository
private val disposable = CompositeDisposable() private val disposable = CompositeDisposable()
@ -292,14 +296,14 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
if (childFragmentManager.isStateSaved) return if (childFragmentManager.isStateSaved) return
activity?.let { activity -> activity?.let { activity ->
when (v.id) { when (v.id) {
R.id.treatment_button -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { if (isAdded) TreatmentDialog().show(childFragmentManager, "Overview") }) R.id.treatment_button -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { if (isAdded) TreatmentDialog().show(childFragmentManager, "Overview") })
R.id.wizard_button -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { if (isAdded) WizardDialog().show(childFragmentManager, "Overview") }) R.id.wizard_button -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { if (isAdded) WizardDialog().show(childFragmentManager, "Overview") })
R.id.insulin_button -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { if (isAdded) InsulinDialog().show(childFragmentManager, "Overview") }) R.id.insulin_button -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { if (isAdded) InsulinDialog().show(childFragmentManager, "Overview") })
R.id.quick_wizard_button -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { if (isAdded) onClickQuickWizard() }) R.id.quick_wizard_button -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { if (isAdded) onClickQuickWizard() })
R.id.carbs_button -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { if (isAdded) CarbsDialog().show(childFragmentManager, "Overview") }) R.id.carbs_button -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { if (isAdded) CarbsDialog().show(childFragmentManager, "Overview") })
R.id.temp_target -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { if (isAdded) TempTargetDialog().show(childFragmentManager, "Overview") }) R.id.temp_target -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { if (isAdded) TempTargetDialog().show(childFragmentManager, "Overview") })
R.id.active_profile -> { R.id.active_profile -> {
ProfileViewerDialog().also { pvd -> ProfileViewerDialog().also { pvd ->
pvd.arguments = Bundle().also { pvd.arguments = Bundle().also {
it.putLong("time", DateUtil.now()) it.putLong("time", DateUtil.now())
@ -308,7 +312,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
}.show(childFragmentManager, "ProfileViewDialog") }.show(childFragmentManager, "ProfileViewDialog")
} }
R.id.cgm_button -> { R.id.cgm_button -> {
if (xdripPlugin.isEnabled(PluginType.BGSOURCE)) if (xdripPlugin.isEnabled(PluginType.BGSOURCE))
openCgmApp("com.eveningoutpost.dexdrip") openCgmApp("com.eveningoutpost.dexdrip")
else if (dexcomPlugin.isEnabled(PluginType.BGSOURCE)) { else if (dexcomPlugin.isEnabled(PluginType.BGSOURCE)) {
@ -319,7 +323,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
} }
} }
R.id.calibration_button -> { R.id.calibration_button -> {
if (xdripPlugin.isEnabled(PluginType.BGSOURCE)) { if (xdripPlugin.isEnabled(PluginType.BGSOURCE)) {
CalibrationDialog().show(childFragmentManager, "CalibrationDialog") CalibrationDialog().show(childFragmentManager, "CalibrationDialog")
} else if (dexcomPlugin.isEnabled(PluginType.BGSOURCE)) { } else if (dexcomPlugin.isEnabled(PluginType.BGSOURCE)) {
@ -334,7 +338,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
} }
} }
R.id.accept_temp_button -> { R.id.accept_temp_button -> {
profileFunction.getProfile() ?: return profileFunction.getProfile() ?: return
if (loopPlugin.isEnabled(PluginType.LOOP)) { if (loopPlugin.isEnabled(PluginType.LOOP)) {
val lastRun = loopPlugin.lastRun val lastRun = loopPlugin.lastRun
@ -346,7 +350,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
uel.log(Action.ACCEPTS_TEMP_BASAL) uel.log(Action.ACCEPTS_TEMP_BASAL)
binding.buttonsLayout.acceptTempButton.visibility = View.GONE binding.buttonsLayout.acceptTempButton.visibility = View.GONE
(context?.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager).cancel(Constants.notificationID) (context?.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager).cancel(Constants.notificationID)
rxBus.send(EventWearDoAction("cancelChangeRequest")) rxBus.send(EventWearInitiateAction("cancelChangeRequest"))
loopPlugin.acceptChangeRequest() loopPlugin.acceptChangeRequest()
}) })
}) })
@ -354,7 +358,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
} }
} }
R.id.aps_mode -> { R.id.aps_mode -> {
protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable {
if (isAdded) LoopDialog().also { dialog -> if (isAdded) LoopDialog().also { dialog ->
dialog.arguments = Bundle().also { it.putInt("showOkCancel", 1) } dialog.arguments = Bundle().also { it.putInt("showOkCancel", 1) }
@ -386,7 +390,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
return true return true
} }
R.id.aps_mode -> { R.id.aps_mode -> {
activity?.let { activity -> activity?.let { activity ->
protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable {
LoopDialog().also { dialog -> LoopDialog().also { dialog ->
@ -396,8 +400,8 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
} }
} }
R.id.temp_target -> v.performClick() R.id.temp_target -> v.performClick()
R.id.active_profile -> activity?.let { activity -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { ProfileSwitchDialog().show(childFragmentManager, "Overview") }) } R.id.active_profile -> activity?.let { activity -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { ProfileSwitchDialog().show(childFragmentManager, "Overview") }) }
} }
return false return false
@ -673,11 +677,11 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
} }
// temp target // temp target
val tempTarget = treatmentsPlugin.tempTargetFromHistory val tempTarget: ValueWrapper<TemporaryTarget> = repository.getTemporaryTargetActiveAt(dateUtil._now()).blockingGet()
if (tempTarget != null) { if (tempTarget is ValueWrapper.Existing) {
binding.loopPumpStatusLayout.tempTarget.setTextColor(resourceHelper.gc(R.color.ribbonTextWarning)) binding.loopPumpStatusLayout.tempTarget.setTextColor(resourceHelper.gc(R.color.ribbonTextWarning))
binding.loopPumpStatusLayout.tempTarget.setBackgroundColor(resourceHelper.gc(R.color.ribbonWarning)) binding.loopPumpStatusLayout.tempTarget.setBackgroundColor(resourceHelper.gc(R.color.ribbonWarning))
binding.loopPumpStatusLayout.tempTarget.text = Profile.toTargetRangeString(tempTarget.low, tempTarget.high, Constants.MGDL, units) + " " + DateUtil.untilString(tempTarget.end(), resourceHelper) binding.loopPumpStatusLayout.tempTarget.text = Profile.toTargetRangeString(tempTarget.value.lowTarget, tempTarget.value.highTarget, Constants.MGDL, units) + " " + DateUtil.untilString(tempTarget.value.end, resourceHelper)
} else { } else {
// If the target is not the same as set in the profile then oref has overridden it // If the target is not the same as set in the profile then oref has overridden it
val targetUsed = lastRun?.constraintsProcessed?.targetBG ?: 0.0 val targetUsed = lastRun?.constraintsProcessed?.targetBG ?: 0.0

View file

@ -15,6 +15,8 @@ import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.GlucoseValueDataPoint import info.nightscout.androidaps.data.GlucoseValueDataPoint
import info.nightscout.androidaps.data.IobTotal import info.nightscout.androidaps.data.IobTotal
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.database.entities.GlucoseValue import info.nightscout.androidaps.database.entities.GlucoseValue
import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.LoopInterface import info.nightscout.androidaps.interfaces.LoopInterface
@ -26,8 +28,10 @@ import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.* import info.nightscout.androidaps.plugins.general.overview.graphExtensions.*
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.DecimalFormatter import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.Round import info.nightscout.androidaps.utils.Round
import info.nightscout.androidaps.utils.extensions.target
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import java.util.* import java.util.*
import javax.inject.Inject import javax.inject.Inject
@ -40,7 +44,6 @@ class GraphData(
private val graph: GraphView, private val graph: GraphView,
private val iobCobCalculatorPlugin: IobCobCalculatorPlugin, private val iobCobCalculatorPlugin: IobCobCalculatorPlugin,
private val treatmentsPlugin: TreatmentsInterface private val treatmentsPlugin: TreatmentsInterface
) { ) {
// IobCobCalculatorPlugin Cannot be injected: HistoryBrowser // IobCobCalculatorPlugin Cannot be injected: HistoryBrowser
@ -48,6 +51,8 @@ class GraphData(
@Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var activePlugin: ActivePluginProvider @Inject lateinit var activePlugin: ActivePluginProvider
@Inject lateinit var repository: AppRepository
@Inject lateinit var dateUtil: DateUtil
var maxY = Double.MIN_VALUE var maxY = Double.MIN_VALUE
private var minY = Double.MAX_VALUE private var minY = Double.MAX_VALUE
@ -212,11 +217,11 @@ class GraphData(
lastRun?.constraintsProcessed?.let { toTime = max(it.latestPredictionsTime, toTime) } lastRun?.constraintsProcessed?.let { toTime = max(it.latestPredictionsTime, toTime) }
var time = fromTime var time = fromTime
while (time < toTime) { while (time < toTime) {
val tt = treatmentsPlugin.getTempTargetFromHistory(time) val tt = repository.getTemporaryTargetActiveAt(time).blockingGet()
val value: Double = if (tt == null) { val value: Double = if (tt is ValueWrapper.Existing) {
Profile.fromMgdlToUnits((profile.getTargetLowMgdl(time) + profile.getTargetHighMgdl(time)) / 2, units) Profile.fromMgdlToUnits(tt.value.target(), units)
} else { } else {
Profile.fromMgdlToUnits(tt.target(), units) Profile.fromMgdlToUnits((profile.getTargetLowMgdl(time) + profile.getTargetHighMgdl(time)) / 2, units)
} }
if (lastTarget != value) { if (lastTarget != value) {
if (lastTarget != -1.0) targetsSeriesArray.add(DataPoint(time.toDouble(), lastTarget)) if (lastTarget != -1.0) targetsSeriesArray.add(DataPoint(time.toDouble(), lastTarget))
@ -344,7 +349,8 @@ class GraphData(
time += 5 * 60 * 1000L time += 5 * 60 * 1000L
continue continue
} }
val deviation = if (devBgiScale) iobCobCalculatorPlugin.getAutosensData(time)?.deviation ?:0.0 else 0.0 val deviation = if (devBgiScale) iobCobCalculatorPlugin.getAutosensData(time)?.deviation
?: 0.0 else 0.0
total = iobCobCalculatorPlugin.calculateFromTreatmentsAndTempsSynchronized(time, profile) total = iobCobCalculatorPlugin.calculateFromTreatmentsAndTempsSynchronized(time, profile)
val bgi: Double = total.activity * profile.getIsfMgdl(time) * 5.0 val bgi: Double = total.activity * profile.getIsfMgdl(time) * 5.0
@ -405,7 +411,7 @@ class GraphData(
if (showPrediction) { if (showPrediction) {
val autosensData = iobCobCalculatorPlugin.getLastAutosensDataSynchronized("GraphData") val autosensData = iobCobCalculatorPlugin.getLastAutosensDataSynchronized("GraphData")
val lastAutosensResult = autosensData?.autosensResult ?: AutosensResult() val lastAutosensResult = autosensData?.autosensResult ?: AutosensResult()
val isTempTarget = treatmentsPlugin.getTempTargetFromHistory(System.currentTimeMillis()) != null val isTempTarget = repository.getTemporaryTargetActiveAt(dateUtil._now()).blockingGet() is ValueWrapper.Existing
val iobPrediction: MutableList<DataPointWithLabelInterface> = ArrayList() val iobPrediction: MutableList<DataPointWithLabelInterface> = ArrayList()
val iobPredictionArray = iobCobCalculatorPlugin.calculateIobArrayForSMB(lastAutosensResult, SMBDefaults.exercise_mode, SMBDefaults.half_basal_exercise_target, isTempTarget) val iobPredictionArray = iobCobCalculatorPlugin.calculateIobArrayForSMB(lastAutosensResult, SMBDefaults.exercise_mode, SMBDefaults.half_basal_exercise_target, isTempTarget)
for (i in iobPredictionArray) { for (i in iobPredictionArray) {
@ -519,10 +525,10 @@ class GraphData(
while (time <= toTime) { while (time <= toTime) {
// if align Dev Scale with BGI scale, then calculate BGI value, else bgi = 0.0 // if align Dev Scale with BGI scale, then calculate BGI value, else bgi = 0.0
val bgi: Double = if (devBgiScale) { val bgi: Double = if (devBgiScale) {
val profile = profileFunction.getProfile(time) val profile = profileFunction.getProfile(time)
total = iobCobCalculatorPlugin.calculateFromTreatmentsAndTempsSynchronized(time, profile) total = iobCobCalculatorPlugin.calculateFromTreatmentsAndTempsSynchronized(time, profile)
total.activity * (profile?.getIsfMgdl(time) ?: 0.0) * 5.0 total.activity * (profile?.getIsfMgdl(time) ?: 0.0) * 5.0
} else 0.0 } else 0.0
iobCobCalculatorPlugin.getAutosensData(time)?.let { autosensData -> iobCobCalculatorPlugin.getAutosensData(time)?.let { autosensData ->
var color = resourceHelper.gc(R.color.deviationblack) // "=" var color = resourceHelper.gc(R.color.deviationblack) // "="

View file

@ -15,9 +15,12 @@ import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.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.database.AppRepository
import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.database.entities.UserEntry.* import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.database.transactions.CancelCurrentTemporaryTargetIfAnyTransaction
import info.nightscout.androidaps.database.transactions.InsertTemporaryTargetAndCancelCurrentTransaction
import info.nightscout.androidaps.db.Source import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.db.TempTarget
import info.nightscout.androidaps.events.EventPreferenceChange import info.nightscout.androidaps.events.EventPreferenceChange
import info.nightscout.androidaps.events.EventRefreshOverview import info.nightscout.androidaps.events.EventRefreshOverview
import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.interfaces.*
@ -27,6 +30,7 @@ import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
@ -47,6 +51,7 @@ import io.reactivex.rxkotlin.plusAssign
import org.apache.commons.lang3.StringUtils import org.apache.commons.lang3.StringUtils
import java.text.Normalizer import java.text.Normalizer
import java.util.* import java.util.*
import java.util.concurrent.TimeUnit
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
import kotlin.math.max import kotlin.math.max
@ -71,7 +76,9 @@ class SmsCommunicatorPlugin @Inject constructor(
private var otp: OneTimePassword, private var otp: OneTimePassword,
private val config: Config, private val config: Config,
private val dateUtil: DateUtil, private val dateUtil: DateUtil,
private val uel: UserEntryLogger private val uel: UserEntryLogger,
private val nsUpload: NSUpload,
private val repository: AppRepository
) : PluginBase(PluginDescription() ) : PluginBase(PluginDescription()
.mainType(PluginType.GENERAL) .mainType(PluginType.GENERAL)
.fragmentClass(SmsCommunicatorFragment::class.java.name) .fragmentClass(SmsCommunicatorFragment::class.java.name)
@ -172,6 +179,7 @@ class SmsCommunicatorPlugin @Inject constructor(
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this) (context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
} }
@Suppress("SpellCheckingInspection")
override fun doWork(): Result { override fun doWork(): Result {
val bundle = bundleStore.pickup(inputData.getLong(DataReceiver.STORE_KEY, -1)) val bundle = bundleStore.pickup(inputData.getLong(DataReceiver.STORE_KEY, -1))
?: return Result.failure() ?: return Result.failure()
@ -238,58 +246,58 @@ class SmsCommunicatorPlugin @Inject constructor(
if (divided.isNotEmpty() && isCommand(divided[0].toUpperCase(Locale.getDefault()), receivedSms.phoneNumber)) { if (divided.isNotEmpty() && isCommand(divided[0].toUpperCase(Locale.getDefault()), receivedSms.phoneNumber)) {
when (divided[0].toUpperCase(Locale.getDefault())) { when (divided[0].toUpperCase(Locale.getDefault())) {
"BG" -> "BG" ->
if (divided.size == 1) processBG(receivedSms) if (divided.size == 1) processBG(receivedSms)
else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat)))
"LOOP" -> "LOOP" ->
if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed))) if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed)))
else if (divided.size == 2 || divided.size == 3) processLOOP(divided, receivedSms) else if (divided.size == 2 || divided.size == 3) processLOOP(divided, receivedSms)
else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat)))
"TREATMENTS" -> "TREATMENTS" ->
if (divided.size == 2) processTREATMENTS(divided, receivedSms) if (divided.size == 2) processTREATMENTS(divided, receivedSms)
else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat)))
"NSCLIENT" -> "NSCLIENT" ->
if (divided.size == 2) processNSCLIENT(divided, receivedSms) if (divided.size == 2) processNSCLIENT(divided, receivedSms)
else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat)))
"PUMP" -> "PUMP" ->
if (!remoteCommandsAllowed && divided.size > 1) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed))) if (!remoteCommandsAllowed && divided.size > 1) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed)))
else if (divided.size <= 3) processPUMP(divided, receivedSms) else if (divided.size <= 3) processPUMP(divided, receivedSms)
else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat)))
"PROFILE" -> "PROFILE" ->
if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed))) if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed)))
else if (divided.size == 2 || divided.size == 3) processPROFILE(divided, receivedSms) else if (divided.size == 2 || divided.size == 3) processPROFILE(divided, receivedSms)
else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat)))
"BASAL" -> "BASAL" ->
if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed))) if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed)))
else if (divided.size == 2 || divided.size == 3) processBASAL(divided, receivedSms) else if (divided.size == 2 || divided.size == 3) processBASAL(divided, receivedSms)
else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat)))
"EXTENDED" -> "EXTENDED" ->
if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed))) if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed)))
else if (divided.size == 2 || divided.size == 3) processEXTENDED(divided, receivedSms) else if (divided.size == 2 || divided.size == 3) processEXTENDED(divided, receivedSms)
else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat)))
"BOLUS" -> "BOLUS" ->
if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed))) if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed)))
else if (divided.size == 2 && DateUtil.now() - lastRemoteBolusTime < minDistance) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotebolusnotallowed))) else if (divided.size == 2 && DateUtil.now() - lastRemoteBolusTime < minDistance) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotebolusnotallowed)))
else if (divided.size == 2 && pump.isSuspended()) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.pumpsuspended))) else if (divided.size == 2 && pump.isSuspended()) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.pumpsuspended)))
else if (divided.size == 2 || divided.size == 3) processBOLUS(divided, receivedSms) else if (divided.size == 2 || divided.size == 3) processBOLUS(divided, receivedSms)
else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat)))
"CARBS" -> "CARBS" ->
if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed))) if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed)))
else if (divided.size == 2 || divided.size == 3) processCARBS(divided, receivedSms) else if (divided.size == 2 || divided.size == 3) processCARBS(divided, receivedSms)
else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat)))
"CAL" -> "CAL" ->
if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed))) if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed)))
else if (divided.size == 2) processCAL(divided, receivedSms) else if (divided.size == 2) processCAL(divided, receivedSms)
else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat)))
"TARGET" -> "TARGET" ->
if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed))) if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed)))
else if (divided.size == 2) processTARGET(divided, receivedSms) else if (divided.size == 2) processTARGET(divided, receivedSms)
else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat)))
"SMS" -> "SMS" ->
if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed))) if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed)))
else if (divided.size == 2) processSMS(divided, receivedSms) else if (divided.size == 2) processSMS(divided, receivedSms)
else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat)))
"HELP" -> "HELP" ->
if (divided.size == 1 || divided.size == 2) processHELP(divided, receivedSms) if (divided.size == 1 || divided.size == 2) processHELP(divided, receivedSms)
else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat)))
else -> else ->
@ -310,8 +318,8 @@ class SmsCommunicatorPlugin @Inject constructor(
if (actualBG != null) { if (actualBG != null) {
reply = resourceHelper.gs(R.string.sms_actualbg) + " " + actualBG.valueToUnitsString(units) + ", " reply = resourceHelper.gs(R.string.sms_actualbg) + " " + actualBG.valueToUnitsString(units) + ", "
} else if (lastBG != null) { } else if (lastBG != null) {
val agoMsec = System.currentTimeMillis() - lastBG.timestamp val agoMilliseconds = System.currentTimeMillis() - lastBG.timestamp
val agoMin = (agoMsec / 60.0 / 1000.0).toInt() val agoMin = (agoMilliseconds / 60.0 / 1000.0).toInt()
reply = resourceHelper.gs(R.string.sms_lastbg) + " " + lastBG.valueToUnitsString(units) + " " + String.format(resourceHelper.gs(R.string.sms_minago), agoMin) + ", " reply = resourceHelper.gs(R.string.sms_lastbg) + " " + lastBG.valueToUnitsString(units) + " " + String.format(resourceHelper.gs(R.string.sms_minago), agoMin) + ", "
} }
val glucoseStatus = GlucoseStatus(injector).glucoseStatusData val glucoseStatus = GlucoseStatus(injector).glucoseStatusData
@ -373,7 +381,7 @@ class SmsCommunicatorPlugin @Inject constructor(
receivedSms.processed = true receivedSms.processed = true
} }
"STATUS" -> { "STATUS" -> {
val reply = if (loopPlugin.isEnabled(PluginType.LOOP)) { val reply = if (loopPlugin.isEnabled(PluginType.LOOP)) {
if (loopPlugin.isSuspended) String.format(resourceHelper.gs(R.string.loopsuspendedfor), loopPlugin.minutesToEndOfSuspend()) if (loopPlugin.isSuspended) String.format(resourceHelper.gs(R.string.loopsuspendedfor), loopPlugin.minutesToEndOfSuspend())
else resourceHelper.gs(R.string.smscommunicator_loopisenabled) else resourceHelper.gs(R.string.smscommunicator_loopisenabled)
@ -383,7 +391,7 @@ class SmsCommunicatorPlugin @Inject constructor(
receivedSms.processed = true receivedSms.processed = true
} }
"RESUME" -> { "RESUME" -> {
val passCode = generatePassCode() val passCode = generatePassCode()
val reply = String.format(resourceHelper.gs(R.string.smscommunicator_loopresumereplywithcode), passCode) val reply = String.format(resourceHelper.gs(R.string.smscommunicator_loopresumereplywithcode), passCode)
receivedSms.processed = true receivedSms.processed = true
@ -407,7 +415,7 @@ class SmsCommunicatorPlugin @Inject constructor(
}) })
} }
"SUSPEND" -> { "SUSPEND" -> {
var duration = 0 var duration = 0
if (divided.size == 3) duration = SafeParse.stringToInt(divided[2]) if (divided.size == 3) duration = SafeParse.stringToInt(divided[2])
duration = max(0, duration) duration = max(0, duration)
@ -573,23 +581,23 @@ class SmsCommunicatorPlugin @Inject constructor(
sendSMS(Sms(receivedSms.phoneNumber, reply)) sendSMS(Sms(receivedSms.phoneNumber, reply))
} }
} else { } else {
val pindex = SafeParse.stringToInt(divided[1]) val pIndex = SafeParse.stringToInt(divided[1])
var percentage = 100 var percentage = 100
if (divided.size > 2) percentage = SafeParse.stringToInt(divided[2]) if (divided.size > 2) percentage = SafeParse.stringToInt(divided[2])
if (pindex > list.size) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) if (pIndex > list.size) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat)))
else if (percentage == 0) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) else if (percentage == 0) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat)))
else if (pindex == 0) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) else if (pIndex == 0) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat)))
else { else {
val profile = store.getSpecificProfile(list[pindex - 1] as String) val profile = store.getSpecificProfile(list[pIndex - 1] as String)
if (profile == null) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.noprofile))) if (profile == null) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.noprofile)))
else { else {
val passCode = generatePassCode() val passCode = generatePassCode()
val reply = String.format(resourceHelper.gs(R.string.smscommunicator_profilereplywithcode), list[pindex - 1], percentage, passCode) val reply = String.format(resourceHelper.gs(R.string.smscommunicator_profilereplywithcode), list[pIndex - 1], percentage, passCode)
receivedSms.processed = true receivedSms.processed = true
val finalPercentage = percentage val finalPercentage = percentage
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(list[pindex - 1] as String, finalPercentage) { messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(list[pIndex - 1] as String, finalPercentage) {
override fun run() { override fun run() {
activePlugin.activeTreatments.doProfileSwitch(store, list[pindex - 1] as String, 0, finalPercentage, 0, DateUtil.now()) activePlugin.activeTreatments.doProfileSwitch(store, list[pIndex - 1] as String, 0, finalPercentage, 0, DateUtil.now())
val replyText = resourceHelper.gs(R.string.profileswitchcreated) val replyText = resourceHelper.gs(R.string.profileswitchcreated)
sendSMS(Sms(receivedSms.phoneNumber, replyText)) sendSMS(Sms(receivedSms.phoneNumber, replyText))
uel.log(Action.SMS_PROFILE, ValueWithUnit(R.string.profileswitchcreated, Units.R_String)) uel.log(Action.SMS_PROFILE, ValueWithUnit(R.string.profileswitchcreated, Units.R_String))
@ -808,14 +816,18 @@ class SmsCommunicatorPlugin @Inject constructor(
currentProfile.units == Constants.MMOL -> Constants.defaultEatingSoonTTmmol currentProfile.units == Constants.MMOL -> Constants.defaultEatingSoonTTmmol
else -> Constants.defaultEatingSoonTTmgdl else -> Constants.defaultEatingSoonTTmgdl
} }
val tempTarget = TempTarget() disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction(
.date(System.currentTimeMillis()) timestamp = System.currentTimeMillis(),
.duration(eatingSoonTTDuration) duration = TimeUnit.MINUTES.toMillis(eatingSoonTTDuration.toLong()),
.reason(resourceHelper.gs(R.string.eatingsoon)) reason = TemporaryTarget.Reason.EATING_SOON,
.source(Source.USER) lowTarget = Profile.toMgdl(eatingSoonTT, profileFunction.getUnits()),
.low(Profile.toMgdl(eatingSoonTT, currentProfile.units)) highTarget = Profile.toMgdl(eatingSoonTT, profileFunction.getUnits())
.high(Profile.toMgdl(eatingSoonTT, currentProfile.units)) )).subscribe({ result ->
activePlugin.activeTreatments.addToHistoryTempTarget(tempTarget) result.inserted.forEach { nsUpload.uploadTempTarget(it) }
result.updated.forEach { nsUpload.updateTempTarget(it) }
}, {
aapsLogger.error(LTag.BGSOURCE, "Error while saving temporary target", it)
})
val tt = if (currentProfile.units == Constants.MMOL) { val tt = if (currentProfile.units == Constants.MMOL) {
DecimalFormatter.to1Decimal(eatingSoonTT) DecimalFormatter.to1Decimal(eatingSoonTT)
} else DecimalFormatter.to0Decimal(eatingSoonTT) } else DecimalFormatter.to0Decimal(eatingSoonTT)
@ -936,14 +948,18 @@ class SmsCommunicatorPlugin @Inject constructor(
var tt = sp.getDouble(keyTarget, if (units == Constants.MMOL) defaultTargetMMOL else defaultTargetMGDL) var tt = sp.getDouble(keyTarget, if (units == Constants.MMOL) defaultTargetMMOL else defaultTargetMGDL)
tt = Profile.toCurrentUnits(profileFunction, tt) tt = Profile.toCurrentUnits(profileFunction, tt)
tt = if (tt > 0) tt else if (units == Constants.MMOL) defaultTargetMMOL else defaultTargetMGDL tt = if (tt > 0) tt else if (units == Constants.MMOL) defaultTargetMMOL else defaultTargetMGDL
val tempTarget = TempTarget() disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction(
.date(System.currentTimeMillis()) timestamp = System.currentTimeMillis(),
.duration(ttDuration) duration = TimeUnit.MINUTES.toMillis(ttDuration.toLong()),
.reason(resourceHelper.gs(R.string.eatingsoon)) reason = TemporaryTarget.Reason.EATING_SOON,
.source(Source.USER) lowTarget = Profile.toMgdl(tt, profileFunction.getUnits()),
.low(Profile.toMgdl(tt, units)) highTarget = Profile.toMgdl(tt, profileFunction.getUnits())
.high(Profile.toMgdl(tt, units)) )).subscribe({ result ->
activePlugin.activeTreatments.addToHistoryTempTarget(tempTarget) result.inserted.forEach { nsUpload.uploadTempTarget(it) }
result.updated.forEach { nsUpload.updateTempTarget(it) }
}, {
aapsLogger.error(LTag.BGSOURCE, "Error while saving temporary target", it)
})
val ttString = if (units == Constants.MMOL) DecimalFormatter.to1Decimal(tt) else DecimalFormatter.to0Decimal(tt) val ttString = if (units == Constants.MMOL) DecimalFormatter.to1Decimal(tt) else DecimalFormatter.to0Decimal(tt)
val replyText = String.format(resourceHelper.gs(R.string.smscommunicator_tt_set), ttString, ttDuration) val replyText = String.format(resourceHelper.gs(R.string.smscommunicator_tt_set), ttString, ttDuration)
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText)) sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
@ -957,13 +973,12 @@ class SmsCommunicatorPlugin @Inject constructor(
receivedSms.processed = true receivedSms.processed = true
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction() { messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction() {
override fun run() { override fun run() {
val tempTarget = TempTarget() disposable += repository.runTransactionForResult(CancelCurrentTemporaryTargetIfAnyTransaction(dateUtil._now()))
.source(Source.USER) .subscribe({ result ->
.date(DateUtil.now()) result.updated.forEach { nsUpload.updateTempTarget(it) }
.duration(0) }, {
.low(0.0) aapsLogger.error(LTag.BGSOURCE, "Error while saving temporary target", it)
.high(0.0) })
activePlugin.activeTreatments.addToHistoryTempTarget(tempTarget)
val replyText = String.format(resourceHelper.gs(R.string.smscommunicator_tt_canceled)) val replyText = String.format(resourceHelper.gs(R.string.smscommunicator_tt_canceled))
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText)) sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
uel.log(Action.SMS_TT, ValueWithUnit(R.string.smscommunicator_tt_canceled, Units.R_String)) uel.log(Action.SMS_TT, ValueWithUnit(R.string.smscommunicator_tt_canceled, Units.R_String))

View file

@ -14,20 +14,29 @@ import info.nightscout.androidaps.danar.DanaRPlugin
import info.nightscout.androidaps.danars.DanaRSPlugin import info.nightscout.androidaps.danars.DanaRSPlugin
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.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.database.entities.TemporaryTarget
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.CareportalEvent import info.nightscout.androidaps.db.CareportalEvent
import info.nightscout.androidaps.db.Source import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.db.TDD import info.nightscout.androidaps.db.TDD
import info.nightscout.androidaps.db.TempTarget
import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.CommandQueueProvider import info.nightscout.androidaps.interfaces.CommandQueueProvider
import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.interfaces.PluginBase
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification
import info.nightscout.androidaps.plugins.general.wear.events.EventWearDoAction import info.nightscout.androidaps.plugins.general.wear.events.EventWearConfirmAction
import info.nightscout.androidaps.plugins.general.wear.events.EventWearInitiateAction
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin
import info.nightscout.androidaps.plugins.treatments.CarbsGenerator import info.nightscout.androidaps.plugins.treatments.CarbsGenerator
@ -43,6 +52,7 @@ import java.text.DateFormat
import java.text.DecimalFormat import java.text.DecimalFormat
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
import java.util.concurrent.TimeUnit
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@ -50,6 +60,7 @@ import javax.inject.Singleton
class ActionStringHandler @Inject constructor( class ActionStringHandler @Inject constructor(
private val sp: SP, private val sp: SP,
private val rxBus: RxBusWrapper, private val rxBus: RxBusWrapper,
private val aapsLogger: AAPSLogger,
aapsSchedulers: AapsSchedulers, aapsSchedulers: AapsSchedulers,
private val resourceHelper: ResourceHelper, private val resourceHelper: ResourceHelper,
private val injector: HasAndroidInjector, private val injector: HasAndroidInjector,
@ -71,7 +82,9 @@ class ActionStringHandler @Inject constructor(
private val hardLimits: HardLimits, private val hardLimits: HardLimits,
private val carbsGenerator: CarbsGenerator, private val carbsGenerator: CarbsGenerator,
private val dateUtil: DateUtil, private val dateUtil: DateUtil,
private val config: Config private val config: Config,
private val repository: AppRepository,
private val nsUpload: NSUpload
) { ) {
private val TIMEOUT = 65 * 1000 private val TIMEOUT = 65 * 1000
@ -83,9 +96,14 @@ class ActionStringHandler @Inject constructor(
init { init {
disposable += rxBus disposable += rxBus
.toObservable(EventWearDoAction::class.java) .toObservable(EventWearInitiateAction::class.java)
.observeOn(aapsSchedulers.main) .observeOn(aapsSchedulers.main)
.subscribe({ handleInitiate(it.action) }, fabricPrivacy::logException) .subscribe({ handleInitiate(it.action) }, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventWearConfirmAction::class.java)
.observeOn(aapsSchedulers.main)
.subscribe({ handleConfirmation(it.action) }, fabricPrivacy::logException)
} }
@Synchronized @Synchronized
@ -203,7 +221,10 @@ class ActionStringHandler @Inject constructor(
} }
val format = DecimalFormat("0.00") val format = DecimalFormat("0.00")
val formatInt = DecimalFormat("0") val formatInt = DecimalFormat("0")
val bolusWizard = BolusWizard(injector).doCalc(profile, profileName, activePlugin.activeTreatments.tempTargetFromHistory, val dbRecord = repository.getTemporaryTargetActiveAt(dateUtil._now()).blockingGet()
val tempTarget = if (dbRecord is ValueWrapper.Existing) dbRecord.value else null
val bolusWizard = BolusWizard(injector).doCalc(profile, profileName, tempTarget,
carbsAfterConstraints, if (cobInfo.displayCob != null) cobInfo.displayCob!! else 0.0, bgReading.valueToUnits(profileFunction.getUnits()), carbsAfterConstraints, if (cobInfo.displayCob != null) cobInfo.displayCob!! else 0.0, bgReading.valueToUnits(profileFunction.getUnits()),
0.0, percentage.toDouble(), useBG, useCOB, useBolusIOB, useBasalIOB, false, useTT, useTrend, false) 0.0, percentage.toDouble(), useBG, useCOB, useBolusIOB, useBasalIOB, false, useTT, useTrend, false)
if (Math.abs(bolusWizard.insulinAfterConstraints - bolusWizard.calculatedTotalInsulin) >= 0.01) { if (Math.abs(bolusWizard.insulinAfterConstraints - bolusWizard.calculatedTotalInsulin) >= 0.01) {
@ -439,10 +460,10 @@ class ActionStringHandler @Inject constructor(
} }
val profile = profileFunction.getProfile() ?: return "No profile set :(" val profile = profileFunction.getProfile() ?: return "No profile set :("
//Check for Temp-Target: //Check for Temp-Target:
val tempTarget = activePlugin.activeTreatments.tempTargetFromHistory val tempTarget = repository.getTemporaryTargetActiveAt(dateUtil._now()).blockingGet()
if (tempTarget != null) { if (tempTarget is ValueWrapper.Existing) {
ret += "Temp Target: " + Profile.toTargetRangeString(tempTarget.low, tempTarget.low, Constants.MGDL, profileFunction.getUnits()) ret += "Temp Target: " + Profile.toTargetRangeString(tempTarget.value.lowTarget, tempTarget.value.lowTarget, Constants.MGDL, profileFunction.getUnits())
ret += "\nuntil: " + dateUtil.timeString(tempTarget.originalEnd()) ret += "\nuntil: " + dateUtil.timeString(tempTarget.value.end)
ret += "\n\n" ret += "\n\n"
} }
ret += "DEFAULT RANGE: " ret += "DEFAULT RANGE: "
@ -565,17 +586,26 @@ class ActionStringHandler @Inject constructor(
} }
private fun generateTempTarget(duration: Int, low: Double, high: Double) { private fun generateTempTarget(duration: Int, low: Double, high: Double) {
val tempTarget = TempTarget() if (duration != 0)
.date(System.currentTimeMillis()) disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction(
.duration(duration) timestamp = System.currentTimeMillis(),
.reason("WearPlugin") duration = TimeUnit.MINUTES.toMillis(duration.toLong()),
.source(Source.USER) reason = TemporaryTarget.Reason.WEAR,
if (tempTarget.durationInMinutes != 0) { lowTarget = Profile.toMgdl(low, profileFunction.getUnits()),
tempTarget.low(low).high(high) highTarget = Profile.toMgdl(high, profileFunction.getUnits())
} else { )).subscribe({ result ->
tempTarget.low(0.0).high(0.0) result.inserted.forEach { nsUpload.uploadTempTarget(it) }
} result.updated.forEach { nsUpload.updateTempTarget(it) }
activePlugin.activeTreatments.addToHistoryTempTarget(tempTarget) }, {
aapsLogger.error("Error while saving temporary target", it)
})
else
disposable += repository.runTransactionForResult(CancelCurrentTemporaryTargetIfAnyTransaction(System.currentTimeMillis()))
.subscribe({ result ->
result.updated.forEach { nsUpload.updateTempTarget(it) }
}, {
aapsLogger.error("Error while saving temporary target", it)
})
} }
private fun doFillBolus(amount: Double) { private fun doFillBolus(amount: Double) {

View file

@ -2,4 +2,4 @@ package info.nightscout.androidaps.plugins.general.wear.events
import info.nightscout.androidaps.events.Event import info.nightscout.androidaps.events.Event
class EventWearDoAction (val action: String) : Event() class EventWearConfirmAction(val action: String) : Event()

View file

@ -0,0 +1,5 @@
package info.nightscout.androidaps.plugins.general.wear.events
import info.nightscout.androidaps.events.Event
class EventWearInitiateAction(val action: String) : Event()

View file

@ -48,7 +48,8 @@ import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
import info.nightscout.androidaps.plugins.bus.RxBusWrapper; import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus; import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus;
import info.nightscout.androidaps.plugins.general.wear.WearPlugin; import info.nightscout.androidaps.plugins.general.wear.WearPlugin;
import info.nightscout.androidaps.plugins.general.wear.events.EventWearDoAction; import info.nightscout.androidaps.plugins.general.wear.events.EventWearConfirmAction;
import info.nightscout.androidaps.plugins.general.wear.events.EventWearInitiateAction;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
@ -261,13 +262,13 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
if (event != null && event.getPath().equals(WEARABLE_INITIATE_ACTIONSTRING_PATH)) { if (event != null && event.getPath().equals(WEARABLE_INITIATE_ACTIONSTRING_PATH)) {
String actionstring = new String(event.getData()); String actionstring = new String(event.getData());
aapsLogger.debug(LTag.WEAR, "Wear: " + actionstring); aapsLogger.debug(LTag.WEAR, "Wear: " + actionstring);
rxBus.send(new EventWearDoAction(actionstring)); rxBus.send(new EventWearInitiateAction(actionstring));
} }
if (event != null && event.getPath().equals(WEARABLE_CONFIRM_ACTIONSTRING_PATH)) { if (event != null && event.getPath().equals(WEARABLE_CONFIRM_ACTIONSTRING_PATH)) {
String actionstring = new String(event.getData()); String actionstring = new String(event.getData());
aapsLogger.debug(LTag.WEAR, "Wear Confirm: " + actionstring); aapsLogger.debug(LTag.WEAR, "Wear Confirm: " + actionstring);
rxBus.send(new EventWearDoAction(actionstring)); rxBus.send(new EventWearConfirmAction(actionstring));
} }
} }
} }

View file

@ -6,7 +6,10 @@ import android.os.SystemClock
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.events.Event import info.nightscout.androidaps.events.Event
import info.nightscout.androidaps.events.EventAutosensCalculationFinished
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.logging.LTag import info.nightscout.androidaps.logging.LTag
@ -17,13 +20,13 @@ import info.nightscout.androidaps.plugins.general.overview.notifications.Notific
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin.Companion.roundUpTime import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin.Companion.roundUpTime
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.data.AutosensData import info.nightscout.androidaps.plugins.iob.iobCobCalculator.data.AutosensData
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensBgLoaded import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensBgLoaded
import info.nightscout.androidaps.events.EventAutosensCalculationFinished
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress
import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.utils.* import info.nightscout.androidaps.utils.*
import info.nightscout.androidaps.utils.buildHelper.BuildHelper import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.extensions.target
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import java.util.* import java.util.*
@ -56,6 +59,7 @@ class IobCobOref1Thread internal constructor(
@Inject lateinit var profiler: Profiler @Inject lateinit var profiler: Profiler
@Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var dateUtil: DateUtil @Inject lateinit var dateUtil: DateUtil
@Inject lateinit var repository: AppRepository
private var mWakeLock: PowerManager.WakeLock? = null private var mWakeLock: PowerManager.WakeLock? = null
@ -292,9 +296,9 @@ class IobCobOref1Thread internal constructor(
// TODO AS-FIX // TODO AS-FIX
@Suppress("SimplifyBooleanWithConstants") @Suppress("SimplifyBooleanWithConstants")
if (false && sp.getBoolean(R.string.key_high_temptarget_raises_sensitivity, SMBDefaults.high_temptarget_raises_sensitivity)) { if (false && sp.getBoolean(R.string.key_high_temptarget_raises_sensitivity, SMBDefaults.high_temptarget_raises_sensitivity)) {
val tempTarget = treatmentsPlugin.getTempTargetFromHistory(bgTime) val tempTarget = repository.getTemporaryTargetActiveAt(dateUtil._now()).blockingGet()
if (tempTarget != null && tempTarget.target() >= 100) { if (tempTarget is ValueWrapper.Existing && tempTarget.value.target() >= 100) {
autosensData.extraDeviation.add(-(tempTarget.target() - 100) / 20) autosensData.extraDeviation.add(-(tempTarget.value.target() - 100) / 20)
} }
} }

View file

@ -290,7 +290,7 @@ class VirtualPumpPlugin @Inject constructor(
override fun cancelExtendedBolus(): PumpEnactResult { override fun cancelExtendedBolus(): PumpEnactResult {
val result = PumpEnactResult(injector) val result = PumpEnactResult(injector)
if (treatmentsPlugin.isInHistoryExtendedBoluslInProgress) { if (treatmentsPlugin.isInHistoryExtendedBolusInProgress) {
val exStop = ExtendedBolus(injector, System.currentTimeMillis()) val exStop = ExtendedBolus(injector, System.currentTimeMillis())
exStop.source = Source.USER exStop.source = Source.USER
treatmentsPlugin.addToHistoryExtendedBolus(exStop) treatmentsPlugin.addToHistoryExtendedBolus(exStop)

View file

@ -149,7 +149,7 @@ class DexcomPlugin @Inject constructor(
} }
} }
}, { }, {
aapsLogger.error(LTag.BGSOURCE, "Error while saving values from Dexcom App", it) aapsLogger.error("Error while saving values from Dexcom App", it)
}) })
} catch (e: Exception) { } catch (e: Exception) {
aapsLogger.error("Error while processing intent from Dexcom App", e) aapsLogger.error("Error while processing intent from Dexcom App", e)

View file

@ -125,7 +125,7 @@ class EversensePlugin @Inject constructor(
nsUpload.uploadBg(it, GlucoseValue.SourceSensor.EVERSENSE.text) nsUpload.uploadBg(it, GlucoseValue.SourceSensor.EVERSENSE.text)
} }
}, { }, {
aapsLogger.error(LTag.BGSOURCE, "Error while saving values from Eversense App", it) aapsLogger.error("Error while saving values from Eversense App", it)
}) })
} }
} }
@ -147,7 +147,7 @@ class EversensePlugin @Inject constructor(
data.put("glucoseType", "Finger") data.put("glucoseType", "Finger")
data.put("glucose", calibrationGlucoseLevels[i]) data.put("glucose", calibrationGlucoseLevels[i])
data.put("units", Constants.MGDL) data.put("units", Constants.MGDL)
nsUpload.uploadCareportalEntryToNS(data) nsUpload.uploadCareportalEntryToNS(data, calibrationTimestamps[i])
} }
} catch (e: JSONException) { } catch (e: JSONException) {
aapsLogger.error("Unhandled exception", e) aapsLogger.error("Unhandled exception", e)

View file

@ -82,7 +82,7 @@ class GlimpPlugin @Inject constructor(
nsUpload.uploadBg(it, GlucoseValue.SourceSensor.GLIMP.text) nsUpload.uploadBg(it, GlucoseValue.SourceSensor.GLIMP.text)
} }
}, { }, {
aapsLogger.error(LTag.BGSOURCE, "Error while saving values from Glimp App", it) aapsLogger.error("Error while saving values from Glimp App", it)
}) })
return Result.success() return Result.success()
} }

View file

@ -100,7 +100,7 @@ class MM640gPlugin @Inject constructor(
nsUpload.uploadBg(it, GlucoseValue.SourceSensor.MM_600_SERIES.text) nsUpload.uploadBg(it, GlucoseValue.SourceSensor.MM_600_SERIES.text)
} }
}, { }, {
aapsLogger.error(LTag.BGSOURCE, "Error while saving values from Eversense App", it) aapsLogger.error("Error while saving values from Eversense App", it)
}) })
} catch (e: JSONException) { } catch (e: JSONException) {
aapsLogger.error("Exception: ", e) aapsLogger.error("Exception: ", e)

View file

@ -139,7 +139,7 @@ class NSClientSourcePlugin @Inject constructor(
nsClientSourcePlugin.detectSource(it) nsClientSourcePlugin.detectSource(it)
} }
}, { }, {
aapsLogger.error(LTag.BGSOURCE, "Error while saving values from NSClient App", it) aapsLogger.error("Error while saving values from NSClient App", it)
}) })
} catch (e: Exception) { } catch (e: Exception) {
aapsLogger.error("Unhandled exception", e) aapsLogger.error("Unhandled exception", e)

View file

@ -93,7 +93,7 @@ class PoctechPlugin @Inject constructor(
nsUpload.uploadBg(it, GlucoseValue.SourceSensor.POCTECH_NATIVE.text) nsUpload.uploadBg(it, GlucoseValue.SourceSensor.POCTECH_NATIVE.text)
} }
}, { }, {
aapsLogger.error(LTag.BGSOURCE, "Error while saving values from Poctech App", it) aapsLogger.error("Error while saving values from Poctech App", it)
}) })
} catch (e: JSONException) { } catch (e: JSONException) {
aapsLogger.error("Exception: ", e) aapsLogger.error("Exception: ", e)

View file

@ -82,7 +82,7 @@ class TomatoPlugin @Inject constructor(
nsUpload.uploadBg(it, GlucoseValue.SourceSensor.LIBRE_1_TOMATO.text) nsUpload.uploadBg(it, GlucoseValue.SourceSensor.LIBRE_1_TOMATO.text)
} }
}, { }, {
aapsLogger.error(LTag.BGSOURCE, "Error while saving values from Tomato App", it) aapsLogger.error("Error while saving values from Tomato App", it)
}) })
return Result.success() return Result.success()
} }

View file

@ -50,7 +50,8 @@ class XdripPlugin @Inject constructor(
GlucoseValue.SourceSensor.DEXCOM_G6_NATIVE, GlucoseValue.SourceSensor.DEXCOM_G6_NATIVE,
GlucoseValue.SourceSensor.DEXCOM_G5_NATIVE, GlucoseValue.SourceSensor.DEXCOM_G5_NATIVE,
GlucoseValue.SourceSensor.DEXCOM_G6_NATIVE_XDRIP, GlucoseValue.SourceSensor.DEXCOM_G6_NATIVE_XDRIP,
GlucoseValue.SourceSensor.DEXCOM_G5_NATIVE_XDRIP GlucoseValue.SourceSensor.DEXCOM_G5_NATIVE_XDRIP,
GlucoseValue.SourceSensor.DEXCOM_G6_G5_NATIVE_XDRIP
).any { it == glucoseValue.sourceSensor } ).any { it == glucoseValue.sourceSensor }
} }
@ -102,4 +103,4 @@ class XdripPlugin @Inject constructor(
return Result.success() return Result.success()
} }
} }
} }

View file

@ -11,14 +11,16 @@ import info.nightscout.androidaps.R
import info.nightscout.androidaps.databinding.TreatmentsFragmentBinding import info.nightscout.androidaps.databinding.TreatmentsFragmentBinding
import info.nightscout.androidaps.events.EventExtendedBolusChange import info.nightscout.androidaps.events.EventExtendedBolusChange
import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.ConfigInterface
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.treatments.fragments.* import info.nightscout.androidaps.plugins.treatments.fragments.*
import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.FabricPrivacy
import io.reactivex.rxkotlin.plusAssign import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.extensions.toVisibility import info.nightscout.androidaps.utils.extensions.toVisibility
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.rx.AapsSchedulers
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import javax.inject.Inject import javax.inject.Inject
class TreatmentsFragment : DaggerFragment() { class TreatmentsFragment : DaggerFragment() {
@ -29,6 +31,7 @@ class TreatmentsFragment : DaggerFragment() {
@Inject lateinit var activePlugin: ActivePluginProvider @Inject lateinit var activePlugin: ActivePluginProvider
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin @Inject lateinit var treatmentsPlugin: TreatmentsPlugin
@Inject lateinit var aapsSchedulers: AapsSchedulers @Inject lateinit var aapsSchedulers: AapsSchedulers
@Inject lateinit var buildHelper: BuildHelper
private val disposable = CompositeDisposable() private val disposable = CompositeDisposable()
@ -44,6 +47,9 @@ class TreatmentsFragment : DaggerFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
binding.tempBasals.visibility = buildHelper.isEngineeringMode().toVisibility()
binding.extendedBoluses.visibility = (buildHelper.isEngineeringMode() && !activePlugin.activePump.isFakingTempsByExtendedBoluses).toVisibility()
binding.treatments.setOnClickListener { binding.treatments.setOnClickListener {
setFragment(TreatmentsBolusFragment()) setFragment(TreatmentsBolusFragment())
setBackgroundColorOnSelected(it) setBackgroundColorOnSelected(it)

View file

@ -8,8 +8,6 @@ import androidx.annotation.Nullable;
import com.google.firebase.analytics.FirebaseAnalytics; import com.google.firebase.analytics.FirebaseAnalytics;
import androidx.annotation.NonNull;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -18,7 +16,6 @@ import javax.inject.Singleton;
import dagger.android.HasAndroidInjector; import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.activities.ErrorHelperActivity; import info.nightscout.androidaps.activities.ErrorHelperActivity;
import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.DetailedBolusInfo;
@ -26,20 +23,19 @@ import info.nightscout.androidaps.data.Intervals;
import info.nightscout.androidaps.data.Iob; import info.nightscout.androidaps.data.Iob;
import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.NonOverlappingIntervals; import info.nightscout.androidaps.data.NonOverlappingIntervals;
import info.nightscout.androidaps.data.OverlappingIntervals;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.ProfileIntervals; import info.nightscout.androidaps.data.ProfileIntervals;
import info.nightscout.androidaps.database.AppRepository;
import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.ProfileSwitch; import info.nightscout.androidaps.db.ProfileSwitch;
import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TempTarget;
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.events.EventReloadProfileSwitchData; import info.nightscout.androidaps.events.EventReloadProfileSwitchData;
import info.nightscout.androidaps.events.EventReloadTempBasalData; import info.nightscout.androidaps.events.EventReloadTempBasalData;
import info.nightscout.androidaps.events.EventReloadTreatmentData; import info.nightscout.androidaps.events.EventReloadTreatmentData;
import info.nightscout.androidaps.events.EventTempTargetChange;
import info.nightscout.androidaps.interfaces.ActivePluginProvider; import info.nightscout.androidaps.interfaces.ActivePluginProvider;
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription; import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.interfaces.PluginType;
@ -81,6 +77,8 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
private final UploadQueue uploadQueue; private final UploadQueue uploadQueue;
private final FabricPrivacy fabricPrivacy; private final FabricPrivacy fabricPrivacy;
private final DateUtil dateUtil; private final DateUtil dateUtil;
private final DatabaseHelperInterface databaseHelper;
private final AppRepository repository;
private final CompositeDisposable disposable = new CompositeDisposable(); private final CompositeDisposable disposable = new CompositeDisposable();
@ -92,7 +90,6 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
private final ArrayList<Treatment> treatments = new ArrayList<>(); private final ArrayList<Treatment> treatments = new ArrayList<>();
private final Intervals<TemporaryBasal> tempBasals = new NonOverlappingIntervals<>(); private final Intervals<TemporaryBasal> tempBasals = new NonOverlappingIntervals<>();
private final Intervals<ExtendedBolus> extendedBoluses = new NonOverlappingIntervals<>(); private final Intervals<ExtendedBolus> extendedBoluses = new NonOverlappingIntervals<>();
private final Intervals<TempTarget> tempTargets = new OverlappingIntervals<>();
private final ProfileIntervals<ProfileSwitch> profiles = new ProfileIntervals<>(); private final ProfileIntervals<ProfileSwitch> profiles = new ProfileIntervals<>();
@Inject @Inject
@ -109,7 +106,9 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
NSUpload nsUpload, NSUpload nsUpload,
FabricPrivacy fabricPrivacy, FabricPrivacy fabricPrivacy,
DateUtil dateUtil, DateUtil dateUtil,
UploadQueue uploadQueue UploadQueue uploadQueue,
DatabaseHelperInterface databaseHelper,
AppRepository repository
) { ) {
super(new PluginDescription() super(new PluginDescription()
.mainType(PluginType.TREATMENT) .mainType(PluginType.TREATMENT)
@ -133,6 +132,8 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
this.dateUtil = dateUtil; this.dateUtil = dateUtil;
this.nsUpload = nsUpload; this.nsUpload = nsUpload;
this.uploadQueue = uploadQueue; this.uploadQueue = uploadQueue;
this.databaseHelper = databaseHelper;
this.repository = repository;
} }
@Override @Override
@ -158,12 +159,6 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
.subscribe(event -> initializeProfileSwitchData(range()), .subscribe(event -> initializeProfileSwitchData(range()),
fabricPrivacy::logException fabricPrivacy::logException
)); ));
disposable.add(rxBus
.toObservable(EventTempTargetChange.class)
.observeOn(aapsSchedulers.getIo())
.subscribe(event -> initializeTempTargetData(range()),
fabricPrivacy::logException
));
disposable.add(rxBus disposable.add(rxBus
.toObservable(EventReloadTempBasalData.class) .toObservable(EventReloadTempBasalData.class)
.observeOn(aapsSchedulers.getIo()) .observeOn(aapsSchedulers.getIo())
@ -198,7 +193,6 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
initializeTempBasalData(range); initializeTempBasalData(range);
initializeTreatmentData(range); initializeTreatmentData(range);
initializeExtendedBolusData(range); initializeExtendedBolusData(range);
initializeTempTargetData(range);
initializeProfileSwitchData(range); initializeProfileSwitchData(range);
} }
@ -213,7 +207,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
private void initializeTempBasalData(long range) { private void initializeTempBasalData(long range) {
getAapsLogger().debug(LTag.DATATREATMENTS, "initializeTempBasalData"); getAapsLogger().debug(LTag.DATATREATMENTS, "initializeTempBasalData");
synchronized (tempBasals) { synchronized (tempBasals) {
tempBasals.reset().add(MainApp.getDbHelper().getTemporaryBasalsDataFromTime(DateUtil.now() - range, false)); tempBasals.reset().add(databaseHelper.getTemporaryBasalsDataFromTime(DateUtil.now() - range, false));
} }
} }
@ -221,22 +215,15 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
private void initializeExtendedBolusData(long range) { private void initializeExtendedBolusData(long range) {
getAapsLogger().debug(LTag.DATATREATMENTS, "initializeExtendedBolusData"); getAapsLogger().debug(LTag.DATATREATMENTS, "initializeExtendedBolusData");
synchronized (extendedBoluses) { synchronized (extendedBoluses) {
extendedBoluses.reset().add(MainApp.getDbHelper().getExtendedBolusDataFromTime(DateUtil.now() - range, false)); extendedBoluses.reset().add(databaseHelper.getExtendedBolusDataFromTime(DateUtil.now() - range, false));
} }
} }
private void initializeTempTargetData(long range) {
getAapsLogger().debug(LTag.DATATREATMENTS, "initializeTempTargetData");
synchronized (tempTargets) {
tempTargets.reset().add(MainApp.getDbHelper().getTemptargetsDataFromTime(DateUtil.now() - range, false));
}
}
private void initializeProfileSwitchData(long range) { private void initializeProfileSwitchData(long range) {
getAapsLogger().debug(LTag.DATATREATMENTS, "initializeProfileSwitchData"); getAapsLogger().debug(LTag.DATATREATMENTS, "initializeProfileSwitchData");
synchronized (profiles) { synchronized (profiles) {
profiles.reset().add(MainApp.getDbHelper().getProfileSwitchData(DateUtil.now() - range, false)); profiles.reset().add(databaseHelper.getProfileSwitchData(DateUtil.now() - range, false));
} }
} }
@ -401,11 +388,11 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
} else { } else {
uploadQueue.removeID("dbAdd", tempBasalId); uploadQueue.removeID("dbAdd", tempBasalId);
} }
MainApp.getDbHelper().delete(tempBasal); databaseHelper.delete(tempBasal);
} }
@Override @Override
public boolean isInHistoryExtendedBoluslInProgress() { public boolean isInHistoryExtendedBolusInProgress() {
return getExtendedBolusFromHistory(System.currentTimeMillis()) != null; //TODO: crosscheck here return getExtendedBolusFromHistory(System.currentTimeMillis()) != null; //TODO: crosscheck here
} }
@ -425,7 +412,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
PumpInterface pumpInterface = activePlugin.getActivePump(); PumpInterface pumpInterface = activePlugin.getActivePump();
synchronized (tempBasals) { synchronized (tempBasals) {
for (Integer pos = 0; pos < tempBasals.size(); pos++) { for (int pos = 0; pos < tempBasals.size(); pos++) {
TemporaryBasal t = tempBasals.get(pos); TemporaryBasal t = tempBasals.get(pos);
if (t.date > time) continue; if (t.date > time) continue;
IobTotal calc; IobTotal calc;
@ -576,7 +563,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
@Override @Override
public boolean addToHistoryExtendedBolus(ExtendedBolus extendedBolus) { public boolean addToHistoryExtendedBolus(ExtendedBolus extendedBolus) {
//log.debug("Adding new ExtentedBolus record" + extendedBolus.log()); //log.debug("Adding new ExtentedBolus record" + extendedBolus.log());
boolean newRecordCreated = MainApp.getDbHelper().createOrUpdate(extendedBolus); boolean newRecordCreated = databaseHelper.createOrUpdate(extendedBolus);
if (newRecordCreated) { if (newRecordCreated) {
if (extendedBolus.durationInMinutes == 0) { if (extendedBolus.durationInMinutes == 0) {
if (activePlugin.getActivePump().isFakingTempsByExtendedBoluses()) if (activePlugin.getActivePump().isFakingTempsByExtendedBoluses())
@ -610,7 +597,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
@Override @Override
public boolean addToHistoryTempBasal(TemporaryBasal tempBasal) { public boolean addToHistoryTempBasal(TemporaryBasal tempBasal) {
//log.debug("Adding new TemporaryBasal record" + tempBasal.toString()); //log.debug("Adding new TemporaryBasal record" + tempBasal.toString());
boolean newRecordCreated = MainApp.getDbHelper().createOrUpdate(tempBasal); boolean newRecordCreated = databaseHelper.createOrUpdate(tempBasal);
if (newRecordCreated) { if (newRecordCreated) {
if (tempBasal.durationInMinutes == 0) if (tempBasal.durationInMinutes == 0)
nsUpload.uploadTempBasalEnd(tempBasal.date, false, tempBasal.pumpId); nsUpload.uploadTempBasalEnd(tempBasal.date, false, tempBasal.pumpId);
@ -711,36 +698,6 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
return oldestTime; return oldestTime;
} }
@Nullable
@Override
public TempTarget getTempTargetFromHistory() {
synchronized (tempTargets) {
return tempTargets.getValueByInterval(System.currentTimeMillis());
}
}
@Nullable
@Override
public TempTarget getTempTargetFromHistory(long time) {
synchronized (tempTargets) {
return tempTargets.getValueByInterval(time);
}
}
@Override
public Intervals<TempTarget> getTempTargetsFromHistory() {
synchronized (tempTargets) {
return new OverlappingIntervals<>(tempTargets);
}
}
@Override
public void addToHistoryTempTarget(TempTarget tempTarget) {
//log.debug("Adding new TemporaryBasal record" + profileSwitch.log());
MainApp.getDbHelper().createOrUpdate(tempTarget);
nsUpload.uploadTempTarget(tempTarget, profileFunction);
}
@Override @Override
@Nullable @Nullable
public ProfileSwitch getProfileSwitchFromHistory(long time) { public ProfileSwitch getProfileSwitchFromHistory(long time) {
@ -760,8 +717,8 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
public void addToHistoryProfileSwitch(ProfileSwitch profileSwitch) { public void addToHistoryProfileSwitch(ProfileSwitch profileSwitch) {
//log.debug("Adding new TemporaryBasal record" + profileSwitch.log()); //log.debug("Adding new TemporaryBasal record" + profileSwitch.log());
rxBus.send(new EventDismissNotification(Notification.PROFILE_SWITCH_MISSING)); rxBus.send(new EventDismissNotification(Notification.PROFILE_SWITCH_MISSING));
MainApp.getDbHelper().createOrUpdate(profileSwitch); databaseHelper.createOrUpdate(profileSwitch);
nsUpload.uploadProfileSwitch(profileSwitch); nsUpload.uploadProfileSwitch(profileSwitch, profileSwitch.date);
} }
@Override @Override

View file

@ -0,0 +1,5 @@
package info.nightscout.androidaps.plugins.treatments.events
import info.nightscout.androidaps.events.EventUpdateGui
class EventTreatmentUpdateGui : EventUpdateGui()

View file

@ -10,38 +10,50 @@ import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import dagger.android.support.DaggerFragment import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Intervals 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.UserEntry.* import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.database.interfaces.end
import info.nightscout.androidaps.database.transactions.InvalidateTemporaryTargetTransaction
import info.nightscout.androidaps.databinding.TreatmentsTemptargetFragmentBinding import info.nightscout.androidaps.databinding.TreatmentsTemptargetFragmentBinding
import info.nightscout.androidaps.databinding.TreatmentsTemptargetItemBinding import info.nightscout.androidaps.databinding.TreatmentsTemptargetItemBinding
import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.db.TempTarget
import info.nightscout.androidaps.events.EventTempTargetChange import info.nightscout.androidaps.events.EventTempTargetChange
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.plugins.general.nsclient.UploadQueue import info.nightscout.androidaps.plugins.general.nsclient.UploadQueue
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart
import info.nightscout.androidaps.plugins.treatments.events.EventTreatmentUpdateGui
import info.nightscout.androidaps.plugins.treatments.fragments.TreatmentsTempTargetFragment.RecyclerViewAdapter.TempTargetsViewHolder import info.nightscout.androidaps.plugins.treatments.fragments.TreatmentsTempTargetFragment.RecyclerViewAdapter.TempTargetsViewHolder
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.buildHelper.BuildHelper import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.extensions.friendlyDescription
import info.nightscout.androidaps.utils.extensions.highValueToUnitsToString
import info.nightscout.androidaps.utils.extensions.lowValueToUnitsToString
import info.nightscout.androidaps.utils.extensions.toVisibility
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
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.Completable
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxkotlin.subscribeBy
import java.util.concurrent.TimeUnit
import javax.inject.Inject import javax.inject.Inject
class TreatmentsTempTargetFragment : DaggerFragment() { class TreatmentsTempTargetFragment : DaggerFragment() {
@Inject lateinit var activePlugin: ActivePluginProvider
@Inject lateinit var sp: SP @Inject lateinit var sp: SP
@Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var nsUpload: NSUpload @Inject lateinit var nsUpload: NSUpload
@ -51,9 +63,12 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
@Inject lateinit var buildHelper: BuildHelper @Inject lateinit var buildHelper: BuildHelper
@Inject lateinit var aapsSchedulers: AapsSchedulers @Inject lateinit var aapsSchedulers: AapsSchedulers
@Inject lateinit var uel: UserEntryLogger @Inject lateinit var uel: UserEntryLogger
@Inject lateinit var repository: AppRepository
private val disposable = CompositeDisposable() private val disposable = CompositeDisposable()
private val millsToThePast = T.days(30).msecs()
private var _binding: TreatmentsTemptargetFragmentBinding? = null private var _binding: TreatmentsTemptargetFragmentBinding? = null
// This property is only valid between onCreateView and // This property is only valid between onCreateView and
@ -66,29 +81,59 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
binding.recyclerview.setHasFixedSize(true) binding.recyclerview.setHasFixedSize(true)
binding.recyclerview.layoutManager = LinearLayoutManager(view.context) binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
binding.recyclerview.adapter = RecyclerViewAdapter(activePlugin.activeTreatments.tempTargetsFromHistory)
binding.refreshFromNightscout.setOnClickListener { binding.refreshFromNightscout.setOnClickListener {
context?.let { context -> context?.let { context ->
OKDialog.showConfirmation(context, resourceHelper.gs(R.string.refresheventsfromnightscout) + " ?", { OKDialog.showConfirmation(context, resourceHelper.gs(R.string.refresheventsfromnightscout) + " ?", {
uel.log(Action.TT_NS_REFRESH) uel.log(Action.TT_NS_REFRESH)
MainApp.getDbHelper().resetTempTargets() disposable += Completable.fromAction { repository.deleteAllTempTargetEntries() }
.subscribeOn(aapsSchedulers.io)
.observeOn(aapsSchedulers.main)
.subscribeBy(
onError = { aapsLogger.error("Error removing entries", it) },
onComplete = { rxBus.send(EventTempTargetChange()) }
)
rxBus.send(EventNSClientRestart()) rxBus.send(EventNSClientRestart())
}) })
} }
} }
val nsUploadOnly = sp.getBoolean(R.string.key_ns_upload_only, true) || !buildHelper.isEngineeringMode() val nsUploadOnly = sp.getBoolean(R.string.key_ns_upload_only, true) || !buildHelper.isEngineeringMode()
if (nsUploadOnly) binding.refreshFromNightscout.visibility = View.GONE if (nsUploadOnly) binding.refreshFromNightscout.visibility = View.INVISIBLE
binding.showInvalidated.setOnCheckedChangeListener { _, _ ->
rxBus.send(EventTreatmentUpdateGui())
}
}
fun swapAdapter() {
val now = System.currentTimeMillis()
if (binding.showInvalidated.isChecked)
repository
.getTemporaryTargetDataIncludingInvalidFromTime(now - millsToThePast, false)
.observeOn(aapsSchedulers.main)
.subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) }
else
repository
.getTemporaryTargetDataFromTime(now - millsToThePast, false)
.observeOn(aapsSchedulers.main)
.subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) }
} }
@Synchronized @Synchronized
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
disposable.add(rxBus swapAdapter()
disposable += rxBus
.toObservable(EventTempTargetChange::class.java) .toObservable(EventTempTargetChange::class.java)
.observeOn(aapsSchedulers.main) .observeOn(aapsSchedulers.io)
.subscribe({ updateGui() }, fabricPrivacy::logException) .debounce(1L, TimeUnit.SECONDS)
) .subscribe({ swapAdapter() }, fabricPrivacy::logException)
updateGui()
disposable += rxBus
.toObservable(EventTreatmentUpdateGui::class.java) // TODO join with above
.observeOn(aapsSchedulers.io)
.debounce(1L, TimeUnit.SECONDS)
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
} }
@Synchronized @Synchronized
@ -100,17 +145,14 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
@Synchronized @Synchronized
override fun onDestroyView() { override fun onDestroyView() {
super.onDestroyView() super.onDestroyView()
binding.recyclerview.adapter = null // avoid leaks
_binding = null _binding = null
} }
private fun updateGui() { inner class RecyclerViewAdapter internal constructor(private var tempTargetList: List<TemporaryTarget>) : RecyclerView.Adapter<TempTargetsViewHolder>() {
if (_binding == null) return
binding.recyclerview.swapAdapter(RecyclerViewAdapter(activePlugin.activeTreatments.tempTargetsFromHistory), false)
}
inner class RecyclerViewAdapter internal constructor(var tempTargetList: Intervals<TempTarget>) : RecyclerView.Adapter<TempTargetsViewHolder>() { private val dbRecord = repository.getTemporaryTargetActiveAt(dateUtil._now()).blockingGet()
private val currentlyActiveTarget = if (dbRecord is ValueWrapper.Existing) dbRecord.value else null
var currentlyActiveTarget: TempTarget? = tempTargetList.getValueByInterval(System.currentTimeMillis())
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): TempTargetsViewHolder = override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): TempTargetsViewHolder =
TempTargetsViewHolder(LayoutInflater.from(viewGroup.context).inflate(R.layout.treatments_temptarget_item, viewGroup, false)) TempTargetsViewHolder(LayoutInflater.from(viewGroup.context).inflate(R.layout.treatments_temptarget_item, viewGroup, false))
@ -118,35 +160,25 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: TempTargetsViewHolder, position: Int) { override fun onBindViewHolder(holder: TempTargetsViewHolder, position: Int) {
val units = profileFunction.getUnits() val units = profileFunction.getUnits()
val tempTarget = tempTargetList.getReversed(position) val tempTarget = tempTargetList[position]
holder.binding.ph.visibility = if (tempTarget.source == Source.PUMP) View.VISIBLE else View.GONE holder.binding.ns.visibility = (tempTarget.interfaceIDs.nightscoutId != null).toVisibility()
holder.binding.ns.visibility = if (NSUpload.isIdValid(tempTarget._id)) View.VISIBLE else View.GONE holder.binding.invalid.visibility = tempTarget.isValid.not().toVisibility()
if (!tempTarget.isEndingEvent) { holder.binding.remove.visibility = tempTarget.isValid.toVisibility()
holder.binding.date.text = dateUtil.dateAndTimeString(tempTarget.date) + " - " + dateUtil.timeString(tempTarget.originalEnd()) holder.binding.date.text = dateUtil.dateAndTimeString(tempTarget.timestamp) + " - " + dateUtil.timeString(tempTarget.end)
holder.binding.duration.text = resourceHelper.gs(R.string.format_mins, tempTarget.durationInMinutes) holder.binding.duration.text = resourceHelper.gs(R.string.format_mins, T.msecs(tempTarget.duration).mins())
holder.binding.low.text = tempTarget.lowValueToUnitsToString(units) holder.binding.low.text = tempTarget.lowValueToUnitsToString(units)
holder.binding.high.text = tempTarget.highValueToUnitsToString(units) holder.binding.high.text = tempTarget.highValueToUnitsToString(units)
holder.binding.reason.text = tempTarget.reason holder.binding.reason.text = tempTarget.reason.text
} else { holder.binding.date.setTextColor(
holder.binding.date.text = dateUtil.dateAndTimeString(tempTarget.date) when {
holder.binding.duration.setText(R.string.cancel) tempTarget.id == currentlyActiveTarget?.id -> resourceHelper.gc(R.color.colorActive)
holder.binding.low.text = "" tempTarget.timestamp > DateUtil.now() -> resourceHelper.gc(R.color.colorScheduled)
holder.binding.high.text = "" else -> holder.binding.reasonColon.currentTextColor
holder.binding.reason.text = "" })
holder.binding.reasonLabel.text = ""
holder.binding.reasonColon.text = ""
}
if (tempTarget.isInProgress && tempTarget === currentlyActiveTarget) {
holder.binding.date.setTextColor(resourceHelper.gc(R.color.colorActive))
} else if (tempTarget.date > DateUtil.now()) {
holder.binding.date.setTextColor(resourceHelper.gc(R.color.colorScheduled))
} else {
holder.binding.date.setTextColor(holder.binding.reasonColon.currentTextColor)
}
holder.binding.remove.tag = tempTarget holder.binding.remove.tag = tempTarget
} }
override fun getItemCount(): Int = tempTargetList.size() override fun getItemCount(): Int = tempTargetList.size
inner class TempTargetsViewHolder(view: View) : RecyclerView.ViewHolder(view) { inner class TempTargetsViewHolder(view: View) : RecyclerView.ViewHolder(view) {
@ -154,20 +186,23 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
init { init {
binding.remove.setOnClickListener { v: View -> binding.remove.setOnClickListener { v: View ->
val tempTarget = v.tag as TempTarget val tempTarget = v.tag as TemporaryTarget
context?.let { context -> context?.let { context ->
OKDialog.showConfirmation(context, resourceHelper.gs(R.string.removerecord), OKDialog.showConfirmation(context, resourceHelper.gs(R.string.removerecord),
""" """
${resourceHelper.gs(R.string.careportal_temporarytarget)}: ${tempTarget.friendlyDescription(profileFunction.getUnits(), resourceHelper)} ${resourceHelper.gs(R.string.careportal_temporarytarget)}: ${tempTarget.friendlyDescription(profileFunction.getUnits(), resourceHelper)}
${dateUtil.dateAndTimeString(tempTarget.date)} ${dateUtil.dateAndTimeString(tempTarget.timestamp)}
""".trimIndent(), """.trimIndent(),
{ _: DialogInterface?, _: Int -> { _: DialogInterface?, _: Int ->
uel.log(Action.TT_REMOVED, ValueWithUnit(tempTarget.reason, Units.TT_Reason), ValueWithUnit(tempTarget.date, Units.Timestamp), ValueWithUnit(tempTarget.low, Units.Mg_Dl), ValueWithUnit(tempTarget.high, Units.Mg_Dl), ValueWithUnit(tempTarget.durationInMinutes, Units.M)) uel.log(Action.TT_REMOVED, ValueWithUnit(tempTarget.reason, Units.TT_Reason), ValueWithUnit(tempTarget.date, Units.Timestamp), ValueWithUnit(tempTarget.low, Units.Mg_Dl), ValueWithUnit(tempTarget.high, Units.Mg_Dl), ValueWithUnit(tempTarget.durationInMinutes, Units.M))
val id = tempTarget._id disposable += repository.runTransactionForResult(InvalidateTemporaryTargetTransaction(tempTarget.id))
if (NSUpload.isIdValid(id)) nsUpload.removeCareportalEntryFromNS(id) .subscribe({
else uploadQueue.removeID("dbAdd", id) val id = tempTarget.interfaceIDs.nightscoutId
if (NSUpload.isIdValid(id)) nsUpload.removeCareportalEntryFromNS(id)
MainApp.getDbHelper().delete(tempTarget) else uploadQueue.removeID("dbAdd", tempTarget.timestamp.toString())
}, {
aapsLogger.error(LTag.BGSOURCE, "Error while invalidating temporary target", it)
})
}, null) }, null)
} }
} }

View file

@ -2,6 +2,9 @@ package info.nightscout.androidaps.setupwizard
import android.Manifest import android.Manifest
import android.content.Context import android.content.Context
import android.content.Intent
import android.net.Uri
import android.provider.Settings
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Config import info.nightscout.androidaps.Config
@ -111,6 +114,17 @@ class SWDefinition @Inject constructor(
.updateDelay(5) .updateDelay(5)
.label(R.string.high_mark) .label(R.string.high_mark)
.comment(R.string.high_mark_comment)) .comment(R.string.high_mark_comment))
private val screenPermissionWindow = SWScreen(injector, R.string.permission)
.skippable(false)
.add(SWInfoText(injector)
.label(resourceHelper.gs(R.string.needsystemwindowpermission)))
.add(SWBreak(injector))
.add(SWButton(injector)
.text(R.string.askforpermission)
.visibility { !Settings.canDrawOverlays(activity) }
.action { activity.startActivity(Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + activity.packageName))) })
.visibility { !Settings.canDrawOverlays(activity) }
.validator { Settings.canDrawOverlays(activity) }
private val screenPermissionBattery = SWScreen(injector, R.string.permission) private val screenPermissionBattery = SWScreen(injector, R.string.permission)
.skippable(false) .skippable(false)
.add(SWInfoText(injector) .add(SWInfoText(injector)
@ -377,6 +391,7 @@ class SWDefinition @Inject constructor(
//.add(screenLanguage) //.add(screenLanguage)
.add(screenEula) .add(screenEula)
.add(if (isRunningTest()) null else screenPermissionBattery) // cannot mock ask battery optimization .add(if (isRunningTest()) null else screenPermissionBattery) // cannot mock ask battery optimization
.add(screenPermissionWindow)
.add(screenPermissionBt) .add(screenPermissionBt)
.add(screenPermissionStore) .add(screenPermissionStore)
.add(screenMasterPassword) .add(screenMasterPassword)
@ -406,6 +421,7 @@ class SWDefinition @Inject constructor(
//.add(screenLanguage) //.add(screenLanguage)
.add(screenEula) .add(screenEula)
.add(if (isRunningTest()) null else screenPermissionBattery) // cannot mock ask battery optimization .add(if (isRunningTest()) null else screenPermissionBattery) // cannot mock ask battery optimization
.add(screenPermissionWindow)
.add(screenPermissionBt) .add(screenPermissionBt)
.add(screenPermissionStore) .add(screenPermissionStore)
.add(screenMasterPassword) .add(screenMasterPassword)
@ -430,6 +446,7 @@ class SWDefinition @Inject constructor(
//.add(screenLanguage) //.add(screenLanguage)
.add(screenEula) .add(screenEula)
.add(if (isRunningTest()) null else screenPermissionBattery) // cannot mock ask battery optimization .add(if (isRunningTest()) null else screenPermissionBattery) // cannot mock ask battery optimization
.add(screenPermissionWindow)
.add(screenPermissionStore) .add(screenPermissionStore)
.add(screenMasterPassword) .add(screenMasterPassword)
.add(screenImport) .add(screenImport)

View file

@ -96,16 +96,16 @@ class HardLimits @Inject constructor(
} }
// safety checks // safety checks
fun checkOnlyHardLimits(value: Double, valueName: String?, lowLimit: Double, highLimit: Double): Boolean { fun checkOnlyHardLimits(value: Double, valueName: Int, lowLimit: Double, highLimit: Double): Boolean {
return value == verifyHardLimits(value, valueName, lowLimit, highLimit) return value == verifyHardLimits(value, valueName, lowLimit, highLimit)
} }
fun verifyHardLimits(value: Double, valueName: String?, lowLimit: Double, highLimit: Double): Double { fun verifyHardLimits(value: Double, valueName: Int, lowLimit: Double, highLimit: Double): Double {
var newvalue = value var newvalue = value
if (newvalue < lowLimit || newvalue > highLimit) { if (newvalue < lowLimit || newvalue > highLimit) {
newvalue = Math.max(newvalue, lowLimit) newvalue = Math.max(newvalue, lowLimit)
newvalue = Math.min(newvalue, highLimit) newvalue = Math.min(newvalue, highLimit)
var msg = String.format(resourceHelper.gs(R.string.valueoutofrange), valueName) var msg = String.format(resourceHelper.gs(R.string.valueoutofrange), resourceHelper.gs(valueName))
msg += ".\n" msg += ".\n"
msg += String.format(resourceHelper.gs(R.string.valuelimitedto), value, newvalue) msg += String.format(resourceHelper.gs(R.string.valuelimitedto), value, newvalue)
aapsLogger.error(msg) aapsLogger.error(msg)

View file

@ -5,8 +5,10 @@ import android.text.Spanned
import android.util.LongSparseArray import android.util.LongSparseArray
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.db.TDD import info.nightscout.androidaps.db.TDD
import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.ActivePluginProvider
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.logging.LTag import info.nightscout.androidaps.logging.LTag
@ -31,15 +33,17 @@ class TddCalculator @Inject constructor(
rxBus: RxBusWrapper, rxBus: RxBusWrapper,
resourceHelper: ResourceHelper, resourceHelper: ResourceHelper,
context: Context, context: Context,
private val aapsSchedulers: AapsSchedulers, aapsSchedulers: AapsSchedulers,
private val sp: SP, sp: SP,
private val activePlugin: ActivePluginProvider, private val activePlugin: ActivePluginProvider,
private val profileFunction: ProfileFunction, private val profileFunction: ProfileFunction,
fabricPrivacy: FabricPrivacy, fabricPrivacy: FabricPrivacy,
nsUpload: NSUpload, nsUpload: NSUpload,
private val dateUtil: DateUtil, private val dateUtil: DateUtil,
uploadQueue: UploadQueue uploadQueue: UploadQueue,
) : TreatmentsPlugin(injector, aapsLogger, rxBus, aapsSchedulers, resourceHelper, context, sp, profileFunction, activePlugin, nsUpload, fabricPrivacy, dateUtil, uploadQueue) { databaseHelper: DatabaseHelperInterface,
repository: AppRepository
) : TreatmentsPlugin(injector, aapsLogger, rxBus, aapsSchedulers, resourceHelper, context, sp, profileFunction, activePlugin, nsUpload, fabricPrivacy, dateUtil, uploadQueue, databaseHelper, repository) {
init { init {
service = TreatmentService(injector) // plugin is not started service = TreatmentService(injector) // plugin is not started
@ -113,6 +117,7 @@ class TddCalculator @Inject constructor(
) )
} }
@Suppress("SameParameterValue")
private fun toText(tdds: LongSparseArray<TDD>, includeCarbs: Boolean): String { private fun toText(tdds: LongSparseArray<TDD>, includeCarbs: Boolean): String {
var t = "" var t = ""
for (i in 0 until tdds.size()) { for (i in 0 until tdds.size()) {

View file

@ -10,10 +10,10 @@ import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.ErrorHelperActivity import info.nightscout.androidaps.activities.ErrorHelperActivity
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.database.entities.TemporaryTarget
import info.nightscout.androidaps.database.entities.UserEntry.* import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.db.CareportalEvent import info.nightscout.androidaps.db.CareportalEvent
import info.nightscout.androidaps.db.Source import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.db.TempTarget
import info.nightscout.androidaps.events.EventRefreshOverview import info.nightscout.androidaps.events.EventRefreshOverview
import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
@ -107,7 +107,7 @@ class BolusWizard @Inject constructor(
// Input // Input
lateinit var profile: Profile lateinit var profile: Profile
lateinit var profileName: String lateinit var profileName: String
var tempTarget: TempTarget? = null var tempTarget: TemporaryTarget? = null
var carbs: Int = 0 var carbs: Int = 0
var cob: Double = 0.0 var cob: Double = 0.0
var bg: Double = 0.0 var bg: Double = 0.0
@ -127,7 +127,7 @@ class BolusWizard @Inject constructor(
@JvmOverloads @JvmOverloads
fun doCalc(profile: Profile, fun doCalc(profile: Profile,
profileName: String, profileName: String,
tempTarget: TempTarget?, tempTarget: TemporaryTarget?,
carbs: Int, carbs: Int,
cob: Double, cob: Double,
bg: Double, bg: Double,
@ -169,8 +169,8 @@ class BolusWizard @Inject constructor(
targetBGLow = Profile.fromMgdlToUnits(profile.targetLowMgdl, profileFunction.getUnits()) targetBGLow = Profile.fromMgdlToUnits(profile.targetLowMgdl, profileFunction.getUnits())
targetBGHigh = Profile.fromMgdlToUnits(profile.targetHighMgdl, profileFunction.getUnits()) targetBGHigh = Profile.fromMgdlToUnits(profile.targetHighMgdl, profileFunction.getUnits())
if (useTT && tempTarget != null) { if (useTT && tempTarget != null) {
targetBGLow = Profile.fromMgdlToUnits(tempTarget.low, profileFunction.getUnits()) targetBGLow = Profile.fromMgdlToUnits(tempTarget.lowTarget, profileFunction.getUnits())
targetBGHigh = Profile.fromMgdlToUnits(tempTarget.high, profileFunction.getUnits()) targetBGHigh = Profile.fromMgdlToUnits(tempTarget.highTarget, profileFunction.getUnits())
} }
if (useBg && bg > 0) { if (useBg && bg > 0) {
bgDiff = when { bgDiff = when {

View file

@ -3,6 +3,8 @@ package info.nightscout.androidaps.utils.wizard
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.database.entities.GlucoseValue import info.nightscout.androidaps.database.entities.GlucoseValue
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
@ -28,11 +30,14 @@ class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjec
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin @Inject lateinit var treatmentsPlugin: TreatmentsPlugin
@Inject lateinit var loopPlugin: LoopPlugin @Inject lateinit var loopPlugin: LoopPlugin
@Inject lateinit var iobCobCalculatorPlugin: IobCobCalculatorPlugin @Inject lateinit var iobCobCalculatorPlugin: IobCobCalculatorPlugin
@Inject lateinit var repository: AppRepository
@Inject lateinit var dateUtil: DateUtil
lateinit var storage: JSONObject lateinit var storage: JSONObject
var position: Int = -1 var position: Int = -1
companion object { companion object {
const val YES = 0 const val YES = 0
const val NO = 1 const val NO = 1
private const val POSITIVE_ONLY = 2 private const val POSITIVE_ONLY = 2
@ -73,7 +78,8 @@ class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjec
fun isActive(): Boolean = Profile.secondsFromMidnight() >= validFrom() && Profile.secondsFromMidnight() <= validTo() fun isActive(): Boolean = Profile.secondsFromMidnight() >= validFrom() && Profile.secondsFromMidnight() <= validTo()
fun doCalc(profile: Profile, profileName: String, lastBG: GlucoseValue, _synchronized: Boolean): BolusWizard { fun doCalc(profile: Profile, profileName: String, lastBG: GlucoseValue, _synchronized: Boolean): BolusWizard {
val tempTarget = treatmentsPlugin.tempTargetFromHistory val dbRecord = repository.getTemporaryTargetActiveAt(dateUtil._now()).blockingGet()
val tempTarget = if (dbRecord is ValueWrapper.Existing) dbRecord.value else null
//BG //BG
var bg = 0.0 var bg = 0.0
if (useBG() == YES) { if (useBG() == YES) {
@ -131,7 +137,7 @@ class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjec
fun validFrom(): Int = safeGetInt(storage, "validFrom") fun validFrom(): Int = safeGetInt(storage, "validFrom")
fun validTo(): Int = safeGetInt(storage, "validTo") private fun validTo(): Int = safeGetInt(storage, "validTo")
fun useBG(): Int = safeGetInt(storage, "useBG", YES) fun useBG(): Int = safeGetInt(storage, "useBG", YES)

View file

@ -1,18 +1,45 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:orientation="vertical"
tools:context="info.nightscout.androidaps.plugins.treatments.fragments.TreatmentsTempTargetFragment"> tools:context="info.nightscout.androidaps.plugins.treatments.fragments.TreatmentsTempTargetFragment">
<info.nightscout.androidaps.utils.ui.SingleClickButton <LinearLayout
android:id="@+id/refresh_from_nightscout"
style="?android:attr/buttonStyle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:orientation="horizontal">
android:drawableStart="@drawable/ic_refresh"
android:text="@string/refresheventsfromnightscout" /> <info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/refresh_from_nightscout"
style="?android:attr/buttonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_weight="1"
android:drawableStart="@drawable/ic_refresh"
android:text="@string/refresheventsfromnightscout"
tools:visibility="visible" />
<CheckBox
android:id="@+id/show_invalidated"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|center_vertical"
android:checked="false"
android:paddingEnd="5dp"
tools:ignore="RtlSymmetry" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:contentDescription="@string/show_calculation"
app:srcCompat="@drawable/ic_visibility" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerview" android:id="@+id/recyclerview"

View file

@ -80,15 +80,6 @@
android:layout_weight="1" android:layout_weight="1"
android:text="" /> android:text="" />
<TextView
android:id="@+id/ph"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:text="PH"
android:textColor="@color/colorSetTempButton"
tools:ignore="HardcodedText" />
<TextView <TextView
android:id="@+id/ns" android:id="@+id/ns"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -134,6 +125,15 @@
android:textStyle="bold" android:textStyle="bold"
tools:ignore="HardcodedText,RtlSymmetry" /> tools:ignore="HardcodedText,RtlSymmetry" />
<TextView
android:id="@+id/invalid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:text="@string/invalid"
android:textColor="@android:color/holo_red_light" />
<TextView <TextView
android:id="@+id/remove" android:id="@+id/remove"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -148,10 +148,10 @@
<View <View
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="2dip" android:layout_height="2dip"
android:layout_marginBottom="5dp"
android:layout_marginLeft="5dp" android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_marginTop="5dp" android:layout_marginTop="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:background="@color/list_delimiter" /> android:background="@color/list_delimiter" />
</LinearLayout> </LinearLayout>

View file

@ -901,4 +901,8 @@ Unerwartetes Verhalten.</string>
<string name="cannula">Kanüle</string> <string name="cannula">Kanüle</string>
<string name="userentry">Benutzereingabe</string> <string name="userentry">Benutzereingabe</string>
<string name="common_values">Verwende die Werte der größten Mahlzeit, die Du normalerweise zu Dir nimmst\n</string> <string name="common_values">Verwende die Werte der größten Mahlzeit, die Du normalerweise zu Dir nimmst\n</string>
<string name="summary_email_for_crash_report">Diese E-Mail-Adresse wird an Absturzberichte angehängt, so dass wir Dich in dringenden Fällen kontaktieren können. Angabe ist optional.</string>
<string name="email_address">EMailAdresse</string>
<string name="privacy_settings">Privatsphäre-Einstellungen</string>
<string name="privacy_summary">Du kannst optional eine E-Mail-Adresse angeben, wenn Du bei Absturzberichten kontaktiert werden möchtest. Dies ist keine Automatik, Du wirst von den Entwicklern in gefährlichen Situationen kontaktiert. </string>
</resources> </resources>

View file

@ -8,6 +8,7 @@
<string name="dia_meaningisequaltodiapump">Dacă considerați ca fiind bună valoarea DIA pe care aţi utilizat-o în pompa dumneavoastră înainte de AndroidAPS și a funcţionat bine, nu este necesară modificarea acesteia atunci când începeţi să faceţi looping.</string> <string name="dia_meaningisequaltodiapump">Dacă considerați ca fiind bună valoarea DIA pe care aţi utilizat-o în pompa dumneavoastră înainte de AndroidAPS și a funcţionat bine, nu este necesară modificarea acesteia atunci când începeţi să faceţi looping.</string>
<string name="dia_valuemustbedetermined">Ar trebui să determinaţi dumneavoastră valoarea corespunzătoare pentru DIA.</string> <string name="dia_valuemustbedetermined">Ar trebui să determinaţi dumneavoastră valoarea corespunzătoare pentru DIA.</string>
<string name="hypott_label">Țintă-Temporară Hipoglicemie</string> <string name="hypott_label">Țintă-Temporară Hipoglicemie</string>
<string name="hypott_whenhypott">Care este motivul principal pentru a stabili o țintă temporară de hipoglicemie?</string>
<string name="hypott_wrongbasal">Pentru a corecta hipoglicemiile cauzate de setările de rată bazală incorecte.</string> <string name="hypott_wrongbasal">Pentru a corecta hipoglicemiile cauzate de setările de rată bazală incorecte.</string>
<string name="hypott_preventoversmb">Pentru a preveni supracorectarea de către AndroidAPS a unei creșteri a glicemiei cauzată de carbohidrații cu acțiune rapidă utilizați pentru a trata o hipoglicemie.</string> <string name="hypott_preventoversmb">Pentru a preveni supracorectarea de către AndroidAPS a unei creșteri a glicemiei cauzată de carbohidrații cu acțiune rapidă utilizați pentru a trata o hipoglicemie.</string>
<string name="hypott_exercise">Pentru corectarea unui episod hipoglicemic indus ca rezultat al exerciţiului fizic.</string> <string name="hypott_exercise">Pentru corectarea unui episod hipoglicemic indus ca rezultat al exerciţiului fizic.</string>
@ -40,12 +41,14 @@
<string name="noisycgm_label">Citiri zgomotoase ale CGM</string> <string name="noisycgm_label">Citiri zgomotoase ale CGM</string>
<string name="noisycgm_whattodo">Ce ar trebui făcut dacă valorile CGM sunt nesigure?</string> <string name="noisycgm_whattodo">Ce ar trebui făcut dacă valorile CGM sunt nesigure?</string>
<string name="noisycgm_nothing">Nu faceți nimic - AndroidAPS se va ocupa de acest lucru.</string> <string name="noisycgm_nothing">Nu faceți nimic - AndroidAPS se va ocupa de acest lucru.</string>
<string name="noisycgm_pause">Dezactivați bucla închisă pentru a evita o posibilă supradozare sau subdozare.</string>
<string name="noisycgm_replacesensor">Înlocuiți senzorii zgomotoși sau inexacti.</string> <string name="noisycgm_replacesensor">Înlocuiți senzorii zgomotoși sau inexacti.</string>
<string name="noisycgm_checksmoothing">Verificaţi că aplicaţia dumneavoastră CGM furnizează date filtrate.</string> <string name="noisycgm_checksmoothing">Verificaţi că aplicaţia dumneavoastră CGM furnizează date filtrate.</string>
<string name="noisycgm_hint1">https://androidaps.readthedocs.io/en/latest/EN/Usage/Smoothing-Blood-Glucose-Data-in-xDrip.html#smoothing-blood-glucose-data</string> <string name="noisycgm_hint1">https://androidaps.readthedocs.io/en/latest/EN/Usage/Smoothing-Blood-Glucose-Data-in-xDrip.html#smoothing-blood-glucose-data</string>
<string name="exerciseprofile_label">Exercițiu și Profiluri</string> <string name="exerciseprofile_label">Exercițiu și Profiluri</string>
<string name="exerciseprofile_whattodo">Cum poți folosi profilurile pentru a ajuta sistemul să facă față exercițiilor aerobe?</string> <string name="exerciseprofile_whattodo">Cum poți folosi profilurile pentru a ajuta sistemul să facă față exercițiilor aerobe?</string>
<string name="exerciseprofile_switchprofilebelow100">Faceți un schimb de profil la mai puțin de 100%.</string> <string name="exerciseprofile_switchprofilebelow100">Faceți un schimb de profil la mai puțin de 100%.</string>
<string name="exerciseprofile_switchprofileabove100">Faceți un schimb de profil de peste 100%.</string>
<string name="exerciseprofile_leaveat100">Lasă profilul setat la 100%.</string> <string name="exerciseprofile_leaveat100">Lasă profilul setat la 100%.</string>
<string name="exerciseprofile_suspendloop">Suspendă bucla.</string> <string name="exerciseprofile_suspendloop">Suspendă bucla.</string>
<string name="exerciseprofile_hint1">https://androidaps.readthedocs.io/en/latest/EN/Usage/temptarget.html#activity-temp-target</string> <string name="exerciseprofile_hint1">https://androidaps.readthedocs.io/en/latest/EN/Usage/temptarget.html#activity-temp-target</string>

View file

@ -235,6 +235,8 @@
<string name="mealbolus">Masă</string> <string name="mealbolus">Masă</string>
<string name="correctionbous">Corecție</string> <string name="correctionbous">Corecție</string>
<string name="actions">Acțiuni</string> <string name="actions">Acțiuni</string>
<string name="ns_upload_only">(E PERICULOS SĂ DEZACTIVEZI) Doar încărcare în NS</string>
<string name="ns_upload_only_summary">Numai încărcare NS (sincronizare dezactivata). Nu este eficient pe SGV (rom. valori de glicemie din senzor) dacă nu este selectată o sursă locală ca xDrip. Nu este eficient pe Profiluri dacă sunt utilizate cele din NS.\n!!! ATENȚIE !!! Dezactivarea acestei opțiuni poate determina disfuncționalități și supradozaj cu insulină dacă oricare dintre componentele dumneavoastră (AAPS, NS, xDrip) este configurată greșit. Urmăriți cu atenție dacă datele afișate de AAPS se potrivesc cu starea pompei!</string>
<string name="pumpNotInitialized">Pompa nu este inițializată!</string> <string name="pumpNotInitialized">Pompa nu este inițializată!</string>
<string name="primefill">Pregătire/umplere</string> <string name="primefill">Pregătire/umplere</string>
<string name="fillwarning">Asigurați-vă că aveți cantitatea specificată de instrucțiunile setului de infuzie!</string> <string name="fillwarning">Asigurați-vă că aveți cantitatea specificată de instrucțiunile setului de infuzie!</string>
@ -286,6 +288,7 @@
<string name="smscommunicator_shortname">SMS</string> <string name="smscommunicator_shortname">SMS</string>
<string name="short_tabtitles">Scurtează titlurile secțiunilor</string> <string name="short_tabtitles">Scurtează titlurile secțiunilor</string>
<string name="always_use_shortavg">Folosește întotdeauna media scurtă a diferenței în locul diferenței simple</string> <string name="always_use_shortavg">Folosește întotdeauna media scurtă a diferenței în locul diferenței simple</string>
<string name="always_use_shortavg_summary">Folositor când datele de la surse nefiltrate precum xDrip+ devin \'\'zgomotoase\".</string>
<string name="profile">Profil</string> <string name="profile">Profil</string>
<string name="openapsama_max_daily_safety_multiplier_summary">Valoare implicită: 3\nAceasta este o setare de critică de securitate a OpenAPS. Asta înseamnă că se limitează bazala lade 3x valoarea maximă a bazalelor tale.Cel mai probabil nu veți schimba această valoare, dar trebuie să țineți cont de ce se discută despre “3x max zilnic; 4x curent” ca valori de siguranță.</string> <string name="openapsama_max_daily_safety_multiplier_summary">Valoare implicită: 3\nAceasta este o setare de critică de securitate a OpenAPS. Asta înseamnă că se limitează bazala lade 3x valoarea maximă a bazalelor tale.Cel mai probabil nu veți schimba această valoare, dar trebuie să țineți cont de ce se discută despre “3x max zilnic; 4x curent” ca valori de siguranță.</string>
<string name="openapsama_current_basal_safety_multiplier_summary">Valoare implicită: 4\nAceasta este cealaltă jumătate a cheii de siguranță a OpenAPS și cealaltă jumătate a \"3x max zilnic; 4x curent\" al setărilor de siguranță.Aceasta înseamnă că bazala dumneavoastră, indiferent de bazala maximă configurată în pompă, nu poate fi mai mare de acest număr înmulțit cu nivelul curent al bazalei active. Această limitare este impusă pentru a evita posibilitatea de a intra pe un teritoriu periculos prin setarea unei bazale maxime excesiv de mari înainte de a înțelege funcționarea algoritmului. Din nou, valoarea implictă este 4x; majoritatea oamenilor nu vor trebui să ajusteze această valoare și vor modifica, mai degrabă, alte valori dacă vor simți că această valoare le stă în cale.</string> <string name="openapsama_current_basal_safety_multiplier_summary">Valoare implicită: 4\nAceasta este cealaltă jumătate a cheii de siguranță a OpenAPS și cealaltă jumătate a \"3x max zilnic; 4x curent\" al setărilor de siguranță.Aceasta înseamnă că bazala dumneavoastră, indiferent de bazala maximă configurată în pompă, nu poate fi mai mare de acest număr înmulțit cu nivelul curent al bazalei active. Această limitare este impusă pentru a evita posibilitatea de a intra pe un teritoriu periculos prin setarea unei bazale maxime excesiv de mari înainte de a înțelege funcționarea algoritmului. Din nou, valoarea implictă este 4x; majoritatea oamenilor nu vor trebui să ajusteze această valoare și vor modifica, mai degrabă, alte valori dacă vor simți că această valoare le stă în cale.</string>
@ -394,6 +397,7 @@
<string name="basal_shortname">R_BAZ</string> <string name="basal_shortname">R_BAZ</string>
<string name="deviation_shortname">DEV</string> <string name="deviation_shortname">DEV</string>
<string name="activity_shortname">ACT</string> <string name="activity_shortname">ACT</string>
<string name="bgi_shortname">-BGI</string>
<string name="abs_insulin_shortname">ABS</string> <string name="abs_insulin_shortname">ABS</string>
<string name="devslope_shortname">DEVSLOPE</string> <string name="devslope_shortname">DEVSLOPE</string>
<string name="nav_about">Despre</string> <string name="nav_about">Despre</string>
@ -467,6 +471,7 @@
<string name="activity_target">țintă activitate</string> <string name="activity_target">țintă activitate</string>
<string name="hypo_duration">durată țintă</string> <string name="hypo_duration">durată țintă</string>
<string name="hypo_target">țintă hipo</string> <string name="hypo_target">țintă hipo</string>
<string name="reuse_profile_pct_hours">Reutilizare %1$d%% %2$dh</string>
<string name="wearcontrol_title">Controlare din ceas</string> <string name="wearcontrol_title">Controlare din ceas</string>
<string name="wearcontrol_summary">Setare Ținte-Temporare și se introduc Tratamente din ceas.</string> <string name="wearcontrol_summary">Setare Ținte-Temporare și se introduc Tratamente din ceas.</string>
<string name="food">Mâncare</string> <string name="food">Mâncare</string>
@ -564,6 +569,7 @@
<string name="ns_autobackfill_summary">Autocompletează valorile glicemiei lipsă din NS</string> <string name="ns_autobackfill_summary">Autocompletează valorile glicemiei lipsă din NS</string>
<string name="loop_smbsetbypump_label">SMB setat de pompă</string> <string name="loop_smbsetbypump_label">SMB setat de pompă</string>
<string name="overview_show_activity">Activitate</string> <string name="overview_show_activity">Activitate</string>
<string name="overview_show_bgi">Impactul glicemiei</string>
<string name="overview_show_sensitivity">Sensibilitate</string> <string name="overview_show_sensitivity">Sensibilitate</string>
<string name="overview_show_deviations">Deviații</string> <string name="overview_show_deviations">Deviații</string>
<string name="overview_show_cob">Carbohidrați activi</string> <string name="overview_show_cob">Carbohidrați activi</string>
@ -689,6 +695,7 @@
<string name="nav_logsettings">Setări loguri</string> <string name="nav_logsettings">Setări loguri</string>
<string name="resettodefaults">Resetare la setările implicite</string> <string name="resettodefaults">Resetare la setările implicite</string>
<string name="nsmalfunction">Funcționare incorectă a NSClient. Aveți în vedere un restart al NS și al NSClient.</string> <string name="nsmalfunction">Funcționare incorectă a NSClient. Aveți în vedere un restart al NS și al NSClient.</string>
<string name="time_offset">Decalaj</string>
<string name="setupwizard_preferred_aps_mode">Modul APS preferat</string> <string name="setupwizard_preferred_aps_mode">Modul APS preferat</string>
<string name="treatments_wizard_total_label">Total</string> <string name="treatments_wizard_total_label">Total</string>
<string name="calculation_short">Calc</string> <string name="calculation_short">Calc</string>
@ -865,6 +872,7 @@
<string name="donate_your_data_to_science">Donează datele în scopuri științifice</string> <string name="donate_your_data_to_science">Donează datele în scopuri științifice</string>
<string name="open_humans_short">OH</string> <string name="open_humans_short">OH</string>
<string name="you_have_been_signed_out_of_open_humans">Ai fost deconectat de la Open Humans</string> <string name="you_have_been_signed_out_of_open_humans">Ai fost deconectat de la Open Humans</string>
<string name="click_here_to_sign_in_again_if_this_wasnt_on_purpose">Dați click aici pentru a vă conecta din nou, dacă a fost din greșeală.</string>
<string name="only_upload_if_connected_to_wifi">Încarcă numai pe conexiune WiFi</string> <string name="only_upload_if_connected_to_wifi">Încarcă numai pe conexiune WiFi</string>
<string name="only_upload_if_charging">Încărca numai dacă telefonul este la încărcat</string> <string name="only_upload_if_charging">Încărca numai dacă telefonul este la încărcat</string>
<string name="worker_state">Stare prelucrare: %s</string> <string name="worker_state">Stare prelucrare: %s</string>
@ -875,12 +883,25 @@
<string name="copytolocalprofile_invalid">Nu se poate crea profilul local. Profilul este invalid.</string> <string name="copytolocalprofile_invalid">Nu se poate crea profilul local. Profilul este invalid.</string>
<string name="cta_dont_kill_my_app_info">Nu-mi opri aplicația?</string> <string name="cta_dont_kill_my_app_info">Nu-mi opri aplicația?</string>
<string name="smscommunicator_report_pump_ureachable_summary">Trimite SMS dacă este generata o alarma de eroare conexiune pompa</string> <string name="smscommunicator_report_pump_ureachable_summary">Trimite SMS dacă este generata o alarma de eroare conexiune pompa</string>
<string name="smscommunicator_pump_ureachable">Raportează pompa inaccesibilă</string>
<string name="advisoralarm">Rulează alarma când este timpul să mănânci</string> <string name="advisoralarm">Rulează alarma când este timpul să mănânci</string>
<string name="alarminxmin">Rulează alarma în %1$d min</string> <string name="alarminxmin">Rulează alarma în %1$d min</string>
<string name="bolusadvisor">Consilier bolus</string> <string name="bolusadvisor">Consilier bolus</string>
<string name="bolusadvisormessage">Glicemia ta e mare. In loc sa mănânci acum, este recomandat sa mai aștepți un pic. Vrei sa faci un bolus de corecție acum si sa setezi o alarma pentru a manca mai târziu? In acest caz, nu vor fi înregistrați carbohidrați si va trebui sa folosești calculatorul de bolus din nou când îți vom reaminti.</string> <string name="bolusadvisormessage">Glicemia ta e mare. In loc sa mănânci acum, este recomandat sa mai aștepți un pic. Vrei sa faci un bolus de corecție acum si sa setezi o alarma pentru a manca mai târziu? In acest caz, nu vor fi înregistrați carbohidrați si va trebui sa folosești calculatorul de bolus din nou când îți vom reaminti.</string>
<string name="enablebolusadvisor">Activare consilier bolus</string> <string name="enablebolusadvisor">Activare consilier bolus</string>
<string name="enablebolusadvisor_summary">Folosește o alarma de reamintire pentru a începe sa mănânci mai târziu în loc de alerta de la calculatorul de bolus din timpul hiperglicemiei (\"pre-bolus\")</string>
<string name="time_to_eat">Timpul sa mănânci!\nRuleaza Calculatorul de Bolus pentru a face calculele din nou.</string> <string name="time_to_eat">Timpul sa mănânci!\nRuleaza Calculatorul de Bolus pentru a face calculele din nou.</string>
<string name="timetoeat">Timpul sa mănânci</string> <string name="timetoeat">Timpul sa mănânci</string>
<string name="fabric_upload_disabled">Încărcarea jurnalelor de erori este dezactivata!</string>
<string name="graph_menu_divider_header">Grafic</string> <string name="graph_menu_divider_header">Grafic</string>
<string name="chart_menu">Meniu diagramă</string>
<string name="clear_filter">Șterge filtru</string>
<string name="trend_arrow">Săgeată tendinţă</string>
<string name="cannula">Canula</string>
<string name="userentry">Înregistrare utilizator</string>
<string name="common_values">Folosește valorile corespunzătoarea celor mai mari mese pe care le ai de obicei\n</string>
<string name="summary_email_for_crash_report">Această adresă de e-mail va fi atașată rapoartelor de eroare, astfel încât să vă putem contacta în cazuri urgente. Este opțională.</string>
<string name="email_address">Adresă de e-mail</string>
<string name="privacy_settings">Setări de confidenţialitate</string>
<string name="privacy_summary">Puteți furniza o adresă de e-mail opțională dacă doriți să fiți notificat despre erorile aplicației. Acesta nu este un serviciu automat. Veți fi contactat de dezvoltatori în situații periculoase.</string>
</resources> </resources>

View file

@ -240,7 +240,7 @@
<string name="smscommunicator_loophasbeenenabled">Loop has been enabled</string> <string name="smscommunicator_loophasbeenenabled">Loop has been enabled</string>
<string name="smscommunicator_loopisenabled">Loop is enabled</string> <string name="smscommunicator_loopisenabled">Loop is enabled</string>
<string name="valuelimitedto">%1$.2f limited to %2$.2f</string> <string name="valuelimitedto">%1$.2f limited to %2$.2f</string>
<string name="valueoutofrange">Value %1$s is out of hard limits</string> <string name="valueoutofrange">»%1$s« is out of hard limits</string>
<string name="smscommunicator_pumpconnectwithcode">To connect pump reply with code %1$s</string> <string name="smscommunicator_pumpconnectwithcode">To connect pump reply with code %1$s</string>
<string name="smscommunicator_pumpconnectfail">Connection to pump failed</string> <string name="smscommunicator_pumpconnectfail">Connection to pump failed</string>
<string name="smscommunicator_pumpdisconnectwithcode">To disconnect pump for %1$d minutes reply with code %2$s</string> <string name="smscommunicator_pumpdisconnectwithcode">To disconnect pump for %1$d minutes reply with code %2$s</string>
@ -1118,6 +1118,16 @@
<string name="email_address">Email address</string> <string name="email_address">Email address</string>
<string name="privacy_settings">Privacy setting</string> <string name="privacy_settings">Privacy setting</string>
<string name="privacy_summary">You can provide optional email address if you want to be notified about app crashes. This is not an automated service. You will be contacted by developers in dangerous situations.</string> <string name="privacy_summary">You can provide optional email address if you want to be notified about app crashes. This is not an automated service. You will be contacted by developers in dangerous situations.</string>
<string name="profile_low_target">Profile low target</string>
<string name="profile_high_target">Profile high target</string>
<string name="temp_target_low_target">Temporary target bottom value</string>
<string name="temp_target_high_target">Temporary target top value</string>
<string name="temp_target_value">Temporary target value</string>
<string name="profile_dia">Profile DIA value</string>
<string name="profile_sensitivity_value">Profile sensitivity value</string>
<string name="profile_max_daily_basal_value">Maximal profile basal value</string>
<string name="current_basal_value">Current basal value</string>
<string name="profile_carbs_ratio_value">Profile carbs ratio value</string>

View file

@ -1,6 +1,5 @@
package info.nightscout.androidaps.data package info.nightscout.androidaps.data
import info.nightscout.androidaps.db.TempTarget
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.T
import org.junit.Assert import org.junit.Assert
@ -13,16 +12,16 @@ import java.util.*
class OverlappingIntervalsTest { class OverlappingIntervalsTest {
private val startDate = DateUtil.now() private val startDate = DateUtil.now()
var list = OverlappingIntervals<TempTarget>() private var list = OverlappingIntervals<TempTargetTest>()
@Test fun doTests() { @Test fun doTests() {
// create one 10h interval and test value in and out // create one 10h interval and test value in and out
list.add(TempTarget().date(startDate).duration(T.hours(10).mins().toInt()).low(100.0).high(100.0)) list.add(TempTargetTest().date(startDate).duration(T.hours(10).mins()).low(100.0).high(100.0))
Assert.assertEquals(null, list.getValueByInterval(startDate - T.secs(1).msecs())) Assert.assertEquals(null, list.getValueByInterval(startDate - T.secs(1).msecs()))
Assert.assertEquals(100.0, list.getValueByInterval(startDate)!!.target(), 0.01) Assert.assertEquals(100.0, list.getValueByInterval(startDate)!!.target(), 0.01)
Assert.assertEquals(null, list.getValueByInterval(startDate + T.hours(10).msecs() + 1)) Assert.assertEquals(null, list.getValueByInterval(startDate + T.hours(10).msecs() + 1))
// stop temp target after 5h // stop temp target after 5h
list.add(TempTarget().date(startDate + T.hours(5).msecs()).duration(0)) list.add(TempTargetTest().date(startDate + T.hours(5).msecs()).duration(0))
Assert.assertEquals(null, list.getValueByInterval(startDate - T.secs(1).msecs())) Assert.assertEquals(null, list.getValueByInterval(startDate - T.secs(1).msecs()))
Assert.assertEquals(100.0, list.getValueByInterval(startDate)!!.target(), 0.01) Assert.assertEquals(100.0, list.getValueByInterval(startDate)!!.target(), 0.01)
Assert.assertEquals(100.0, list.getValueByInterval(startDate + T.hours(5).msecs() - 1)!!.target(), 0.01) Assert.assertEquals(100.0, list.getValueByInterval(startDate + T.hours(5).msecs() - 1)!!.target(), 0.01)
@ -30,7 +29,7 @@ class OverlappingIntervalsTest {
Assert.assertEquals(null, list.getValueByInterval(startDate + T.hours(10).msecs() + 1)) Assert.assertEquals(null, list.getValueByInterval(startDate + T.hours(10).msecs() + 1))
// insert 1h interval inside // insert 1h interval inside
list.add(TempTarget().date(startDate + T.hours(3).msecs()).duration(T.hours(1).mins().toInt()).low(200.0).high(200.0)) list.add(TempTargetTest().date(startDate + T.hours(3).msecs()).duration(T.hours(1).mins()).low(200.0).high(200.0))
Assert.assertEquals(null, list.getValueByInterval(startDate - T.secs(1).msecs())) Assert.assertEquals(null, list.getValueByInterval(startDate - T.secs(1).msecs()))
Assert.assertEquals(100.0, list.getValueByInterval(startDate)!!.target(), 0.01) Assert.assertEquals(100.0, list.getValueByInterval(startDate)!!.target(), 0.01)
Assert.assertEquals(100.0, list.getValueByInterval(startDate + T.hours(5).msecs() - 1)!!.target(), 0.01) Assert.assertEquals(100.0, list.getValueByInterval(startDate + T.hours(5).msecs() - 1)!!.target(), 0.01)
@ -42,19 +41,19 @@ class OverlappingIntervalsTest {
@Test fun testCopyConstructor() { @Test fun testCopyConstructor() {
list.reset() list.reset()
list.add(TempTarget().date(startDate).duration(T.hours(10).mins().toInt()).low(100.0).high(100.0)) list.add(TempTargetTest().date(startDate).duration(T.hours(10).mins()).low(100.0).high(100.0))
val list2 = OverlappingIntervals(list) val list2 = OverlappingIntervals(list)
Assert.assertEquals(1, list2.list.size.toLong()) Assert.assertEquals(1, list2.list.size.toLong())
} }
@Test fun testReversingArrays() { @Test fun testReversingArrays() {
val someList: MutableList<TempTarget> = ArrayList() val someList: MutableList<TempTargetTest> = ArrayList()
someList.add(TempTarget().date(startDate).duration(T.hours(3).mins().toInt()).low(200.0).high(200.0)) someList.add(TempTargetTest().date(startDate).duration(T.hours(3).mins()).low(200.0).high(200.0))
someList.add(TempTarget().date(startDate + T.hours(1).msecs()).duration(T.hours(1).mins().toInt()).low(100.0).high(100.0)) someList.add(TempTargetTest().date(startDate + T.hours(1).msecs()).duration(T.hours(1).mins()).low(100.0).high(100.0))
list.reset() list.reset()
list.add(someList) list.add(someList)
Assert.assertEquals(startDate, list[0].date) Assert.assertEquals(startDate, list[0].data.timestamp)
Assert.assertEquals(startDate + T.hours(1).msecs(), list.getReversed(0).date) Assert.assertEquals(startDate + T.hours(1).msecs(), list.getReversed(0).data.timestamp)
Assert.assertEquals(startDate + T.hours(1).msecs(), list.reversedList[0].date) Assert.assertEquals(startDate + T.hours(1).msecs(), list.reversedList[0].data.timestamp)
} }
} }

View file

@ -0,0 +1,83 @@
package info.nightscout.androidaps.data
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.core.R
import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.database.interfaces.end
import info.nightscout.androidaps.interfaces.Interval
import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.resources.ResourceHelper
import java.util.concurrent.TimeUnit
class TempTargetTest(
var data: TemporaryTarget = TemporaryTarget(
timestamp = 0,
utcOffset = 0,
reason = TemporaryTarget.Reason.CUSTOM,
highTarget = 0.0,
lowTarget = 0.0,
duration = 0
)
) : Interval {
fun date(timestamp: Long): TempTargetTest {
data.timestamp = timestamp
return this
}
fun duration(duration: Long): TempTargetTest {
data.duration = T.mins(duration).msecs()
return this
}
fun low(low: Double): TempTargetTest {
data.lowTarget = low
return this
}
fun high(high: Double): TempTargetTest {
data.highTarget = high
return this
}
fun target(): Double {
return (data.lowTarget + data.highTarget) / 2
}
// -------- Interval interface ---------
private var cuttedEnd: Long? = null
override fun durationInMsec(): Long = data.duration
override fun start(): Long = data.timestamp
override fun originalEnd(): Long = data.end // planned end time at time of creation
override fun end(): Long = cuttedEnd ?: originalEnd() // end time after cut
override fun cutEndTo(end: Long) {
cuttedEnd = end
}
override fun match(time: Long): Boolean = start() <= time && end() >= time
override fun before(time: Long): Boolean = end() < time
override fun after(time: Long): Boolean = start() > time
override fun isInProgress(): Boolean = match(System.currentTimeMillis())
override fun isEndingEvent(): Boolean = data.duration == 0L
override fun isValid(): Boolean = true
// -------- Interval interface end ---------
fun lowValueToUnitsToString(units: String): String =
if (units == Constants.MGDL) DecimalFormatter.to0Decimal(data.lowTarget)
else DecimalFormatter.to1Decimal(data.lowTarget * Constants.MGDL_TO_MMOLL)
fun highValueToUnitsToString(units: String): String =
if (units == Constants.MGDL) DecimalFormatter.to0Decimal(data.highTarget)
else DecimalFormatter.to1Decimal(data.highTarget * Constants.MGDL_TO_MMOLL)
override fun toString(): String = data.toString()
fun friendlyDescription(units: String, resourceHelper: ResourceHelper): String =
Profile.toTargetRangeString(data.lowTarget, data.highTarget, Constants.MGDL, units) +
units +
"@" + resourceHelper.gs(R.string.format_mins, TimeUnit.MILLISECONDS.toMinutes(data.duration)) + "(" + data.reason.text + ")"
}

View file

@ -10,6 +10,7 @@ import info.nightscout.androidaps.TestBaseWithProfile
import info.nightscout.androidaps.dana.DanaPump import info.nightscout.androidaps.dana.DanaPump
import info.nightscout.androidaps.danar.DanaRPlugin import info.nightscout.androidaps.danar.DanaRPlugin
import info.nightscout.androidaps.danars.DanaRSPlugin import info.nightscout.androidaps.danars.DanaRSPlugin
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAPlugin import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAPlugin
import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin
@ -52,7 +53,7 @@ import java.util.*
MainApp::class, ConfigBuilderPlugin::class, ConstraintChecker::class, SP::class, Context::class, MainApp::class, ConfigBuilderPlugin::class, ConstraintChecker::class, SP::class, Context::class,
OpenAPSAMAPlugin::class, OpenAPSSMBPlugin::class, TreatmentsPlugin::class, TreatmentService::class, OpenAPSAMAPlugin::class, OpenAPSSMBPlugin::class, TreatmentsPlugin::class, TreatmentService::class,
VirtualPumpPlugin::class, DetailedBolusInfoStorage::class, GlimpPlugin::class, Profiler::class, VirtualPumpPlugin::class, DetailedBolusInfoStorage::class, GlimpPlugin::class, Profiler::class,
UserEntryLogger::class, IobCobCalculatorPlugin::class, LoggerUtils::class) UserEntryLogger::class, IobCobCalculatorPlugin::class, LoggerUtils::class, AppRepository::class)
class ConstraintsCheckerTest : TestBaseWithProfile() { class ConstraintsCheckerTest : TestBaseWithProfile() {
@Mock lateinit var activePlugin: ActivePluginProvider @Mock lateinit var activePlugin: ActivePluginProvider
@ -70,6 +71,7 @@ class ConstraintsCheckerTest : TestBaseWithProfile() {
@Mock lateinit var uel: UserEntryLogger @Mock lateinit var uel: UserEntryLogger
@Mock lateinit var loggerUtils: LoggerUtils @Mock lateinit var loggerUtils: LoggerUtils
@Mock lateinit var databaseHelper: DatabaseHelperInterface @Mock lateinit var databaseHelper: DatabaseHelperInterface
@Mock lateinit var repository: AppRepository
private lateinit var danaPump: DanaPump private lateinit var danaPump: DanaPump
@ -128,8 +130,8 @@ class ConstraintsCheckerTest : TestBaseWithProfile() {
danaRPlugin = DanaRPlugin(injector, aapsLogger, aapsSchedulers, rxBus, context, resourceHelper, constraintChecker, activePlugin, sp, commandQueue, danaPump, dateUtil, fabricPrivacy) danaRPlugin = DanaRPlugin(injector, aapsLogger, aapsSchedulers, rxBus, context, resourceHelper, constraintChecker, activePlugin, sp, commandQueue, danaPump, dateUtil, fabricPrivacy)
danaRSPlugin = DanaRSPlugin(injector, aapsLogger, aapsSchedulers, rxBus, context, resourceHelper, constraintChecker, profileFunction, activePluginProvider, sp, commandQueue, danaPump, detailedBolusInfoStorage, fabricPrivacy, dateUtil) danaRSPlugin = DanaRSPlugin(injector, aapsLogger, aapsSchedulers, rxBus, context, resourceHelper, constraintChecker, profileFunction, activePluginProvider, sp, commandQueue, danaPump, detailedBolusInfoStorage, fabricPrivacy, dateUtil)
insightPlugin = LocalInsightPlugin(injector, aapsLogger, rxBus, resourceHelper, treatmentsInterface, sp, commandQueue, profileFunction, nsUpload, context, uploadQueue, Config(), dateUtil, databaseHelper) insightPlugin = LocalInsightPlugin(injector, aapsLogger, rxBus, resourceHelper, treatmentsInterface, sp, commandQueue, profileFunction, nsUpload, context, uploadQueue, Config(), dateUtil, databaseHelper)
openAPSSMBPlugin = OpenAPSSMBPlugin(injector, aapsLogger, rxBus, constraintChecker, resourceHelper, profileFunction, context, activePlugin, treatmentsInterface, iobCobCalculatorPlugin, hardLimits, profiler, sp) openAPSSMBPlugin = OpenAPSSMBPlugin(injector, aapsLogger, rxBus, constraintChecker, resourceHelper, profileFunction, context, activePlugin, treatmentsInterface, iobCobCalculatorPlugin, hardLimits, profiler, sp, dateUtil, repository)
openAPSAMAPlugin = OpenAPSAMAPlugin(injector, aapsLogger, rxBus, constraintChecker, resourceHelper, profileFunction, context, activePlugin, treatmentsInterface, iobCobCalculatorPlugin, hardLimits, profiler, fabricPrivacy) openAPSAMAPlugin = OpenAPSAMAPlugin(injector, aapsLogger, rxBus, constraintChecker, resourceHelper, profileFunction, context, activePlugin, treatmentsInterface, iobCobCalculatorPlugin, hardLimits, profiler, fabricPrivacy, dateUtil, repository)
safetyPlugin = SafetyPlugin(injector, aapsLogger, resourceHelper, sp, rxBus, constraintChecker, openAPSAMAPlugin, openAPSSMBPlugin, sensitivityOref1Plugin, activePlugin, hardLimits, BuildHelper(Config(), loggerUtils), treatmentsInterface, Config()) safetyPlugin = SafetyPlugin(injector, aapsLogger, resourceHelper, sp, rxBus, constraintChecker, openAPSAMAPlugin, openAPSSMBPlugin, sensitivityOref1Plugin, activePlugin, hardLimits, BuildHelper(Config(), loggerUtils), treatmentsInterface, Config())
val constraintsPluginsList = ArrayList<PluginBase>() val constraintsPluginsList = ArrayList<PluginBase>()
constraintsPluginsList.add(safetyPlugin) constraintsPluginsList.add(safetyPlugin)

View file

@ -7,11 +7,7 @@ import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Config import info.nightscout.androidaps.Config
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.TestBase import info.nightscout.androidaps.TestBase
import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.interfaces.CommandQueueProvider
import info.nightscout.androidaps.interfaces.PluginType
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.interfaces.PumpDescription
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
@ -53,15 +49,16 @@ class LoopPluginTest : TestBase() {
@Mock lateinit var receiverStatusStore: ReceiverStatusStore @Mock lateinit var receiverStatusStore: ReceiverStatusStore
@Mock lateinit var nsUpload: NSUpload @Mock lateinit var nsUpload: NSUpload
@Mock lateinit var notificationManager: NotificationManager @Mock lateinit var notificationManager: NotificationManager
@Mock lateinit var databaseHelper: DatabaseHelperInterface
private lateinit var hardLimits: HardLimits private lateinit var hardLimits: HardLimits
lateinit var loopPlugin: LoopPlugin private lateinit var loopPlugin: LoopPlugin
val injector = HasAndroidInjector { AndroidInjector { } } val injector = HasAndroidInjector { AndroidInjector { } }
@Before fun prepareMock() { @Before fun prepareMock() {
hardLimits = HardLimits(aapsLogger, rxBus, sp, resourceHelper, context, nsUpload) hardLimits = HardLimits(aapsLogger, rxBus, sp, resourceHelper, context, nsUpload)
loopPlugin = LoopPlugin(injector, aapsLogger, aapsSchedulers, rxBus, sp, Config(), constraintChecker, resourceHelper, profileFunction, context, commandQueue, activePlugin, treatmentsPlugin, virtualPumpPlugin, iobCobCalculatorPlugin, receiverStatusStore, fabricPrivacy, nsUpload, hardLimits) loopPlugin = LoopPlugin(injector, aapsLogger, aapsSchedulers, rxBus, sp, Config(), constraintChecker, resourceHelper, profileFunction, context, commandQueue, activePlugin, treatmentsPlugin, virtualPumpPlugin, iobCobCalculatorPlugin, receiverStatusStore, fabricPrivacy, nsUpload, databaseHelper, hardLimits)
`when`(activePlugin.activePump).thenReturn(virtualPumpPlugin) `when`(activePlugin.activePump).thenReturn(virtualPumpPlugin)
`when`(context.getSystemService(Context.NOTIFICATION_SERVICE)).thenReturn(notificationManager) `when`(context.getSystemService(Context.NOTIFICATION_SERVICE)).thenReturn(notificationManager)
} }

View file

@ -12,7 +12,9 @@ import info.nightscout.androidaps.R
import info.nightscout.androidaps.TestBaseWithProfile import info.nightscout.androidaps.TestBaseWithProfile
import info.nightscout.androidaps.data.IobTotal import info.nightscout.androidaps.data.IobTotal
import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.GlucoseValue import info.nightscout.androidaps.database.entities.GlucoseValue
import info.nightscout.androidaps.database.transactions.InsertTemporaryTargetAndCancelCurrentTransaction
import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.CommandQueueProvider import info.nightscout.androidaps.interfaces.CommandQueueProvider
import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.interfaces.Constraint
@ -21,6 +23,7 @@ import info.nightscout.androidaps.interfaces.PumpDescription
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.plugins.general.smsCommunicator.otp.OneTimePassword import info.nightscout.androidaps.plugins.general.smsCommunicator.otp.OneTimePassword
import info.nightscout.androidaps.plugins.general.smsCommunicator.otp.OneTimePasswordValidationResult import info.nightscout.androidaps.plugins.general.smsCommunicator.otp.OneTimePasswordValidationResult
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.CobInfo import info.nightscout.androidaps.plugins.iob.iobCobCalculator.CobInfo
@ -37,6 +40,7 @@ import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.XdripCalibrations import info.nightscout.androidaps.utils.XdripCalibrations
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import io.reactivex.Single
import org.junit.Assert import org.junit.Assert
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
@ -53,7 +57,11 @@ import org.powermock.modules.junit4.PowerMockRunner
import java.util.* import java.util.*
@RunWith(PowerMockRunner::class) @RunWith(PowerMockRunner::class)
@PrepareForTest(ConstraintChecker::class, FabricPrivacy::class, VirtualPumpPlugin::class, XdripCalibrations::class, SmsManager::class, CommandQueue::class, LocalProfilePlugin::class, DateUtil::class, IobCobCalculatorPlugin::class, OneTimePassword::class, UserEntryLogger::class, LoopPlugin::class) @PrepareForTest(
ConstraintChecker::class, FabricPrivacy::class, VirtualPumpPlugin::class, XdripCalibrations::class,
SmsManager::class, CommandQueue::class, LocalProfilePlugin::class, DateUtil::class,
IobCobCalculatorPlugin::class, OneTimePassword::class, UserEntryLogger::class, LoopPlugin::class,
AppRepository::class)
class SmsCommunicatorPluginTest : TestBaseWithProfile() { class SmsCommunicatorPluginTest : TestBaseWithProfile() {
@Mock lateinit var context: Context @Mock lateinit var context: Context
@ -69,6 +77,8 @@ class SmsCommunicatorPluginTest : TestBaseWithProfile() {
@Mock lateinit var otp: OneTimePassword @Mock lateinit var otp: OneTimePassword
@Mock lateinit var xdripCalibrations: XdripCalibrations @Mock lateinit var xdripCalibrations: XdripCalibrations
@Mock lateinit var uel: UserEntryLogger @Mock lateinit var uel: UserEntryLogger
@Mock lateinit var nsUpload: NSUpload
@Mock lateinit var repository: AppRepository
var injector: HasAndroidInjector = HasAndroidInjector { var injector: HasAndroidInjector = HasAndroidInjector {
AndroidInjector { AndroidInjector {
@ -108,7 +118,12 @@ class SmsCommunicatorPluginTest : TestBaseWithProfile() {
`when`(SmsManager.getDefault()).thenReturn(smsManager) `when`(SmsManager.getDefault()).thenReturn(smsManager)
`when`(sp.getString(R.string.key_smscommunicator_allowednumbers, "")).thenReturn("1234;5678") `when`(sp.getString(R.string.key_smscommunicator_allowednumbers, "")).thenReturn("1234;5678")
smsCommunicatorPlugin = SmsCommunicatorPlugin(injector, aapsLogger, resourceHelper, aapsSchedulers, sp, constraintChecker, rxBus, profileFunction, fabricPrivacy, activePlugin, commandQueue, loopPlugin, iobCobCalculatorPlugin, xdripCalibrations, otp, Config(), DateUtil(context), uel) `when`(
repository.runTransactionForResult(anyObject<InsertTemporaryTargetAndCancelCurrentTransaction>())
).thenReturn(Single.just(InsertTemporaryTargetAndCancelCurrentTransaction.TransactionResult().apply {
}))
smsCommunicatorPlugin = SmsCommunicatorPlugin(injector, aapsLogger, resourceHelper, aapsSchedulers, sp, constraintChecker, rxBus, profileFunction, fabricPrivacy, activePlugin, commandQueue, loopPlugin, iobCobCalculatorPlugin, xdripCalibrations, otp, Config(), DateUtil(context), uel, nsUpload, repository)
smsCommunicatorPlugin.setPluginEnabled(PluginType.GENERAL, true) smsCommunicatorPlugin.setPluginEnabled(PluginType.GENERAL, true)
Mockito.doAnswer { invocation: InvocationOnMock -> Mockito.doAnswer { invocation: InvocationOnMock ->
val callback = invocation.getArgument<Callback>(1) val callback = invocation.getArgument<Callback>(1)

View file

@ -3,10 +3,10 @@ package info.nightscout.androidaps.plugins.treatments
import android.content.Context import android.content.Context
import dagger.android.AndroidInjector import dagger.android.AndroidInjector
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.TestBaseWithProfile import info.nightscout.androidaps.TestBaseWithProfile
import info.nightscout.androidaps.db.DatabaseHelper import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.db.TemporaryBasal import info.nightscout.androidaps.db.TemporaryBasal
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.plugins.general.nsclient.UploadQueue import info.nightscout.androidaps.plugins.general.nsclient.UploadQueue
import info.nightscout.androidaps.plugins.insulin.InsulinOrefRapidActingPlugin import info.nightscout.androidaps.plugins.insulin.InsulinOrefRapidActingPlugin
@ -21,21 +21,21 @@ import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers import org.mockito.ArgumentMatchers
import org.mockito.Mock import org.mockito.Mock
import org.mockito.Mockito.`when` import org.mockito.Mockito.`when`
import org.powermock.api.mockito.PowerMockito
import org.powermock.core.classloader.annotations.PrepareForTest import org.powermock.core.classloader.annotations.PrepareForTest
import org.powermock.modules.junit4.PowerMockRunner import org.powermock.modules.junit4.PowerMockRunner
@Suppress("SpellCheckingInspection") @Suppress("SpellCheckingInspection")
@RunWith(PowerMockRunner::class) @RunWith(PowerMockRunner::class)
@PrepareForTest(FabricPrivacy::class, MainApp::class, DatabaseHelper::class) @PrepareForTest(FabricPrivacy::class, DatabaseHelperInterface::class, AppRepository::class)
class TreatmentsPluginTest : TestBaseWithProfile() { class TreatmentsPluginTest : TestBaseWithProfile() {
@Mock lateinit var context: Context @Mock lateinit var context: Context
@Mock lateinit var sp: SP @Mock lateinit var sp: SP
@Mock lateinit var databaseHelper: DatabaseHelper
@Mock lateinit var treatmentService: TreatmentService @Mock lateinit var treatmentService: TreatmentService
@Mock lateinit var nsUpload: NSUpload @Mock lateinit var nsUpload: NSUpload
@Mock lateinit var uploadQueue: UploadQueue @Mock lateinit var uploadQueue: UploadQueue
@Mock lateinit var repository: AppRepository
@Mock lateinit var databaseHelper: DatabaseHelperInterface
val injector = HasAndroidInjector { val injector = HasAndroidInjector {
AndroidInjector { AndroidInjector {
@ -44,6 +44,7 @@ class TreatmentsPluginTest : TestBaseWithProfile() {
it.activePlugin = activePluginProvider it.activePlugin = activePluginProvider
it.profileFunction = profileFunction it.profileFunction = profileFunction
it.sp = sp it.sp = sp
it.dateUtil = DateUtil(context)
} }
} }
} }
@ -53,15 +54,12 @@ class TreatmentsPluginTest : TestBaseWithProfile() {
@Before @Before
fun prepare() { fun prepare() {
PowerMockito.mockStatic(MainApp::class.java)
`when`(MainApp.getDbHelper()).thenReturn(databaseHelper)
insulinOrefRapidActingPlugin = InsulinOrefRapidActingPlugin(profileInjector, resourceHelper, profileFunction, rxBus, aapsLogger) insulinOrefRapidActingPlugin = InsulinOrefRapidActingPlugin(profileInjector, resourceHelper, profileFunction, rxBus, aapsLogger)
`when`(profileFunction.getProfile(ArgumentMatchers.anyLong())).thenReturn(validProfile) `when`(profileFunction.getProfile(ArgumentMatchers.anyLong())).thenReturn(validProfile)
`when`(activePluginProvider.activeInsulin).thenReturn(insulinOrefRapidActingPlugin) `when`(activePluginProvider.activeInsulin).thenReturn(insulinOrefRapidActingPlugin)
sot = TreatmentsPlugin(profileInjector, aapsLogger, rxBus, aapsSchedulers, resourceHelper, context, sp, profileFunction, activePluginProvider, nsUpload, fabricPrivacy, dateUtil, uploadQueue) sot = TreatmentsPlugin(profileInjector, aapsLogger, rxBus, aapsSchedulers, resourceHelper, context, sp, profileFunction, activePluginProvider, nsUpload, fabricPrivacy, dateUtil, uploadQueue, databaseHelper, repository)
sot.service = treatmentService sot.service = treatmentService
} }

View file

@ -7,27 +7,38 @@ import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.automation.R import info.nightscout.androidaps.automation.R
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.Source import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.db.TempTarget import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.database.transactions.InsertTemporaryTargetAndCancelCurrentTransaction
import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.general.automation.elements.ComparatorExists import info.nightscout.androidaps.plugins.general.automation.elements.ComparatorExists
import info.nightscout.androidaps.plugins.general.automation.elements.InputDuration import info.nightscout.androidaps.plugins.general.automation.elements.InputDuration
import info.nightscout.androidaps.plugins.general.automation.elements.InputTempTarget import info.nightscout.androidaps.plugins.general.automation.elements.InputTempTarget
import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement
import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerTempTarget import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerTempTarget
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.JsonHelper import info.nightscout.androidaps.utils.JsonHelper
import info.nightscout.androidaps.utils.JsonHelper.safeGetDouble import info.nightscout.androidaps.utils.JsonHelper.safeGetDouble
import info.nightscout.androidaps.utils.extensions.friendlyDescription
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import org.json.JSONObject import org.json.JSONObject
import java.util.concurrent.TimeUnit
import javax.inject.Inject import javax.inject.Inject
class ActionStartTempTarget(injector: HasAndroidInjector) : Action(injector) { class ActionStartTempTarget(injector: HasAndroidInjector) : Action(injector) {
@Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var activePlugin: ActivePluginProvider @Inject lateinit var activePlugin: ActivePluginProvider
@Inject lateinit var repository: AppRepository
@Inject lateinit var nsUpload: NSUpload
private val disposable = CompositeDisposable()
var value = InputTempTarget(injector) var value = InputTempTarget(injector)
var duration = InputDuration(injector, 30, InputDuration.TimeUnit.MINUTES) var duration = InputDuration(injector, 30, InputDuration.TimeUnit.MINUTES)
@ -41,8 +52,15 @@ class ActionStartTempTarget(injector: HasAndroidInjector) : Action(injector) {
@DrawableRes override fun icon(): Int = R.drawable.ic_temptarget_high @DrawableRes override fun icon(): Int = R.drawable.ic_temptarget_high
override fun doAction(callback: Callback) { override fun doAction(callback: Callback) {
activePlugin.activeTreatments.addToHistoryTempTarget(tt()) disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction(tt()))
callback.result(PumpEnactResult(injector).success(true).comment(R.string.ok))?.run() .subscribe({ result ->
result.inserted.forEach { nsUpload.uploadTempTarget(it) }
result.updated.forEach { nsUpload.updateTempTarget(it) }
callback.result(PumpEnactResult(injector).success(true).comment(R.string.ok))?.run()
}, {
aapsLogger.error(LTag.BGSOURCE, "Error while saving temporary target", it)
callback.result(PumpEnactResult(injector).success(false).comment(R.string.error))?.run()
})
} }
override fun generateDialog(root: LinearLayout) { override fun generateDialog(root: LinearLayout) {
@ -76,14 +94,13 @@ class ActionStartTempTarget(injector: HasAndroidInjector) : Action(injector) {
return this return this
} }
fun tt(): TempTarget = fun tt() = TemporaryTarget(
TempTarget() timestamp = DateUtil.now(),
.date(DateUtil.now()) duration = TimeUnit.MINUTES.toMillis(duration.getMinutes().toLong()),
.duration(duration.getMinutes()) reason = TemporaryTarget.Reason.AUTOMATION,
.reason("Automation") lowTarget = Profile.toMgdl(value.value, value.units),
.source(Source.USER) highTarget = Profile.toMgdl(value.value, value.units)
.low(Profile.toMgdl(value.value, value.units)) )
.high(Profile.toMgdl(value.value, value.units))
override fun isValid(): Boolean = override fun isValid(): Boolean =
if (value.units == Constants.MMOL) { // mmol if (value.units == Constants.MMOL) { // mmol

View file

@ -3,31 +3,39 @@ package info.nightscout.androidaps.plugins.general.automation.actions
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.automation.R import info.nightscout.androidaps.automation.R
import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.db.Source import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.db.TempTarget import info.nightscout.androidaps.database.transactions.CancelCurrentTemporaryTargetIfAnyTransaction
import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import javax.inject.Inject import javax.inject.Inject
class ActionStopTempTarget(injector: HasAndroidInjector) : Action(injector) { class ActionStopTempTarget(injector: HasAndroidInjector) : Action(injector) {
@Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var activePlugin: ActivePluginProvider @Inject lateinit var activePlugin: ActivePluginProvider
@Inject lateinit var repository: AppRepository
@Inject lateinit var nsUpload: NSUpload
@Inject lateinit var dateUtil: DateUtil
private val disposable = CompositeDisposable()
override fun friendlyName(): Int = R.string.stoptemptarget override fun friendlyName(): Int = R.string.stoptemptarget
override fun shortDescription(): String = resourceHelper.gs(R.string.stoptemptarget) override fun shortDescription(): String = resourceHelper.gs(R.string.stoptemptarget)
override fun icon(): Int = R.drawable.ic_stop_24dp override fun icon(): Int = R.drawable.ic_stop_24dp
override fun doAction(callback: Callback) { override fun doAction(callback: Callback) {
val tempTarget = TempTarget() disposable += repository.runTransactionForResult(CancelCurrentTemporaryTargetIfAnyTransaction(DateUtil.now()))
.date(DateUtil.now()) .subscribe({ result ->
.duration(0) result.updated.forEach { nsUpload.updateTempTarget(it) }
.reason("Automation") }, {
.source(Source.USER) aapsLogger.error(LTag.BGSOURCE, "Error while saving temporary target", it)
.low(0.0).high(0.0) })
activePlugin.activeTreatments.addToHistoryTempTarget(tempTarget)
callback.result(PumpEnactResult(injector).success(true).comment(R.string.ok))?.run() callback.result(PumpEnactResult(injector).success(true).comment(R.string.ok))?.run()
} }

View file

@ -4,14 +4,21 @@ import android.widget.LinearLayout
import com.google.common.base.Optional import com.google.common.base.Optional
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.automation.R import info.nightscout.androidaps.automation.R
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.general.automation.elements.ComparatorExists import info.nightscout.androidaps.plugins.general.automation.elements.ComparatorExists
import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder
import info.nightscout.androidaps.plugins.general.automation.elements.StaticLabel import info.nightscout.androidaps.plugins.general.automation.elements.StaticLabel
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.JsonHelper import info.nightscout.androidaps.utils.JsonHelper
import org.json.JSONObject import org.json.JSONObject
import javax.inject.Inject
class TriggerTempTarget(injector: HasAndroidInjector) : Trigger(injector) { class TriggerTempTarget(injector: HasAndroidInjector) : Trigger(injector) {
@Inject lateinit var repository: AppRepository
@Inject lateinit var dateUtil: DateUtil
var comparator = ComparatorExists(injector) var comparator = ComparatorExists(injector)
constructor(injector: HasAndroidInjector, compare: ComparatorExists.Compare) : this(injector) { constructor(injector: HasAndroidInjector, compare: ComparatorExists.Compare) : this(injector) {
@ -28,7 +35,7 @@ class TriggerTempTarget(injector: HasAndroidInjector) : Trigger(injector) {
} }
override fun shouldRun(): Boolean { override fun shouldRun(): Boolean {
val tt = treatmentsInterface.tempTargetFromHistory val tt = repository.getTemporaryTargetActiveAt(dateUtil._now()).blockingGet()
if (tt == null && comparator.value == ComparatorExists.Compare.NOT_EXISTS) { if (tt == null && comparator.value == ComparatorExists.Compare.NOT_EXISTS) {
aapsLogger.debug(LTag.AUTOMATION, "Ready for execution: " + friendlyDescription()) aapsLogger.debug(LTag.AUTOMATION, "Ready for execution: " + friendlyDescription())
return true return true

View file

@ -7,6 +7,7 @@
<string name="automation_missing_trigger">Mindestens eine auslösende Bedingung angeben.</string> <string name="automation_missing_trigger">Mindestens eine auslösende Bedingung angeben.</string>
<string name="automation_missing_action">Mindestens eine Aktion angeben.</string> <string name="automation_missing_action">Mindestens eine Aktion angeben.</string>
<string name="alarm_message">Alarm: %1$s</string> <string name="alarm_message">Alarm: %1$s</string>
<string name="alarm_short">Alarm:</string>
<string name="message_short">Nachricht:</string> <string name="message_short">Nachricht:</string>
<string name="alreadyenabled">Bereits aktiviert</string> <string name="alreadyenabled">Bereits aktiviert</string>
<string name="alreadydisabled">Bereits deaktiviert</string> <string name="alreadydisabled">Bereits deaktiviert</string>
@ -88,6 +89,7 @@
<string name="glucose_u">Glukosewert [%1$s]:</string> <string name="glucose_u">Glukosewert [%1$s]:</string>
<string name="lastboluslabel">Letzter Bolus vor</string> <string name="lastboluslabel">Letzter Bolus vor</string>
<string name="lastboluscompared">Letzter Bolus vor %1$s %2$s Min</string> <string name="lastboluscompared">Letzter Bolus vor %1$s %2$s Min</string>
<string name="triggercoblabel">COB</string>
<string name="cobcompared">COB %1$s %2$.0f</string> <string name="cobcompared">COB %1$s %2$.0f</string>
<string name="iob_u">IOB [IE]:</string> <string name="iob_u">IOB [IE]:</string>
<string name="distance_short">Umkreis [m]:</string> <string name="distance_short">Umkreis [m]:</string>

View file

@ -7,6 +7,7 @@
<string name="automation_missing_trigger">Vă rugăm să specificați cel puțin un factor declanșator.</string> <string name="automation_missing_trigger">Vă rugăm să specificați cel puțin un factor declanșator.</string>
<string name="automation_missing_action">Trebuie să specificați cel puțin o acțiune.</string> <string name="automation_missing_action">Trebuie să specificați cel puțin o acțiune.</string>
<string name="alarm_message">Alarmă: %1$s</string> <string name="alarm_message">Alarmă: %1$s</string>
<string name="alarm_short">Alarmă:</string>
<string name="message_short">Msj:</string> <string name="message_short">Msj:</string>
<string name="alreadyenabled">Deja activată</string> <string name="alreadyenabled">Deja activată</string>
<string name="alreadydisabled">Deja dezactivată</string> <string name="alreadydisabled">Deja dezactivată</string>
@ -88,6 +89,7 @@
<string name="glucose_u">Glicemie [%1$s]:</string> <string name="glucose_u">Glicemie [%1$s]:</string>
<string name="lastboluslabel">Ultimul bolus</string> <string name="lastboluslabel">Ultimul bolus</string>
<string name="lastboluscompared">Ultimul bolus acum %1$s %2$s min</string> <string name="lastboluscompared">Ultimul bolus acum %1$s %2$s min</string>
<string name="triggercoblabel">COB</string>
<string name="cobcompared">COB %1$s %2$.0f</string> <string name="cobcompared">COB %1$s %2$.0f</string>
<string name="iob_u">IOB [U]:</string> <string name="iob_u">IOB [U]:</string>
<string name="distance_short">Dist [m]:</string> <string name="distance_short">Dist [m]:</string>

View file

@ -5,6 +5,7 @@ import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.androidaps.utils.rx.TestAapsSchedulers import info.nightscout.androidaps.utils.rx.TestAapsSchedulers
import org.junit.Before import org.junit.Before
import org.junit.Rule import org.junit.Rule
import org.mockito.ArgumentMatcher
import org.mockito.Mockito import org.mockito.Mockito
import org.mockito.junit.MockitoJUnit import org.mockito.junit.MockitoJUnit
import org.mockito.junit.MockitoRule import org.mockito.junit.MockitoRule
@ -35,6 +36,17 @@ open class TestBase {
return uninitialized() return uninitialized()
} }
fun <T> argThatKotlin(matcher: ArgumentMatcher<T>): T {
Mockito.argThat(matcher)
return uninitialized()
}
fun <T> eqObject(expected: T): T {
Mockito.eq<T>(expected)
return uninitialized()
}
@Suppress("Unchecked_Cast") @Suppress("Unchecked_Cast")
fun <T> uninitialized(): T = null as T fun <T> uninitialized(): T = null as T
} }

View file

@ -2,13 +2,18 @@ package info.nightscout.androidaps.plugins.general.automation.actions
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.automation.R import info.nightscout.androidaps.automation.R
import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.database.transactions.InsertTemporaryTargetAndCancelCurrentTransaction
import info.nightscout.androidaps.database.transactions.Transaction
import info.nightscout.androidaps.plugins.general.automation.elements.InputDuration import info.nightscout.androidaps.plugins.general.automation.elements.InputDuration
import info.nightscout.androidaps.plugins.general.automation.elements.InputTempTarget import info.nightscout.androidaps.plugins.general.automation.elements.InputTempTarget
import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.queue.Callback
import io.reactivex.Single
import org.junit.Assert import org.junit.Assert
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.mockito.ArgumentMatcher
import org.mockito.Mockito import org.mockito.Mockito
import org.mockito.Mockito.`when` import org.mockito.Mockito.`when`
import org.powermock.modules.junit4.PowerMockRunner import org.powermock.modules.junit4.PowerMockRunner
@ -41,13 +46,47 @@ class ActionStartTempTargetTest : ActionsTestBase() {
} }
@Test fun doActionTest() { @Test fun doActionTest() {
`when`(activePlugin.activeTreatments).thenReturn(treatmentsInterface)
val expectedTarget = TemporaryTarget(
id = 0,
version = 0,
dateCreated = -1,
isValid = true,
referenceId = null,
interfaceIDs_backing = null,
timestamp = 0,
utcOffset = 0,
reason = TemporaryTarget.Reason.AUTOMATION,
highTarget = 110.0,
lowTarget = 110.0,
duration = 1800000
)
val inserted = mutableListOf<TemporaryTarget>().apply {
add(expectedTarget)
}
val updated = mutableListOf<TemporaryTarget>().apply {
// TODO insert all updated TTs
}
`when`(
repository.runTransactionForResult(argThatKotlin<InsertTemporaryTargetAndCancelCurrentTransaction> {
it.temporaryTarget
.copy(timestamp = expectedTarget.timestamp, utcOffset = expectedTarget.utcOffset) // those can be different
.contentEqualsTo(expectedTarget)
})
).thenReturn(Single.just(InsertTemporaryTargetAndCancelCurrentTransaction.TransactionResult().apply {
inserted.addAll(inserted)
updated.addAll(updated)
}))
sut.doAction(object : Callback() { sut.doAction(object : Callback() {
override fun run() { override fun run() {
Assert.assertTrue(result.success) Assert.assertTrue(result.success)
} }
}) })
Mockito.verify(treatmentsInterface, Mockito.times(1)).addToHistoryTempTarget(anyObject()) Mockito.verify(repository, Mockito.times(1)).runTransactionForResult(anyObject<Transaction<InsertTemporaryTargetAndCancelCurrentTransaction.TransactionResult>>())
} }
@Test fun hasDialogTest() { @Test fun hasDialogTest() {

View file

@ -1,7 +1,11 @@
package info.nightscout.androidaps.plugins.general.automation.actions package info.nightscout.androidaps.plugins.general.automation.actions
import info.nightscout.androidaps.automation.R import info.nightscout.androidaps.automation.R
import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.database.transactions.CancelCurrentTemporaryTargetIfAnyTransaction
import info.nightscout.androidaps.database.transactions.Transaction
import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.queue.Callback
import io.reactivex.Single
import org.junit.Assert import org.junit.Assert
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
@ -35,13 +39,26 @@ class ActionStopTempTargetTest : ActionsTestBase() {
} }
@Test fun doActionTest() { @Test fun doActionTest() {
`when`(activePlugin.activeTreatments).thenReturn(treatmentsInterface) val inserted = mutableListOf<TemporaryTarget>().apply {
// insert all inserted TTs
}
val updated = mutableListOf<TemporaryTarget>().apply {
// add(TemporaryTarget(id = 0, version = 0, dateCreated = 0, isValid = false, referenceId = null, interfaceIDs_backing = null, timestamp = 0, utcOffset = 0, reason =, highTarget = 0.0, lowTarget = 0.0, duration = 0))
// insert all updated TTs
}
`when`(
repository.runTransactionForResult(anyObject<Transaction<CancelCurrentTemporaryTargetIfAnyTransaction.TransactionResult>>())
).thenReturn(Single.just(CancelCurrentTemporaryTargetIfAnyTransaction.TransactionResult().apply {
inserted.addAll(inserted)
updated.addAll(updated)
}))
sut.doAction(object : Callback() { sut.doAction(object : Callback() {
override fun run() { override fun run() {
Assert.assertTrue(result.success) Assert.assertTrue(result.success)
} }
}) })
Mockito.verify(treatmentsInterface, Mockito.times(1)).addToHistoryTempTarget(anyObject()) Mockito.verify(repository, Mockito.times(1)).runTransactionForResult((anyObject<Transaction<CancelCurrentTemporaryTargetIfAnyTransaction.TransactionResult>>()))
} }
@Test fun hasDialogTest() { @Test fun hasDialogTest() {

View file

@ -6,6 +6,7 @@ import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.TestBaseWithProfile import info.nightscout.androidaps.TestBaseWithProfile
import info.nightscout.androidaps.TestPumpPlugin import info.nightscout.androidaps.TestPumpPlugin
import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.interfaces.*
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
@ -17,7 +18,7 @@ import org.mockito.Mock
import org.mockito.Mockito.`when` import org.mockito.Mockito.`when`
import org.powermock.core.classloader.annotations.PrepareForTest import org.powermock.core.classloader.annotations.PrepareForTest
@PrepareForTest(RxBusWrapper::class, ActionsTestBase.TestLoopPlugin::class) @PrepareForTest(RxBusWrapper::class, ActionsTestBase.TestLoopPlugin::class, AppRepository::class)
open class ActionsTestBase : TestBaseWithProfile() { open class ActionsTestBase : TestBaseWithProfile() {
open class TestLoopPlugin( open class TestLoopPlugin(
@ -44,6 +45,7 @@ open class ActionsTestBase : TestBaseWithProfile() {
@Mock lateinit var profilePlugin: ProfileInterface @Mock lateinit var profilePlugin: ProfileInterface
@Mock lateinit var smsCommunicatorPlugin: SmsCommunicatorInterface @Mock lateinit var smsCommunicatorPlugin: SmsCommunicatorInterface
@Mock lateinit var loopPlugin: TestLoopPlugin @Mock lateinit var loopPlugin: TestLoopPlugin
@Mock lateinit var repository: AppRepository
private val pluginDescription = PluginDescription() private val pluginDescription = PluginDescription()
lateinit var testPumpPlugin: TestPumpPlugin lateinit var testPumpPlugin: TestPumpPlugin
@ -54,11 +56,13 @@ open class ActionsTestBase : TestBaseWithProfile() {
it.aapsLogger = aapsLogger it.aapsLogger = aapsLogger
it.resourceHelper = resourceHelper it.resourceHelper = resourceHelper
it.activePlugin = activePlugin it.activePlugin = activePlugin
it.repository = repository
} }
if (it is ActionStartTempTarget) { if (it is ActionStartTempTarget) {
it.aapsLogger = aapsLogger it.aapsLogger = aapsLogger
it.resourceHelper = resourceHelper it.resourceHelper = resourceHelper
it.activePlugin = activePlugin it.activePlugin = activePlugin
it.repository = repository
} }
if (it is ActionSendSMS) { if (it is ActionSendSMS) {
it.aapsLogger = aapsLogger it.aapsLogger = aapsLogger

View file

@ -2,7 +2,6 @@ package info.nightscout.androidaps.plugins.general.automation.triggers
import com.google.common.base.Optional import com.google.common.base.Optional
import info.nightscout.androidaps.automation.R import info.nightscout.androidaps.automation.R
import info.nightscout.androidaps.db.TempTarget
import info.nightscout.androidaps.plugins.general.automation.elements.ComparatorExists import info.nightscout.androidaps.plugins.general.automation.elements.ComparatorExists
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import org.json.JSONObject import org.json.JSONObject
@ -10,7 +9,6 @@ import org.junit.Assert
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.mockito.Mockito.`when`
import org.powermock.api.mockito.PowerMockito import org.powermock.api.mockito.PowerMockito
import org.powermock.core.classloader.annotations.PrepareForTest import org.powermock.core.classloader.annotations.PrepareForTest
import org.powermock.modules.junit4.PowerMockRunner import org.powermock.modules.junit4.PowerMockRunner
@ -25,20 +23,20 @@ class TriggerTempTargetTest : TriggerTestBase() {
PowerMockito.mockStatic(DateUtil::class.java) PowerMockito.mockStatic(DateUtil::class.java)
PowerMockito.`when`(DateUtil.now()).thenReturn(now) PowerMockito.`when`(DateUtil.now()).thenReturn(now)
} }
/*
@Test fun shouldRunTest() { @Test fun shouldRunTest() {
`when`(treatmentsInterface.tempTargetFromHistory).thenReturn(null) `when`(repository.getTemporaryTargetActiveAt(anyObject())).thenReturn(null)
var t: TriggerTempTarget = TriggerTempTarget(injector).comparator(ComparatorExists.Compare.EXISTS) var t: TriggerTempTarget = TriggerTempTarget(injector).comparator(ComparatorExists.Compare.EXISTS)
Assert.assertFalse(t.shouldRun()) Assert.assertFalse(t.shouldRun())
t = TriggerTempTarget(injector).comparator(ComparatorExists.Compare.NOT_EXISTS) t = TriggerTempTarget(injector).comparator(ComparatorExists.Compare.NOT_EXISTS)
Assert.assertTrue(t.shouldRun()) Assert.assertTrue(t.shouldRun())
PowerMockito.`when`(treatmentsInterface.tempTargetFromHistory).thenReturn(TempTarget()) PowerMockito.`when`(repository.getTemporaryTargetActiveAt(anyObject())).thenReturn(TemporaryTarget(duration = 0, highTarget = 0.0, lowTarget = 0.0, reason = TemporaryTarget.Reason.CUSTOM, timestamp = 0))
t = TriggerTempTarget(injector).comparator(ComparatorExists.Compare.NOT_EXISTS) t = TriggerTempTarget(injector).comparator(ComparatorExists.Compare.NOT_EXISTS)
Assert.assertFalse(t.shouldRun()) Assert.assertFalse(t.shouldRun())
t = TriggerTempTarget(injector).comparator(ComparatorExists.Compare.EXISTS) t = TriggerTempTarget(injector).comparator(ComparatorExists.Compare.EXISTS)
Assert.assertTrue(t.shouldRun()) Assert.assertTrue(t.shouldRun())
} }
*/
@Test fun copyConstructorTest() { @Test fun copyConstructorTest() {
val t: TriggerTempTarget = TriggerTempTarget(injector).comparator(ComparatorExists.Compare.NOT_EXISTS) val t: TriggerTempTarget = TriggerTempTarget(injector).comparator(ComparatorExists.Compare.NOT_EXISTS)
val t1 = t.duplicate() as TriggerTempTarget val t1 = t.duplicate() as TriggerTempTarget

View file

@ -5,6 +5,7 @@ import dagger.android.AndroidInjector
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.TestBaseWithProfile import info.nightscout.androidaps.TestBaseWithProfile
import info.nightscout.androidaps.TestPumpPlugin import info.nightscout.androidaps.TestPumpPlugin
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.IobCobCalculatorInterface import info.nightscout.androidaps.interfaces.IobCobCalculatorInterface
import info.nightscout.androidaps.interfaces.PluginDescription import info.nightscout.androidaps.interfaces.PluginDescription
@ -20,10 +21,9 @@ import info.nightscout.androidaps.utils.sharedPreferences.SP
import org.junit.Before import org.junit.Before
import org.mockito.Mock import org.mockito.Mock
import org.mockito.Mockito.`when` import org.mockito.Mockito.`when`
import org.powermock.api.mockito.PowerMockito
import org.powermock.core.classloader.annotations.PrepareForTest import org.powermock.core.classloader.annotations.PrepareForTest
@PrepareForTest(LastLocationDataContainer::class, AutomationPlugin::class) @PrepareForTest(LastLocationDataContainer::class, AutomationPlugin::class, AppRepository::class)
open class TriggerTestBase : TestBaseWithProfile() { open class TriggerTestBase : TestBaseWithProfile() {
@Mock lateinit var sp: SP @Mock lateinit var sp: SP
@ -32,6 +32,7 @@ open class TriggerTestBase : TestBaseWithProfile() {
@Mock lateinit var iobCobCalculatorPlugin: IobCobCalculatorInterface @Mock lateinit var iobCobCalculatorPlugin: IobCobCalculatorInterface
@Mock lateinit var context: Context @Mock lateinit var context: Context
@Mock lateinit var automationPlugin: AutomationPlugin @Mock lateinit var automationPlugin: AutomationPlugin
@Mock lateinit var repository: AppRepository
lateinit var receiverStatusStore: ReceiverStatusStore lateinit var receiverStatusStore: ReceiverStatusStore
private val pluginDescription = PluginDescription() private val pluginDescription = PluginDescription()

View file

@ -3,6 +3,7 @@
<string name="description_pump_combo">Integrare cu pompele Accu-Chek, necesită aplicația Ruffy</string> <string name="description_pump_combo">Integrare cu pompele Accu-Chek, necesită aplicația Ruffy</string>
<string name="combo_programming_bolus">Se programează pompa pentru livrare bolus</string> <string name="combo_programming_bolus">Se programează pompa pentru livrare bolus</string>
<string name="combo_pump_state_label">Stare</string> <string name="combo_pump_state_label">Stare</string>
<string name="combo_pump_activity_label">Activitate</string>
<string name="combo_no_pump_connection">Fără conexiune de %1$d min</string> <string name="combo_no_pump_connection">Fără conexiune de %1$d min</string>
<string name="combo_tbr_remaining">%1$d%% (%2$d min rămase)</string> <string name="combo_tbr_remaining">%1$d%% (%2$d min rămase)</string>
<string name="combo_pump_state_initializing">Inițializare</string> <string name="combo_pump_state_initializing">Inițializare</string>

View file

@ -6,8 +6,6 @@ import com.j256.ormlite.table.DatabaseTable;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import info.nightscout.androidaps.utils.DateUtil;
/** /**
* Created by mike on 27.02.2016. * Created by mike on 27.02.2016.
* <p> * <p>
@ -35,10 +33,10 @@ public class DbRequest {
} }
// dbAdd // dbAdd
public DbRequest(String action, String collection, JSONObject json) { public DbRequest(String action, String collection, JSONObject json, long nsClientId) {
this.action = action; this.action = action;
this.collection = collection; this.collection = collection;
this.nsClientID = "" + DateUtil.now(); this.nsClientID = "" + nsClientId;
try { try {
json.put("NSCLIENT_ID", nsClientID); json.put("NSCLIENT_ID", nsClientID);
} catch (JSONException e) { } catch (JSONException e) {
@ -49,10 +47,10 @@ public class DbRequest {
} }
// dbUpdate, dbUpdateUnset // dbUpdate, dbUpdateUnset
public DbRequest(String action, String collection, String _id, JSONObject json) { public DbRequest(String action, String collection, String _id, JSONObject json, long nsClientId) {
this.action = action; this.action = action;
this.collection = collection; this.collection = collection;
this.nsClientID = "" + DateUtil.now(); this.nsClientID = "" + nsClientId;
try { try {
json.put("NSCLIENT_ID", nsClientID); json.put("NSCLIENT_ID", nsClientID);
} catch (JSONException e) { } catch (JSONException e) {
@ -63,12 +61,11 @@ public class DbRequest {
} }
// dbRemove // dbRemove
public DbRequest(String action, String collection, public DbRequest(String action, String collection, String _id, long nsClientId) {
String _id) {
JSONObject json = new JSONObject(); JSONObject json = new JSONObject();
this.action = action; this.action = action;
this.collection = collection; this.collection = collection;
this.nsClientID = "" + DateUtil.now(); this.nsClientID = "" + nsClientId;
try { try {
json.put("NSCLIENT_ID", nsClientID); json.put("NSCLIENT_ID", nsClientID);
} catch (JSONException e) { } catch (JSONException e) {

View file

@ -1,199 +0,0 @@
package info.nightscout.androidaps.db;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
import java.util.Objects;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.core.R;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.interfaces.Interval;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.DecimalFormatter;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
@DatabaseTable(tableName = "TempTargets")
public class TempTarget implements Interval {
@DatabaseField(id = true)
public long date;
@DatabaseField
public boolean isValid = true;
@DatabaseField
public int source = Source.NONE;
@DatabaseField
public String _id = null; // NS _id
@DatabaseField
public double low; // in mgdl
@DatabaseField
public double high; // in mgdl
@DatabaseField
public String reason;
@DatabaseField
public int durationInMinutes;
public double target() {
return (low + high) / 2;
}
public boolean isEqual(TempTarget other) {
if (date != other.date) {
return false;
}
if (durationInMinutes != other.durationInMinutes)
return false;
if (low != other.low)
return false;
if (high != other.high)
return false;
if (!Objects.equals(reason, other.reason))
return false;
if (!Objects.equals(_id, other._id))
return false;
return true;
}
public void copyFrom(TempTarget t) {
date = t.date;
_id = t._id;
durationInMinutes = t.durationInMinutes;
low = t.low;
high = t.high;
reason = t.reason;
}
public TempTarget date(long date) {
this.date = date;
return this;
}
public TempTarget low(double low) {
this.low = low;
return this;
}
public TempTarget high(double high) {
this.high = high;
return this;
}
public TempTarget duration(int duration) {
this.durationInMinutes = duration;
return this;
}
public TempTarget reason(String reason) {
this.reason = reason;
return this;
}
public TempTarget _id(String _id) {
this._id = _id;
return this;
}
public TempTarget source(int source) {
this.source = source;
return this;
}
// -------- Interval interface ---------
Long cuttedEnd = null;
public long durationInMsec() {
return durationInMinutes * 60 * 1000L;
}
public long start() {
return date;
}
// planned end time at time of creation
public long originalEnd() {
return date + durationInMinutes * 60 * 1000L;
}
// end time after cut
public long end() {
if (cuttedEnd != null)
return cuttedEnd;
return originalEnd();
}
public void cutEndTo(long end) {
cuttedEnd = end;
}
public boolean match(long time) {
if (start() <= time && end() >= time)
return true;
return false;
}
public boolean before(long time) {
if (end() < time)
return true;
return false;
}
public boolean after(long time) {
if (start() > time)
return true;
return false;
}
@Override
public boolean isInProgress() {
return match(System.currentTimeMillis());
}
@Override
public boolean isEndingEvent() {
return durationInMinutes == 0;
}
@Override
public boolean isValid() {
return true;
}
// -------- Interval interface end ---------
public String lowValueToUnitsToString(String units) {
if (units.equals(Constants.MGDL)) return DecimalFormatter.to0Decimal(low);
else return DecimalFormatter.to1Decimal(low * Constants.MGDL_TO_MMOLL);
}
public String highValueToUnitsToString(String units) {
if (units.equals(Constants.MGDL)) return DecimalFormatter.to0Decimal(high);
else return DecimalFormatter.to1Decimal(low * Constants.MGDL_TO_MMOLL);
}
public String toString(DateUtil dateUtil) {
return "TemporaryTarget{" +
"date=" + date +
"date=" + dateUtil.dateAndTimeString(date) +
", isValid=" + isValid +
", duration=" + durationInMinutes +
", reason=" + reason +
", low=" + low +
", high=" + high +
'}';
}
public String friendlyDescription(String units, ResourceHelper resourceHelper) {
return Profile.toTargetRangeString(low, high, Constants.MGDL, units) +
units +
"@" + resourceHelper.gs(R.string.mins, durationInMinutes) +
(reason != null && !reason.equals("") ? "(" + reason + ")" : "");
}
}

View file

@ -33,7 +33,7 @@ public class TemporaryBasal implements Interval, DbObjectBase {
@Inject public ProfileFunction profileFunction; @Inject public ProfileFunction profileFunction;
@Inject public ActivePluginProvider activePlugin; @Inject public ActivePluginProvider activePlugin;
@Inject public SP sp; @Inject public SP sp;
@Inject DateUtil dateUtil; @Inject public DateUtil dateUtil;
private HasAndroidInjector injector; private HasAndroidInjector injector;

View file

@ -27,7 +27,7 @@ abstract class DialogFragmentWithDate : DaggerDialogFragment() {
@Inject lateinit var sp: SP @Inject lateinit var sp: SP
@Inject lateinit var dateUtil: DateUtil @Inject lateinit var dateUtil: DateUtil
var eventTime = DateUtil.now() var eventTime: Long = 0
var eventTimeChanged = false var eventTimeChanged = false
//one shot guards //one shot guards
@ -60,7 +60,7 @@ abstract class DialogFragmentWithDate : DaggerDialogFragment() {
val eventDateView = view.findViewById(R.id.eventdate) as TextView? val eventDateView = view.findViewById(R.id.eventdate) as TextView?
val eventTimeView = view.findViewById(R.id.eventtime) as TextView? val eventTimeView = view.findViewById(R.id.eventtime) as TextView?
eventTime = savedInstanceState?.getLong("eventTime") ?: DateUtil.now() eventTime = savedInstanceState?.getLong("eventTime") ?: dateUtil.nowWithoutMilliseconds()
eventTimeChanged = savedInstanceState?.getBoolean("eventTimeChanged") ?: false eventTimeChanged = savedInstanceState?.getBoolean("eventTimeChanged") ?: false
eventDateView?.text = DateUtil.dateString(eventTime) eventDateView?.text = DateUtil.dateString(eventTime)

View file

@ -2,10 +2,16 @@ package info.nightscout.androidaps.interfaces
import com.j256.ormlite.dao.CloseableIterator import com.j256.ormlite.dao.CloseableIterator
import info.nightscout.androidaps.db.* import info.nightscout.androidaps.db.*
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import org.json.JSONObject
interface DatabaseHelperInterface { interface DatabaseHelperInterface {
fun resetDatabases()
fun createOrUpdate(careportalEvent: CareportalEvent) fun createOrUpdate(careportalEvent: CareportalEvent)
fun createOrUpdate(extendedBolus: ExtendedBolus): Boolean
fun createOrUpdate(profileSwitch: ProfileSwitch)
fun createOrUpdate(record: DanaRHistoryRecord) fun createOrUpdate(record: DanaRHistoryRecord)
fun createOrUpdate(record: OmnipodHistoryRecord) fun createOrUpdate(record: OmnipodHistoryRecord)
fun createOrUpdate(record: InsightBolusID) fun createOrUpdate(record: InsightBolusID)
@ -17,14 +23,16 @@ interface DatabaseHelperInterface {
fun size(table: String): Long fun size(table: String): Long
fun deleteAllDbRequests() fun deleteAllDbRequests()
fun deleteDbRequest(id: String): Int fun deleteDbRequest(id: String): Int
fun delete(tempBasal: TemporaryBasal)
fun delete(extendedBolus: ExtendedBolus) fun delete(extendedBolus: ExtendedBolus)
fun deleteDbRequestbyMongoId(action: String, _id: String) fun deleteDbRequestbyMongoId(action: String, _id: String)
fun getDbRequestInterator(): CloseableIterator<DbRequest> fun getDbRequestInterator(): CloseableIterator<DbRequest>
fun roundDateToSec(date: Long): Long fun roundDateToSec(date: Long): Long
fun createOrUpdateTDD(record: TDD) fun createOrUpdateTDD(record: TDD)
fun createOrUpdate(tempBasal: TemporaryBasal) fun createOrUpdate(tempBasal: TemporaryBasal): Boolean
fun findTempBasalByPumpId(id: Long): TemporaryBasal fun findTempBasalByPumpId(id: Long): TemporaryBasal
fun getTemporaryBasalsDataFromTime(mills: Long, ascending: Boolean): List<TemporaryBasal> fun getTemporaryBasalsDataFromTime(mills: Long, ascending: Boolean): List<TemporaryBasal>
fun getExtendedBolusDataFromTime(mills: Long, ascending: Boolean): List<ExtendedBolus>
fun getCareportalEventFromTimestamp(timestamp: Long): CareportalEvent? fun getCareportalEventFromTimestamp(timestamp: Long): CareportalEvent?
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?
@ -32,6 +40,16 @@ interface DatabaseHelperInterface {
fun getProfileSwitchData(from: Long, ascending: Boolean): List<ProfileSwitch> fun getProfileSwitchData(from: Long, ascending: Boolean): List<ProfileSwitch>
fun getExtendedBolusByPumpId(pumpId: Long): ExtendedBolus? fun getExtendedBolusByPumpId(pumpId: Long): ExtendedBolus?
// old DB model
fun deleteTempBasalById(_id: String)
fun deleteExtendedBolusById(_id: String)
fun deleteCareportalEventById(_id: String)
fun deleteProfileSwitchById(_id: String)
fun createTempBasalFromJsonIfNotExists(json: JSONObject)
fun createExtendedBolusFromJsonIfNotExists(json: JSONObject)
fun createCareportalEventFromJsonIfNotExists(json: JSONObject)
fun createProfileSwitchFromJsonIfNotExists(activePluginProvider: ActivePluginProvider, nsUpload: NSUpload, trJson: JSONObject)
fun getInsightBolusID(pumpSerial: String, bolusID: Int, timestamp: Long): InsightBolusID? fun getInsightBolusID(pumpSerial: String, bolusID: Int, timestamp: Long): InsightBolusID?
fun getInsightHistoryOffset(pumpSerial: String): InsightHistoryOffset? fun getInsightHistoryOffset(pumpSerial: String): InsightHistoryOffset?
fun getPumpStoppedEvent(pumpSerial: String, before: Long): InsightPumpID? fun getPumpStoppedEvent(pumpSerial: String, before: Long): InsightPumpID?

View file

@ -11,7 +11,6 @@ import info.nightscout.androidaps.data.NonOverlappingIntervals;
import info.nightscout.androidaps.data.ProfileIntervals; import info.nightscout.androidaps.data.ProfileIntervals;
import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.ProfileSwitch; import info.nightscout.androidaps.db.ProfileSwitch;
import info.nightscout.androidaps.db.TempTarget;
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.plugins.treatments.TreatmentUpdateReturn; import info.nightscout.androidaps.plugins.treatments.TreatmentUpdateReturn;
@ -42,6 +41,7 @@ public interface TreatmentsInterface {
List<Treatment> getTreatmentsFromHistoryAfterTimestamp(long timestamp); List<Treatment> getTreatmentsFromHistoryAfterTimestamp(long timestamp);
long getLastBolusTime(); long getLastBolusTime();
long getLastBolusTime(boolean excludeSMB); long getLastBolusTime(boolean excludeSMB);
// real basals (not faked by extended bolus) // real basals (not faked by extended bolus)
@ -60,7 +60,7 @@ public interface TreatmentsInterface {
void removeTempBasal(TemporaryBasal temporaryBasal); void removeTempBasal(TemporaryBasal temporaryBasal);
boolean isInHistoryExtendedBoluslInProgress(); boolean isInHistoryExtendedBolusInProgress();
ExtendedBolus getExtendedBolusFromHistory(long time); ExtendedBolus getExtendedBolusFromHistory(long time);
@ -70,14 +70,6 @@ public interface TreatmentsInterface {
boolean addToHistoryTreatment(DetailedBolusInfo detailedBolusInfo, boolean allowUpdate); boolean addToHistoryTreatment(DetailedBolusInfo detailedBolusInfo, boolean allowUpdate);
TempTarget getTempTargetFromHistory();
TempTarget getTempTargetFromHistory(long time);
Intervals<TempTarget> getTempTargetsFromHistory();
void addToHistoryTempTarget(TempTarget tempTarget);
ProfileSwitch getProfileSwitchFromHistory(long time); ProfileSwitch getProfileSwitchFromHistory(long time);
ProfileIntervals<ProfileSwitch> getProfileSwitchesFromHistory(); ProfileIntervals<ProfileSwitch> getProfileSwitchesFromHistory();

View file

@ -20,12 +20,12 @@ import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.database.entities.GlucoseValue; import info.nightscout.androidaps.database.entities.GlucoseValue;
import info.nightscout.androidaps.database.entities.TemporaryTarget;
import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.db.DbRequest; import info.nightscout.androidaps.db.DbRequest;
import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.ProfileSwitch; import info.nightscout.androidaps.db.ProfileSwitch;
import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface; import info.nightscout.androidaps.interfaces.DatabaseHelperInterface;
import info.nightscout.androidaps.interfaces.IobCobCalculatorInterface; import info.nightscout.androidaps.interfaces.IobCobCalculatorInterface;
@ -42,6 +42,7 @@ import info.nightscout.androidaps.plugins.configBuilder.RunningConfiguration;
import info.nightscout.androidaps.receivers.ReceiverStatusStore; import info.nightscout.androidaps.receivers.ReceiverStatusStore;
import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.JsonHelper; import info.nightscout.androidaps.utils.JsonHelper;
import info.nightscout.androidaps.utils.T;
import info.nightscout.androidaps.utils.resources.ResourceHelper; import info.nightscout.androidaps.utils.resources.ResourceHelper;
import info.nightscout.androidaps.utils.sharedPreferences.SP; import info.nightscout.androidaps.utils.sharedPreferences.SP;
@ -55,10 +56,12 @@ public class NSUpload {
private final AAPSLogger aapsLogger; private final AAPSLogger aapsLogger;
private final ResourceHelper resourceHelper; private final ResourceHelper resourceHelper;
private final SP sp; private final SP sp;
private final Context context;
private final UploadQueueInterface uploadQueue; private final UploadQueueInterface uploadQueue;
private final DatabaseHelperInterface databaseHelper; private final DatabaseHelperInterface databaseHelper;
private final RunningConfiguration runningConfiguration; private final RunningConfiguration runningConfiguration;
private final ProfileFunction profileFunction;
public static String ISVALID = "isValid";
@Inject @Inject
public NSUpload( public NSUpload(
@ -66,19 +69,19 @@ public class NSUpload {
AAPSLogger aapsLogger, AAPSLogger aapsLogger,
ResourceHelper resourceHelper, ResourceHelper resourceHelper,
SP sp, SP sp,
Context context,
UploadQueueInterface uploadQueue, UploadQueueInterface uploadQueue,
RunningConfiguration runningConfiguration, RunningConfiguration runningConfiguration,
DatabaseHelperInterface databaseHelper DatabaseHelperInterface databaseHelper,
ProfileFunction profileFunction
) { ) {
this.injector = injector; this.injector = injector;
this.aapsLogger = aapsLogger; this.aapsLogger = aapsLogger;
this.resourceHelper = resourceHelper; this.resourceHelper = resourceHelper;
this.sp = sp; this.sp = sp;
this.context = context;
this.uploadQueue = uploadQueue; this.uploadQueue = uploadQueue;
this.runningConfiguration = runningConfiguration; this.runningConfiguration = runningConfiguration;
this.databaseHelper = databaseHelper; this.databaseHelper = databaseHelper;
this.profileFunction = profileFunction;
} }
public void uploadTempBasalStartAbsolute(TemporaryBasal temporaryBasal, Double originalExtendedAmount) { public void uploadTempBasalStartAbsolute(TemporaryBasal temporaryBasal, Double originalExtendedAmount) {
@ -94,7 +97,7 @@ public class NSUpload {
data.put("enteredBy", "openaps://" + "AndroidAPS"); data.put("enteredBy", "openaps://" + "AndroidAPS");
if (originalExtendedAmount != null) if (originalExtendedAmount != null)
data.put("originalExtendedAmount", originalExtendedAmount); // for back synchronization data.put("originalExtendedAmount", originalExtendedAmount); // for back synchronization
uploadQueue.add(new DbRequest("dbAdd", "treatments", data)); uploadQueue.add(new DbRequest("dbAdd", "treatments", data, temporaryBasal.date));
} catch (JSONException e) { } catch (JSONException e) {
aapsLogger.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
} }
@ -125,7 +128,7 @@ public class NSUpload {
data.put("pumpId", temporaryBasal.pumpId); data.put("pumpId", temporaryBasal.pumpId);
data.put("created_at", DateUtil.toISOString(temporaryBasal.date)); data.put("created_at", DateUtil.toISOString(temporaryBasal.date));
data.put("enteredBy", "openaps://" + "AndroidAPS"); data.put("enteredBy", "openaps://" + "AndroidAPS");
uploadQueue.add(new DbRequest("dbAdd", "treatments", data)); uploadQueue.add(new DbRequest("dbAdd", "treatments", data, temporaryBasal.date));
} }
} catch (JSONException e) { } catch (JSONException e) {
aapsLogger.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
@ -142,7 +145,7 @@ public class NSUpload {
data.put("isFakedTempBasal", isFakedTempBasal); data.put("isFakedTempBasal", isFakedTempBasal);
if (pumpId != 0) if (pumpId != 0)
data.put("pumpId", pumpId); data.put("pumpId", pumpId);
uploadQueue.add(new DbRequest("dbAdd", "treatments", data)); uploadQueue.add(new DbRequest("dbAdd", "treatments", data, time));
} catch (JSONException e) { } catch (JSONException e) {
aapsLogger.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
} }
@ -161,7 +164,7 @@ public class NSUpload {
data.put("pumpId", extendedBolus.pumpId); data.put("pumpId", extendedBolus.pumpId);
data.put("created_at", DateUtil.toISOString(extendedBolus.date)); data.put("created_at", DateUtil.toISOString(extendedBolus.date));
data.put("enteredBy", "openaps://" + "AndroidAPS"); data.put("enteredBy", "openaps://" + "AndroidAPS");
uploadQueue.add(new DbRequest("dbAdd", "treatments", data)); uploadQueue.add(new DbRequest("dbAdd", "treatments", data, extendedBolus.date));
} catch (JSONException e) { } catch (JSONException e) {
aapsLogger.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
} }
@ -180,7 +183,7 @@ public class NSUpload {
data.put("enteredBy", "openaps://" + "AndroidAPS"); data.put("enteredBy", "openaps://" + "AndroidAPS");
if (pumpId != 0) if (pumpId != 0)
data.put("pumpId", pumpId); data.put("pumpId", pumpId);
uploadQueue.add(new DbRequest("dbAdd", "treatments", data)); uploadQueue.add(new DbRequest("dbAdd", "treatments", data, time));
} catch (JSONException e) { } catch (JSONException e) {
aapsLogger.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
} }
@ -241,14 +244,13 @@ public class NSUpload {
deviceStatus.pump = pumpstatus; deviceStatus.pump = pumpstatus;
} }
int batteryLevel = receiverStatusStore.getBatteryLevel(); deviceStatus.uploaderBattery = receiverStatusStore.getBatteryLevel();
deviceStatus.uploaderBattery = batteryLevel;
deviceStatus.created_at = DateUtil.toISOString(new Date()); deviceStatus.created_at = DateUtil.toISOString(new Date());
deviceStatus.configuration = runningConfiguration.configuration(); deviceStatus.configuration = runningConfiguration.configuration();
uploadQueue.add(new DbRequest("dbAdd", "devicestatus", deviceStatus.mongoRecord())); uploadQueue.add(new DbRequest("dbAdd", "devicestatus", deviceStatus.mongoRecord(), System.currentTimeMillis()));
} catch (JSONException e) { } catch (JSONException e) {
aapsLogger.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
} }
@ -279,32 +281,53 @@ public class NSUpload {
} catch (JSONException e) { } catch (JSONException e) {
aapsLogger.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
} }
uploadCareportalEntryToNS(data); uploadCareportalEntryToNS(data, detailedBolusInfo.date);
} }
public void uploadProfileSwitch(ProfileSwitch profileSwitch) { public void uploadProfileSwitch(ProfileSwitch profileSwitch, long nsClientId) {
try { try {
JSONObject data = getJson(profileSwitch); JSONObject data = getJson(profileSwitch);
uploadCareportalEntryToNS(data); uploadCareportalEntryToNS(data, nsClientId);
} catch (JSONException e) { } catch (JSONException e) {
aapsLogger.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
} }
} }
public void uploadTempTarget(TempTarget tempTarget, ProfileFunction profileFunction) { public void uploadTempTarget(TemporaryTarget tempTarget) {
try { try {
JSONObject data = new JSONObject(); JSONObject data = new JSONObject();
data.put("eventType", CareportalEvent.TEMPORARYTARGET); data.put("eventType", CareportalEvent.TEMPORARYTARGET);
data.put("duration", tempTarget.durationInMinutes); data.put("duration", T.msecs(tempTarget.getDuration()).mins());
if (tempTarget.low > 0) { data.put(ISVALID, tempTarget.isValid());
data.put("reason", tempTarget.reason); if (tempTarget.getLowTarget() > 0) {
data.put("targetBottom", Profile.fromMgdlToUnits(tempTarget.low, profileFunction.getUnits())); data.put("reason", tempTarget.getReason().getText());
data.put("targetTop", Profile.fromMgdlToUnits(tempTarget.high, profileFunction.getUnits())); data.put("targetBottom", Profile.fromMgdlToUnits(tempTarget.getLowTarget(), profileFunction.getUnits()));
data.put("targetTop", Profile.fromMgdlToUnits(tempTarget.getHighTarget(), profileFunction.getUnits()));
data.put("units", profileFunction.getUnits()); data.put("units", profileFunction.getUnits());
} }
data.put("created_at", DateUtil.toISOString(tempTarget.date)); data.put("created_at", DateUtil.toISOString(tempTarget.getTimestamp()));
data.put("enteredBy", "AndroidAPS"); data.put("enteredBy", "AndroidAPS");
uploadCareportalEntryToNS(data); uploadCareportalEntryToNS(data, tempTarget.getTimestamp());
} catch (JSONException e) {
aapsLogger.error("Unhandled exception", e);
}
}
public void updateTempTarget(TemporaryTarget tempTarget) {
try {
JSONObject data = new JSONObject();
data.put("eventType", CareportalEvent.TEMPORARYTARGET);
data.put("duration", T.msecs(tempTarget.getDuration()).mins());
data.put(ISVALID, tempTarget.isValid());
if (tempTarget.getLowTarget() > 0) {
data.put("reason", tempTarget.getReason().getText());
data.put("targetBottom", Profile.fromMgdlToUnits(tempTarget.getLowTarget(), profileFunction.getUnits()));
data.put("targetTop", Profile.fromMgdlToUnits(tempTarget.getHighTarget(), profileFunction.getUnits()));
data.put("units", profileFunction.getUnits());
}
data.put("created_at", DateUtil.toISOString(tempTarget.getTimestamp()));
data.put("enteredBy", "AndroidAPS");
uploadQueue.add(new DbRequest("dbUpdate", "treatments", tempTarget.getInterfaceIDs().getNightscoutId(), data, tempTarget.getTimestamp()));
} catch (JSONException e) { } catch (JSONException e) {
aapsLogger.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
} }
@ -314,7 +337,7 @@ public class NSUpload {
try { try {
JSONObject data = getJson(profileSwitch); JSONObject data = getJson(profileSwitch);
if (profileSwitch._id != null) { if (profileSwitch._id != null) {
uploadQueue.add(new DbRequest("dbUpdate", "treatments", profileSwitch._id, data)); uploadQueue.add(new DbRequest("dbUpdate", "treatments", profileSwitch._id, data, profileSwitch.date));
} }
} catch (JSONException e) { } catch (JSONException e) {
aapsLogger.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
@ -339,7 +362,7 @@ public class NSUpload {
return data; return data;
} }
public void uploadCareportalEntryToNS(JSONObject data) { public void uploadCareportalEntryToNS(JSONObject data, long nsClientId) {
try { try {
if (data.has("preBolus") && data.has("carbs")) { if (data.has("preBolus") && data.has("carbs")) {
JSONObject prebolus = new JSONObject(); JSONObject prebolus = new JSONObject();
@ -351,9 +374,9 @@ public class NSUpload {
long mills = DateUtil.fromISODateString(data.getString("created_at")).getTime(); long mills = DateUtil.fromISODateString(data.getString("created_at")).getTime();
Date preBolusDate = new Date(mills + data.getInt("preBolus") * 60000L + 1000L); Date preBolusDate = new Date(mills + data.getInt("preBolus") * 60000L + 1000L);
prebolus.put("created_at", DateUtil.toISOString(preBolusDate)); prebolus.put("created_at", DateUtil.toISOString(preBolusDate));
uploadCareportalEntryToNS(prebolus); uploadCareportalEntryToNS(prebolus, preBolusDate.getTime());
} }
DbRequest dbr = new DbRequest("dbAdd", "treatments", data); DbRequest dbr = new DbRequest("dbAdd", "treatments", data, nsClientId);
aapsLogger.debug("Prepared: " + dbr.log()); aapsLogger.debug("Prepared: " + dbr.log());
uploadQueue.add(dbr); uploadQueue.add(dbr);
} catch (Exception e) { } catch (Exception e) {
@ -363,7 +386,7 @@ public class NSUpload {
} }
public void removeCareportalEntryFromNS(String _id) { public void removeCareportalEntryFromNS(String _id) {
uploadQueue.add(new DbRequest("dbRemove", "treatments", _id)); uploadQueue.add(new DbRequest("dbRemove", "treatments", _id, System.currentTimeMillis()));
} }
public void uploadOpenAPSOffline(CareportalEvent event) { public void uploadOpenAPSOffline(CareportalEvent event) {
@ -371,7 +394,7 @@ public class NSUpload {
JSONObject data = new JSONObject(event.json); JSONObject data = new JSONObject(event.json);
data.put("created_at", DateUtil.toISOString(event.date)); data.put("created_at", DateUtil.toISOString(event.date));
data.put("enteredBy", "openaps://" + "AndroidAPS"); data.put("enteredBy", "openaps://" + "AndroidAPS");
uploadQueue.add(new DbRequest("dbAdd", "treatments", data)); uploadQueue.add(new DbRequest("dbAdd", "treatments", data, event.date));
} catch (JSONException e) { } catch (JSONException e) {
aapsLogger.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
} }
@ -392,7 +415,7 @@ public class NSUpload {
} catch (JSONException e) { } catch (JSONException e) {
aapsLogger.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
} }
uploadQueue.add(new DbRequest("dbAdd", "treatments", data)); uploadQueue.add(new DbRequest("dbAdd", "treatments", data, date.getTime()));
} }
public void uploadBg(GlucoseValue reading, String source) { public void uploadBg(GlucoseValue reading, String source) {
@ -407,7 +430,7 @@ public class NSUpload {
} catch (JSONException e) { } catch (JSONException e) {
aapsLogger.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
} }
uploadQueue.add(new DbRequest("dbAdd", "entries", data)); uploadQueue.add(new DbRequest("dbAdd", "entries", data, reading.getTimestamp()));
} }
public void updateBg(GlucoseValue reading, String source) { public void updateBg(GlucoseValue reading, String source) {
@ -419,10 +442,9 @@ public class NSUpload {
data.put("sgv", reading.getValue()); data.put("sgv", reading.getValue());
data.put("direction", reading.getTrendArrow().getText()); data.put("direction", reading.getTrendArrow().getText());
data.put("type", "sgv"); data.put("type", "sgv");
if (reading.getInterfaceIDs() != null) if (reading.getInterfaceIDs().getNightscoutId() != null) {
if (reading.getInterfaceIDs().getNightscoutId() != null) { uploadQueue.add(new DbRequest("dbUpdate", "entries", reading.getInterfaceIDs().getNightscoutId(), data, System.currentTimeMillis()));
uploadQueue.add(new DbRequest("dbUpdate", "entries", reading.getInterfaceIDs().getNightscoutId(), data)); }
}
} catch (JSONException e) { } catch (JSONException e) {
aapsLogger.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
} }
@ -438,13 +460,13 @@ public class NSUpload {
} catch (JSONException e) { } catch (JSONException e) {
aapsLogger.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
} }
uploadQueue.add(new DbRequest("dbAdd", "treatments", data)); uploadQueue.add(new DbRequest("dbAdd", "treatments", data, System.currentTimeMillis()));
} }
} }
public void uploadProfileStore(JSONObject profileStore) { public void uploadProfileStore(JSONObject profileStore) {
if (sp.getBoolean(R.string.key_ns_uploadlocalprofile, false)) { if (sp.getBoolean(R.string.key_ns_uploadlocalprofile, false)) {
uploadQueue.add(new DbRequest("dbAdd", "profile", profileStore)); uploadQueue.add(new DbRequest("dbAdd", "profile", profileStore, System.currentTimeMillis()));
} }
} }
@ -460,12 +482,12 @@ public class NSUpload {
} catch (JSONException e) { } catch (JSONException e) {
aapsLogger.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
} }
uploadQueue.add(new DbRequest("dbAdd", "treatments", data)); uploadQueue.add(new DbRequest("dbAdd", "treatments", data, time));
} }
public void removeFoodFromNS(String _id) { public void removeFoodFromNS(String _id) {
try { try {
uploadQueue.add(new DbRequest("dbRemove", "food", _id)); uploadQueue.add(new DbRequest("dbRemove", "food", _id, System.currentTimeMillis()));
} catch (Exception e) { } catch (Exception e) {
aapsLogger.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
} }
@ -482,9 +504,9 @@ public class NSUpload {
JsonHelper.safeGetInt(data, "timeshift"), JsonHelper.safeGetInt(data, "timeshift"),
eventTime eventTime
); );
uploadProfileSwitch(profileSwitch); uploadProfileSwitch(profileSwitch, eventTime);
} else { } else {
uploadCareportalEntryToNS(data); uploadCareportalEntryToNS(data, eventTime);
} }
} }

View file

@ -51,7 +51,7 @@ public class DateUtil {
/** /**
* The date format in iso. * The date format in iso.
*/ */
private static final String FORMAT_DATE_ISO_OUT = "yyyy-MM-dd'T'HH:mm:ss'Z'"; private static final String FORMAT_DATE_ISO_OUT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
/** /**
* Takes in an ISO date string of the following format: * Takes in an ISO date string of the following format:
@ -255,6 +255,12 @@ public class DateUtil {
return System.currentTimeMillis(); return System.currentTimeMillis();
} }
public long nowWithoutMilliseconds() {
long n = System.currentTimeMillis();
n = n - n % 1000;
return n;
}
public static long now() { public static long now() {
return System.currentTimeMillis(); return System.currentTimeMillis();
} }

View file

@ -1,6 +1,5 @@
package info.nightscout.androidaps.utils package info.nightscout.androidaps.utils
import android.content.Context
import android.os.Bundle import android.os.Bundle
import com.google.firebase.analytics.FirebaseAnalytics import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.analytics.ktx.analytics import com.google.firebase.analytics.ktx.analytics
@ -79,7 +78,7 @@ class FabricPrivacy @Inject constructor(
// Crashlytics logException // Crashlytics logException
fun logException(throwable: Throwable) { fun logException(throwable: Throwable) {
FirebaseCrashlytics.getInstance().recordException(throwable) FirebaseCrashlytics.getInstance().recordException(throwable)
aapsLogger.debug(LTag.CORE, "Exception: ", throwable) aapsLogger.error("Exception: ", throwable)
} }
fun fabricEnabled(): Boolean { fun fabricEnabled(): Boolean {

View file

@ -129,9 +129,21 @@ object JsonHelper {
return result return result
} }
fun safeGetLongAllowNull(json: JSONObject?, fieldName: String, defaultValue: Long? = null): Long? {
var result: Long? = defaultValue
if (json != null && json.has(fieldName)) {
try {
result = json.getLong(fieldName)
} catch (ignored: JSONException) {
}
}
return result
}
@JvmStatic @JvmStatic
fun safeGetBoolean(json: JSONObject?, fieldName: String): Boolean { @JvmOverloads
var result = false fun safeGetBoolean(json: JSONObject?, fieldName: String, defaultValue: Boolean = false): Boolean {
var result = defaultValue
if (json != null && json.has(fieldName)) { if (json != null && json.has(fieldName)) {
try { try {
result = json.getBoolean(fieldName) result = json.getBoolean(fieldName)

View file

@ -0,0 +1,84 @@
package info.nightscout.androidaps.utils.extensions
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.core.R
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.JsonHelper
import info.nightscout.androidaps.utils.resources.ResourceHelper
import org.json.JSONObject
import java.util.concurrent.TimeUnit
fun TemporaryTarget.lowValueToUnitsToString(units: String): String =
if (units == Constants.MGDL) DecimalFormatter.to0Decimal(this.lowTarget)
else DecimalFormatter.to1Decimal(this.lowTarget * Constants.MGDL_TO_MMOLL)
fun TemporaryTarget.highValueToUnitsToString(units: String): String =
if (units == Constants.MGDL) DecimalFormatter.to0Decimal(this.highTarget)
else DecimalFormatter.to1Decimal(this.highTarget * Constants.MGDL_TO_MMOLL)
fun TemporaryTarget.target(): Double =
(this.lowTarget + this.highTarget) / 2
fun TemporaryTarget.friendlyDescription(units: String, resourceHelper: ResourceHelper): String =
Profile.toTargetRangeString(lowTarget, highTarget, Constants.MGDL, units) +
units +
"@" + resourceHelper.gs(R.string.format_mins, TimeUnit.MILLISECONDS.toMinutes(duration)) + "(" + reason.text + ")"
/*
create fake object with nsID and isValid == false
*/
fun temporaryTargetFromNsIdForInvalidating(nsId: String): TemporaryTarget =
temporaryTargetFromJson(
JSONObject()
.put("mills", 1)
.put("duration", -1)
.put("reason", "fake")
.put("_id", nsId)
.put(NSUpload.ISVALID, false)
)!!
fun temporaryTargetFromJson(jsonObject: JSONObject): TemporaryTarget? {
val units = JsonHelper.safeGetString(jsonObject, "units", Constants.MGDL)
val timestamp = JsonHelper.safeGetLongAllowNull(jsonObject, "mills", null) ?: return null
val duration = JsonHelper.safeGetLongAllowNull(jsonObject, "duration", null) ?: return null
var low = JsonHelper.safeGetDouble(jsonObject, "targetBottom")
low = Profile.toMgdl(low, units)
var high = JsonHelper.safeGetDouble(jsonObject, "targetTop")
high = Profile.toMgdl(high, units)
val reasonString = if (duration != 0L) JsonHelper.safeGetStringAllowNull(jsonObject, "reason", null)
?: return null else ""
// this string can be localized from NS, it will not work in this case CUSTOM will be used
val reason = TemporaryTarget.Reason.fromString(reasonString)
val id = JsonHelper.safeGetStringAllowNull(jsonObject, "_id", null) ?: return null
val isValid = JsonHelper.safeGetBoolean(jsonObject, NSUpload.ISVALID, true)
if (duration > 0L) {
// not ending event
if (units == Constants.MMOL) {
if (low < Constants.MIN_TT_MMOL) return null
if (low > Constants.MAX_TT_MMOL) return null
if (high < Constants.MIN_TT_MMOL) return null
if (high > Constants.MAX_TT_MMOL) return null
if (low > high) return null
} else {
if (low < Constants.MIN_TT_MGDL) return null
if (low > Constants.MAX_TT_MGDL) return null
if (high < Constants.MIN_TT_MGDL) return null
if (high > Constants.MAX_TT_MGDL) return null
if (low > high) return null
}
}
val tt = TemporaryTarget(
timestamp = timestamp,
duration = TimeUnit.MINUTES.toMillis(duration),
reason = reason,
lowTarget = low,
highTarget = high,
isValid = isValid
)
tt.interfaceIDs.nightscoutId = id
return tt
}

View file

@ -76,10 +76,33 @@
<string name="limitingmaxiob">Begrenze max. IOB auf %1$.1f IE wegen %2$s</string> <string name="limitingmaxiob">Begrenze max. IOB auf %1$.1f IE wegen %2$s</string>
<string name="unsafeusage">Unsichere Benutzung</string> <string name="unsafeusage">Unsichere Benutzung</string>
<string name="pump_unreachable">Pumpe nicht erreichbar</string> <string name="pump_unreachable">Pumpe nicht erreichbar</string>
<string name="extended_bolus">Verzögerter Bolus</string>
<string name="pump_time_updated">Pumpenzeit aktualisiert</string>
<string name="exit">Verlassen</string>
<string name="serial_number">Seriennummer</string>
<string name="removerecord">Eintrag löschen</string>
<string name="loopisdisabled">Loop ist deaktiviert.</string> <string name="loopisdisabled">Loop ist deaktiviert.</string>
<string name="alarm">Alarm</string>
<string name="disableloop">Loop deaktivieren</string>
<string name="enableloop">Loop aktivieren</string>
<string name="resumeloop">Loop fortsetzen</string>
<string name="suspendloop">Loop pausieren</string>
<string name="duration_min_label">Dauer [min]</string> <string name="duration_min_label">Dauer [min]</string>
<string name="notification">Benachrichtigung</string>
<string name="noprofile">Bisher noch kein Profil von Nightscout geladen</string>
<string name="exists">vorhanden</string>
<string name="notexists">nicht vorhanden</string>
<string name="glucose">Glukose</string>
<string name="iob">IOB</string>
<string name="cob">COB</string>
<string name="name_short">Name:</string>
<string name="time">Zeit</string>
<string name="ns_wifi_ssids">WLAN SSID</string>
<string name="loading">Lade…</string>
<string name="event_time_label">Ereignis-Zeit</string>
<string name="notes_label">Notizen</string> <string name="notes_label">Notizen</string>
<string name="remove_button">Löschen</string> <string name="remove_button">Löschen</string>
<string name="addnew">Weiteren hinzufügen</string>
<!-- Constraints--> <!-- Constraints-->
<string name="limitingbasalratio">Begrenzung der max. Basalrate auf %1$.2f IE/h wegen %2$s</string> <string name="limitingbasalratio">Begrenzung der max. Basalrate auf %1$.2f IE/h wegen %2$s</string>
<string name="pumplimit">Limit der Pumpe</string> <string name="pumplimit">Limit der Pumpe</string>

View file

@ -1,2 +1,24 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources></resources> <resources>
<string name="error_only_numeric_digits_allowed">Nur numerische Ziffern zulässig.</string>
<string name="error_only_numeric_digits_range_allowed">Bitte verwende nur Ziffern von %1$s - %2$s.</string>
<string name="error_this_field_cannot_contain_special_character">Dieses Feld darf kein Sonderzeichen enthalten.</string>
<string name="error_only_standard_letters_are_allowed">Nur Standard-Buchstaben erlaubt</string>
<string name="error_field_must_not_be_empty">Das Feld darf nicht leer sein.</string>
<string name="error_email_address_not_valid">E-Mail Adresse ungültig</string>
<string name="error_creditcard_number_not_valid">Kreditkartennummer ungültig</string>
<string name="error_phone_not_valid">Telefonnummer ungültig</string>
<string name="error_domain_not_valid">Domain-Name ungültig</string>
<string name="error_ip_not_valid">IP-Adresse ungültig</string>
<string name="error_url_not_valid">Web-Adresse (URL) ungültig</string>
<string name="error_notvalid_personname">Kein gültiger Vor- oder Nachname</string>
<string name="error_notvalid_personfullname">Kein gültiger Name</string>
<string name="error_date_not_valid">Format ungültig</string>
<string name="error_mustbe4digitnumber">Bitte 4-stellige Zahl verwenden</string>
<string name="error_mustbe6digitnumber">Bitte 6-stellige Zahl verwenden</string>
<string name="error_mustbe12hexadidits">Bitte 12 Zeichen aus ABCDEF0123456789 verwenden</string>
<string name="error_mustbe8hexadidits">Bitte 8 Zeichen aus ABCDEF0123456789 verwenden</string>
<string name="error_mustbe4hexadidits">Bitte 4 Zeichen aus ABCDEF0123456789 verwenden</string>
<string name="error_not_a_minimum_length">Mindestlänge nicht erreicht</string>
<string name="error_pin_not_valid">Pin sollte 3- bis 6-stellig sein, unterschiedliche und nicht aufeinanderfolgende Zahlen enthalten.</string>
</resources>

View file

@ -1,2 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources></resources> <resources>
<string name="error_only_numeric_digits_allowed">Alleen cijfers zijn toegestaan.</string>
<string name="error_only_numeric_digits_range_allowed">Alleen cijfers binnen het bereik %1$s - %2$s zijn toegestaan.</string>
</resources>

View file

@ -2,6 +2,7 @@
<resources> <resources>
<!-- Keys--> <!-- Keys-->
<!-- General--> <!-- General-->
<string name="refresh">Actualizează</string>
<string name="error">Eroare</string> <string name="error">Eroare</string>
<string name="not_set_short">Nesetată</string> <string name="not_set_short">Nesetată</string>
<string name="failedupdatebasalprofile">Actualizarea profilului bazalei a eșuat</string> <string name="failedupdatebasalprofile">Actualizarea profilului bazalei a eșuat</string>
@ -68,6 +69,40 @@
<string name="pairing">Împerechere</string> <string name="pairing">Împerechere</string>
<string name="yes">Da</string> <string name="yes">Da</string>
<string name="no">Nu</string> <string name="no">Nu</string>
<string name="loopdisabled">BUCLĂ DEZACTIVATĂ DATORITĂ CONSTRÂNGERILOR</string>
<string name="bolusdelivered">Bolusul de %1$.2fU a fost livrat cu succes</string>
<string name="virtualpump_resultok">OK</string>
<string name="novalidbasalrate">Nu s-a citit o rată bazală validă din pompă</string>
<string name="limitingmaxiob">Se limitează maximum IOB la %1$.1f U datorită %2$s</string>
<string name="unsafeusage">utilizare nesigură</string>
<string name="pump_unreachable">Pompă indisponibilă</string>
<string name="extended_bolus">Bolus extins</string>
<string name="pump_time_updated">Timpul din pompă a fost actualizat</string>
<string name="exit">Ieșire</string>
<string name="serial_number">Număr serial</string>
<string name="removerecord">Șterge înregistrarea</string>
<string name="loopisdisabled">Bucla este dezactivată</string>
<string name="alarm">Alarmă</string>
<string name="disableloop">Dezactivează bucla</string>
<string name="enableloop">Activează bucla</string>
<string name="resumeloop">Repornește bucla</string>
<string name="suspendloop">Suspendă bucla</string>
<string name="duration_min_label">Durată [min]</string>
<string name="notification">Notificare</string>
<string name="noprofile">Nu s-a încărcat încă un profil din NS</string>
<string name="exists">există</string>
<string name="notexists">nu există</string>
<string name="glucose">Glicemie</string>
<string name="iob">IOB</string>
<string name="cob">COB</string>
<string name="name_short">Nume:</string>
<string name="time">Timp</string>
<string name="ns_wifi_ssids">SSID WiFi</string>
<string name="loading">Se încarcă…</string>
<string name="event_time_label">Ora evenimentului</string>
<string name="notes_label">Note</string>
<string name="remove_button">Șterge</string>
<string name="addnew">Adăugare</string>
<!-- Constraints--> <!-- Constraints-->
<string name="limitingbasalratio">Se limitează maximul ratei bazale la %1$.2f U/o datorită %2$s</string> <string name="limitingbasalratio">Se limitează maximul ratei bazale la %1$.2f U/o datorită %2$s</string>
<string name="pumplimit">limită pompă</string> <string name="pumplimit">limită pompă</string>
@ -217,6 +252,7 @@
<string name="history_group_glucose">Glicemie</string> <string name="history_group_glucose">Glicemie</string>
<string name="mute5min">Dezactivează pentru 5 minute</string> <string name="mute5min">Dezactivează pentru 5 minute</string>
<!-- Maintenance --> <!-- Maintenance -->
<string name="metadata_label_format">Format fișier</string>
<string name="metadata_label_created_at">Creat la</string> <string name="metadata_label_created_at">Creat la</string>
<string name="metadata_label_aaps_version">Versiune AAPS</string> <string name="metadata_label_aaps_version">Versiune AAPS</string>
<string name="metadata_label_aaps_flavour">Versiune de build</string> <string name="metadata_label_aaps_flavour">Versiune de build</string>
@ -255,7 +291,15 @@
<string name="running_invalid_version">S-a detectat rularea unei versiuni invalide. Buclă dezactivată!</string> <string name="running_invalid_version">S-a detectat rularea unei versiuni invalide. Buclă dezactivată!</string>
<string name="versionavailable">Versiunea %1$s este disponibilă</string> <string name="versionavailable">Versiunea %1$s este disponibilă</string>
<!-- Permissions --> <!-- Permissions -->
<string name="alert_dialog_storage_permission_text">Restartați telefonul sau reporniți aplicația AndroidAPS din Setările de sistem \naltfel AndroidAPS nu va avea jurnalizare (importanta pentru monitorizare si verifica funcționarea corecta a algoritmilor)!</string>
<!-- WeekdayPicker --> <!-- WeekdayPicker -->
<string name="monday_short">L</string>
<string name="tuesday_short">Ma</string>
<string name="wednesday_short">Mi</string>
<string name="thursday_short">J</string>
<string name="friday_short">V</string>
<string name="saturday_short">S</string>
<string name="sunday_short">D</string>
<plurals name="days"> <plurals name="days">
<item quantity="one">%1$d zi</item> <item quantity="one">%1$d zi</item>
<item quantity="few">%1$d zile</item> <item quantity="few">%1$d zile</item>

View file

@ -1,2 +1,24 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources></resources> <resources>
<string name="error_only_numeric_digits_allowed">Se acceptă doar valori numerice.</string>
<string name="error_only_numeric_digits_range_allowed">Se acceptă doar valori numerice între %1$s - %2$s.</string>
<string name="error_this_field_cannot_contain_special_character">Acest câmp nu poate conține caractere speciale</string>
<string name="error_only_standard_letters_are_allowed">Sunt permise doar litere standard</string>
<string name="error_field_must_not_be_empty">Acest câmp nu trebuie lăsat necompletat</string>
<string name="error_email_address_not_valid">Adresă de e-mail nu este validă</string>
<string name="error_creditcard_number_not_valid">Numărul cardului de credit nu este valid</string>
<string name="error_phone_not_valid">Numărul de telefon nu este valid</string>
<string name="error_domain_not_valid">Numele domeniului nu este valid</string>
<string name="error_ip_not_valid">Adresa IP nu este validă</string>
<string name="error_url_not_valid">Url-ul web nu este valid</string>
<string name="error_notvalid_personname">Numele sau prenumele nu este valid.</string>
<string name="error_notvalid_personfullname">Nu este un nume valid.</string>
<string name="error_date_not_valid">Formatul nu este valid</string>
<string name="error_mustbe4digitnumber">Trebuie sa conțină 4 cifre</string>
<string name="error_mustbe6digitnumber">Trebuie sa conțină 6 cifre</string>
<string name="error_mustbe12hexadidits">Trebuie să conțină 12 caractere din șirul ABCDEF0123456789</string>
<string name="error_mustbe8hexadidits">Trebuie să conțină 8 caractere din șirul ABCDEF0123456789</string>
<string name="error_mustbe4hexadidits">Trebuie să conțină 4 caractere din șirul ABCDEF0123456789</string>
<string name="error_not_a_minimum_length">Nu respecta lungimea minimă</string>
<string name="error_pin_not_valid">Pinul trebuie să fie format din 3 până la 6 cifre neconsecutive și care nu se repeta</string>
</resources>

View file

@ -28,8 +28,8 @@ class DateUtilTest : TestBase() {
@Test @Test
fun toISOStringTest() { fun toISOStringTest() {
Assert.assertEquals("2017-12-22T00:32:30Z", DateUtil.toISOString(Date(1513902750000L))) Assert.assertEquals("2017-12-22T00:32:30.000Z", DateUtil.toISOString(Date(1513902750000L)))
Assert.assertEquals("2017-12-22T00:32:30Z", DateUtil.toISOString(1513902750000L)) Assert.assertEquals("2017-12-22T00:32:30.000Z", DateUtil.toISOString(1513902750000L))
} }
@Test fun toDateTest() { @Test fun toDateTest() {

View file

@ -91,7 +91,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
boolean previousValue = useExtendedBoluses; boolean previousValue = useExtendedBoluses;
useExtendedBoluses = sp.getBoolean(R.string.key_danar_useextended, false); useExtendedBoluses = sp.getBoolean(R.string.key_danar_useextended, false);
if (useExtendedBoluses != previousValue && activePlugin.getActiveTreatments().isInHistoryExtendedBoluslInProgress()) { if (useExtendedBoluses != previousValue && activePlugin.getActiveTreatments().isInHistoryExtendedBolusInProgress()) {
sExecutionService.extendedBolusStop(); sExecutionService.extendedBolusStop();
} }
} }
@ -197,9 +197,6 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
public PumpEnactResult setTempBasalAbsolute(double absoluteRate, int durationInMinutes, @NonNull Profile profile, boolean enforceNew) { public PumpEnactResult setTempBasalAbsolute(double absoluteRate, int durationInMinutes, @NonNull Profile profile, boolean enforceNew) {
// Recheck pump status if older than 30 min // Recheck pump status if older than 30 min
//This should not be needed while using queue because connection should be done before calling this //This should not be needed while using queue because connection should be done before calling this
//if (pump.lastConnection.getTime() + 30 * 60 * 1000L < System.currentTimeMillis()) {
// connect("setTempBasalAbsolute old data");
//}
PumpEnactResult result = new PumpEnactResult(getInjector()); PumpEnactResult result = new PumpEnactResult(getInjector());
absoluteRate = constraintChecker.applyBasalConstraints(new Constraint<>(absoluteRate), profile).value(); absoluteRate = constraintChecker.applyBasalConstraints(new Constraint<>(absoluteRate), profile).value();
@ -235,7 +232,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
if (doLowTemp || doHighTemp) { if (doLowTemp || doHighTemp) {
int percentRate = Double.valueOf(absoluteRate / getBaseBasalRate() * 100).intValue(); int percentRate = Double.valueOf(absoluteRate / getBaseBasalRate() * 100).intValue();
// Any basal less than 0.10u/h will be dumped once per hour, not every 4 mins. So if it's less than .10u/h, set a zero temp. // Any basal less than 0.10u/h will be dumped once per hour, not every 4 minutes. So if it's less than .10u/h, set a zero temp.
if (absoluteRate < 0.10d) percentRate = 0; if (absoluteRate < 0.10d) percentRate = 0;
if (percentRate < 100) percentRate = Round.ceilTo((double) percentRate, 10d).intValue(); if (percentRate < 100) percentRate = Round.ceilTo((double) percentRate, 10d).intValue();
else percentRate = Round.floorTo((double) percentRate, 10d).intValue(); else percentRate = Round.floorTo((double) percentRate, 10d).intValue();
@ -273,7 +270,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
} }
} }
// Convert duration from minutes to hours // Convert duration from minutes to hours
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Setting temp basal " + percentRate + "% for " + durationInMinutes + " mins (doLowTemp || doHighTemp)"); aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Setting temp basal " + percentRate + "% for " + durationInMinutes + " minutes (doLowTemp || doHighTemp)");
return setTempBasalPercent(percentRate, durationInMinutes, profile, false); return setTempBasalPercent(percentRate, durationInMinutes, profile, false);
} }
if (doExtendedTemp) { if (doExtendedTemp) {
@ -294,7 +291,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
Double extendedRateToSet = absoluteRate - getBaseBasalRate(); Double extendedRateToSet = absoluteRate - getBaseBasalRate();
extendedRateToSet = constraintChecker.applyBasalConstraints(new Constraint<>(extendedRateToSet), profile).value(); extendedRateToSet = constraintChecker.applyBasalConstraints(new Constraint<>(extendedRateToSet), profile).value();
// needs to be rounded to 0.1 // needs to be rounded to 0.1
extendedRateToSet = Round.roundTo(extendedRateToSet, pumpDescription.extendedBolusStep * 2); // *2 because of halfhours extendedRateToSet = Round.roundTo(extendedRateToSet, pumpDescription.extendedBolusStep * 2); // *2 because of half hours
// What is current rate of extended bolusing in u/h? // What is current rate of extended bolusing in u/h?
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Extended bolus in progress: " + (activeExtended != null) + " rate: " + danaPump.getExtendedBolusAbsoluteRate() + "U/h duration remaining: " + danaPump.getExtendedBolusRemainingMinutes() + "min"); aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Extended bolus in progress: " + (activeExtended != null) + " rate: " + danaPump.getExtendedBolusAbsoluteRate() + "U/h duration remaining: " + danaPump.getExtendedBolusRemainingMinutes() + "min");
@ -315,7 +312,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
// Now set new extended, no need to to stop previous (if running) because it's replaced // Now set new extended, no need to to stop previous (if running) because it's replaced
double extendedAmount = extendedRateToSet / 2 * durationInHalfHours; double extendedAmount = extendedRateToSet / 2 * durationInHalfHours;
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Setting extended: " + extendedAmount + "U halfhours: " + durationInHalfHours); aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Setting extended: " + extendedAmount + "U half hours: " + durationInHalfHours);
result = setExtendedBolus(extendedAmount, durationInMinutes); result = setExtendedBolus(extendedAmount, durationInMinutes);
if (!result.success) { if (!result.success) {
aapsLogger.error("setTempBasalAbsolute: Failed to set extended bolus"); aapsLogger.error("setTempBasalAbsolute: Failed to set extended bolus");
@ -336,7 +333,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
public PumpEnactResult cancelTempBasal(boolean force) { public PumpEnactResult cancelTempBasal(boolean force) {
if (activePlugin.getActiveTreatments().isInHistoryRealTempBasalInProgress()) if (activePlugin.getActiveTreatments().isInHistoryRealTempBasalInProgress())
return cancelRealTempBasal(); return cancelRealTempBasal();
if (activePlugin.getActiveTreatments().isInHistoryExtendedBoluslInProgress() && useExtendedBoluses) { if (activePlugin.getActiveTreatments().isInHistoryExtendedBolusInProgress() && useExtendedBoluses) {
return cancelExtendedBolus(); return cancelExtendedBolus();
} }
PumpEnactResult result = new PumpEnactResult(getInjector()); PumpEnactResult result = new PumpEnactResult(getInjector());
@ -374,13 +371,13 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
return result; return result;
} }
@Override @NonNull @Override
public PumpEnactResult loadEvents() { public PumpEnactResult loadEvents() {
return null; // no history, not needed return new PumpEnactResult(getInjector()); // no history, not needed
} }
@Override @NonNull @Override
public PumpEnactResult setUserOptions() { public PumpEnactResult setUserOptions() {
return null; return new PumpEnactResult(getInjector());
} }
} }

View file

@ -88,7 +88,7 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
boolean previousValue = useExtendedBoluses; boolean previousValue = useExtendedBoluses;
useExtendedBoluses = sp.getBoolean(R.string.key_danar_useextended, false); useExtendedBoluses = sp.getBoolean(R.string.key_danar_useextended, false);
if (useExtendedBoluses != previousValue && activePlugin.getActiveTreatments().isInHistoryExtendedBoluslInProgress()) { if (useExtendedBoluses != previousValue && activePlugin.getActiveTreatments().isInHistoryExtendedBolusInProgress()) {
sExecutionService.extendedBolusStop(); sExecutionService.extendedBolusStop();
} }
} }
@ -192,12 +192,9 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
// This is called from APS // This is called from APS
@NonNull @Override @NonNull @Override
public PumpEnactResult setTempBasalAbsolute(double absoluteRate, int durationInMinutes, Profile profile, boolean enforceNew) { public PumpEnactResult setTempBasalAbsolute(double absoluteRate, int durationInMinutes, @NonNull Profile profile, boolean enforceNew) {
// Recheck pump status if older than 30 min // Recheck pump status if older than 30 min
//This should not be needed while using queue because connection should be done before calling this //This should not be needed while using queue because connection should be done before calling this
//if (pump.lastConnection.getTime() + 30 * 60 * 1000L < System.currentTimeMillis()) {
// connect("setTempBasalAbsolute old data");
//}
PumpEnactResult result = new PumpEnactResult(getInjector()); PumpEnactResult result = new PumpEnactResult(getInjector());
absoluteRate = constraintChecker.applyBasalConstraints(new Constraint<>(absoluteRate), profile).value(); absoluteRate = constraintChecker.applyBasalConstraints(new Constraint<>(absoluteRate), profile).value();
@ -232,8 +229,8 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
} }
if (doLowTemp || doHighTemp) { if (doLowTemp || doHighTemp) {
Integer percentRate = Double.valueOf(absoluteRate / getBaseBasalRate() * 100).intValue(); int percentRate = Double.valueOf(absoluteRate / getBaseBasalRate() * 100).intValue();
// Any basal less than 0.10u/h will be dumped once per hour, not every 4 mins. So if it's less than .10u/h, set a zero temp. // Any basal less than 0.10u/h will be dumped once per hour, not every 4 minutes. So if it's less than .10u/h, set a zero temp.
if (absoluteRate < 0.10d) percentRate = 0; if (absoluteRate < 0.10d) percentRate = 0;
if (percentRate < 100) percentRate = Round.ceilTo((double) percentRate, 10d).intValue(); if (percentRate < 100) percentRate = Round.ceilTo((double) percentRate, 10d).intValue();
else percentRate = Round.floorTo((double) percentRate, 10d).intValue(); else percentRate = Round.floorTo((double) percentRate, 10d).intValue();
@ -271,7 +268,7 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
} }
} }
// Convert duration from minutes to hours // Convert duration from minutes to hours
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Setting temp basal " + percentRate + "% for " + durationInMinutes + " mins (doLowTemp || doHighTemp)"); aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Setting temp basal " + percentRate + "% for " + durationInMinutes + " minutes (doLowTemp || doHighTemp)");
return setTempBasalPercent(percentRate, durationInMinutes, profile, false); return setTempBasalPercent(percentRate, durationInMinutes, profile, false);
} }
if (doExtendedTemp) { if (doExtendedTemp) {
@ -292,7 +289,7 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
Double extendedRateToSet = absoluteRate - getBaseBasalRate(); Double extendedRateToSet = absoluteRate - getBaseBasalRate();
extendedRateToSet = constraintChecker.applyBasalConstraints(new Constraint<>(extendedRateToSet), profile).value(); extendedRateToSet = constraintChecker.applyBasalConstraints(new Constraint<>(extendedRateToSet), profile).value();
// needs to be rounded to 0.1 // needs to be rounded to 0.1
extendedRateToSet = Round.roundTo(extendedRateToSet, pumpDescription.extendedBolusStep * 2); // *2 because of halfhours extendedRateToSet = Round.roundTo(extendedRateToSet, pumpDescription.extendedBolusStep * 2); // *2 because of half hours
// What is current rate of extended bolusing in u/h? // What is current rate of extended bolusing in u/h?
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Extended bolus in progress: " + (activeExtended != null) + " rate: " + danaPump.getExtendedBolusAbsoluteRate() + "U/h duration remaining: " + danaPump.getExtendedBolusRemainingMinutes() + "min"); aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Extended bolus in progress: " + (activeExtended != null) + " rate: " + danaPump.getExtendedBolusAbsoluteRate() + "U/h duration remaining: " + danaPump.getExtendedBolusRemainingMinutes() + "min");
@ -313,7 +310,7 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
// Now set new extended, no need to to stop previous (if running) because it's replaced // Now set new extended, no need to to stop previous (if running) because it's replaced
double extendedAmount = extendedRateToSet / 2 * durationInHalfHours; double extendedAmount = extendedRateToSet / 2 * durationInHalfHours;
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Setting extended: " + extendedAmount + "U halfhours: " + durationInHalfHours); aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Setting extended: " + extendedAmount + "U half hours: " + durationInHalfHours);
result = setExtendedBolus(extendedAmount, durationInMinutes); result = setExtendedBolus(extendedAmount, durationInMinutes);
if (!result.success) { if (!result.success) {
aapsLogger.error("setTempBasalAbsolute: Failed to set extended bolus"); aapsLogger.error("setTempBasalAbsolute: Failed to set extended bolus");
@ -334,7 +331,7 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
public PumpEnactResult cancelTempBasal(boolean force) { public PumpEnactResult cancelTempBasal(boolean force) {
if (activePlugin.getActiveTreatments().isInHistoryRealTempBasalInProgress()) if (activePlugin.getActiveTreatments().isInHistoryRealTempBasalInProgress())
return cancelRealTempBasal(); return cancelRealTempBasal();
if (activePlugin.getActiveTreatments().isInHistoryExtendedBoluslInProgress() && useExtendedBoluses) { if (activePlugin.getActiveTreatments().isInHistoryExtendedBolusInProgress() && useExtendedBoluses) {
return cancelExtendedBolus(); return cancelExtendedBolus();
} }
PumpEnactResult result = new PumpEnactResult(getInjector()); PumpEnactResult result = new PumpEnactResult(getInjector());
@ -363,22 +360,21 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
result.isTempCancel = true; result.isTempCancel = true;
result.comment = resourceHelper.gs(R.string.ok); result.comment = resourceHelper.gs(R.string.ok);
aapsLogger.debug(LTag.PUMP, "cancelRealTempBasal: OK"); aapsLogger.debug(LTag.PUMP, "cancelRealTempBasal: OK");
return result;
} else { } else {
result.success = false; result.success = false;
result.comment = resourceHelper.gs(R.string.danar_valuenotsetproperly); result.comment = resourceHelper.gs(R.string.danar_valuenotsetproperly);
result.isTempCancel = true; result.isTempCancel = true;
aapsLogger.error("cancelRealTempBasal: Failed to cancel temp basal"); aapsLogger.error("cancelRealTempBasal: Failed to cancel temp basal");
return result;
} }
return result;
} }
@Override @NonNull @Override
public PumpEnactResult loadEvents() { public PumpEnactResult loadEvents() {
return null; // no history, not needed return new PumpEnactResult(getInjector()); // no history, not needed
} }
@Override @NonNull @Override
public PumpEnactResult setUserOptions() { public PumpEnactResult setUserOptions() {
return sExecutionService.setUserOptions(); return sExecutionService.setUserOptions();
} }

View file

@ -24,8 +24,6 @@ class AppRepository @Inject internal constructor(
fun changeObservable(): Observable<List<DBEntry>> = changeSubject.subscribeOn(Schedulers.io()) fun changeObservable(): Observable<List<DBEntry>> = changeSubject.subscribeOn(Schedulers.io())
val databaseVersion = DATABASE_VERSION
/** /**
* Executes a transaction ignoring its result * Executes a transaction ignoring its result
* Runs on IO scheduler * Runs on IO scheduler
@ -88,16 +86,25 @@ class AppRepository @Inject internal constructor(
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
// TEMP TARGETS // TEMP TARGETS
fun compatGetTemporaryTargetData(): List<TemporaryTarget> = fun compatGetTemporaryTargetData(): Single<List<TemporaryTarget>> =
database.temporaryTargetDao.compatGetTemporaryTargetData() database.temporaryTargetDao.getTemporaryTargetData()
.subscribeOn(Schedulers.io())
fun compatGetTemporaryTargetDataFromTime(timestamp: Long, ascending: Boolean): Single<List<TemporaryTarget>> = fun getTemporaryTargetDataFromTime(timestamp: Long, ascending: Boolean): Single<List<TemporaryTarget>> =
database.temporaryTargetDao.compatGetTemporaryTargetDataFromTime(timestamp) database.temporaryTargetDao.getTemporaryTargetDataFromTime(timestamp)
.map { if (!ascending) it.reversed() else it } .map { if (!ascending) it.reversed() else it }
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
fun findTemporaryTargetByNSIdSingle(nsId: String): Single<ValueWrapper<TemporaryTarget>> = fun getTemporaryTargetDataIncludingInvalidFromTime(timestamp: Long, ascending: Boolean): Single<List<TemporaryTarget>> =
database.temporaryTargetDao.findByNSIdMaybe(nsId).toWrappedSingle() database.temporaryTargetDao.getTemporaryTargetDataIncludingInvalidFromTime(timestamp)
.map { if (!ascending) it.reversed() else it }
.subscribeOn(Schedulers.io())
fun findTemporaryTargetByNSIdSingle(nsId: String): TemporaryTarget? =
database.temporaryTargetDao.findByNSId(nsId)
fun findTemporaryTargetByTimestamp(timestamp: Long): TemporaryTarget? =
database.temporaryTargetDao.findByTimestamp(timestamp)
fun getModifiedTemporaryTargetsDataFromId(lastId: Long): Single<List<TemporaryTarget>> = fun getModifiedTemporaryTargetsDataFromId(lastId: Long): Single<List<TemporaryTarget>> =
database.temporaryTargetDao.getModifiedFrom(lastId) database.temporaryTargetDao.getModifiedFrom(lastId)
@ -106,6 +113,14 @@ class AppRepository @Inject internal constructor(
fun getTemporaryTargetsCorrespondingLastHistoryRecord(lastId: Long): TemporaryTarget? = fun getTemporaryTargetsCorrespondingLastHistoryRecord(lastId: Long): TemporaryTarget? =
database.temporaryTargetDao.getLastHistoryRecord(lastId) database.temporaryTargetDao.getLastHistoryRecord(lastId)
fun getTemporaryTargetActiveAt(timestamp: Long): Single<ValueWrapper<TemporaryTarget>> =
database.temporaryTargetDao.getTemporaryTargetActiveAt(timestamp)
.subscribeOn(Schedulers.io())
.toWrappedSingle()
fun deleteAllTempTargetEntries() =
database.temporaryTargetDao.deleteAllEntries()
// USER ENTRY // USER ENTRY
fun getAllUserEntries(): Single<List<UserEntry>> = fun getAllUserEntries(): Single<List<UserEntry>> =
database.userEntryDao.getAll() database.userEntryDao.getAll()

View file

@ -5,7 +5,6 @@ import androidx.room.Query
import info.nightscout.androidaps.database.TABLE_TEMPORARY_TARGETS import info.nightscout.androidaps.database.TABLE_TEMPORARY_TARGETS
import info.nightscout.androidaps.database.entities.TemporaryTarget import info.nightscout.androidaps.database.entities.TemporaryTarget
import io.reactivex.Maybe import io.reactivex.Maybe
import io.reactivex.Observable
import io.reactivex.Single import io.reactivex.Single
@Suppress("FunctionName") @Suppress("FunctionName")
@ -19,16 +18,22 @@ internal interface TemporaryTargetDao : TraceableDao<TemporaryTarget> {
override fun deleteAllEntries() override fun deleteAllEntries()
@Query("SELECT * FROM $TABLE_TEMPORARY_TARGETS WHERE nightscoutId = :nsId AND referenceId IS NULL") @Query("SELECT * FROM $TABLE_TEMPORARY_TARGETS WHERE nightscoutId = :nsId AND referenceId IS NULL")
fun findByNSIdMaybe(nsId: String): Maybe<TemporaryTarget> fun findByNSId(nsId: String): TemporaryTarget?
@Query("SELECT * FROM $TABLE_TEMPORARY_TARGETS WHERE timestamp = :timestamp AND referenceId IS NULL")
fun findByTimestamp(timestamp: Long): TemporaryTarget?
@Query("SELECT * FROM $TABLE_TEMPORARY_TARGETS WHERE timestamp <= :timestamp AND (timestamp + duration) > :timestamp AND referenceId IS NULL AND isValid = 1 ORDER BY timestamp DESC LIMIT 1") @Query("SELECT * FROM $TABLE_TEMPORARY_TARGETS WHERE timestamp <= :timestamp AND (timestamp + duration) > :timestamp AND referenceId IS NULL AND isValid = 1 ORDER BY timestamp DESC LIMIT 1")
fun getTemporaryTargetActiveAt(timestamp: Long): TemporaryTarget? fun getTemporaryTargetActiveAt(timestamp: Long): Maybe<TemporaryTarget>
@Query("SELECT * FROM $TABLE_TEMPORARY_TARGETS WHERE timestamp >= :timestamp AND isValid = 1 AND referenceId IS NULL ORDER BY timestamp ASC") @Query("SELECT * FROM $TABLE_TEMPORARY_TARGETS WHERE timestamp >= :timestamp AND isValid = 1 AND referenceId IS NULL ORDER BY timestamp ASC")
fun compatGetTemporaryTargetDataFromTime(timestamp: Long): Single<List<TemporaryTarget>> fun getTemporaryTargetDataFromTime(timestamp: Long): Single<List<TemporaryTarget>>
@Query("SELECT * FROM $TABLE_TEMPORARY_TARGETS WHERE timestamp >= :timestamp AND referenceId IS NULL ORDER BY timestamp ASC")
fun getTemporaryTargetDataIncludingInvalidFromTime(timestamp: Long): Single<List<TemporaryTarget>>
@Query("SELECT * FROM $TABLE_TEMPORARY_TARGETS WHERE isValid = 1 AND referenceId IS NULL ORDER BY timestamp ASC") @Query("SELECT * FROM $TABLE_TEMPORARY_TARGETS WHERE isValid = 1 AND referenceId IS NULL ORDER BY timestamp ASC")
fun compatGetTemporaryTargetData(): List<TemporaryTarget> fun getTemporaryTargetData(): Single<List<TemporaryTarget>>
@Query("SELECT * FROM $TABLE_TEMPORARY_TARGETS WHERE referenceId = :id ORDER BY id DESC LIMIT 1") @Query("SELECT * FROM $TABLE_TEMPORARY_TARGETS WHERE referenceId = :id ORDER BY id DESC LIMIT 1")
fun getLastHistoryRecord(id: Long): TemporaryTarget? fun getLastHistoryRecord(id: Long): TemporaryTarget?

View file

@ -77,6 +77,7 @@ data class GlucoseValue(
@SerializedName("DexcomG5") DEXCOM_G5_XDRIP("DexcomG5"), @SerializedName("DexcomG5") DEXCOM_G5_XDRIP("DexcomG5"),
@SerializedName("G6 Native") DEXCOM_G6_NATIVE_XDRIP("G6 Native"), @SerializedName("G6 Native") DEXCOM_G6_NATIVE_XDRIP("G6 Native"),
@SerializedName("G5 Native") DEXCOM_G5_NATIVE_XDRIP("G5 Native"), @SerializedName("G5 Native") DEXCOM_G5_NATIVE_XDRIP("G5 Native"),
@SerializedName("G6 Native / G5 Native") DEXCOM_G6_G5_NATIVE_XDRIP("G6 Native / G5 Native"),
@SerializedName("Network libre") LIBRE_1_NET("Network libre"), @SerializedName("Network libre") LIBRE_1_NET("Network libre"),
@SerializedName("BlueReader") LIBRE_1_BLUE("BlueReader"), @SerializedName("BlueReader") LIBRE_1_BLUE("BlueReader"),
@SerializedName("Transmiter PL") LIBRE_1_PL("Transmiter PL"), @SerializedName("Transmiter PL") LIBRE_1_PL("Transmiter PL"),
@ -104,4 +105,4 @@ data class GlucoseValue(
fun fromString(source: String?) = values().firstOrNull { it.text == source } ?: UNKNOWN fun fromString(source: String?) = values().firstOrNull { it.text == source } ?: UNKNOWN
} }
} }
} }

View file

@ -57,11 +57,13 @@ data class TemporaryTarget(
@SerializedName("Eating Soon") @SerializedName("Eating Soon")
EATING_SOON("Eating Soon"), EATING_SOON("Eating Soon"),
@SerializedName("Automation") @SerializedName("Automation")
AUTOMATION("Automation") AUTOMATION("Automation"),
@SerializedName("Wear")
WEAR("Wear")
; ;
companion object { companion object {
fun fromString(direction: String?) = values().firstOrNull { it.text == direction } fun fromString(reason: String?) = values().firstOrNull { it.text == reason }
?: CUSTOM ?: CUSTOM
} }
} }

View file

@ -5,12 +5,21 @@ import info.nightscout.androidaps.database.interfaces.end
class CancelCurrentTemporaryTargetIfAnyTransaction( class CancelCurrentTemporaryTargetIfAnyTransaction(
val timestamp: Long val timestamp: Long
) : Transaction<Unit>() { ) : Transaction<CancelCurrentTemporaryTargetIfAnyTransaction.TransactionResult>() {
override fun run() {
val current = database.temporaryTargetDao.getTemporaryTargetActiveAt(timestamp) override fun run(): TransactionResult {
val result = TransactionResult()
val current = database.temporaryTargetDao.getTemporaryTargetActiveAt(timestamp).blockingGet()
if (current != null) { if (current != null) {
current.end = timestamp current.end = timestamp
database.temporaryTargetDao.updateExistingEntry(current) database.temporaryTargetDao.updateExistingEntry(current)
result.updated.add(current)
} }
return result
}
class TransactionResult {
val updated = mutableListOf<TemporaryTarget>()
} }
} }

View file

@ -4,18 +4,27 @@ import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.database.interfaces.end import info.nightscout.androidaps.database.interfaces.end
class InsertTemporaryTargetAndCancelCurrentTransaction( class InsertTemporaryTargetAndCancelCurrentTransaction(
private val temporaryTarget: TemporaryTarget val temporaryTarget: TemporaryTarget
) : Transaction<Unit>() { ) : Transaction<InsertTemporaryTargetAndCancelCurrentTransaction.TransactionResult>() {
constructor(timestamp: Long, duration: Long, reason: TemporaryTarget.Reason, lowTarget: Double, highTarget: Double) : constructor(timestamp: Long, duration: Long, reason: TemporaryTarget.Reason, lowTarget: Double, highTarget: Double) :
this(TemporaryTarget(timestamp = timestamp, reason = reason, lowTarget = lowTarget, highTarget = highTarget, duration = duration)) this(TemporaryTarget(timestamp = timestamp, reason = reason, lowTarget = lowTarget, highTarget = highTarget, duration = duration))
override fun run() { override fun run(): TransactionResult {
val current = database.temporaryTargetDao.getTemporaryTargetActiveAt(temporaryTarget.timestamp) val result = TransactionResult()
val current = database.temporaryTargetDao.getTemporaryTargetActiveAt(temporaryTarget.timestamp).blockingGet()
if (current != null) { if (current != null) {
current.end = temporaryTarget.timestamp current.end = temporaryTarget.timestamp
database.temporaryTargetDao.updateExistingEntry(current) database.temporaryTargetDao.updateExistingEntry(current)
result.updated.add(current)
} }
database.temporaryTargetDao.insertNewEntry(temporaryTarget) database.temporaryTargetDao.insertNewEntry(temporaryTarget)
result.inserted.add(temporaryTarget)
return result
}
class TransactionResult {
val inserted = mutableListOf<TemporaryTarget>()
val updated = mutableListOf<TemporaryTarget>()
} }
} }

View file

@ -0,0 +1,71 @@
package info.nightscout.androidaps.database.transactions
import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.database.interfaces.end
import kotlin.math.abs
/**
* Sync the TemporaryTarget from NS
*/
class SyncTemporaryTargetTransaction(private val temporaryTarget: TemporaryTarget) : Transaction<SyncTemporaryTargetTransaction.TransactionResult>() {
override fun run(): TransactionResult {
val result = TransactionResult()
if (temporaryTarget.duration != 0L) {
// not ending event
val current: TemporaryTarget? =
temporaryTarget.interfaceIDs.nightscoutId?.let {
database.temporaryTargetDao.findByNSId(it)
}
if (current != null) {
// nsId exists, allow only invalidation
if (current.isValid && !temporaryTarget.isValid) {
current.isValid = false
database.temporaryTargetDao.updateExistingEntry(current)
result.invalidated.add(current)
}
return result
}
// not known nsId
val running = database.temporaryTargetDao.getTemporaryTargetActiveAt(temporaryTarget.timestamp).blockingGet()
if (running != null && abs(running.timestamp - temporaryTarget.timestamp) < 1000 && running.interfaceIDs.nightscoutId == null) { // allow missing milliseconds
// the same record, update nsId only
running.interfaceIDs.nightscoutId = temporaryTarget.interfaceIDs.nightscoutId
database.temporaryTargetDao.updateExistingEntry(running)
result.updatedNsId.add(running)
} else if (running != null) {
// another running record. end current and insert new
running.end = temporaryTarget.timestamp
database.temporaryTargetDao.updateExistingEntry(running)
database.temporaryTargetDao.insertNewEntry(temporaryTarget)
result.ended.add(running)
result.inserted.add(temporaryTarget)
} else {
database.temporaryTargetDao.insertNewEntry(temporaryTarget)
result.inserted.add(temporaryTarget)
}
return result
} else {
// ending event
val running = database.temporaryTargetDao.getTemporaryTargetActiveAt(temporaryTarget.timestamp).blockingGet()
if (running != null) {
running.end = temporaryTarget.timestamp
database.temporaryTargetDao.updateExistingEntry(running)
result.ended.add(running)
}
}
return result
}
class TransactionResult {
val updatedNsId = mutableListOf<TemporaryTarget>()
val inserted = mutableListOf<TemporaryTarget>()
val invalidated = mutableListOf<TemporaryTarget>()
val ended = mutableListOf<TemporaryTarget>()
}
}

View file

@ -31,6 +31,9 @@ import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.ExtendedBolus;
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.Source;
import info.nightscout.androidaps.db.TDD; import info.nightscout.androidaps.db.TDD;
import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.TemporaryBasal;
@ -108,9 +111,6 @@ import info.nightscout.androidaps.plugins.pump.insight.app_layer.status.GetPumpS
import info.nightscout.androidaps.plugins.pump.insight.app_layer.status.GetTotalDailyDoseMessage; import info.nightscout.androidaps.plugins.pump.insight.app_layer.status.GetTotalDailyDoseMessage;
import info.nightscout.androidaps.plugins.pump.insight.app_layer.status.ResetPumpStatusRegisterMessage; import info.nightscout.androidaps.plugins.pump.insight.app_layer.status.ResetPumpStatusRegisterMessage;
import info.nightscout.androidaps.plugins.pump.insight.connection_service.InsightConnectionService; import info.nightscout.androidaps.plugins.pump.insight.connection_service.InsightConnectionService;
import info.nightscout.androidaps.db.InsightBolusID;
import info.nightscout.androidaps.db.InsightHistoryOffset;
import info.nightscout.androidaps.db.InsightPumpID;
import info.nightscout.androidaps.plugins.pump.insight.descriptors.ActiveBasalRate; import info.nightscout.androidaps.plugins.pump.insight.descriptors.ActiveBasalRate;
import info.nightscout.androidaps.plugins.pump.insight.descriptors.ActiveBolus; import info.nightscout.androidaps.plugins.pump.insight.descriptors.ActiveBolus;
import info.nightscout.androidaps.plugins.pump.insight.descriptors.ActiveTBR; import info.nightscout.androidaps.plugins.pump.insight.descriptors.ActiveTBR;
@ -131,7 +131,6 @@ import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_erro
import info.nightscout.androidaps.plugins.pump.insight.utils.ExceptionTranslator; import info.nightscout.androidaps.plugins.pump.insight.utils.ExceptionTranslator;
import info.nightscout.androidaps.plugins.pump.insight.utils.ParameterBlockUtil; import info.nightscout.androidaps.plugins.pump.insight.utils.ParameterBlockUtil;
import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.TimeChangeType;
import info.nightscout.androidaps.utils.resources.ResourceHelper; import info.nightscout.androidaps.utils.resources.ResourceHelper;
import info.nightscout.androidaps.utils.sharedPreferences.SP; import info.nightscout.androidaps.utils.sharedPreferences.SP;
@ -998,6 +997,7 @@ public class LocalInsightPlugin extends PumpPluginBase implements PumpInterface,
try { try {
extended.put("ActiveProfile", profileFunction.getProfileName()); extended.put("ActiveProfile", profileFunction.getProfileName());
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace();
} }
TemporaryBasal tb = treatmentsPlugin.getTempBasalFromHistory(now); TemporaryBasal tb = treatmentsPlugin.getTempBasalFromHistory(now);
if (tb != null) { if (tb != null) {
@ -1576,7 +1576,7 @@ public class LocalInsightPlugin extends PumpPluginBase implements PumpInterface,
careportalEvent.eventType = CareportalEvent.NOTE; careportalEvent.eventType = CareportalEvent.NOTE;
careportalEvent.json = data.toString(); careportalEvent.json = data.toString();
databaseHelper.createOrUpdate(careportalEvent); databaseHelper.createOrUpdate(careportalEvent);
nsUpload.uploadCareportalEntryToNS(data); nsUpload.uploadCareportalEntryToNS(data, date);
} catch (JSONException e) { } catch (JSONException e) {
aapsLogger.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
} }
@ -1610,7 +1610,7 @@ public class LocalInsightPlugin extends PumpPluginBase implements PumpInterface,
careportalEvent.eventType = event; careportalEvent.eventType = event;
careportalEvent.json = data.toString(); careportalEvent.json = data.toString();
databaseHelper.createOrUpdate(careportalEvent); databaseHelper.createOrUpdate(careportalEvent);
nsUpload.uploadCareportalEntryToNS(data); nsUpload.uploadCareportalEntryToNS(data, date);
} catch (JSONException e) { } catch (JSONException e) {
aapsLogger.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
} }
@ -1681,8 +1681,4 @@ public class LocalInsightPlugin extends PumpPluginBase implements PumpInterface,
return true; return true;
} }
@Override
public void timezoneOrDSTChanged(TimeChangeType changeType) {
}
} }

View file

@ -2,7 +2,9 @@
<resources> <resources>
<string name="alert_r7_description"><![CDATA[Menge: <b>%1$d%%</b>\nDauer: <b>%2$s h</b>]]></string> <string name="alert_r7_description"><![CDATA[Menge: <b>%1$d%%</b>\nDauer: <b>%2$s h</b>]]></string>
<string name="alert_w31_description"><![CDATA[Ampullenfüllmenge: <b>%1$s U</b>]]></string> <string name="alert_w31_description"><![CDATA[Ampullenfüllmenge: <b>%1$s U</b>]]></string>
<string name="alert_w32_description">Batterie wechseln.</string>
<string name="alert_w33_description">Datum/Uhrzeit einstellen.</string> <string name="alert_w33_description">Datum/Uhrzeit einstellen.</string>
<string name="alert_w34_description">Kontaktiere den Accu-Chek-Kundendienst.</string>
<string name="alert_w36_description"><![CDATA[Menge: <b>%1$d%%</b><br/>Dauer: <b>%2$s h</b>]]></string> <string name="alert_w36_description"><![CDATA[Menge: <b>%1$d%%</b><br/>Dauer: <b>%2$s h</b>]]></string>
<string name="alert_w38_description"><![CDATA[Eingestellt: <b>%1$s U</b><br/>Abgegeben: <b>%2$s U</b>]]></string> <string name="alert_w38_description"><![CDATA[Eingestellt: <b>%1$s U</b><br/>Abgegeben: <b>%2$s U</b>]]></string>
<string name="alert_m20_description">Ampulle einsetzen.</string> <string name="alert_m20_description">Ampulle einsetzen.</string>
@ -11,9 +13,12 @@
<string name="alert_m23_description">Pumpenstatus überprüfen.</string> <string name="alert_m23_description">Pumpenstatus überprüfen.</string>
<string name="alert_m24_description">Infusionsset wechseln.</string> <string name="alert_m24_description">Infusionsset wechseln.</string>
<string name="alert_m25_description">Kontaktiere den Accu-Chek-Kundendienst.</string> <string name="alert_m25_description">Kontaktiere den Accu-Chek-Kundendienst.</string>
<string name="alert_m26_description">Ampulle wechseln.</string>
<string name="alert_m27_description">Datenübertragung neu starten.</string> <string name="alert_m27_description">Datenübertragung neu starten.</string>
<string name="alert_m28_description">Pumpenstatus überprüfen.</string>
<string name="alert_m29_description">Batterietyp einstellen.</string> <string name="alert_m29_description">Batterietyp einstellen.</string>
<string name="alert_m30_description">Ampullentyp einstellen.</string> <string name="alert_m30_description">Ampullentyp einstellen.</string>
<string name="alert_e6_description">Batterie und Ampulle wechseln.</string> <string name="alert_e6_description">Batterie und Ampulle wechseln.</string>
<string name="alert_e10_description">Ampulle wechseln.</string>
<string name="alert_e13_description">Andere Sprache wählen.</string> <string name="alert_e13_description">Andere Sprache wählen.</string>
</resources> </resources>

View file

@ -3,6 +3,7 @@
<string name="alert_r1_title">Bolusabgabe</string> <string name="alert_r1_title">Bolusabgabe</string>
<string name="alert_r2_title">Versäumter Bolus</string> <string name="alert_r2_title">Versäumter Bolus</string>
<string name="alert_r3_title">Wecker</string> <string name="alert_r3_title">Wecker</string>
<string name="alert_r4_title">Infusionsset wechseln</string>
<string name="alert_r7_title">TBR abgeschlossen</string> <string name="alert_r7_title">TBR abgeschlossen</string>
<string name="alert_w31_title">Ampulle fast leer</string> <string name="alert_w31_title">Ampulle fast leer</string>
<string name="alert_w32_title">Batterie fast leer</string> <string name="alert_w32_title">Batterie fast leer</string>

View file

@ -2,7 +2,9 @@
<resources> <resources>
<string name="alert_r7_description"><![CDATA[Cantitate: <b>%1$d%%</b>\nDurata: <b>%2$s h</b>]]></string> <string name="alert_r7_description"><![CDATA[Cantitate: <b>%1$d%%</b>\nDurata: <b>%2$s h</b>]]></string>
<string name="alert_w31_description"><![CDATA[Conţinut rezervor: <b>%1$s U</b>]]></string> <string name="alert_w31_description"><![CDATA[Conţinut rezervor: <b>%1$s U</b>]]></string>
<string name="alert_w32_description">Schimbați bateria.</string>
<string name="alert_w33_description">Setați ora/data.</string> <string name="alert_w33_description">Setați ora/data.</string>
<string name="alert_w34_description">Contactați departamentul de suport Accu-Chek.</string>
<string name="alert_w36_description"><![CDATA[Cantitate: <b>%1$d%%</b><br/>Durată: <b>%2$s h</b>]]></string> <string name="alert_w36_description"><![CDATA[Cantitate: <b>%1$d%%</b><br/>Durată: <b>%2$s h</b>]]></string>
<string name="alert_w38_description"><![CDATA[Stabilit: <b>%1$s U</b><br/>Livrat: <b>%2$s U</b>]]></string> <string name="alert_w38_description"><![CDATA[Stabilit: <b>%1$s U</b><br/>Livrat: <b>%2$s U</b>]]></string>
<string name="alert_m20_description">Introduceți cartușul.</string> <string name="alert_m20_description">Introduceți cartușul.</string>
@ -11,7 +13,9 @@
<string name="alert_m23_description">Verificați starea pompei pe ecranul acesteia.</string> <string name="alert_m23_description">Verificați starea pompei pe ecranul acesteia.</string>
<string name="alert_m24_description">Schimbați setul de infuzie.</string> <string name="alert_m24_description">Schimbați setul de infuzie.</string>
<string name="alert_m25_description">Contactați departamentul de suport Accu-Chek.</string> <string name="alert_m25_description">Contactați departamentul de suport Accu-Chek.</string>
<string name="alert_m26_description">Schimbați cartușul.</string>
<string name="alert_m27_description">Reporniţi descărcarea datelor.</string> <string name="alert_m27_description">Reporniţi descărcarea datelor.</string>
<string name="alert_m28_description">Verificaţi starea pompei.</string>
<string name="alert_m29_description">Setaţi tipul de baterie.</string> <string name="alert_m29_description">Setaţi tipul de baterie.</string>
<string name="alert_m30_description">Setaţi tipul de rezervor.</string> <string name="alert_m30_description">Setaţi tipul de rezervor.</string>
<string name="alert_e6_description">Schimbați bateria și rezervorul.</string> <string name="alert_e6_description">Schimbați bateria și rezervorul.</string>

Some files were not shown because too many files have changed in this diff Show more