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
*.apk
build/
!.idea/dictionaries/project-dictionary.xml
.idea/*
!.idea/codeStyles/
full/

View file

@ -2,22 +2,6 @@
<code_scheme name="Project" version="173">
<option name="AUTODETECT_INDENTS" value="false" />
<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="NAME_COUNT_TO_USE_STAR_IMPORT" 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 {
multiDexEnabled true
versionCode 1500
version "2.8.2.1-dev-b"
version "2.8.2.1-dev-c"
buildConfigField "String", "VERSION", '"' + version + '"'
buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"'
buildConfigField "String", "REMOTE", '"' + generateGitRemote() + '"'

View file

@ -140,7 +140,10 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
else defaultProfileDPV.profile(age, tdd, pct / 100.0, profileFunction.getUnits())
profile?.let {
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())
})
}

View file

@ -74,9 +74,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
@Inject OpenHumansUploader openHumansUploader;
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_TEMPTARGETS = "TempTargets";
public static final String DATABASE_DANARHISTORY = "DanaRHistory";
public static final String DATABASE_DBREQUESTS = "DBRequests";
public static final String DATABASE_CAREPORTALEVENTS = "CareportalEvents";
@ -87,15 +85,9 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
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 ScheduledFuture<?> scheduledTemBasalsPost = null;
private static final ScheduledExecutorService tempTargetWorker = Executors.newSingleThreadScheduledExecutor();
private static ScheduledFuture<?> scheduledTemTargetPost = null;
private static final ScheduledExecutorService extendedBolusWorker = Executors.newSingleThreadScheduledExecutor();
private static ScheduledFuture<?> scheduledExtendedBolusPost = null;
@ -119,8 +111,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public void onCreate(SQLiteDatabase database, ConnectionSource connectionSource) {
try {
aapsLogger.info(LTag.DATABASE, "onCreate");
TableUtils.createTableIfNotExists(connectionSource, TempTarget.class);
//TableUtils.createTableIfNotExists(connectionSource, BgReading.class);
TableUtils.createTableIfNotExists(connectionSource, DanaRHistoryRecord.class);
TableUtils.createTableIfNotExists(connectionSource, DbRequest.class);
TableUtils.createTableIfNotExists(connectionSource, TemporaryBasal.class);
@ -151,8 +141,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
if (oldVersion < 7) {
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, DbRequest.class, true);
TableUtils.dropTable(connectionSource, TemporaryBasal.class, true);
@ -201,8 +189,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public void resetDatabases() {
try {
TableUtils.dropTable(connectionSource, TempTarget.class, true);
//TableUtils.dropTable(connectionSource, BgReading.class, true);
TableUtils.dropTable(connectionSource, DanaRHistoryRecord.class, true);
TableUtils.dropTable(connectionSource, DbRequest.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, TDD.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, DbRequest.class);
TableUtils.createTableIfNotExists(connectionSource, TemporaryBasal.class);
@ -228,7 +212,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
virtualPumpPlugin.setFakingStatus(true);
scheduleTemporaryBasalChange();
scheduleExtendedBolusChange();
scheduleTemporaryTargetChange();
scheduleCareportalEventChange();
scheduleProfileSwitchChange();
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() {
try {
TableUtils.dropTable(connectionSource, TemporaryBasal.class, true);
@ -306,10 +279,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
// ------------------ getDao -------------------------------------------
private Dao<TempTarget, Long> getDaoTempTargets() throws SQLException {
return getDao(TempTarget.class);
}
private Dao<DanaRHistoryRecord, String> getDaoDanaRHistory() throws SQLException {
return getDao(DanaRHistoryRecord.class);
}
@ -476,8 +445,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
}
}
// -------------------- TEMPTARGET HANDLING -------------------
public static void updateEarliestDataChange(long newDate) {
if (earliestDataChange == null) {
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 --------------------
public void createOrUpdate(DanaRHistoryRecord record) {
@ -1723,7 +1500,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
if (stored != null) {
aapsLogger.debug(LTag.DATABASE, "PROFILESWITCH: Removing ProfileSwitch record from database: " + stored.toString());
delete(stored);
scheduleTemporaryTargetChange();
scheduleProfileSwitchChange();
}
}
@ -1958,8 +1735,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
+ getDaoCareportalEvents().countOf()
+ getDaoProfileSwitch().countOf()
+ getDaoTDD().countOf()
+ getDaoTemporaryBasal().countOf()
+ getDaoTempTargets().countOf();
+ getDaoTemporaryBasal().countOf();
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);
}

View file

@ -5,6 +5,7 @@ import androidx.annotation.NonNull;
import com.j256.ormlite.dao.CloseableIterator;
import org.jetbrains.annotations.Nullable;
import org.json.JSONObject;
import java.sql.SQLException;
import java.util.List;
@ -13,7 +14,9 @@ import javax.inject.Inject;
import javax.inject.Singleton;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface;
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
@Singleton
public class DatabaseHelperProvider implements DatabaseHelperInterface {
@ -77,8 +80,8 @@ public class DatabaseHelperProvider implements DatabaseHelperInterface {
MainApp.getDbHelper().createOrUpdateTDD(record);
}
@Override public void createOrUpdate(@NonNull TemporaryBasal tempBasal) {
MainApp.getDbHelper().createOrUpdate(tempBasal);
@Override public boolean createOrUpdate(@NonNull TemporaryBasal tempBasal) {
return MainApp.getDbHelper().createOrUpdate(tempBasal);
}
@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) {
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.R
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.transactions.InsertTemporaryTargetAndCancelCurrentTransaction
import info.nightscout.androidaps.databinding.DialogCarbsBinding
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.ProfileFunction
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
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.extensions.formatColor
import info.nightscout.androidaps.utils.resources.ResourceHelper
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import java.text.DecimalFormat
import java.util.*
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import kotlin.math.max
@ -46,6 +51,7 @@ class CarbsDialog : DialogFragmentWithDate() {
@Inject lateinit var carbsGenerator: CarbsGenerator
@Inject lateinit var uel: UserEntryLogger
@Inject lateinit var carbTimer: CarbTimer
@Inject lateinit var repository: AppRepository
companion object {
@ -54,6 +60,8 @@ class CarbsDialog : DialogFragmentWithDate() {
private const val FAV3_DEFAULT = 20
}
private val disposable = CompositeDisposable()
private val textWatcher: TextWatcher = object : TextWatcher {
override fun afterTextChanged(s: Editable) {
validateInputs()
@ -154,6 +162,7 @@ class CarbsDialog : DialogFragmentWithDate() {
override fun onDestroyView() {
super.onDestroyView()
disposable.clear()
_binding = null
}
@ -214,38 +223,50 @@ class CarbsDialog : DialogFragmentWithDate() {
when {
activitySelected -> {
uel.log(Action.TT_ACTIVITY, ValueWithUnit(activityTT, units) , ValueWithUnit(activityTTDuration, Units.M))
val tempTarget = TempTarget()
.date(System.currentTimeMillis())
.duration(activityTTDuration)
.reason(resourceHelper.gs(R.string.activity))
.source(Source.USER)
.low(Profile.toMgdl(activityTT, profileFunction.getUnits()))
.high(Profile.toMgdl(activityTT, profileFunction.getUnits()))
treatmentsPlugin.addToHistoryTempTarget(tempTarget)
disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction(
timestamp = System.currentTimeMillis(),
duration = TimeUnit.MINUTES.toMillis(activityTTDuration.toLong()),
reason = TemporaryTarget.Reason.ACTIVITY,
lowTarget = Profile.toMgdl(activityTT, profileFunction.getUnits()),
highTarget = Profile.toMgdl(activityTT, 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)
})
}
eatingSoonSelected -> {
uel.log(Action.TT_EATING_SOON, ValueWithUnit(eatingSoonTT, units) , ValueWithUnit(eatingSoonTTDuration, Units.M))
val tempTarget = TempTarget()
.date(System.currentTimeMillis())
.duration(eatingSoonTTDuration)
.reason(resourceHelper.gs(R.string.eatingsoon))
.source(Source.USER)
.low(Profile.toMgdl(eatingSoonTT, profileFunction.getUnits()))
.high(Profile.toMgdl(eatingSoonTT, profileFunction.getUnits()))
treatmentsPlugin.addToHistoryTempTarget(tempTarget)
disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction(
timestamp = System.currentTimeMillis(),
duration = TimeUnit.MINUTES.toMillis(eatingSoonTTDuration.toLong()),
reason = TemporaryTarget.Reason.EATING_SOON,
lowTarget = Profile.toMgdl(eatingSoonTT, profileFunction.getUnits()),
highTarget = Profile.toMgdl(eatingSoonTT, 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)
})
}
hypoSelected -> {
uel.log(Action.TT_HYPO, ValueWithUnit(hypoTT, units) , ValueWithUnit(hypoTTDuration, Units.M))
val tempTarget = TempTarget()
.date(System.currentTimeMillis())
.duration(hypoTTDuration)
.reason(resourceHelper.gs(R.string.hypo))
.source(Source.USER)
.low(Profile.toMgdl(hypoTT, profileFunction.getUnits()))
.high(Profile.toMgdl(hypoTT, profileFunction.getUnits()))
treatmentsPlugin.addToHistoryTempTarget(tempTarget)
disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction(
timestamp = System.currentTimeMillis(),
duration = TimeUnit.MINUTES.toMillis(hypoTTDuration.toLong()),
reason = TemporaryTarget.Reason.HYPOGLYCEMIA,
lowTarget = Profile.toMgdl(hypoTT, profileFunction.getUnits()),
highTarget = Profile.toMgdl(hypoTT, 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 (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.db.CareportalEvent
import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
@ -40,6 +41,7 @@ class CareDialog : DialogFragmentWithDate() {
@Inject lateinit var nsUpload: NSUpload
@Inject lateinit var translator: Translator
@Inject lateinit var uel: UserEntryLogger
@Inject lateinit var databaseHelper: DatabaseHelperInterface
enum class EventType {
BGCHECK,
@ -227,8 +229,8 @@ class CareDialog : DialogFragmentWithDate() {
uel.log(Action.CAREPORTAL, notes, ValueWithUnit(eventTime, Units.Timestamp), ValueWithUnit(careportalEvent.eventType, Units.CPEvent))
else
uel.log(Action.CAREPORTAL, notes, ValueWithUnit(careportalEvent.eventType, Units.CPEvent))
MainApp.getDbHelper().createOrUpdate(careportalEvent)
nsUpload.uploadCareportalEntryToNS(json)
databaseHelper.createOrUpdate(careportalEvent)
nsUpload.uploadCareportalEntryToNS(json, eventTime)
}, null)
}
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.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.transactions.InsertTemporaryTargetAndCancelCurrentTransaction
import info.nightscout.androidaps.databinding.DialogInsulinBinding
import info.nightscout.androidaps.db.CareportalEvent
import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.db.TempTarget
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.CommandQueueProvider
import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger
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.utils.*
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.toVisibility
import info.nightscout.androidaps.utils.resources.ResourceHelper
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import java.text.DecimalFormat
import java.util.*
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import kotlin.math.abs
import kotlin.math.max
@ -51,6 +57,7 @@ class InsulinDialog : DialogFragmentWithDate() {
@Inject lateinit var repository: AppRepository
@Inject lateinit var config: Config
@Inject lateinit var uel: UserEntryLogger
@Inject lateinit var nsUpload: NSUpload
companion object {
@ -59,6 +66,8 @@ class InsulinDialog : DialogFragmentWithDate() {
private const val PLUS3_DEFAULT = 2.0
}
private val disposable = CompositeDisposable()
private val textWatcher: TextWatcher = object : TextWatcher {
override fun afterTextChanged(s: Editable) {
validateInputs()
@ -140,6 +149,7 @@ class InsulinDialog : DialogFragmentWithDate() {
override fun onDestroyView() {
super.onDestroyView()
disposable.clear()
_binding = null
}
@ -180,14 +190,18 @@ class InsulinDialog : DialogFragmentWithDate() {
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.bolus), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
if (eatingSoonChecked) {
uel.log(Action.TT_EATING_SOON, notes, ValueWithUnit(eatingSoonTT, units), ValueWithUnit(eatingSoonTTDuration, Units.M))
val tempTarget = TempTarget()
.date(System.currentTimeMillis())
.duration(eatingSoonTTDuration)
.reason(resourceHelper.gs(R.string.eatingsoon))
.source(Source.USER)
.low(Profile.toMgdl(eatingSoonTT, profileFunction.getUnits()))
.high(Profile.toMgdl(eatingSoonTT, profileFunction.getUnits()))
activePlugin.activeTreatments.addToHistoryTempTarget(tempTarget)
disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction(
timestamp = System.currentTimeMillis(),
duration = TimeUnit.MINUTES.toMillis(eatingSoonTTDuration.toLong()),
reason = TemporaryTarget.Reason.EATING_SOON,
lowTarget = Profile.toMgdl(eatingSoonTT, profileFunction.getUnits()),
highTarget = Profile.toMgdl(eatingSoonTT, 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 (insulinAfterConstraints > 0) {
val detailedBolusInfo = DetailedBolusInfo()

View file

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

View file

@ -19,26 +19,24 @@ import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R
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.events.EventAutosensCalculationFinished
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.interfaces.TreatmentsInterface
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
import info.nightscout.androidaps.events.EventAutosensCalculationFinished
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.*
import info.nightscout.androidaps.utils.extensions.toVisibility
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.androidaps.utils.sharedPreferences.SP
import info.nightscout.androidaps.utils.valueToUnits
import info.nightscout.androidaps.utils.wizard.BolusWizard
import io.reactivex.disposables.CompositeDisposable
import java.text.DecimalFormat
@ -58,9 +56,11 @@ class WizardDialog : DaggerDialogFragment() {
@Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin
@Inject lateinit var activePlugin: ActivePluginProvider
@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
@ -207,7 +207,7 @@ class WizardDialog : DaggerDialogFragment() {
private fun onCheckedChanged(buttonView: CompoundButton, @Suppress("UNUSED_PARAMETER") state: Boolean) {
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)
processCobCheckBox()
calculateInsulin()
@ -271,7 +271,7 @@ class WizardDialog : DaggerDialogFragment() {
} else {
binding.bgInput.value = 0.0
}
binding.ttcheckbox.isEnabled = treatmentsPlugin.tempTargetFromHistory != null
binding.ttcheckbox.isEnabled = repository.getTemporaryTargetActiveAt(dateUtil._now()).blockingGet() is ValueWrapper.Existing
// IOB calculation
treatmentsPlugin.updateTotalIOBTreatments()
@ -313,7 +313,8 @@ class WizardDialog : DaggerDialogFragment() {
}
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
var cob = 0.0

View file

@ -2,7 +2,9 @@ package info.nightscout.androidaps.historyBrowser
import android.content.Context
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
@ -32,8 +34,10 @@ class TreatmentsPluginHistory @Inject constructor(
nsUpload: NSUpload,
fabricPrivacy: FabricPrivacy,
dateUtil: DateUtil,
uploadQueue: UploadQueue
) : TreatmentsPlugin(injector, aapsLogger, rxBus, aapsSchedulers, resourceHelper, context, sp, profileFunction, activePlugin, nsUpload, fabricPrivacy, dateUtil, uploadQueue) {
uploadQueue: UploadQueue,
databaseHelper: DatabaseHelperInterface,
repository: AppRepository
) : TreatmentsPlugin(injector, aapsLogger, rxBus, aapsSchedulers, resourceHelper, context, sp, profileFunction, activePlugin, nsUpload, fabricPrivacy, dateUtil, uploadQueue, databaseHelper, repository) {
init {
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.EventNewNotification
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.events.EventAutosensCalculationFinished
import info.nightscout.androidaps.plugins.general.wear.events.EventWearConfirmAction
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.queue.Callback
@ -75,6 +76,7 @@ open class LoopPlugin @Inject constructor(
private val receiverStatusStore: ReceiverStatusStore,
private val fabricPrivacy: FabricPrivacy,
private val nsUpload: NSUpload,
private val databaseHelper: DatabaseHelperInterface,
private val hardLimits: HardLimits
) : PluginBase(PluginDescription()
.mainType(PluginType.LOOP)
@ -368,7 +370,7 @@ open class LoopPlugin @Inject constructor(
//only send to wear if Native notifications are turned off
if (!sp.getBoolean(R.string.key_raise_notifications_as_android_notifications, true)) {
// Send to Wear
rxBus.send(EventWearDoAction("changeRequest"))
rxBus.send(EventWearInitiateAction("changeRequest"))
}
}
} else {
@ -472,14 +474,14 @@ open class LoopPlugin @Inject constructor(
rxBus.send(EventNewOpenLoopNotification())
// Send to Wear
rxBus.send(EventWearDoAction("changeRequest"))
rxBus.send(EventWearInitiateAction("changeRequest"))
}
private fun dismissSuggestion() {
// dismiss notifications
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.cancel(Constants.notificationID)
rxBus.send(EventWearDoAction("cancelChangeRequest"))
rxBus.send(EventWearConfirmAction("cancelChangeRequest"))
}
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() {
override fun run() {
if (!result.success) {
@ -663,7 +665,7 @@ open class LoopPlugin @Inject constructor(
event.source = Source.USER
event.eventType = CareportalEvent.OPENAPSOFFLINE
event.json = data.toString()
MainApp.getDbHelper().createOrUpdate(event)
databaseHelper.createOrUpdate(event)
nsUpload.uploadOpenAPSOffline(event)
}

View file

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

View file

@ -6,6 +6,8 @@ import androidx.preference.SwitchPreference
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
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.logging.AAPSLogger
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.Profiler
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.sharedPreferences.SP
import javax.inject.Inject
@ -40,7 +43,9 @@ open class OpenAPSSMBPlugin @Inject constructor(
private val iobCobCalculatorPlugin: IobCobCalculatorPlugin,
private val hardLimits: HardLimits,
private val profiler: Profiler,
private val sp: SP
private val sp: SP,
private val dateUtil: DateUtil,
private val repository: AppRepository
) : PluginBase(PluginDescription()
.mainType(PluginType.APS)
.fragmentClass(OpenAPSSMBFragment::class.java.name)
@ -114,21 +119,22 @@ open class OpenAPSSMBPlugin @Inject constructor(
inputConstraints.copyReasons(maxIOBAllowedConstraint)
}.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 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 targetBg = hardLimits.verifyHardLimits(profile.targetMgdl, "targetBg", hardLimits.VERY_HARD_LIMIT_TARGET_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_TARGET_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), 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, R.string.temp_target_value, hardLimits.VERY_HARD_LIMIT_TARGET_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_TARGET_BG[1].toDouble())
var isTempTarget = false
treatmentsPlugin.getTempTargetFromHistory(System.currentTimeMillis())?.let { tempTarget ->
val tempTarget = repository.getTemporaryTargetActiveAt(dateUtil._now()).blockingGet()
if (tempTarget is ValueWrapper.Existing) {
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())
maxBg = hardLimits.verifyHardLimits(tempTarget.high, "maxBg", 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())
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.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.getIcTimeFromMidnight(Profile.secondsFromMidnight()), "carbratio", hardLimits.minIC(), hardLimits.maxIC())) return
if (!hardLimits.checkOnlyHardLimits(profile.isfMgdl, "sens", hardLimits.MINISF, hardLimits.MAXISF)) return
if (!hardLimits.checkOnlyHardLimits(profile.maxDailyBasal, "max_daily_basal", 0.02, hardLimits.maxBasal())) return
if (!hardLimits.checkOnlyHardLimits(pump.baseBasalRate, "current_basal", 0.01, hardLimits.maxBasal())) return
if (!hardLimits.checkOnlyHardLimits(profile.dia, R.string.profile_dia, hardLimits.minDia(), hardLimits.maxDia())) return
if (!hardLimits.checkOnlyHardLimits(profile.getIcTimeFromMidnight(Profile.secondsFromMidnight()), R.string.profile_carbs_ratio_value, hardLimits.minIC(), hardLimits.maxIC())) return
if (!hardLimits.checkOnlyHardLimits(profile.isfMgdl, R.string.profile_sensitivity_value, hardLimits.MINISF, hardLimits.MAXISF)) return
if (!hardLimits.checkOnlyHardLimits(profile.maxDailyBasal, R.string.profile_max_daily_basal_value, 0.02, hardLimits.maxBasal())) return
if (!hardLimits.checkOnlyHardLimits(pump.baseBasalRate, R.string.current_basal_value, 0.01, hardLimits.maxBasal())) return
startPart = System.currentTimeMillis()
if (constraintChecker.isAutosensModeEnabled().value()) {
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
}
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
}
return value

View file

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

View file

@ -10,10 +10,10 @@ import android.os.HandlerThread;
import android.os.IBinder;
import android.text.Spanned;
import androidx.annotation.NonNull;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.SwitchPreference;
import androidx.annotation.NonNull;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@ -27,8 +27,10 @@ import javax.inject.Singleton;
import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
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.events.EventAppExit;
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.EventPreferenceChange;
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.logging.UserEntryLogger;
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
import info.nightscout.androidaps.plugins.general.nsclient.data.AlarmAck;
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 io.reactivex.disposables.CompositeDisposable;
import static info.nightscout.androidaps.utils.extensions.TemporaryTargetExtensionKt.temporaryTargetFromJson;
import static info.nightscout.androidaps.utils.extensions.TemporaryTargetExtensionKt.temporaryTargetFromNsIdForInvalidating;
@Singleton
public class NSClientPlugin extends PluginBase {
private final CompositeDisposable disposable = new CompositeDisposable();
@ -78,6 +85,9 @@ public class NSClientPlugin extends PluginBase {
private final BuildHelper buildHelper;
private final ActivePluginProvider activePlugin;
private final NSUpload nsUpload;
private final AppRepository repository;
private final DatabaseHelperInterface databaseHelper;
private final UserEntryLogger uel;
public Handler handler;
@ -107,7 +117,10 @@ public class NSClientPlugin extends PluginBase {
Config config,
BuildHelper buildHelper,
ActivePluginProvider activePlugin,
NSUpload nsUpload
NSUpload nsUpload,
DatabaseHelperInterface databaseHelper,
AppRepository repository,
UserEntryLogger uel
) {
super(new PluginDescription()
.mainType(PluginType.GENERAL)
@ -132,6 +145,9 @@ public class NSClientPlugin extends PluginBase {
this.buildHelper = buildHelper;
this.activePlugin = activePlugin;
this.nsUpload = nsUpload;
this.databaseHelper = databaseHelper;
this.repository = repository;
this.uel = uel;
if (config.getNSCLIENT()) {
getPluginDescription().alwaysEnabled(true).visibleByDefault(true);
@ -170,12 +186,12 @@ public class NSClientPlugin extends PluginBase {
disposable.add(rxBus
.toObservable(EventNetworkChange.class)
.observeOn(aapsSchedulers.getIo())
.subscribe(event -> nsClientReceiverDelegate.onStatusEvent(event), fabricPrivacy::logException)
.subscribe(nsClientReceiverDelegate::onStatusEvent, fabricPrivacy::logException)
);
disposable.add(rxBus
.toObservable(EventPreferenceChange.class)
.observeOn(aapsSchedulers.getIo())
.subscribe(event -> nsClientReceiverDelegate.onStatusEvent(event), fabricPrivacy::logException)
.subscribe(nsClientReceiverDelegate::onStatusEvent, fabricPrivacy::logException)
);
disposable.add(rxBus
.toObservable(EventAppExit.class)
@ -197,7 +213,7 @@ public class NSClientPlugin extends PluginBase {
disposable.add(rxBus
.toObservable(EventChargingState.class)
.observeOn(aapsSchedulers.getIo())
.subscribe(event -> nsClientReceiverDelegate.onStatusEvent(event), fabricPrivacy::logException)
.subscribe(nsClientReceiverDelegate::onStatusEvent, fabricPrivacy::logException)
);
disposable.add(rxBus
.toObservable(EventNSClientResend.class)
@ -402,16 +418,21 @@ public class NSClientPlugin extends PluginBase {
}
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
EventNsTreatment evtTreatment = new EventNsTreatment(EventNsTreatment.Companion.getREMOVE(), json);
rxBus.send(evtTreatment);
// old DB model
String _id = JsonHelper.safeGetString(json, "_id");
MainApp.getDbHelper().deleteTempTargetById(_id);
MainApp.getDbHelper().deleteTempBasalById(_id);
MainApp.getDbHelper().deleteExtendedBolusById(_id);
MainApp.getDbHelper().deleteCareportalEventById(_id);
MainApp.getDbHelper().deleteProfileSwitchById(_id);
databaseHelper.deleteTempBasalById(_id);
databaseHelper.deleteExtendedBolusById(_id);
databaseHelper.deleteCareportalEventById(_id);
databaseHelper.deleteProfileSwitchById(_id);
}
private void handleTreatmentFromNS(JSONObject json, String action) {
@ -428,13 +449,24 @@ public class NSClientPlugin extends PluginBase {
EventNsTreatment evtTreatment = new EventNsTreatment(mode, json);
rxBus.send(evtTreatment);
} 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)) {
MainApp.getDbHelper().createTempBasalFromJsonIfNotExists(json);
databaseHelper.createTempBasalFromJsonIfNotExists(json);
} else if (eventType.equals(CareportalEvent.COMBOBOLUS)) {
MainApp.getDbHelper().createExtendedBolusFromJsonIfNotExists(json);
databaseHelper.createExtendedBolusFromJsonIfNotExists(json);
} else if (eventType.equals(CareportalEvent.PROFILESWITCH)) {
MainApp.getDbHelper().createProfileSwitchFromJsonIfNotExists(activePlugin, nsUpload, json);
databaseHelper.createProfileSwitchFromJsonIfNotExists(activePlugin, nsUpload, json);
} else if (eventType.equals(CareportalEvent.SITECHANGE) ||
eventType.equals(CareportalEvent.INSULINCHANGE) ||
eventType.equals(CareportalEvent.SENSORCHANGE) ||
@ -446,7 +478,7 @@ public class NSClientPlugin extends PluginBase {
eventType.equals(CareportalEvent.EXERCISE) ||
eventType.equals(CareportalEvent.OPENAPSOFFLINE) ||
eventType.equals(CareportalEvent.PUMPBATTERYCHANGE)) {
MainApp.getDbHelper().createCareportalEventFromJsonIfNotExists(json);
databaseHelper.createCareportalEventFromJsonIfNotExists(json);
}
if (eventType.equals(CareportalEvent.ANNOUNCEMENT)) {
@ -468,7 +500,7 @@ public class NSClientPlugin extends PluginBase {
private void storeMbg(JSONObject mbgJson) {
NSMbg nsMbg = new NSMbg(mbgJson);
CareportalEvent careportalEvent = new CareportalEvent(nsMbg);
MainApp.getDbHelper().createOrUpdate(careportalEvent);
databaseHelper.createOrUpdate(careportalEvent);
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.database.AppRepository
import info.nightscout.androidaps.database.entities.GlucoseValue
import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.db.*
import info.nightscout.androidaps.events.EventPreferenceChange
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.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import io.reactivex.rxkotlin.plusAssign
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.androidaps.utils.sharedPreferences.SP
@ -36,6 +36,7 @@ import io.reactivex.Observable
import io.reactivex.Single
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable
import io.reactivex.rxkotlin.plusAssign
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
@ -268,16 +269,15 @@ class OpenHumansUploader @Inject constructor(
}
@JvmOverloads
fun enqueueTempTarget(tempTarget: TempTarget?, deleted: Boolean = false) = tempTarget?.let {
fun enqueueTempTarget(tempTarget: TemporaryTarget?, deleted: Boolean = false) = tempTarget?.let {
insertQueueItem("TempTargets") {
put("date", tempTarget.date)
put("date", tempTarget.timestamp)
put("isValid", tempTarget.isValid)
put("source", tempTarget.source)
put("nsId", tempTarget._id)
put("low", tempTarget.low)
put("high", tempTarget.high)
put("nsId", tempTarget.interfaceIDs_backing?.nightscoutId)
put("low", tempTarget.lowTarget)
put("high", tempTarget.highTarget)
put("reason", tempTarget.reason)
put("durationInMinutes", tempTarget.durationInMinutes)
put("durationInMinutes", tempTarget.duration)
put("isDeletion", deleted)
}
}
@ -384,7 +384,7 @@ class OpenHumansUploader @Inject constructor(
.andThen(Observable.defer { Observable.fromIterable(MainApp.getDbHelper().allTemporaryBasals) })
.map { enqueueTemporaryBasal(it); increaseCounter() }
.ignoreElements()
.andThen(Observable.defer { Observable.fromIterable(MainApp.getDbHelper().allTempTargets) })
.andThen(Observable.defer { Observable.fromIterable(repository.compatGetTemporaryTargetData().blockingGet()) })
.map { enqueueTempTarget(it); increaseCounter() }
.ignoreElements()
.doOnSubscribe {

View file

@ -28,7 +28,11 @@ import info.nightscout.androidaps.Config
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R
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.interfaces.end
import info.nightscout.androidaps.databinding.OverviewFragmentBinding
import info.nightscout.androidaps.dialogs.*
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.graphData.GraphData
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.IobCobCalculatorPlugin
import info.nightscout.androidaps.events.EventAutosensCalculationFinished
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
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 databaseHelper: DatabaseHelperInterface
@Inject lateinit var uel: UserEntryLogger
@Inject lateinit var repository: AppRepository
private val disposable = CompositeDisposable()
@ -292,14 +296,14 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
if (childFragmentManager.isStateSaved) return
activity?.let { activity ->
when (v.id) {
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.insulin_button -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { if (isAdded) InsulinDialog().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.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.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.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.active_profile -> {
R.id.active_profile -> {
ProfileViewerDialog().also { pvd ->
pvd.arguments = Bundle().also {
it.putLong("time", DateUtil.now())
@ -308,7 +312,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
}.show(childFragmentManager, "ProfileViewDialog")
}
R.id.cgm_button -> {
R.id.cgm_button -> {
if (xdripPlugin.isEnabled(PluginType.BGSOURCE))
openCgmApp("com.eveningoutpost.dexdrip")
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)) {
CalibrationDialog().show(childFragmentManager, "CalibrationDialog")
} 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
if (loopPlugin.isEnabled(PluginType.LOOP)) {
val lastRun = loopPlugin.lastRun
@ -346,7 +350,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
uel.log(Action.ACCEPTS_TEMP_BASAL)
binding.buttonsLayout.acceptTempButton.visibility = View.GONE
(context?.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager).cancel(Constants.notificationID)
rxBus.send(EventWearDoAction("cancelChangeRequest"))
rxBus.send(EventWearInitiateAction("cancelChangeRequest"))
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 {
if (isAdded) LoopDialog().also { dialog ->
dialog.arguments = Bundle().also { it.putInt("showOkCancel", 1) }
@ -386,7 +390,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
return true
}
R.id.aps_mode -> {
R.id.aps_mode -> {
activity?.let { activity ->
protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable {
LoopDialog().also { dialog ->
@ -396,8 +400,8 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
}
}
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.temp_target -> v.performClick()
R.id.active_profile -> activity?.let { activity -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { ProfileSwitchDialog().show(childFragmentManager, "Overview") }) }
}
return false
@ -673,11 +677,11 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
}
// temp target
val tempTarget = treatmentsPlugin.tempTargetFromHistory
if (tempTarget != null) {
val tempTarget: ValueWrapper<TemporaryTarget> = repository.getTemporaryTargetActiveAt(dateUtil._now()).blockingGet()
if (tempTarget is ValueWrapper.Existing) {
binding.loopPumpStatusLayout.tempTarget.setTextColor(resourceHelper.gc(R.color.ribbonTextWarning))
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 {
// If the target is not the same as set in the profile then oref has overridden it
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.IobTotal
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.interfaces.ActivePluginProvider
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.iob.iobCobCalculator.AutosensResult
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.Round
import info.nightscout.androidaps.utils.extensions.target
import info.nightscout.androidaps.utils.resources.ResourceHelper
import java.util.*
import javax.inject.Inject
@ -40,7 +44,6 @@ class GraphData(
private val graph: GraphView,
private val iobCobCalculatorPlugin: IobCobCalculatorPlugin,
private val treatmentsPlugin: TreatmentsInterface
) {
// IobCobCalculatorPlugin Cannot be injected: HistoryBrowser
@ -48,6 +51,8 @@ class GraphData(
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var activePlugin: ActivePluginProvider
@Inject lateinit var repository: AppRepository
@Inject lateinit var dateUtil: DateUtil
var maxY = Double.MIN_VALUE
private var minY = Double.MAX_VALUE
@ -212,11 +217,11 @@ class GraphData(
lastRun?.constraintsProcessed?.let { toTime = max(it.latestPredictionsTime, toTime) }
var time = fromTime
while (time < toTime) {
val tt = treatmentsPlugin.getTempTargetFromHistory(time)
val value: Double = if (tt == null) {
Profile.fromMgdlToUnits((profile.getTargetLowMgdl(time) + profile.getTargetHighMgdl(time)) / 2, units)
val tt = repository.getTemporaryTargetActiveAt(time).blockingGet()
val value: Double = if (tt is ValueWrapper.Existing) {
Profile.fromMgdlToUnits(tt.value.target(), units)
} else {
Profile.fromMgdlToUnits(tt.target(), units)
Profile.fromMgdlToUnits((profile.getTargetLowMgdl(time) + profile.getTargetHighMgdl(time)) / 2, units)
}
if (lastTarget != value) {
if (lastTarget != -1.0) targetsSeriesArray.add(DataPoint(time.toDouble(), lastTarget))
@ -344,7 +349,8 @@ class GraphData(
time += 5 * 60 * 1000L
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)
val bgi: Double = total.activity * profile.getIsfMgdl(time) * 5.0
@ -405,7 +411,7 @@ class GraphData(
if (showPrediction) {
val autosensData = iobCobCalculatorPlugin.getLastAutosensDataSynchronized("GraphData")
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 iobPredictionArray = iobCobCalculatorPlugin.calculateIobArrayForSMB(lastAutosensResult, SMBDefaults.exercise_mode, SMBDefaults.half_basal_exercise_target, isTempTarget)
for (i in iobPredictionArray) {
@ -519,10 +525,10 @@ class GraphData(
while (time <= toTime) {
// if align Dev Scale with BGI scale, then calculate BGI value, else bgi = 0.0
val bgi: Double = if (devBgiScale) {
val profile = profileFunction.getProfile(time)
total = iobCobCalculatorPlugin.calculateFromTreatmentsAndTempsSynchronized(time, profile)
total.activity * (profile?.getIsfMgdl(time) ?: 0.0) * 5.0
} else 0.0
val profile = profileFunction.getProfile(time)
total = iobCobCalculatorPlugin.calculateFromTreatmentsAndTempsSynchronized(time, profile)
total.activity * (profile?.getIsfMgdl(time) ?: 0.0) * 5.0
} else 0.0
iobCobCalculatorPlugin.getAutosensData(time)?.let { autosensData ->
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.data.DetailedBolusInfo
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.transactions.CancelCurrentTemporaryTargetIfAnyTransaction
import info.nightscout.androidaps.database.transactions.InsertTemporaryTargetAndCancelCurrentTransaction
import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.db.TempTarget
import info.nightscout.androidaps.events.EventPreferenceChange
import info.nightscout.androidaps.events.EventRefreshOverview
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.bus.RxBusWrapper
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.overview.events.EventNewNotification
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 java.text.Normalizer
import java.util.*
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import javax.inject.Singleton
import kotlin.math.max
@ -71,7 +76,9 @@ class SmsCommunicatorPlugin @Inject constructor(
private var otp: OneTimePassword,
private val config: Config,
private val dateUtil: DateUtil,
private val uel: UserEntryLogger
private val uel: UserEntryLogger,
private val nsUpload: NSUpload,
private val repository: AppRepository
) : PluginBase(PluginDescription()
.mainType(PluginType.GENERAL)
.fragmentClass(SmsCommunicatorFragment::class.java.name)
@ -172,6 +179,7 @@ class SmsCommunicatorPlugin @Inject constructor(
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
}
@Suppress("SpellCheckingInspection")
override fun doWork(): Result {
val bundle = bundleStore.pickup(inputData.getLong(DataReceiver.STORE_KEY, -1))
?: return Result.failure()
@ -238,58 +246,58 @@ class SmsCommunicatorPlugin @Inject constructor(
if (divided.isNotEmpty() && isCommand(divided[0].toUpperCase(Locale.getDefault()), receivedSms.phoneNumber)) {
when (divided[0].toUpperCase(Locale.getDefault())) {
"BG" ->
"BG" ->
if (divided.size == 1) processBG(receivedSms)
else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat)))
"LOOP" ->
"LOOP" ->
if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed)))
else if (divided.size == 2 || divided.size == 3) processLOOP(divided, receivedSms)
else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat)))
"TREATMENTS" ->
if (divided.size == 2) processTREATMENTS(divided, receivedSms)
else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat)))
"NSCLIENT" ->
"NSCLIENT" ->
if (divided.size == 2) processNSCLIENT(divided, receivedSms)
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)))
else if (divided.size <= 3) processPUMP(divided, receivedSms)
else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat)))
"PROFILE" ->
"PROFILE" ->
if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed)))
else if (divided.size == 2 || divided.size == 3) processPROFILE(divided, receivedSms)
else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat)))
"BASAL" ->
"BASAL" ->
if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed)))
else if (divided.size == 2 || divided.size == 3) processBASAL(divided, receivedSms)
else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat)))
"EXTENDED" ->
"EXTENDED" ->
if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed)))
else if (divided.size == 2 || divided.size == 3) processEXTENDED(divided, receivedSms)
else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat)))
"BOLUS" ->
"BOLUS" ->
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 && pump.isSuspended()) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.pumpsuspended)))
else if (divided.size == 2 || divided.size == 3) processBOLUS(divided, receivedSms)
else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat)))
"CARBS" ->
"CARBS" ->
if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed)))
else if (divided.size == 2 || divided.size == 3) processCARBS(divided, receivedSms)
else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat)))
"CAL" ->
"CAL" ->
if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed)))
else if (divided.size == 2) processCAL(divided, receivedSms)
else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat)))
"TARGET" ->
"TARGET" ->
if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed)))
else if (divided.size == 2) processTARGET(divided, receivedSms)
else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat)))
"SMS" ->
"SMS" ->
if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed)))
else if (divided.size == 2) processSMS(divided, receivedSms)
else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat)))
"HELP" ->
"HELP" ->
if (divided.size == 1 || divided.size == 2) processHELP(divided, receivedSms)
else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat)))
else ->
@ -310,8 +318,8 @@ class SmsCommunicatorPlugin @Inject constructor(
if (actualBG != null) {
reply = resourceHelper.gs(R.string.sms_actualbg) + " " + actualBG.valueToUnitsString(units) + ", "
} else if (lastBG != null) {
val agoMsec = System.currentTimeMillis() - lastBG.timestamp
val agoMin = (agoMsec / 60.0 / 1000.0).toInt()
val agoMilliseconds = System.currentTimeMillis() - lastBG.timestamp
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) + ", "
}
val glucoseStatus = GlucoseStatus(injector).glucoseStatusData
@ -373,7 +381,7 @@ class SmsCommunicatorPlugin @Inject constructor(
receivedSms.processed = true
}
"STATUS" -> {
"STATUS" -> {
val reply = if (loopPlugin.isEnabled(PluginType.LOOP)) {
if (loopPlugin.isSuspended) String.format(resourceHelper.gs(R.string.loopsuspendedfor), loopPlugin.minutesToEndOfSuspend())
else resourceHelper.gs(R.string.smscommunicator_loopisenabled)
@ -383,7 +391,7 @@ class SmsCommunicatorPlugin @Inject constructor(
receivedSms.processed = true
}
"RESUME" -> {
"RESUME" -> {
val passCode = generatePassCode()
val reply = String.format(resourceHelper.gs(R.string.smscommunicator_loopresumereplywithcode), passCode)
receivedSms.processed = true
@ -407,7 +415,7 @@ class SmsCommunicatorPlugin @Inject constructor(
})
}
"SUSPEND" -> {
"SUSPEND" -> {
var duration = 0
if (divided.size == 3) duration = SafeParse.stringToInt(divided[2])
duration = max(0, duration)
@ -573,23 +581,23 @@ class SmsCommunicatorPlugin @Inject constructor(
sendSMS(Sms(receivedSms.phoneNumber, reply))
}
} else {
val pindex = SafeParse.stringToInt(divided[1])
val pIndex = SafeParse.stringToInt(divided[1])
var percentage = 100
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 (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 {
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)))
else {
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
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() {
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)
sendSMS(Sms(receivedSms.phoneNumber, replyText))
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
else -> Constants.defaultEatingSoonTTmgdl
}
val tempTarget = TempTarget()
.date(System.currentTimeMillis())
.duration(eatingSoonTTDuration)
.reason(resourceHelper.gs(R.string.eatingsoon))
.source(Source.USER)
.low(Profile.toMgdl(eatingSoonTT, currentProfile.units))
.high(Profile.toMgdl(eatingSoonTT, currentProfile.units))
activePlugin.activeTreatments.addToHistoryTempTarget(tempTarget)
disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction(
timestamp = System.currentTimeMillis(),
duration = TimeUnit.MINUTES.toMillis(eatingSoonTTDuration.toLong()),
reason = TemporaryTarget.Reason.EATING_SOON,
lowTarget = Profile.toMgdl(eatingSoonTT, profileFunction.getUnits()),
highTarget = Profile.toMgdl(eatingSoonTT, 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)
})
val tt = if (currentProfile.units == Constants.MMOL) {
DecimalFormatter.to1Decimal(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)
tt = Profile.toCurrentUnits(profileFunction, tt)
tt = if (tt > 0) tt else if (units == Constants.MMOL) defaultTargetMMOL else defaultTargetMGDL
val tempTarget = TempTarget()
.date(System.currentTimeMillis())
.duration(ttDuration)
.reason(resourceHelper.gs(R.string.eatingsoon))
.source(Source.USER)
.low(Profile.toMgdl(tt, units))
.high(Profile.toMgdl(tt, units))
activePlugin.activeTreatments.addToHistoryTempTarget(tempTarget)
disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction(
timestamp = System.currentTimeMillis(),
duration = TimeUnit.MINUTES.toMillis(ttDuration.toLong()),
reason = TemporaryTarget.Reason.EATING_SOON,
lowTarget = Profile.toMgdl(tt, profileFunction.getUnits()),
highTarget = Profile.toMgdl(tt, 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)
})
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)
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
@ -957,13 +973,12 @@ class SmsCommunicatorPlugin @Inject constructor(
receivedSms.processed = true
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction() {
override fun run() {
val tempTarget = TempTarget()
.source(Source.USER)
.date(DateUtil.now())
.duration(0)
.low(0.0)
.high(0.0)
activePlugin.activeTreatments.addToHistoryTempTarget(tempTarget)
disposable += repository.runTransactionForResult(CancelCurrentTemporaryTargetIfAnyTransaction(dateUtil._now()))
.subscribe({ result ->
result.updated.forEach { nsUpload.updateTempTarget(it) }
}, {
aapsLogger.error(LTag.BGSOURCE, "Error while saving temporary target", it)
})
val replyText = String.format(resourceHelper.gs(R.string.smscommunicator_tt_canceled))
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
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.data.DetailedBolusInfo
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.Source
import info.nightscout.androidaps.db.TDD
import info.nightscout.androidaps.db.TempTarget
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.CommandQueueProvider
import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.interfaces.PluginBase
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.bus.RxBusWrapper
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.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.pump.insight.LocalInsightPlugin
import info.nightscout.androidaps.plugins.treatments.CarbsGenerator
@ -43,6 +52,7 @@ import java.text.DateFormat
import java.text.DecimalFormat
import java.text.SimpleDateFormat
import java.util.*
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import javax.inject.Singleton
@ -50,6 +60,7 @@ import javax.inject.Singleton
class ActionStringHandler @Inject constructor(
private val sp: SP,
private val rxBus: RxBusWrapper,
private val aapsLogger: AAPSLogger,
aapsSchedulers: AapsSchedulers,
private val resourceHelper: ResourceHelper,
private val injector: HasAndroidInjector,
@ -71,7 +82,9 @@ class ActionStringHandler @Inject constructor(
private val hardLimits: HardLimits,
private val carbsGenerator: CarbsGenerator,
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
@ -83,9 +96,14 @@ class ActionStringHandler @Inject constructor(
init {
disposable += rxBus
.toObservable(EventWearDoAction::class.java)
.toObservable(EventWearInitiateAction::class.java)
.observeOn(aapsSchedulers.main)
.subscribe({ handleInitiate(it.action) }, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventWearConfirmAction::class.java)
.observeOn(aapsSchedulers.main)
.subscribe({ handleConfirmation(it.action) }, fabricPrivacy::logException)
}
@Synchronized
@ -203,7 +221,10 @@ class ActionStringHandler @Inject constructor(
}
val format = DecimalFormat("0.00")
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()),
0.0, percentage.toDouble(), useBG, useCOB, useBolusIOB, useBasalIOB, false, useTT, useTrend, false)
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 :("
//Check for Temp-Target:
val tempTarget = activePlugin.activeTreatments.tempTargetFromHistory
if (tempTarget != null) {
ret += "Temp Target: " + Profile.toTargetRangeString(tempTarget.low, tempTarget.low, Constants.MGDL, profileFunction.getUnits())
ret += "\nuntil: " + dateUtil.timeString(tempTarget.originalEnd())
val tempTarget = repository.getTemporaryTargetActiveAt(dateUtil._now()).blockingGet()
if (tempTarget is ValueWrapper.Existing) {
ret += "Temp Target: " + Profile.toTargetRangeString(tempTarget.value.lowTarget, tempTarget.value.lowTarget, Constants.MGDL, profileFunction.getUnits())
ret += "\nuntil: " + dateUtil.timeString(tempTarget.value.end)
ret += "\n\n"
}
ret += "DEFAULT RANGE: "
@ -565,17 +586,26 @@ class ActionStringHandler @Inject constructor(
}
private fun generateTempTarget(duration: Int, low: Double, high: Double) {
val tempTarget = TempTarget()
.date(System.currentTimeMillis())
.duration(duration)
.reason("WearPlugin")
.source(Source.USER)
if (tempTarget.durationInMinutes != 0) {
tempTarget.low(low).high(high)
} else {
tempTarget.low(0.0).high(0.0)
}
activePlugin.activeTreatments.addToHistoryTempTarget(tempTarget)
if (duration != 0)
disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction(
timestamp = System.currentTimeMillis(),
duration = TimeUnit.MINUTES.toMillis(duration.toLong()),
reason = TemporaryTarget.Reason.WEAR,
lowTarget = Profile.toMgdl(low, profileFunction.getUnits()),
highTarget = Profile.toMgdl(high, profileFunction.getUnits())
)).subscribe({ result ->
result.inserted.forEach { nsUpload.uploadTempTarget(it) }
result.updated.forEach { nsUpload.updateTempTarget(it) }
}, {
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) {

View file

@ -2,4 +2,4 @@ package info.nightscout.androidaps.plugins.general.wear.events
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.general.nsclient.data.NSDeviceStatus;
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.IobCobCalculatorPlugin;
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)) {
String actionstring = new String(event.getData());
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)) {
String actionstring = new String(event.getData());
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 info.nightscout.androidaps.Constants
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.EventAutosensCalculationFinished
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.AAPSLogger
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.data.AutosensData
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.sensitivity.SensitivityAAPSPlugin
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.utils.*
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.sharedPreferences.SP
import java.util.*
@ -56,6 +59,7 @@ class IobCobOref1Thread internal constructor(
@Inject lateinit var profiler: Profiler
@Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var dateUtil: DateUtil
@Inject lateinit var repository: AppRepository
private var mWakeLock: PowerManager.WakeLock? = null
@ -292,9 +296,9 @@ class IobCobOref1Thread internal constructor(
// TODO AS-FIX
@Suppress("SimplifyBooleanWithConstants")
if (false && sp.getBoolean(R.string.key_high_temptarget_raises_sensitivity, SMBDefaults.high_temptarget_raises_sensitivity)) {
val tempTarget = treatmentsPlugin.getTempTargetFromHistory(bgTime)
if (tempTarget != null && tempTarget.target() >= 100) {
autosensData.extraDeviation.add(-(tempTarget.target() - 100) / 20)
val tempTarget = repository.getTemporaryTargetActiveAt(dateUtil._now()).blockingGet()
if (tempTarget is ValueWrapper.Existing && tempTarget.value.target() >= 100) {
autosensData.extraDeviation.add(-(tempTarget.value.target() - 100) / 20)
}
}

View file

@ -290,7 +290,7 @@ class VirtualPumpPlugin @Inject constructor(
override fun cancelExtendedBolus(): PumpEnactResult {
val result = PumpEnactResult(injector)
if (treatmentsPlugin.isInHistoryExtendedBoluslInProgress) {
if (treatmentsPlugin.isInHistoryExtendedBolusInProgress) {
val exStop = ExtendedBolus(injector, System.currentTimeMillis())
exStop.source = Source.USER
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) {
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)
}
}, {
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("glucose", calibrationGlucoseLevels[i])
data.put("units", Constants.MGDL)
nsUpload.uploadCareportalEntryToNS(data)
nsUpload.uploadCareportalEntryToNS(data, calibrationTimestamps[i])
}
} catch (e: JSONException) {
aapsLogger.error("Unhandled exception", e)

View file

@ -82,7 +82,7 @@ class GlimpPlugin @Inject constructor(
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()
}

View file

@ -100,7 +100,7 @@ class MM640gPlugin @Inject constructor(
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) {
aapsLogger.error("Exception: ", e)

View file

@ -139,7 +139,7 @@ class NSClientSourcePlugin @Inject constructor(
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) {
aapsLogger.error("Unhandled exception", e)

View file

@ -93,7 +93,7 @@ class PoctechPlugin @Inject constructor(
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) {
aapsLogger.error("Exception: ", e)

View file

@ -82,7 +82,7 @@ class TomatoPlugin @Inject constructor(
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()
}

View file

@ -50,7 +50,8 @@ class XdripPlugin @Inject constructor(
GlucoseValue.SourceSensor.DEXCOM_G6_NATIVE,
GlucoseValue.SourceSensor.DEXCOM_G5_NATIVE,
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 }
}
@ -102,4 +103,4 @@ class XdripPlugin @Inject constructor(
return Result.success()
}
}
}
}

View file

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

View file

@ -8,8 +8,6 @@ import androidx.annotation.Nullable;
import com.google.firebase.analytics.FirebaseAnalytics;
import androidx.annotation.NonNull;
import java.util.ArrayList;
import java.util.List;
@ -18,7 +16,6 @@ import javax.inject.Singleton;
import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.activities.ErrorHelperActivity;
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.IobTotal;
import info.nightscout.androidaps.data.NonOverlappingIntervals;
import info.nightscout.androidaps.data.OverlappingIntervals;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.ProfileIntervals;
import info.nightscout.androidaps.database.AppRepository;
import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.ProfileSwitch;
import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.events.EventReloadProfileSwitchData;
import info.nightscout.androidaps.events.EventReloadTempBasalData;
import info.nightscout.androidaps.events.EventReloadTreatmentData;
import info.nightscout.androidaps.events.EventTempTargetChange;
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
@ -81,6 +77,8 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
private final UploadQueue uploadQueue;
private final FabricPrivacy fabricPrivacy;
private final DateUtil dateUtil;
private final DatabaseHelperInterface databaseHelper;
private final AppRepository repository;
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 Intervals<TemporaryBasal> tempBasals = new NonOverlappingIntervals<>();
private final Intervals<ExtendedBolus> extendedBoluses = new NonOverlappingIntervals<>();
private final Intervals<TempTarget> tempTargets = new OverlappingIntervals<>();
private final ProfileIntervals<ProfileSwitch> profiles = new ProfileIntervals<>();
@Inject
@ -109,7 +106,9 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
NSUpload nsUpload,
FabricPrivacy fabricPrivacy,
DateUtil dateUtil,
UploadQueue uploadQueue
UploadQueue uploadQueue,
DatabaseHelperInterface databaseHelper,
AppRepository repository
) {
super(new PluginDescription()
.mainType(PluginType.TREATMENT)
@ -133,6 +132,8 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
this.dateUtil = dateUtil;
this.nsUpload = nsUpload;
this.uploadQueue = uploadQueue;
this.databaseHelper = databaseHelper;
this.repository = repository;
}
@Override
@ -158,12 +159,6 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
.subscribe(event -> initializeProfileSwitchData(range()),
fabricPrivacy::logException
));
disposable.add(rxBus
.toObservable(EventTempTargetChange.class)
.observeOn(aapsSchedulers.getIo())
.subscribe(event -> initializeTempTargetData(range()),
fabricPrivacy::logException
));
disposable.add(rxBus
.toObservable(EventReloadTempBasalData.class)
.observeOn(aapsSchedulers.getIo())
@ -198,7 +193,6 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
initializeTempBasalData(range);
initializeTreatmentData(range);
initializeExtendedBolusData(range);
initializeTempTargetData(range);
initializeProfileSwitchData(range);
}
@ -213,7 +207,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
private void initializeTempBasalData(long range) {
getAapsLogger().debug(LTag.DATATREATMENTS, "initializeTempBasalData");
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) {
getAapsLogger().debug(LTag.DATATREATMENTS, "initializeExtendedBolusData");
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) {
getAapsLogger().debug(LTag.DATATREATMENTS, "initializeProfileSwitchData");
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 {
uploadQueue.removeID("dbAdd", tempBasalId);
}
MainApp.getDbHelper().delete(tempBasal);
databaseHelper.delete(tempBasal);
}
@Override
public boolean isInHistoryExtendedBoluslInProgress() {
public boolean isInHistoryExtendedBolusInProgress() {
return getExtendedBolusFromHistory(System.currentTimeMillis()) != null; //TODO: crosscheck here
}
@ -425,7 +412,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
PumpInterface pumpInterface = activePlugin.getActivePump();
synchronized (tempBasals) {
for (Integer pos = 0; pos < tempBasals.size(); pos++) {
for (int pos = 0; pos < tempBasals.size(); pos++) {
TemporaryBasal t = tempBasals.get(pos);
if (t.date > time) continue;
IobTotal calc;
@ -576,7 +563,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
@Override
public boolean addToHistoryExtendedBolus(ExtendedBolus extendedBolus) {
//log.debug("Adding new ExtentedBolus record" + extendedBolus.log());
boolean newRecordCreated = MainApp.getDbHelper().createOrUpdate(extendedBolus);
boolean newRecordCreated = databaseHelper.createOrUpdate(extendedBolus);
if (newRecordCreated) {
if (extendedBolus.durationInMinutes == 0) {
if (activePlugin.getActivePump().isFakingTempsByExtendedBoluses())
@ -610,7 +597,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
@Override
public boolean addToHistoryTempBasal(TemporaryBasal tempBasal) {
//log.debug("Adding new TemporaryBasal record" + tempBasal.toString());
boolean newRecordCreated = MainApp.getDbHelper().createOrUpdate(tempBasal);
boolean newRecordCreated = databaseHelper.createOrUpdate(tempBasal);
if (newRecordCreated) {
if (tempBasal.durationInMinutes == 0)
nsUpload.uploadTempBasalEnd(tempBasal.date, false, tempBasal.pumpId);
@ -711,36 +698,6 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
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
@Nullable
public ProfileSwitch getProfileSwitchFromHistory(long time) {
@ -760,8 +717,8 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
public void addToHistoryProfileSwitch(ProfileSwitch profileSwitch) {
//log.debug("Adding new TemporaryBasal record" + profileSwitch.log());
rxBus.send(new EventDismissNotification(Notification.PROFILE_SWITCH_MISSING));
MainApp.getDbHelper().createOrUpdate(profileSwitch);
nsUpload.uploadProfileSwitch(profileSwitch);
databaseHelper.createOrUpdate(profileSwitch);
nsUpload.uploadProfileSwitch(profileSwitch, profileSwitch.date);
}
@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.RecyclerView
import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.MainApp
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.interfaces.end
import info.nightscout.androidaps.database.transactions.InvalidateTemporaryTargetTransaction
import info.nightscout.androidaps.databinding.TreatmentsTemptargetFragmentBinding
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.interfaces.ActivePluginProvider
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.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.plugins.general.nsclient.UploadQueue
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.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
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.rx.AapsSchedulers
import info.nightscout.androidaps.utils.sharedPreferences.SP
import io.reactivex.Completable
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxkotlin.subscribeBy
import java.util.concurrent.TimeUnit
import javax.inject.Inject
class TreatmentsTempTargetFragment : DaggerFragment() {
@Inject lateinit var activePlugin: ActivePluginProvider
@Inject lateinit var sp: SP
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var nsUpload: NSUpload
@ -51,9 +63,12 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
@Inject lateinit var buildHelper: BuildHelper
@Inject lateinit var aapsSchedulers: AapsSchedulers
@Inject lateinit var uel: UserEntryLogger
@Inject lateinit var repository: AppRepository
private val disposable = CompositeDisposable()
private val millsToThePast = T.days(30).msecs()
private var _binding: TreatmentsTemptargetFragmentBinding? = null
// This property is only valid between onCreateView and
@ -66,29 +81,59 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
binding.recyclerview.setHasFixedSize(true)
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
binding.recyclerview.adapter = RecyclerViewAdapter(activePlugin.activeTreatments.tempTargetsFromHistory)
binding.refreshFromNightscout.setOnClickListener {
context?.let { context ->
OKDialog.showConfirmation(context, resourceHelper.gs(R.string.refresheventsfromnightscout) + " ?", {
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())
})
}
}
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
override fun onResume() {
super.onResume()
disposable.add(rxBus
swapAdapter()
disposable += rxBus
.toObservable(EventTempTargetChange::class.java)
.observeOn(aapsSchedulers.main)
.subscribe({ updateGui() }, fabricPrivacy::logException)
)
updateGui()
.observeOn(aapsSchedulers.io)
.debounce(1L, TimeUnit.SECONDS)
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventTreatmentUpdateGui::class.java) // TODO join with above
.observeOn(aapsSchedulers.io)
.debounce(1L, TimeUnit.SECONDS)
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
}
@Synchronized
@ -100,17 +145,14 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
@Synchronized
override fun onDestroyView() {
super.onDestroyView()
binding.recyclerview.adapter = null // avoid leaks
_binding = null
}
private fun updateGui() {
if (_binding == null) return
binding.recyclerview.swapAdapter(RecyclerViewAdapter(activePlugin.activeTreatments.tempTargetsFromHistory), false)
}
inner class RecyclerViewAdapter internal constructor(private var tempTargetList: List<TemporaryTarget>) : RecyclerView.Adapter<TempTargetsViewHolder>() {
inner class RecyclerViewAdapter internal constructor(var tempTargetList: Intervals<TempTarget>) : RecyclerView.Adapter<TempTargetsViewHolder>() {
var currentlyActiveTarget: TempTarget? = tempTargetList.getValueByInterval(System.currentTimeMillis())
private val dbRecord = repository.getTemporaryTargetActiveAt(dateUtil._now()).blockingGet()
private val currentlyActiveTarget = if (dbRecord is ValueWrapper.Existing) dbRecord.value else null
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): TempTargetsViewHolder =
TempTargetsViewHolder(LayoutInflater.from(viewGroup.context).inflate(R.layout.treatments_temptarget_item, viewGroup, false))
@ -118,35 +160,25 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
@SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: TempTargetsViewHolder, position: Int) {
val units = profileFunction.getUnits()
val tempTarget = tempTargetList.getReversed(position)
holder.binding.ph.visibility = if (tempTarget.source == Source.PUMP) View.VISIBLE else View.GONE
holder.binding.ns.visibility = if (NSUpload.isIdValid(tempTarget._id)) View.VISIBLE else View.GONE
if (!tempTarget.isEndingEvent) {
holder.binding.date.text = dateUtil.dateAndTimeString(tempTarget.date) + " - " + dateUtil.timeString(tempTarget.originalEnd())
holder.binding.duration.text = resourceHelper.gs(R.string.format_mins, tempTarget.durationInMinutes)
holder.binding.low.text = tempTarget.lowValueToUnitsToString(units)
holder.binding.high.text = tempTarget.highValueToUnitsToString(units)
holder.binding.reason.text = tempTarget.reason
} else {
holder.binding.date.text = dateUtil.dateAndTimeString(tempTarget.date)
holder.binding.duration.setText(R.string.cancel)
holder.binding.low.text = ""
holder.binding.high.text = ""
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)
}
val tempTarget = tempTargetList[position]
holder.binding.ns.visibility = (tempTarget.interfaceIDs.nightscoutId != null).toVisibility()
holder.binding.invalid.visibility = tempTarget.isValid.not().toVisibility()
holder.binding.remove.visibility = tempTarget.isValid.toVisibility()
holder.binding.date.text = dateUtil.dateAndTimeString(tempTarget.timestamp) + " - " + dateUtil.timeString(tempTarget.end)
holder.binding.duration.text = resourceHelper.gs(R.string.format_mins, T.msecs(tempTarget.duration).mins())
holder.binding.low.text = tempTarget.lowValueToUnitsToString(units)
holder.binding.high.text = tempTarget.highValueToUnitsToString(units)
holder.binding.reason.text = tempTarget.reason.text
holder.binding.date.setTextColor(
when {
tempTarget.id == currentlyActiveTarget?.id -> resourceHelper.gc(R.color.colorActive)
tempTarget.timestamp > DateUtil.now() -> resourceHelper.gc(R.color.colorScheduled)
else -> holder.binding.reasonColon.currentTextColor
})
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) {
@ -154,20 +186,23 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
init {
binding.remove.setOnClickListener { v: View ->
val tempTarget = v.tag as TempTarget
val tempTarget = v.tag as TemporaryTarget
context?.let { context ->
OKDialog.showConfirmation(context, resourceHelper.gs(R.string.removerecord),
"""
${resourceHelper.gs(R.string.careportal_temporarytarget)}: ${tempTarget.friendlyDescription(profileFunction.getUnits(), resourceHelper)}
${dateUtil.dateAndTimeString(tempTarget.date)}
${dateUtil.dateAndTimeString(tempTarget.timestamp)}
""".trimIndent(),
{ _: 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))
val id = tempTarget._id
if (NSUpload.isIdValid(id)) nsUpload.removeCareportalEntryFromNS(id)
else uploadQueue.removeID("dbAdd", id)
MainApp.getDbHelper().delete(tempTarget)
disposable += repository.runTransactionForResult(InvalidateTemporaryTargetTransaction(tempTarget.id))
.subscribe({
val id = tempTarget.interfaceIDs.nightscoutId
if (NSUpload.isIdValid(id)) nsUpload.removeCareportalEntryFromNS(id)
else uploadQueue.removeID("dbAdd", tempTarget.timestamp.toString())
}, {
aapsLogger.error(LTag.BGSOURCE, "Error while invalidating temporary target", it)
})
}, null)
}
}

View file

@ -2,6 +2,9 @@ package info.nightscout.androidaps.setupwizard
import android.Manifest
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.provider.Settings
import androidx.appcompat.app.AppCompatActivity
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Config
@ -111,6 +114,17 @@ class SWDefinition @Inject constructor(
.updateDelay(5)
.label(R.string.high_mark)
.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)
.skippable(false)
.add(SWInfoText(injector)
@ -377,6 +391,7 @@ class SWDefinition @Inject constructor(
//.add(screenLanguage)
.add(screenEula)
.add(if (isRunningTest()) null else screenPermissionBattery) // cannot mock ask battery optimization
.add(screenPermissionWindow)
.add(screenPermissionBt)
.add(screenPermissionStore)
.add(screenMasterPassword)
@ -406,6 +421,7 @@ class SWDefinition @Inject constructor(
//.add(screenLanguage)
.add(screenEula)
.add(if (isRunningTest()) null else screenPermissionBattery) // cannot mock ask battery optimization
.add(screenPermissionWindow)
.add(screenPermissionBt)
.add(screenPermissionStore)
.add(screenMasterPassword)
@ -430,6 +446,7 @@ class SWDefinition @Inject constructor(
//.add(screenLanguage)
.add(screenEula)
.add(if (isRunningTest()) null else screenPermissionBattery) // cannot mock ask battery optimization
.add(screenPermissionWindow)
.add(screenPermissionStore)
.add(screenMasterPassword)
.add(screenImport)

View file

@ -96,16 +96,16 @@ class HardLimits @Inject constructor(
}
// 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)
}
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
if (newvalue < lowLimit || newvalue > highLimit) {
newvalue = Math.max(newvalue, lowLimit)
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 += String.format(resourceHelper.gs(R.string.valuelimitedto), value, newvalue)
aapsLogger.error(msg)

View file

@ -5,8 +5,10 @@ import android.text.Spanned
import android.util.LongSparseArray
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.db.TDD
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
@ -31,15 +33,17 @@ class TddCalculator @Inject constructor(
rxBus: RxBusWrapper,
resourceHelper: ResourceHelper,
context: Context,
private val aapsSchedulers: AapsSchedulers,
private val sp: SP,
aapsSchedulers: AapsSchedulers,
sp: SP,
private val activePlugin: ActivePluginProvider,
private val profileFunction: ProfileFunction,
fabricPrivacy: FabricPrivacy,
nsUpload: NSUpload,
private val dateUtil: DateUtil,
uploadQueue: UploadQueue
) : TreatmentsPlugin(injector, aapsLogger, rxBus, aapsSchedulers, resourceHelper, context, sp, profileFunction, activePlugin, nsUpload, fabricPrivacy, dateUtil, uploadQueue) {
uploadQueue: UploadQueue,
databaseHelper: DatabaseHelperInterface,
repository: AppRepository
) : TreatmentsPlugin(injector, aapsLogger, rxBus, aapsSchedulers, resourceHelper, context, sp, profileFunction, activePlugin, nsUpload, fabricPrivacy, dateUtil, uploadQueue, databaseHelper, repository) {
init {
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 {
var t = ""
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.data.DetailedBolusInfo
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.db.CareportalEvent
import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.db.TempTarget
import info.nightscout.androidaps.events.EventRefreshOverview
import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.logging.AAPSLogger
@ -107,7 +107,7 @@ class BolusWizard @Inject constructor(
// Input
lateinit var profile: Profile
lateinit var profileName: String
var tempTarget: TempTarget? = null
var tempTarget: TemporaryTarget? = null
var carbs: Int = 0
var cob: Double = 0.0
var bg: Double = 0.0
@ -127,7 +127,7 @@ class BolusWizard @Inject constructor(
@JvmOverloads
fun doCalc(profile: Profile,
profileName: String,
tempTarget: TempTarget?,
tempTarget: TemporaryTarget?,
carbs: Int,
cob: Double,
bg: Double,
@ -169,8 +169,8 @@ class BolusWizard @Inject constructor(
targetBGLow = Profile.fromMgdlToUnits(profile.targetLowMgdl, profileFunction.getUnits())
targetBGHigh = Profile.fromMgdlToUnits(profile.targetHighMgdl, profileFunction.getUnits())
if (useTT && tempTarget != null) {
targetBGLow = Profile.fromMgdlToUnits(tempTarget.low, profileFunction.getUnits())
targetBGHigh = Profile.fromMgdlToUnits(tempTarget.high, profileFunction.getUnits())
targetBGLow = Profile.fromMgdlToUnits(tempTarget.lowTarget, profileFunction.getUnits())
targetBGHigh = Profile.fromMgdlToUnits(tempTarget.highTarget, profileFunction.getUnits())
}
if (useBg && bg > 0) {
bgDiff = when {

View file

@ -3,6 +3,8 @@ package info.nightscout.androidaps.utils.wizard
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
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.interfaces.ProfileFunction
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 loopPlugin: LoopPlugin
@Inject lateinit var iobCobCalculatorPlugin: IobCobCalculatorPlugin
@Inject lateinit var repository: AppRepository
@Inject lateinit var dateUtil: DateUtil
lateinit var storage: JSONObject
var position: Int = -1
companion object {
const val YES = 0
const val NO = 1
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 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
var bg = 0.0
if (useBG() == YES) {
@ -131,7 +137,7 @@ class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjec
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)

View file

@ -1,18 +1,45 @@
<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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="info.nightscout.androidaps.plugins.treatments.fragments.TreatmentsTempTargetFragment">
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/refresh_from_nightscout"
style="?android:attr/buttonStyle"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:drawableStart="@drawable/ic_refresh"
android:text="@string/refresheventsfromnightscout" />
android:orientation="horizontal">
<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
android:id="@+id/recyclerview"

View file

@ -80,15 +80,6 @@
android:layout_weight="1"
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
android:id="@+id/ns"
android:layout_width="wrap_content"
@ -134,6 +125,15 @@
android:textStyle="bold"
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
android:id="@+id/remove"
android:layout_width="wrap_content"
@ -148,10 +148,10 @@
<View
android:layout_width="fill_parent"
android:layout_height="2dip"
android:layout_marginBottom="5dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_marginTop="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:background="@color/list_delimiter" />
</LinearLayout>

View file

@ -901,4 +901,8 @@ Unerwartetes Verhalten.</string>
<string name="cannula">Kanüle</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="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>

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_valuemustbedetermined">Ar trebui să determinaţi dumneavoastră valoarea corespunzătoare pentru DIA.</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_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>
@ -40,12 +41,14 @@
<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_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_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="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_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_suspendloop">Suspendă bucla.</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="correctionbous">Corecție</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="primefill">Pregătire/umplere</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="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_summary">Folositor când datele de la surse nefiltrate precum xDrip+ devin \'\'zgomotoase\".</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_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="deviation_shortname">DEV</string>
<string name="activity_shortname">ACT</string>
<string name="bgi_shortname">-BGI</string>
<string name="abs_insulin_shortname">ABS</string>
<string name="devslope_shortname">DEVSLOPE</string>
<string name="nav_about">Despre</string>
@ -467,6 +471,7 @@
<string name="activity_target">țintă activitate</string>
<string name="hypo_duration">durată țintă</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_summary">Setare Ținte-Temporare și se introduc Tratamente din ceas.</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="loop_smbsetbypump_label">SMB setat de pompă</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_deviations">Deviații</string>
<string name="overview_show_cob">Carbohidrați activi</string>
@ -689,6 +695,7 @@
<string name="nav_logsettings">Setări loguri</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="time_offset">Decalaj</string>
<string name="setupwizard_preferred_aps_mode">Modul APS preferat</string>
<string name="treatments_wizard_total_label">Total</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="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="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_charging">Încărca numai dacă telefonul este la încărcat</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="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_pump_ureachable">Raportează pompa inaccesibilă</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="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="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="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="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>

View file

@ -240,7 +240,7 @@
<string name="smscommunicator_loophasbeenenabled">Loop has been enabled</string>
<string name="smscommunicator_loopisenabled">Loop is enabled</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_pumpconnectfail">Connection to pump failed</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="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="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
import info.nightscout.androidaps.db.TempTarget
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.T
import org.junit.Assert
@ -13,16 +12,16 @@ import java.util.*
class OverlappingIntervalsTest {
private val startDate = DateUtil.now()
var list = OverlappingIntervals<TempTarget>()
private var list = OverlappingIntervals<TempTargetTest>()
@Test fun doTests() {
// 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(100.0, list.getValueByInterval(startDate)!!.target(), 0.01)
Assert.assertEquals(null, list.getValueByInterval(startDate + T.hours(10).msecs() + 1))
// 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(100.0, list.getValueByInterval(startDate)!!.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))
// 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(100.0, list.getValueByInterval(startDate)!!.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() {
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)
Assert.assertEquals(1, list2.list.size.toLong())
}
@Test fun testReversingArrays() {
val someList: MutableList<TempTarget> = ArrayList()
someList.add(TempTarget().date(startDate).duration(T.hours(3).mins().toInt()).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))
val someList: MutableList<TempTargetTest> = ArrayList()
someList.add(TempTargetTest().date(startDate).duration(T.hours(3).mins()).low(200.0).high(200.0))
someList.add(TempTargetTest().date(startDate + T.hours(1).msecs()).duration(T.hours(1).mins()).low(100.0).high(100.0))
list.reset()
list.add(someList)
Assert.assertEquals(startDate, list[0].date)
Assert.assertEquals(startDate + T.hours(1).msecs(), list.getReversed(0).date)
Assert.assertEquals(startDate + T.hours(1).msecs(), list.reversedList[0].date)
Assert.assertEquals(startDate, list[0].data.timestamp)
Assert.assertEquals(startDate + T.hours(1).msecs(), list.getReversed(0).data.timestamp)
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.danar.DanaRPlugin
import info.nightscout.androidaps.danars.DanaRSPlugin
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAPlugin
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,
OpenAPSAMAPlugin::class, OpenAPSSMBPlugin::class, TreatmentsPlugin::class, TreatmentService::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() {
@Mock lateinit var activePlugin: ActivePluginProvider
@ -70,6 +71,7 @@ class ConstraintsCheckerTest : TestBaseWithProfile() {
@Mock lateinit var uel: UserEntryLogger
@Mock lateinit var loggerUtils: LoggerUtils
@Mock lateinit var databaseHelper: DatabaseHelperInterface
@Mock lateinit var repository: AppRepository
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)
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)
openAPSSMBPlugin = OpenAPSSMBPlugin(injector, aapsLogger, rxBus, constraintChecker, resourceHelper, profileFunction, context, activePlugin, treatmentsInterface, iobCobCalculatorPlugin, hardLimits, profiler, sp)
openAPSAMAPlugin = OpenAPSAMAPlugin(injector, aapsLogger, rxBus, constraintChecker, resourceHelper, profileFunction, context, activePlugin, treatmentsInterface, iobCobCalculatorPlugin, hardLimits, profiler, fabricPrivacy)
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, dateUtil, repository)
safetyPlugin = SafetyPlugin(injector, aapsLogger, resourceHelper, sp, rxBus, constraintChecker, openAPSAMAPlugin, openAPSSMBPlugin, sensitivityOref1Plugin, activePlugin, hardLimits, BuildHelper(Config(), loggerUtils), treatmentsInterface, Config())
val constraintsPluginsList = ArrayList<PluginBase>()
constraintsPluginsList.add(safetyPlugin)

View file

@ -7,11 +7,7 @@ import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Config
import info.nightscout.androidaps.R
import info.nightscout.androidaps.TestBase
import info.nightscout.androidaps.interfaces.ActivePluginProvider
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.interfaces.*
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
@ -53,15 +49,16 @@ class LoopPluginTest : TestBase() {
@Mock lateinit var receiverStatusStore: ReceiverStatusStore
@Mock lateinit var nsUpload: NSUpload
@Mock lateinit var notificationManager: NotificationManager
@Mock lateinit var databaseHelper: DatabaseHelperInterface
private lateinit var hardLimits: HardLimits
lateinit var loopPlugin: LoopPlugin
private lateinit var loopPlugin: LoopPlugin
val injector = HasAndroidInjector { AndroidInjector { } }
@Before fun prepareMock() {
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`(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.data.IobTotal
import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.database.AppRepository
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.CommandQueueProvider
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.plugins.aps.loop.LoopPlugin
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.OneTimePasswordValidationResult
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.XdripCalibrations
import info.nightscout.androidaps.utils.sharedPreferences.SP
import io.reactivex.Single
import org.junit.Assert
import org.junit.Before
import org.junit.Test
@ -53,7 +57,11 @@ import org.powermock.modules.junit4.PowerMockRunner
import java.util.*
@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() {
@Mock lateinit var context: Context
@ -69,6 +77,8 @@ class SmsCommunicatorPluginTest : TestBaseWithProfile() {
@Mock lateinit var otp: OneTimePassword
@Mock lateinit var xdripCalibrations: XdripCalibrations
@Mock lateinit var uel: UserEntryLogger
@Mock lateinit var nsUpload: NSUpload
@Mock lateinit var repository: AppRepository
var injector: HasAndroidInjector = HasAndroidInjector {
AndroidInjector {
@ -108,7 +118,12 @@ class SmsCommunicatorPluginTest : TestBaseWithProfile() {
`when`(SmsManager.getDefault()).thenReturn(smsManager)
`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)
Mockito.doAnswer { invocation: InvocationOnMock ->
val callback = invocation.getArgument<Callback>(1)

View file

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

View file

@ -7,27 +7,38 @@ import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.automation.R
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.db.TempTarget
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.database.transactions.InsertTemporaryTargetAndCancelCurrentTransaction
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.InputDuration
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.LayoutBuilder
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.utils.DateUtil
import info.nightscout.androidaps.utils.JsonHelper
import info.nightscout.androidaps.utils.JsonHelper.safeGetDouble
import info.nightscout.androidaps.utils.extensions.friendlyDescription
import info.nightscout.androidaps.utils.resources.ResourceHelper
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import org.json.JSONObject
import java.util.concurrent.TimeUnit
import javax.inject.Inject
class ActionStartTempTarget(injector: HasAndroidInjector) : Action(injector) {
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var activePlugin: ActivePluginProvider
@Inject lateinit var repository: AppRepository
@Inject lateinit var nsUpload: NSUpload
private val disposable = CompositeDisposable()
var value = InputTempTarget(injector)
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
override fun doAction(callback: Callback) {
activePlugin.activeTreatments.addToHistoryTempTarget(tt())
callback.result(PumpEnactResult(injector).success(true).comment(R.string.ok))?.run()
disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction(tt()))
.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) {
@ -76,14 +94,13 @@ class ActionStartTempTarget(injector: HasAndroidInjector) : Action(injector) {
return this
}
fun tt(): TempTarget =
TempTarget()
.date(DateUtil.now())
.duration(duration.getMinutes())
.reason("Automation")
.source(Source.USER)
.low(Profile.toMgdl(value.value, value.units))
.high(Profile.toMgdl(value.value, value.units))
fun tt() = TemporaryTarget(
timestamp = DateUtil.now(),
duration = TimeUnit.MINUTES.toMillis(duration.getMinutes().toLong()),
reason = TemporaryTarget.Reason.AUTOMATION,
lowTarget = Profile.toMgdl(value.value, value.units),
highTarget = Profile.toMgdl(value.value, value.units)
)
override fun isValid(): Boolean =
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 info.nightscout.androidaps.automation.R
import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.db.TempTarget
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.transactions.CancelCurrentTemporaryTargetIfAnyTransaction
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.utils.DateUtil
import info.nightscout.androidaps.utils.resources.ResourceHelper
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import javax.inject.Inject
class ActionStopTempTarget(injector: HasAndroidInjector) : Action(injector) {
@Inject lateinit var resourceHelper: ResourceHelper
@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 shortDescription(): String = resourceHelper.gs(R.string.stoptemptarget)
override fun icon(): Int = R.drawable.ic_stop_24dp
override fun doAction(callback: Callback) {
val tempTarget = TempTarget()
.date(DateUtil.now())
.duration(0)
.reason("Automation")
.source(Source.USER)
.low(0.0).high(0.0)
activePlugin.activeTreatments.addToHistoryTempTarget(tempTarget)
disposable += repository.runTransactionForResult(CancelCurrentTemporaryTargetIfAnyTransaction(DateUtil.now()))
.subscribe({ result ->
result.updated.forEach { nsUpload.updateTempTarget(it) }
}, {
aapsLogger.error(LTag.BGSOURCE, "Error while saving temporary target", it)
})
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 dagger.android.HasAndroidInjector
import info.nightscout.androidaps.automation.R
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.logging.LTag
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.StaticLabel
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.JsonHelper
import org.json.JSONObject
import javax.inject.Inject
class TriggerTempTarget(injector: HasAndroidInjector) : Trigger(injector) {
@Inject lateinit var repository: AppRepository
@Inject lateinit var dateUtil: DateUtil
var comparator = ComparatorExists(injector)
constructor(injector: HasAndroidInjector, compare: ComparatorExists.Compare) : this(injector) {
@ -28,7 +35,7 @@ class TriggerTempTarget(injector: HasAndroidInjector) : Trigger(injector) {
}
override fun shouldRun(): Boolean {
val tt = treatmentsInterface.tempTargetFromHistory
val tt = repository.getTemporaryTargetActiveAt(dateUtil._now()).blockingGet()
if (tt == null && comparator.value == ComparatorExists.Compare.NOT_EXISTS) {
aapsLogger.debug(LTag.AUTOMATION, "Ready for execution: " + friendlyDescription())
return true

View file

@ -7,6 +7,7 @@
<string name="automation_missing_trigger">Mindestens eine auslösende Bedingung angeben.</string>
<string name="automation_missing_action">Mindestens eine Aktion angeben.</string>
<string name="alarm_message">Alarm: %1$s</string>
<string name="alarm_short">Alarm:</string>
<string name="message_short">Nachricht:</string>
<string name="alreadyenabled">Bereits aktiviert</string>
<string name="alreadydisabled">Bereits deaktiviert</string>
@ -88,6 +89,7 @@
<string name="glucose_u">Glukosewert [%1$s]:</string>
<string name="lastboluslabel">Letzter Bolus vor</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="iob_u">IOB [IE]:</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_action">Trebuie să specificați cel puțin o acțiune.</string>
<string name="alarm_message">Alarmă: %1$s</string>
<string name="alarm_short">Alarmă:</string>
<string name="message_short">Msj:</string>
<string name="alreadyenabled">Deja activată</string>
<string name="alreadydisabled">Deja dezactivată</string>
@ -88,6 +89,7 @@
<string name="glucose_u">Glicemie [%1$s]:</string>
<string name="lastboluslabel">Ultimul bolus</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="iob_u">IOB [U]:</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 org.junit.Before
import org.junit.Rule
import org.mockito.ArgumentMatcher
import org.mockito.Mockito
import org.mockito.junit.MockitoJUnit
import org.mockito.junit.MockitoRule
@ -35,6 +36,17 @@ open class TestBase {
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")
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.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.InputTempTarget
import info.nightscout.androidaps.queue.Callback
import io.reactivex.Single
import org.junit.Assert
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatcher
import org.mockito.Mockito
import org.mockito.Mockito.`when`
import org.powermock.modules.junit4.PowerMockRunner
@ -41,13 +46,47 @@ class ActionStartTempTargetTest : ActionsTestBase() {
}
@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() {
override fun run() {
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() {

View file

@ -1,7 +1,11 @@
package info.nightscout.androidaps.plugins.general.automation.actions
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 io.reactivex.Single
import org.junit.Assert
import org.junit.Before
import org.junit.Test
@ -35,13 +39,26 @@ class ActionStopTempTargetTest : ActionsTestBase() {
}
@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() {
override fun run() {
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() {

View file

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

View file

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

View file

@ -5,6 +5,7 @@ import dagger.android.AndroidInjector
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.TestBaseWithProfile
import info.nightscout.androidaps.TestPumpPlugin
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.IobCobCalculatorInterface
import info.nightscout.androidaps.interfaces.PluginDescription
@ -20,10 +21,9 @@ import info.nightscout.androidaps.utils.sharedPreferences.SP
import org.junit.Before
import org.mockito.Mock
import org.mockito.Mockito.`when`
import org.powermock.api.mockito.PowerMockito
import org.powermock.core.classloader.annotations.PrepareForTest
@PrepareForTest(LastLocationDataContainer::class, AutomationPlugin::class)
@PrepareForTest(LastLocationDataContainer::class, AutomationPlugin::class, AppRepository::class)
open class TriggerTestBase : TestBaseWithProfile() {
@Mock lateinit var sp: SP
@ -32,6 +32,7 @@ open class TriggerTestBase : TestBaseWithProfile() {
@Mock lateinit var iobCobCalculatorPlugin: IobCobCalculatorInterface
@Mock lateinit var context: Context
@Mock lateinit var automationPlugin: AutomationPlugin
@Mock lateinit var repository: AppRepository
lateinit var receiverStatusStore: ReceiverStatusStore
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="combo_programming_bolus">Se programează pompa pentru livrare bolus</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_tbr_remaining">%1$d%% (%2$d min rămase)</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.JSONObject;
import info.nightscout.androidaps.utils.DateUtil;
/**
* Created by mike on 27.02.2016.
* <p>
@ -35,10 +33,10 @@ public class DbRequest {
}
// dbAdd
public DbRequest(String action, String collection, JSONObject json) {
public DbRequest(String action, String collection, JSONObject json, long nsClientId) {
this.action = action;
this.collection = collection;
this.nsClientID = "" + DateUtil.now();
this.nsClientID = "" + nsClientId;
try {
json.put("NSCLIENT_ID", nsClientID);
} catch (JSONException e) {
@ -49,10 +47,10 @@ public class DbRequest {
}
// 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.collection = collection;
this.nsClientID = "" + DateUtil.now();
this.nsClientID = "" + nsClientId;
try {
json.put("NSCLIENT_ID", nsClientID);
} catch (JSONException e) {
@ -63,12 +61,11 @@ public class DbRequest {
}
// dbRemove
public DbRequest(String action, String collection,
String _id) {
public DbRequest(String action, String collection, String _id, long nsClientId) {
JSONObject json = new JSONObject();
this.action = action;
this.collection = collection;
this.nsClientID = "" + DateUtil.now();
this.nsClientID = "" + nsClientId;
try {
json.put("NSCLIENT_ID", nsClientID);
} 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 ActivePluginProvider activePlugin;
@Inject public SP sp;
@Inject DateUtil dateUtil;
@Inject public DateUtil dateUtil;
private HasAndroidInjector injector;

View file

@ -27,7 +27,7 @@ abstract class DialogFragmentWithDate : DaggerDialogFragment() {
@Inject lateinit var sp: SP
@Inject lateinit var dateUtil: DateUtil
var eventTime = DateUtil.now()
var eventTime: Long = 0
var eventTimeChanged = false
//one shot guards
@ -60,7 +60,7 @@ abstract class DialogFragmentWithDate : DaggerDialogFragment() {
val eventDateView = view.findViewById(R.id.eventdate) 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
eventDateView?.text = DateUtil.dateString(eventTime)

View file

@ -2,10 +2,16 @@ package info.nightscout.androidaps.interfaces
import com.j256.ormlite.dao.CloseableIterator
import info.nightscout.androidaps.db.*
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import org.json.JSONObject
interface DatabaseHelperInterface {
fun resetDatabases()
fun createOrUpdate(careportalEvent: CareportalEvent)
fun createOrUpdate(extendedBolus: ExtendedBolus): Boolean
fun createOrUpdate(profileSwitch: ProfileSwitch)
fun createOrUpdate(record: DanaRHistoryRecord)
fun createOrUpdate(record: OmnipodHistoryRecord)
fun createOrUpdate(record: InsightBolusID)
@ -17,14 +23,16 @@ interface DatabaseHelperInterface {
fun size(table: String): Long
fun deleteAllDbRequests()
fun deleteDbRequest(id: String): Int
fun delete(tempBasal: TemporaryBasal)
fun delete(extendedBolus: ExtendedBolus)
fun deleteDbRequestbyMongoId(action: String, _id: String)
fun getDbRequestInterator(): CloseableIterator<DbRequest>
fun roundDateToSec(date: Long): Long
fun createOrUpdateTDD(record: TDD)
fun createOrUpdate(tempBasal: TemporaryBasal)
fun createOrUpdate(tempBasal: TemporaryBasal): Boolean
fun findTempBasalByPumpId(id: Long): TemporaryBasal
fun getTemporaryBasalsDataFromTime(mills: Long, ascending: Boolean): List<TemporaryBasal>
fun getExtendedBolusDataFromTime(mills: Long, ascending: Boolean): List<ExtendedBolus>
fun getCareportalEventFromTimestamp(timestamp: Long): CareportalEvent?
fun getAllOmnipodHistoryRecordsFromTimestamp(timestamp: Long, ascending: Boolean): List<OmnipodHistoryRecord>
fun findOmnipodHistoryRecordByPumpId(pumpId: Long): OmnipodHistoryRecord?
@ -32,6 +40,16 @@ interface DatabaseHelperInterface {
fun getProfileSwitchData(from: Long, ascending: Boolean): List<ProfileSwitch>
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 getInsightHistoryOffset(pumpSerial: String): InsightHistoryOffset?
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.db.ExtendedBolus;
import info.nightscout.androidaps.db.ProfileSwitch;
import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.plugins.treatments.TreatmentUpdateReturn;
@ -42,6 +41,7 @@ public interface TreatmentsInterface {
List<Treatment> getTreatmentsFromHistoryAfterTimestamp(long timestamp);
long getLastBolusTime();
long getLastBolusTime(boolean excludeSMB);
// real basals (not faked by extended bolus)
@ -60,7 +60,7 @@ public interface TreatmentsInterface {
void removeTempBasal(TemporaryBasal temporaryBasal);
boolean isInHistoryExtendedBoluslInProgress();
boolean isInHistoryExtendedBolusInProgress();
ExtendedBolus getExtendedBolusFromHistory(long time);
@ -70,14 +70,6 @@ public interface TreatmentsInterface {
boolean addToHistoryTreatment(DetailedBolusInfo detailedBolusInfo, boolean allowUpdate);
TempTarget getTempTargetFromHistory();
TempTarget getTempTargetFromHistory(long time);
Intervals<TempTarget> getTempTargetsFromHistory();
void addToHistoryTempTarget(TempTarget tempTarget);
ProfileSwitch getProfileSwitchFromHistory(long time);
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.Profile;
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.DbRequest;
import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.ProfileSwitch;
import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface;
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.utils.DateUtil;
import info.nightscout.androidaps.utils.JsonHelper;
import info.nightscout.androidaps.utils.T;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
import info.nightscout.androidaps.utils.sharedPreferences.SP;
@ -55,10 +56,12 @@ public class NSUpload {
private final AAPSLogger aapsLogger;
private final ResourceHelper resourceHelper;
private final SP sp;
private final Context context;
private final UploadQueueInterface uploadQueue;
private final DatabaseHelperInterface databaseHelper;
private final RunningConfiguration runningConfiguration;
private final ProfileFunction profileFunction;
public static String ISVALID = "isValid";
@Inject
public NSUpload(
@ -66,19 +69,19 @@ public class NSUpload {
AAPSLogger aapsLogger,
ResourceHelper resourceHelper,
SP sp,
Context context,
UploadQueueInterface uploadQueue,
RunningConfiguration runningConfiguration,
DatabaseHelperInterface databaseHelper
DatabaseHelperInterface databaseHelper,
ProfileFunction profileFunction
) {
this.injector = injector;
this.aapsLogger = aapsLogger;
this.resourceHelper = resourceHelper;
this.sp = sp;
this.context = context;
this.uploadQueue = uploadQueue;
this.runningConfiguration = runningConfiguration;
this.databaseHelper = databaseHelper;
this.profileFunction = profileFunction;
}
public void uploadTempBasalStartAbsolute(TemporaryBasal temporaryBasal, Double originalExtendedAmount) {
@ -94,7 +97,7 @@ public class NSUpload {
data.put("enteredBy", "openaps://" + "AndroidAPS");
if (originalExtendedAmount != null)
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) {
aapsLogger.error("Unhandled exception", e);
}
@ -125,7 +128,7 @@ public class NSUpload {
data.put("pumpId", temporaryBasal.pumpId);
data.put("created_at", DateUtil.toISOString(temporaryBasal.date));
data.put("enteredBy", "openaps://" + "AndroidAPS");
uploadQueue.add(new DbRequest("dbAdd", "treatments", data));
uploadQueue.add(new DbRequest("dbAdd", "treatments", data, temporaryBasal.date));
}
} catch (JSONException e) {
aapsLogger.error("Unhandled exception", e);
@ -142,7 +145,7 @@ public class NSUpload {
data.put("isFakedTempBasal", isFakedTempBasal);
if (pumpId != 0)
data.put("pumpId", pumpId);
uploadQueue.add(new DbRequest("dbAdd", "treatments", data));
uploadQueue.add(new DbRequest("dbAdd", "treatments", data, time));
} catch (JSONException e) {
aapsLogger.error("Unhandled exception", e);
}
@ -161,7 +164,7 @@ public class NSUpload {
data.put("pumpId", extendedBolus.pumpId);
data.put("created_at", DateUtil.toISOString(extendedBolus.date));
data.put("enteredBy", "openaps://" + "AndroidAPS");
uploadQueue.add(new DbRequest("dbAdd", "treatments", data));
uploadQueue.add(new DbRequest("dbAdd", "treatments", data, extendedBolus.date));
} catch (JSONException e) {
aapsLogger.error("Unhandled exception", e);
}
@ -180,7 +183,7 @@ public class NSUpload {
data.put("enteredBy", "openaps://" + "AndroidAPS");
if (pumpId != 0)
data.put("pumpId", pumpId);
uploadQueue.add(new DbRequest("dbAdd", "treatments", data));
uploadQueue.add(new DbRequest("dbAdd", "treatments", data, time));
} catch (JSONException e) {
aapsLogger.error("Unhandled exception", e);
}
@ -241,14 +244,13 @@ public class NSUpload {
deviceStatus.pump = pumpstatus;
}
int batteryLevel = receiverStatusStore.getBatteryLevel();
deviceStatus.uploaderBattery = batteryLevel;
deviceStatus.uploaderBattery = receiverStatusStore.getBatteryLevel();
deviceStatus.created_at = DateUtil.toISOString(new Date());
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) {
aapsLogger.error("Unhandled exception", e);
}
@ -279,32 +281,53 @@ public class NSUpload {
} catch (JSONException 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 {
JSONObject data = getJson(profileSwitch);
uploadCareportalEntryToNS(data);
uploadCareportalEntryToNS(data, nsClientId);
} catch (JSONException e) {
aapsLogger.error("Unhandled exception", e);
}
}
public void uploadTempTarget(TempTarget tempTarget, ProfileFunction profileFunction) {
public void uploadTempTarget(TemporaryTarget tempTarget) {
try {
JSONObject data = new JSONObject();
data.put("eventType", CareportalEvent.TEMPORARYTARGET);
data.put("duration", tempTarget.durationInMinutes);
if (tempTarget.low > 0) {
data.put("reason", tempTarget.reason);
data.put("targetBottom", Profile.fromMgdlToUnits(tempTarget.low, profileFunction.getUnits()));
data.put("targetTop", Profile.fromMgdlToUnits(tempTarget.high, profileFunction.getUnits()));
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.date));
data.put("created_at", DateUtil.toISOString(tempTarget.getTimestamp()));
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) {
aapsLogger.error("Unhandled exception", e);
}
@ -314,7 +337,7 @@ public class NSUpload {
try {
JSONObject data = getJson(profileSwitch);
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) {
aapsLogger.error("Unhandled exception", e);
@ -339,7 +362,7 @@ public class NSUpload {
return data;
}
public void uploadCareportalEntryToNS(JSONObject data) {
public void uploadCareportalEntryToNS(JSONObject data, long nsClientId) {
try {
if (data.has("preBolus") && data.has("carbs")) {
JSONObject prebolus = new JSONObject();
@ -351,9 +374,9 @@ public class NSUpload {
long mills = DateUtil.fromISODateString(data.getString("created_at")).getTime();
Date preBolusDate = new Date(mills + data.getInt("preBolus") * 60000L + 1000L);
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());
uploadQueue.add(dbr);
} catch (Exception e) {
@ -363,7 +386,7 @@ public class NSUpload {
}
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) {
@ -371,7 +394,7 @@ public class NSUpload {
JSONObject data = new JSONObject(event.json);
data.put("created_at", DateUtil.toISOString(event.date));
data.put("enteredBy", "openaps://" + "AndroidAPS");
uploadQueue.add(new DbRequest("dbAdd", "treatments", data));
uploadQueue.add(new DbRequest("dbAdd", "treatments", data, event.date));
} catch (JSONException e) {
aapsLogger.error("Unhandled exception", e);
}
@ -392,7 +415,7 @@ public class NSUpload {
} catch (JSONException 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) {
@ -407,7 +430,7 @@ public class NSUpload {
} catch (JSONException 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) {
@ -419,10 +442,9 @@ public class NSUpload {
data.put("sgv", reading.getValue());
data.put("direction", reading.getTrendArrow().getText());
data.put("type", "sgv");
if (reading.getInterfaceIDs() != null)
if (reading.getInterfaceIDs().getNightscoutId() != null) {
uploadQueue.add(new DbRequest("dbUpdate", "entries", reading.getInterfaceIDs().getNightscoutId(), data));
}
if (reading.getInterfaceIDs().getNightscoutId() != null) {
uploadQueue.add(new DbRequest("dbUpdate", "entries", reading.getInterfaceIDs().getNightscoutId(), data, System.currentTimeMillis()));
}
} catch (JSONException e) {
aapsLogger.error("Unhandled exception", e);
}
@ -438,13 +460,13 @@ public class NSUpload {
} catch (JSONException 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) {
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) {
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) {
try {
uploadQueue.add(new DbRequest("dbRemove", "food", _id));
uploadQueue.add(new DbRequest("dbRemove", "food", _id, System.currentTimeMillis()));
} catch (Exception e) {
aapsLogger.error("Unhandled exception", e);
}
@ -482,9 +504,9 @@ public class NSUpload {
JsonHelper.safeGetInt(data, "timeshift"),
eventTime
);
uploadProfileSwitch(profileSwitch);
uploadProfileSwitch(profileSwitch, eventTime);
} else {
uploadCareportalEntryToNS(data);
uploadCareportalEntryToNS(data, eventTime);
}
}

View file

@ -51,7 +51,7 @@ public class DateUtil {
/**
* 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:
@ -255,6 +255,12 @@ public class DateUtil {
return System.currentTimeMillis();
}
public long nowWithoutMilliseconds() {
long n = System.currentTimeMillis();
n = n - n % 1000;
return n;
}
public static long now() {
return System.currentTimeMillis();
}

View file

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

View file

@ -129,9 +129,21 @@ object JsonHelper {
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
fun safeGetBoolean(json: JSONObject?, fieldName: String): Boolean {
var result = false
@JvmOverloads
fun safeGetBoolean(json: JSONObject?, fieldName: String, defaultValue: Boolean = false): Boolean {
var result = defaultValue
if (json != null && json.has(fieldName)) {
try {
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="unsafeusage">Unsichere Benutzung</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="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="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="remove_button">Löschen</string>
<string name="addnew">Weiteren hinzufügen</string>
<!-- Constraints-->
<string name="limitingbasalratio">Begrenzung der max. Basalrate auf %1$.2f IE/h wegen %2$s</string>
<string name="pumplimit">Limit der Pumpe</string>

View file

@ -1,2 +1,24 @@
<?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"?>
<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>
<!-- Keys-->
<!-- General-->
<string name="refresh">Actualizează</string>
<string name="error">Eroare</string>
<string name="not_set_short">Nesetată</string>
<string name="failedupdatebasalprofile">Actualizarea profilului bazalei a eșuat</string>
@ -68,6 +69,40 @@
<string name="pairing">Împerechere</string>
<string name="yes">Da</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-->
<string name="limitingbasalratio">Se limitează maximul ratei bazale la %1$.2f U/o datorită %2$s</string>
<string name="pumplimit">limită pompă</string>
@ -217,6 +252,7 @@
<string name="history_group_glucose">Glicemie</string>
<string name="mute5min">Dezactivează pentru 5 minute</string>
<!-- Maintenance -->
<string name="metadata_label_format">Format fișier</string>
<string name="metadata_label_created_at">Creat la</string>
<string name="metadata_label_aaps_version">Versiune AAPS</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="versionavailable">Versiunea %1$s este disponibilă</string>
<!-- 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 -->
<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">
<item quantity="one">%1$d zi</item>
<item quantity="few">%1$d zile</item>

View file

@ -1,2 +1,24 @@
<?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
fun toISOStringTest() {
Assert.assertEquals("2017-12-22T00:32:30Z", DateUtil.toISOString(Date(1513902750000L)))
Assert.assertEquals("2017-12-22T00:32:30Z", DateUtil.toISOString(1513902750000L))
Assert.assertEquals("2017-12-22T00:32:30.000Z", DateUtil.toISOString(Date(1513902750000L)))
Assert.assertEquals("2017-12-22T00:32:30.000Z", DateUtil.toISOString(1513902750000L))
}
@Test fun toDateTest() {

View file

@ -91,7 +91,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
boolean previousValue = useExtendedBoluses;
useExtendedBoluses = sp.getBoolean(R.string.key_danar_useextended, false);
if (useExtendedBoluses != previousValue && activePlugin.getActiveTreatments().isInHistoryExtendedBoluslInProgress()) {
if (useExtendedBoluses != previousValue && activePlugin.getActiveTreatments().isInHistoryExtendedBolusInProgress()) {
sExecutionService.extendedBolusStop();
}
}
@ -197,9 +197,6 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
public PumpEnactResult setTempBasalAbsolute(double absoluteRate, int durationInMinutes, @NonNull Profile profile, boolean enforceNew) {
// Recheck pump status if older than 30 min
//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());
absoluteRate = constraintChecker.applyBasalConstraints(new Constraint<>(absoluteRate), profile).value();
@ -235,7 +232,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
if (doLowTemp || doHighTemp) {
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 (percentRate < 100) percentRate = Round.ceilTo((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
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);
}
if (doExtendedTemp) {
@ -294,7 +291,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
Double extendedRateToSet = absoluteRate - getBaseBasalRate();
extendedRateToSet = constraintChecker.applyBasalConstraints(new Constraint<>(extendedRateToSet), profile).value();
// 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?
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
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);
if (!result.success) {
aapsLogger.error("setTempBasalAbsolute: Failed to set extended bolus");
@ -336,7 +333,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
public PumpEnactResult cancelTempBasal(boolean force) {
if (activePlugin.getActiveTreatments().isInHistoryRealTempBasalInProgress())
return cancelRealTempBasal();
if (activePlugin.getActiveTreatments().isInHistoryExtendedBoluslInProgress() && useExtendedBoluses) {
if (activePlugin.getActiveTreatments().isInHistoryExtendedBolusInProgress() && useExtendedBoluses) {
return cancelExtendedBolus();
}
PumpEnactResult result = new PumpEnactResult(getInjector());
@ -374,13 +371,13 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
return result;
}
@Override
@NonNull @Override
public PumpEnactResult loadEvents() {
return null; // no history, not needed
return new PumpEnactResult(getInjector()); // no history, not needed
}
@Override
@NonNull @Override
public PumpEnactResult setUserOptions() {
return null;
return new PumpEnactResult(getInjector());
}
}

View file

@ -88,7 +88,7 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
boolean previousValue = useExtendedBoluses;
useExtendedBoluses = sp.getBoolean(R.string.key_danar_useextended, false);
if (useExtendedBoluses != previousValue && activePlugin.getActiveTreatments().isInHistoryExtendedBoluslInProgress()) {
if (useExtendedBoluses != previousValue && activePlugin.getActiveTreatments().isInHistoryExtendedBolusInProgress()) {
sExecutionService.extendedBolusStop();
}
}
@ -192,12 +192,9 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
// This is called from APS
@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
//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());
absoluteRate = constraintChecker.applyBasalConstraints(new Constraint<>(absoluteRate), profile).value();
@ -232,8 +229,8 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
}
if (doLowTemp || doHighTemp) {
Integer 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.
int percentRate = Double.valueOf(absoluteRate / getBaseBasalRate() * 100).intValue();
// 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 (percentRate < 100) percentRate = Round.ceilTo((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
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);
}
if (doExtendedTemp) {
@ -292,7 +289,7 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
Double extendedRateToSet = absoluteRate - getBaseBasalRate();
extendedRateToSet = constraintChecker.applyBasalConstraints(new Constraint<>(extendedRateToSet), profile).value();
// 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?
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
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);
if (!result.success) {
aapsLogger.error("setTempBasalAbsolute: Failed to set extended bolus");
@ -334,7 +331,7 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
public PumpEnactResult cancelTempBasal(boolean force) {
if (activePlugin.getActiveTreatments().isInHistoryRealTempBasalInProgress())
return cancelRealTempBasal();
if (activePlugin.getActiveTreatments().isInHistoryExtendedBoluslInProgress() && useExtendedBoluses) {
if (activePlugin.getActiveTreatments().isInHistoryExtendedBolusInProgress() && useExtendedBoluses) {
return cancelExtendedBolus();
}
PumpEnactResult result = new PumpEnactResult(getInjector());
@ -363,22 +360,21 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
result.isTempCancel = true;
result.comment = resourceHelper.gs(R.string.ok);
aapsLogger.debug(LTag.PUMP, "cancelRealTempBasal: OK");
return result;
} else {
result.success = false;
result.comment = resourceHelper.gs(R.string.danar_valuenotsetproperly);
result.isTempCancel = true;
aapsLogger.error("cancelRealTempBasal: Failed to cancel temp basal");
return result;
}
return result;
}
@Override
@NonNull @Override
public PumpEnactResult loadEvents() {
return null; // no history, not needed
return new PumpEnactResult(getInjector()); // no history, not needed
}
@Override
@NonNull @Override
public PumpEnactResult setUserOptions() {
return sExecutionService.setUserOptions();
}

View file

@ -24,8 +24,6 @@ class AppRepository @Inject internal constructor(
fun changeObservable(): Observable<List<DBEntry>> = changeSubject.subscribeOn(Schedulers.io())
val databaseVersion = DATABASE_VERSION
/**
* Executes a transaction ignoring its result
* Runs on IO scheduler
@ -88,16 +86,25 @@ class AppRepository @Inject internal constructor(
.subscribeOn(Schedulers.io())
// TEMP TARGETS
fun compatGetTemporaryTargetData(): List<TemporaryTarget> =
database.temporaryTargetDao.compatGetTemporaryTargetData()
fun compatGetTemporaryTargetData(): Single<List<TemporaryTarget>> =
database.temporaryTargetDao.getTemporaryTargetData()
.subscribeOn(Schedulers.io())
fun compatGetTemporaryTargetDataFromTime(timestamp: Long, ascending: Boolean): Single<List<TemporaryTarget>> =
database.temporaryTargetDao.compatGetTemporaryTargetDataFromTime(timestamp)
fun getTemporaryTargetDataFromTime(timestamp: Long, ascending: Boolean): Single<List<TemporaryTarget>> =
database.temporaryTargetDao.getTemporaryTargetDataFromTime(timestamp)
.map { if (!ascending) it.reversed() else it }
.subscribeOn(Schedulers.io())
fun findTemporaryTargetByNSIdSingle(nsId: String): Single<ValueWrapper<TemporaryTarget>> =
database.temporaryTargetDao.findByNSIdMaybe(nsId).toWrappedSingle()
fun getTemporaryTargetDataIncludingInvalidFromTime(timestamp: Long, ascending: Boolean): Single<List<TemporaryTarget>> =
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>> =
database.temporaryTargetDao.getModifiedFrom(lastId)
@ -106,6 +113,14 @@ class AppRepository @Inject internal constructor(
fun getTemporaryTargetsCorrespondingLastHistoryRecord(lastId: Long): TemporaryTarget? =
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
fun getAllUserEntries(): Single<List<UserEntry>> =
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.entities.TemporaryTarget
import io.reactivex.Maybe
import io.reactivex.Observable
import io.reactivex.Single
@Suppress("FunctionName")
@ -19,16 +18,22 @@ internal interface TemporaryTargetDao : TraceableDao<TemporaryTarget> {
override fun deleteAllEntries()
@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")
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")
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")
fun compatGetTemporaryTargetData(): List<TemporaryTarget>
fun getTemporaryTargetData(): Single<List<TemporaryTarget>>
@Query("SELECT * FROM $TABLE_TEMPORARY_TARGETS WHERE referenceId = :id ORDER BY id DESC LIMIT 1")
fun getLastHistoryRecord(id: Long): TemporaryTarget?

View file

@ -77,6 +77,7 @@ data class GlucoseValue(
@SerializedName("DexcomG5") DEXCOM_G5_XDRIP("DexcomG5"),
@SerializedName("G6 Native") DEXCOM_G6_NATIVE_XDRIP("G6 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("BlueReader") LIBRE_1_BLUE("BlueReader"),
@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
}
}
}
}

View file

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

View file

@ -5,12 +5,21 @@ import info.nightscout.androidaps.database.interfaces.end
class CancelCurrentTemporaryTargetIfAnyTransaction(
val timestamp: Long
) : Transaction<Unit>() {
override fun run() {
val current = database.temporaryTargetDao.getTemporaryTargetActiveAt(timestamp)
) : Transaction<CancelCurrentTemporaryTargetIfAnyTransaction.TransactionResult>() {
override fun run(): TransactionResult {
val result = TransactionResult()
val current = database.temporaryTargetDao.getTemporaryTargetActiveAt(timestamp).blockingGet()
if (current != null) {
current.end = timestamp
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
class InsertTemporaryTargetAndCancelCurrentTransaction(
private val temporaryTarget: TemporaryTarget
) : Transaction<Unit>() {
val temporaryTarget: TemporaryTarget
) : Transaction<InsertTemporaryTargetAndCancelCurrentTransaction.TransactionResult>() {
constructor(timestamp: Long, duration: Long, reason: TemporaryTarget.Reason, lowTarget: Double, highTarget: Double) :
this(TemporaryTarget(timestamp = timestamp, reason = reason, lowTarget = lowTarget, highTarget = highTarget, duration = duration))
override fun run() {
val current = database.temporaryTargetDao.getTemporaryTargetActiveAt(temporaryTarget.timestamp)
override fun run(): TransactionResult {
val result = TransactionResult()
val current = database.temporaryTargetDao.getTemporaryTargetActiveAt(temporaryTarget.timestamp).blockingGet()
if (current != null) {
current.end = temporaryTarget.timestamp
database.temporaryTargetDao.updateExistingEntry(current)
result.updated.add(current)
}
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.db.CareportalEvent;
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.TDD;
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.ResetPumpStatusRegisterMessage;
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.ActiveBolus;
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.ParameterBlockUtil;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.TimeChangeType;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
import info.nightscout.androidaps.utils.sharedPreferences.SP;
@ -998,6 +997,7 @@ public class LocalInsightPlugin extends PumpPluginBase implements PumpInterface,
try {
extended.put("ActiveProfile", profileFunction.getProfileName());
} catch (Exception e) {
e.printStackTrace();
}
TemporaryBasal tb = treatmentsPlugin.getTempBasalFromHistory(now);
if (tb != null) {
@ -1576,7 +1576,7 @@ public class LocalInsightPlugin extends PumpPluginBase implements PumpInterface,
careportalEvent.eventType = CareportalEvent.NOTE;
careportalEvent.json = data.toString();
databaseHelper.createOrUpdate(careportalEvent);
nsUpload.uploadCareportalEntryToNS(data);
nsUpload.uploadCareportalEntryToNS(data, date);
} catch (JSONException e) {
aapsLogger.error("Unhandled exception", e);
}
@ -1610,7 +1610,7 @@ public class LocalInsightPlugin extends PumpPluginBase implements PumpInterface,
careportalEvent.eventType = event;
careportalEvent.json = data.toString();
databaseHelper.createOrUpdate(careportalEvent);
nsUpload.uploadCareportalEntryToNS(data);
nsUpload.uploadCareportalEntryToNS(data, date);
} catch (JSONException e) {
aapsLogger.error("Unhandled exception", e);
}
@ -1681,8 +1681,4 @@ public class LocalInsightPlugin extends PumpPluginBase implements PumpInterface,
return true;
}
@Override
public void timezoneOrDSTChanged(TimeChangeType changeType) {
}
}

View file

@ -2,7 +2,9 @@
<resources>
<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_w32_description">Batterie wechseln.</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_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>
@ -11,9 +13,12 @@
<string name="alert_m23_description">Pumpenstatus überprüfen.</string>
<string name="alert_m24_description">Infusionsset wechseln.</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_m28_description">Pumpenstatus überprüfen.</string>
<string name="alert_m29_description">Batterietyp einstellen.</string>
<string name="alert_m30_description">Ampullentyp einstellen.</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>
</resources>

View file

@ -3,6 +3,7 @@
<string name="alert_r1_title">Bolusabgabe</string>
<string name="alert_r2_title">Versäumter Bolus</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_w31_title">Ampulle fast leer</string>
<string name="alert_w32_title">Batterie fast leer</string>

View file

@ -2,7 +2,9 @@
<resources>
<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_w32_description">Schimbați bateria.</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_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>
@ -11,7 +13,9 @@
<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_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_m28_description">Verificaţi starea pompei.</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_e6_description">Schimbați bateria și rezervorul.</string>

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