diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 9f7af3102b..bcc1e93abd 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -166,6 +166,8 @@
android:name=".plugins.Overview.notifications.DismissNotificationService"
android:exported="false" />
+
+
diff --git a/app/src/main/assets/OpenAPSSMB/determine-basal.js b/app/src/main/assets/OpenAPSSMB/determine-basal.js
index 84bd684cf6..c2db0f270b 100644
--- a/app/src/main/assets/OpenAPSSMB/determine-basal.js
+++ b/app/src/main/assets/OpenAPSSMB/determine-basal.js
@@ -406,8 +406,8 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
} else {
console.error("SMB disabled (no enableSMB preferences active)");
}
- // enable UAM (if enabled in preferences) if SMB is enabled
- var enableUAM=(profile.enableUAM && enableSMB);
+ // enable UAM (if enabled in preferences)
+ var enableUAM=(profile.enableUAM);
//console.error(meal_data);
@@ -942,10 +942,10 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
var durationReq = round(60*worstCaseInsulinReq / profile.current_basal);
if (durationReq < 0) {
durationReq = 0;
- // don't set a temp longer than 120 minutes
+ // don't set an SMB zero temp longer than 60 minutess
} else {
durationReq = round(durationReq/30)*30;
- durationReq = Math.min(120,Math.max(0,durationReq));
+ durationReq = Math.min(60,Math.max(0,durationReq));
}
//console.error(durationReq);
//rT.reason += "insulinReq " + insulinReq + "; "
diff --git a/app/src/main/java/info/nightscout/androidaps/HistoryBrowseActivity.java b/app/src/main/java/info/nightscout/androidaps/HistoryBrowseActivity.java
index c308cd2efe..636db14086 100644
--- a/app/src/main/java/info/nightscout/androidaps/HistoryBrowseActivity.java
+++ b/app/src/main/java/info/nightscout/androidaps/HistoryBrowseActivity.java
@@ -176,13 +176,19 @@ public class HistoryBrowseActivity extends AppCompatActivity {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
- updateGUI("EventAutosensCalculationFinished");
+ synchronized (HistoryBrowseActivity.this) {
+ updateGUI("EventAutosensCalculationFinished");
+ }
}
});
}
}
void updateGUI(String from) {
+
+ if (noProfile == null || buttonDate == null || buttonZoom == null || bgGraph == null || iobGraph == null || seekBar == null)
+ return;
+
final PumpInterface pump = ConfigBuilderPlugin.getActivePump();
final Profile profile = MainApp.getConfigBuilder().getProfile();
diff --git a/app/src/main/java/info/nightscout/androidaps/MainActivity.java b/app/src/main/java/info/nightscout/androidaps/MainActivity.java
index c1b616c086..ea8948abdd 100644
--- a/app/src/main/java/info/nightscout/androidaps/MainActivity.java
+++ b/app/src/main/java/info/nightscout/androidaps/MainActivity.java
@@ -20,7 +20,6 @@ import android.support.v7.widget.Toolbar;
import android.text.SpannableString;
import android.text.method.LinkMovementMethod;
import android.text.util.Linkify;
-import android.util.Log;
import android.util.TypedValue;
import android.view.Menu;
import android.view.MenuItem;
@@ -42,11 +41,11 @@ import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.events.EventAppExit;
import info.nightscout.androidaps.events.EventFeatureRunning;
+import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.events.EventRefreshGui;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Food.FoodPlugin;
-import info.nightscout.androidaps.plugins.Overview.events.EventSetWakeLock;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.androidaps.setupwizard.SetupWizardActivity;
import info.nightscout.androidaps.tabs.TabPageAdapter;
@@ -88,7 +87,8 @@ public class MainActivity extends AppCompatActivity {
drawerLayout.addDrawerListener(actionBarDrawerToggle);
actionBarDrawerToggle.syncState();
- onStatusEvent(new EventSetWakeLock(SP.getBoolean("lockscreen", false)));
+ // initialize screen wake lock
+ onEventPreferenceChange(new EventPreferenceChange(R.string.key_keep_screen_on));
doMigrations();
@@ -156,15 +156,18 @@ public class MainActivity extends AppCompatActivity {
}
@Subscribe
- public void onStatusEvent(final EventSetWakeLock ev) {
- final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
- if (ev.lock) {
- mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "AAPS");
- if (!mWakeLock.isHeld())
- mWakeLock.acquire();
- } else {
- if (mWakeLock != null && mWakeLock.isHeld())
- mWakeLock.release();
+ public void onEventPreferenceChange(final EventPreferenceChange ev) {
+ if (ev.isChanged(R.string.key_keep_screen_on)) {
+ boolean keepScreenOn = SP.getBoolean(R.string.key_keep_screen_on, false);
+ final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
+ if (keepScreenOn) {
+ mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "AAPS");
+ if (!mWakeLock.isHeld())
+ mWakeLock.acquire();
+ } else {
+ if (mWakeLock != null && mWakeLock.isHeld())
+ mWakeLock.release();
+ }
}
}
@@ -184,8 +187,8 @@ public class MainActivity extends AppCompatActivity {
}
}
- boolean lockScreen = BuildConfig.NSCLIENTOLNY && SP.getBoolean("lockscreen", false);
- if (lockScreen)
+ boolean keepScreenOn = BuildConfig.NSCLIENTOLNY && SP.getBoolean(R.string.key_keep_screen_on, false);
+ if (keepScreenOn)
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
else
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
diff --git a/app/src/main/java/info/nightscout/androidaps/MainApp.java b/app/src/main/java/info/nightscout/androidaps/MainApp.java
index a677b65d6a..24631b10c8 100644
--- a/app/src/main/java/info/nightscout/androidaps/MainApp.java
+++ b/app/src/main/java/info/nightscout/androidaps/MainApp.java
@@ -5,6 +5,7 @@ import android.content.IntentFilter;
import android.content.res.Resources;
import android.os.SystemClock;
import android.support.annotation.Nullable;
+import android.support.annotation.PluralsRes;
import android.support.v4.content.LocalBroadcastManager;
import com.crashlytics.android.Crashlytics;
@@ -47,8 +48,6 @@ import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin;
import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAPlugin;
import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin;
import info.nightscout.androidaps.plugins.Overview.OverviewPlugin;
-import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
-import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
import info.nightscout.androidaps.plugins.Persistentnotification.PersistentNotificationPlugin;
import info.nightscout.androidaps.plugins.ProfileLocal.LocalProfilePlugin;
import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin;
@@ -61,9 +60,10 @@ import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin;
import info.nightscout.androidaps.plugins.PumpInsight.InsightPlugin;
import info.nightscout.androidaps.plugins.PumpMDI.MDIPlugin;
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
-import info.nightscout.androidaps.plugins.SensitivityAAPS.SensitivityAAPSPlugin;
-import info.nightscout.androidaps.plugins.SensitivityOref0.SensitivityOref0Plugin;
-import info.nightscout.androidaps.plugins.SensitivityWeightedAverage.SensitivityWeightedAveragePlugin;
+import info.nightscout.androidaps.plugins.Sensitivity.SensitivityAAPSPlugin;
+import info.nightscout.androidaps.plugins.Sensitivity.SensitivityOref0Plugin;
+import info.nightscout.androidaps.plugins.Sensitivity.SensitivityOref1Plugin;
+import info.nightscout.androidaps.plugins.Sensitivity.SensitivityWeightedAveragePlugin;
import info.nightscout.androidaps.plugins.SmsCommunicator.SmsCommunicatorPlugin;
import info.nightscout.androidaps.plugins.Source.SourceDexcomG5Plugin;
import info.nightscout.androidaps.plugins.Source.SourceGlimpPlugin;
@@ -149,6 +149,7 @@ public class MainApp extends Application {
pluginsList.add(SensitivityOref0Plugin.getPlugin());
pluginsList.add(SensitivityAAPSPlugin.getPlugin());
pluginsList.add(SensitivityWeightedAveragePlugin.getPlugin());
+ pluginsList.add(SensitivityOref1Plugin.getPlugin());
if (Config.HWPUMPS) pluginsList.add(DanaRPlugin.getPlugin());
if (Config.HWPUMPS) pluginsList.add(DanaRKoreanPlugin.getPlugin());
if (Config.HWPUMPS) pluginsList.add(DanaRv2Plugin.getPlugin());
@@ -186,7 +187,7 @@ public class MainApp extends Application {
pluginsList.add(WearPlugin.initPlugin(this));
pluginsList.add(StatuslinePlugin.initPlugin(this));
- pluginsList.add(new PersistentNotificationPlugin(this));
+ pluginsList.add(PersistentNotificationPlugin.getPlugin());
pluginsList.add(NSClientPlugin.getPlugin());
pluginsList.add(sConfigBuilder = ConfigBuilderPlugin.getPlugin());
@@ -281,6 +282,10 @@ public class MainApp extends Application {
return sResources.getString(id, args);
}
+ public static String gq(@PluralsRes int id, int quantity, Object... args) {
+ return sResources.getQuantityString(id, quantity, args);
+ }
+
public static int gc(int id) {
return sResources.getColor(id);
}
diff --git a/app/src/main/java/info/nightscout/androidaps/PreferencesActivity.java b/app/src/main/java/info/nightscout/androidaps/PreferencesActivity.java
index c2d3e8411b..0f50458570 100644
--- a/app/src/main/java/info/nightscout/androidaps/PreferencesActivity.java
+++ b/app/src/main/java/info/nightscout/androidaps/PreferencesActivity.java
@@ -31,9 +31,10 @@ import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin;
import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin;
import info.nightscout.androidaps.plugins.PumpInsight.InsightPlugin;
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
-import info.nightscout.androidaps.plugins.SensitivityAAPS.SensitivityAAPSPlugin;
-import info.nightscout.androidaps.plugins.SensitivityOref0.SensitivityOref0Plugin;
-import info.nightscout.androidaps.plugins.SensitivityWeightedAverage.SensitivityWeightedAveragePlugin;
+import info.nightscout.androidaps.plugins.Sensitivity.SensitivityAAPSPlugin;
+import info.nightscout.androidaps.plugins.Sensitivity.SensitivityOref0Plugin;
+import info.nightscout.androidaps.plugins.Sensitivity.SensitivityOref1Plugin;
+import info.nightscout.androidaps.plugins.Sensitivity.SensitivityWeightedAveragePlugin;
import info.nightscout.androidaps.plugins.SmsCommunicator.SmsCommunicatorPlugin;
import info.nightscout.androidaps.plugins.Source.SourceDexcomG5Plugin;
import info.nightscout.androidaps.plugins.Wear.WearPlugin;
@@ -153,6 +154,7 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
addPreferencesFromResourceIfEnabled(SensitivityAAPSPlugin.getPlugin(), PluginType.SENSITIVITY);
addPreferencesFromResourceIfEnabled(SensitivityWeightedAveragePlugin.getPlugin(), PluginType.SENSITIVITY);
addPreferencesFromResourceIfEnabled(SensitivityOref0Plugin.getPlugin(), PluginType.SENSITIVITY);
+ addPreferencesFromResourceIfEnabled(SensitivityOref1Plugin.getPlugin(), PluginType.SENSITIVITY);
if (Config.HWPUMPS) {
addPreferencesFromResourceIfEnabled(DanaRPlugin.getPlugin(), PluginType.PUMP);
diff --git a/app/src/main/java/info/nightscout/androidaps/Services/DataService.java b/app/src/main/java/info/nightscout/androidaps/Services/DataService.java
index f8a9ed5d5e..9f3873cb93 100644
--- a/app/src/main/java/info/nightscout/androidaps/Services/DataService.java
+++ b/app/src/main/java/info/nightscout/androidaps/Services/DataService.java
@@ -604,6 +604,7 @@ public class DataService extends IntentService {
NSSgv nsSgv = new NSSgv(sgvJson);
BgReading bgReading = new BgReading(nsSgv);
MainApp.getDbHelper().createIfNotExists(bgReading, "NS");
+ SourceNSClientPlugin.getPlugin().detectSource(JsonHelper.safeGetString(sgvJson, "device"), JsonHelper.safeGetLong(sgvJson, "mills"));
}
private void handleNewSMS(Intent intent) {
diff --git a/app/src/main/java/info/nightscout/androidaps/data/ConstraintChecker.java b/app/src/main/java/info/nightscout/androidaps/data/ConstraintChecker.java
index 3161cb19f3..bfbbfedbd1 100644
--- a/app/src/main/java/info/nightscout/androidaps/data/ConstraintChecker.java
+++ b/app/src/main/java/info/nightscout/androidaps/data/ConstraintChecker.java
@@ -4,12 +4,10 @@ import java.util.ArrayList;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
-import info.nightscout.androidaps.interfaces.BgSourceInterface;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginType;
-import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
/**
* Created by mike on 19.03.2018.
@@ -25,7 +23,7 @@ public class ConstraintChecker implements ConstraintsInterface {
public Constraint isLoopInvokationAllowed() {
- return isLoopInvokationAllowed(new Constraint<>(true));
+ return isLoopInvocationAllowed(new Constraint<>(true));
}
public Constraint isClosedLoopAllowed() {
@@ -69,13 +67,13 @@ public class ConstraintChecker implements ConstraintsInterface {
}
@Override
- public Constraint isLoopInvokationAllowed(Constraint value) {
+ public Constraint isLoopInvocationAllowed(Constraint value) {
ArrayList constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
for (PluginBase p : constraintsPlugins) {
ConstraintsInterface constraint = (ConstraintsInterface) p;
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
- constraint.isLoopInvokationAllowed(value);
+ constraint.isLoopInvocationAllowed(value);
}
return value;
}
diff --git a/app/src/main/java/info/nightscout/androidaps/data/DetailedBolusInfo.java b/app/src/main/java/info/nightscout/androidaps/data/DetailedBolusInfo.java
index c2f9d16dc3..6e65e6d6d3 100644
--- a/app/src/main/java/info/nightscout/androidaps/data/DetailedBolusInfo.java
+++ b/app/src/main/java/info/nightscout/androidaps/data/DetailedBolusInfo.java
@@ -10,6 +10,7 @@ import java.util.Date;
import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.db.Source;
+import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
/**
* Created by mike on 29.05.2017.
@@ -17,6 +18,7 @@ import info.nightscout.androidaps.db.Source;
public class DetailedBolusInfo {
public long date = System.currentTimeMillis();
+ public long lastKnownBolusTime;
public String eventType = CareportalEvent.MEALBOLUS;
public double insulin = 0;
public double carbs = 0;
diff --git a/app/src/main/java/info/nightscout/androidaps/data/Profile.java b/app/src/main/java/info/nightscout/androidaps/data/Profile.java
index 844fa6472a..7412f8ce4c 100644
--- a/app/src/main/java/info/nightscout/androidaps/data/Profile.java
+++ b/app/src/main/java/info/nightscout/androidaps/data/Profile.java
@@ -202,6 +202,12 @@ public class Profile {
if (targetHigh_v == null)
targetHigh_v = convertToSparseArray(targetHigh);
validate(targetHigh_v);
+
+ if (targetHigh_v.size() != targetLow_v.size()) isValid = false;
+ else for (int i = 0; i < targetHigh_v.size(); i++)
+ if (targetHigh_v.valueAt(i) < targetLow_v.valueAt(i))
+ isValid = false;
+
isValidated = true;
}
@@ -239,16 +245,16 @@ public class Profile {
isValidated = false;
}
- }
+ }
return isValid;
}
protected void sendBelowMinimumNotification(String from) {
- MainApp.bus().post(new EventNewNotification(new Notification(Notification.MINIMAL_BASAL_VALUE_REPLACED, String.format(MainApp.gs(R.string.minimalbasalvaluereplaced), from), Notification.NORMAL)));
+ MainApp.bus().post(new EventNewNotification(new Notification(Notification.MINIMAL_BASAL_VALUE_REPLACED, String.format(MainApp.gs(R.string.minimalbasalvaluereplaced), from), Notification.NORMAL)));
}
protected void sendAboveMaximumNotification(String from) {
- MainApp.bus().post(new EventNewNotification(new Notification(Notification.MAXIMUM_BASAL_VALUE_REPLACED, String.format(MainApp.gs(R.string.maximumbasalvaluereplaced), from), Notification.NORMAL)));
+ MainApp.bus().post(new EventNewNotification(new Notification(Notification.MAXIMUM_BASAL_VALUE_REPLACED, String.format(MainApp.gs(R.string.maximumbasalvaluereplaced), from), Notification.NORMAL)));
}
private void validate(LongSparseArray array) {
@@ -452,12 +458,12 @@ public class Profile {
return ret;
}
- public double getTarget(){
- return getTarget(secondsFromMidnight(System.currentTimeMillis()));
+ public double getTarget() {
+ return getTarget(secondsFromMidnight(System.currentTimeMillis()));
}
protected double getTarget(int timeAsSeconds) {
- return (getTargetLowTimeFromMidnight(timeAsSeconds) + getTargetHighTimeFromMidnight(timeAsSeconds))/2;
+ return (getTargetLowTimeFromMidnight(timeAsSeconds) + getTargetHighTimeFromMidnight(timeAsSeconds)) / 2;
}
public double getTargetLow() {
@@ -552,6 +558,12 @@ public class Profile {
else return DecimalFormatter.to1Decimal(valueInMmol);
}
+ public static String toSignedUnitsString(Double valueInMgdl, Double valueInMmol, String units) {
+ if (units.equals(Constants.MGDL))
+ return (valueInMgdl > 0 ? "+" : "") + DecimalFormatter.to0Decimal(valueInMgdl);
+ else return (valueInMmol > 0 ? "+" : "") + DecimalFormatter.to1Decimal(valueInMmol);
+ }
+
// targets are stored in mg/dl but profile vary
public static String toTargetRangeString(double low, double high, String sourceUnits, String units) {
double lowMgdl = toMgdl(low, sourceUnits);
diff --git a/app/src/main/java/info/nightscout/androidaps/db/CareportalEvent.java b/app/src/main/java/info/nightscout/androidaps/db/CareportalEvent.java
index a963158f2f..747391404a 100644
--- a/app/src/main/java/info/nightscout/androidaps/db/CareportalEvent.java
+++ b/app/src/main/java/info/nightscout/androidaps/db/CareportalEvent.java
@@ -24,15 +24,17 @@ 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.interfaces.Interval;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSMbg;
import info.nightscout.androidaps.plugins.Overview.OverviewFragment;
import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface;
import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries;
import info.nightscout.utils.DateUtil;
+import info.nightscout.utils.T;
import info.nightscout.utils.Translator;
@DatabaseTable(tableName = DatabaseHelper.DATABASE_CAREPORTALEVENTS)
-public class CareportalEvent implements DataPointWithLabelInterface {
+public class CareportalEvent implements DataPointWithLabelInterface, Interval {
private static Logger log = LoggerFactory.getLogger(CareportalEvent.class);
@DatabaseField(id = true)
@@ -127,6 +129,19 @@ public class CareportalEvent implements DataPointWithLabelInterface {
return result;
}
+
+ public static boolean isEvent5minBack(List list, long time) {
+ for (int i = 0; i < list.size(); i++) {
+ CareportalEvent event = list.get(i);
+ if (event.date <= time && event.date > (time - T.mins(5).msecs())) {
+ //log.debug("Found event for time: " + DateUtil.dateAndTimeString(time) + " " + event.toString());
+ return true;
+ }
+ }
+ //log.debug("WWWWWW No found event for time: " + DateUtil.dateAndTimeString(time));
+ return false;
+ }
+
// -------- DataPointWithLabelInterface -------
@Override
@@ -207,14 +222,7 @@ public class CareportalEvent implements DataPointWithLabelInterface {
@Override
public long getDuration() {
- try {
- JSONObject object = new JSONObject(json);
- if (object.has("duration"))
- return object.getInt("duration") * 60 * 1000L;
- } catch (JSONException e) {
- log.error("Unhandled exception", e);
- }
- return 0;
+ return end() - start();
}
@Override
@@ -253,8 +261,79 @@ public class CareportalEvent implements DataPointWithLabelInterface {
if (eventType.equals(EXERCISE))
return Color.BLUE;
if (eventType.equals(OPENAPSOFFLINE))
- return Color.GRAY;
+ return Color.GRAY & 0x80FFFFFF;
return Color.GRAY;
}
+ // Interval interface
+ Long cuttedEnd = null;
+
+ @Override
+ public long durationInMsec() {
+ try {
+ JSONObject object = new JSONObject(json);
+ if (object.has("duration"))
+ return object.getInt("duration") * 60 * 1000L;
+ } catch (JSONException e) {
+ log.error("Unhandled exception", e);
+ }
+ return 0;
+ }
+
+ @Override
+ public long start() {
+ return date;
+ }
+
+ @Override
+ public long originalEnd() {
+ return date + durationInMsec();
+ }
+
+ @Override
+ public long end() {
+ if (cuttedEnd != null)
+ return cuttedEnd;
+ return originalEnd();
+ }
+
+ @Override
+ public void cutEndTo(long end) {
+ cuttedEnd = end;
+ }
+
+ @Override
+ 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 durationInMsec() == 0;
+ }
+
+ @Override
+ public boolean isValid() {
+ return eventType.equals(OPENAPSOFFLINE);
+ }
+
}
diff --git a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java
index 7174c19ec4..5095195872 100644
--- a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java
+++ b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java
@@ -30,6 +30,7 @@ import java.util.concurrent.TimeUnit;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.data.OverlappingIntervals;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.events.EventCareportalEventChange;
@@ -1242,6 +1243,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
where.ge("date", mills);
PreparedQuery preparedQuery = queryBuilder.prepare();
careportalEvents = getDaoCareportalEvents().query(preparedQuery);
+ preprocessOpenAPSOfflineEvents(careportalEvents);
return careportalEvents;
} catch (SQLException e) {
log.error("Unhandled exception", e);
@@ -1249,13 +1251,41 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return new ArrayList<>();
}
- public List getCareportalEventsFromTime(boolean ascending) {
+ public void preprocessOpenAPSOfflineEvents(List list) {
+ OverlappingIntervals offlineEvents = new OverlappingIntervals();
+ for (int i = 0; i < list.size(); i++) {
+ CareportalEvent event = list.get(i);
+ if (!event.eventType.equals(CareportalEvent.OPENAPSOFFLINE)) continue;
+ offlineEvents.add(event);
+ }
+
+ }
+
+ public List getCareportalEventsFromTime(long mills, String type, boolean ascending) {
+ try {
+ List careportalEvents;
+ QueryBuilder queryBuilder = getDaoCareportalEvents().queryBuilder();
+ queryBuilder.orderBy("date", ascending);
+ Where where = queryBuilder.where();
+ where.ge("date", mills).and().eq("eventType", type);
+ PreparedQuery preparedQuery = queryBuilder.prepare();
+ careportalEvents = getDaoCareportalEvents().query(preparedQuery);
+ preprocessOpenAPSOfflineEvents(careportalEvents);
+ return careportalEvents;
+ } catch (SQLException e) {
+ log.error("Unhandled exception", e);
+ }
+ return new ArrayList<>();
+ }
+
+ public List getCareportalEvents(boolean ascending) {
try {
List careportalEvents;
QueryBuilder queryBuilder = getDaoCareportalEvents().queryBuilder();
queryBuilder.orderBy("date", ascending);
PreparedQuery preparedQuery = queryBuilder.prepare();
careportalEvents = getDaoCareportalEvents().query(preparedQuery);
+ preprocessOpenAPSOfflineEvents(careportalEvents);
return careportalEvents;
} catch (SQLException e) {
log.error("Unhandled exception", e);
@@ -1470,14 +1500,19 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
profileSwitch.profileJson = trJson.getString("profileJson");
else {
ProfileStore store = MainApp.getConfigBuilder().getActiveProfileInterface().getProfile();
- Profile profile = store.getSpecificProfile(profileSwitch.profileName);
- if (profile != null) {
- profileSwitch.profileJson = profile.getData().toString();
- log.debug("Profile switch prefilled with JSON from local store");
- // Update data in NS
- NSUpload.updateProfileSwitch(profileSwitch);
+ if (store != null) {
+ Profile profile = store.getSpecificProfile(profileSwitch.profileName);
+ if (profile != null) {
+ profileSwitch.profileJson = profile.getData().toString();
+ log.debug("Profile switch prefilled with JSON from local store");
+ // Update data in NS
+ NSUpload.updateProfileSwitch(profileSwitch);
+ } else {
+ log.debug("JSON for profile switch doesn't exist. Ignoring: " + trJson.toString());
+ return;
+ }
} else {
- log.debug("JSON for profile switch doesn't exist. Ignoring: " + trJson.toString());
+ log.debug("Store for profile switch doesn't exist. Ignoring: " + trJson.toString());
return;
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/db/ProfileSwitch.java b/app/src/main/java/info/nightscout/androidaps/db/ProfileSwitch.java
index 6022525afb..40c8e50c6d 100644
--- a/app/src/main/java/info/nightscout/androidaps/db/ProfileSwitch.java
+++ b/app/src/main/java/info/nightscout/androidaps/db/ProfileSwitch.java
@@ -103,14 +103,11 @@ public class ProfileSwitch implements Interval, DataPointWithLabelInterface {
if(LocalProfilePlugin.LOCAL_PROFILE.equals(name)){
name = DecimalFormatter.to2Decimal(getProfileObject().percentageBasalSum()) + "U ";
}
- //Test if name is already containing percentage or timeshift
- if (!name.endsWith("h)") || !name.endsWith("%)")) {
- if (isCPP) {
- name += "(" + percentage + "%";
- if (timeshift != 0)
- name += "," + timeshift + "h";
- name += ")";
- }
+ if (isCPP) {
+ name += "(" + percentage + "%";
+ if (timeshift != 0)
+ name += "," + timeshift + "h";
+ name += ")";
}
return name;
}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventNetworkChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventNetworkChange.java
index 03df71f31b..57050bdcc9 100644
--- a/app/src/main/java/info/nightscout/androidaps/events/EventNetworkChange.java
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventNetworkChange.java
@@ -1,5 +1,8 @@
package info.nightscout.androidaps.events;
+
+import info.nightscout.utils.StringUtils;
+
public class EventNetworkChange extends Event {
public boolean mobileConnected = false;
@@ -9,6 +12,6 @@ public class EventNetworkChange extends Event {
public boolean roaming = false;
public String getSsid() {
- return ssid.replace("SSID: ","").replaceAll("\"","");
+ return StringUtils.removeSurroundingQuotes(ssid);
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/ConstraintsInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/ConstraintsInterface.java
index a1daa08a56..820170dc0f 100644
--- a/app/src/main/java/info/nightscout/androidaps/interfaces/ConstraintsInterface.java
+++ b/app/src/main/java/info/nightscout/androidaps/interfaces/ConstraintsInterface.java
@@ -7,7 +7,7 @@ import info.nightscout.androidaps.data.Profile;
*/
public interface ConstraintsInterface {
- default Constraint isLoopInvokationAllowed(Constraint value) {
+ default Constraint isLoopInvocationAllowed(Constraint value) {
return value;
}
diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java b/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java
index ed9b5672a2..9f3e4fe5c0 100644
--- a/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java
+++ b/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java
@@ -1,11 +1,13 @@
package info.nightscout.androidaps.interfaces;
import android.os.SystemClock;
+import android.support.v4.app.FragmentActivity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
/**
@@ -32,6 +34,12 @@ public abstract class PluginBase {
this.pluginDescription = pluginDescription;
}
+ // Default always calls invoke
+ // Plugins that have special constraints if they get switched to may override this method
+ public void switchAllowed(ConfigBuilderFragment.PluginViewHolder.PluginSwitcher pluginSwitcher, FragmentActivity activity) {
+ pluginSwitcher.invoke();
+ }
+
// public PluginType getType() {
// return mainType;
// }
diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/SensitivityInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/SensitivityInterface.java
index deb649c21f..25dab4494b 100644
--- a/app/src/main/java/info/nightscout/androidaps/interfaces/SensitivityInterface.java
+++ b/app/src/main/java/info/nightscout/androidaps/interfaces/SensitivityInterface.java
@@ -1,11 +1,28 @@
package info.nightscout.androidaps.interfaces;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+
+import info.nightscout.androidaps.Config;
+import info.nightscout.androidaps.R;
import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult;
+import info.nightscout.utils.Round;
+import info.nightscout.utils.SP;
+import info.nightscout.utils.SafeParse;
/**
* Created by mike on 24.06.2017.
*/
public interface SensitivityInterface {
+
+ double MIN_HOURS = 1;
+ double MIN_HOURS_FULL_AUTOSENS = 4;
+
AutosensResult detectSensitivity(long fromTime, long toTime);
+
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderFragment.java
index e91ad8079f..3e60ca2b77 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderFragment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderFragment.java
@@ -4,6 +4,7 @@ package info.nightscout.androidaps.plugins.ConfigBuilder;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
+import android.support.annotation.StringRes;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -22,9 +23,7 @@ import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
-import butterknife.OnCheckedChanged;
import butterknife.OnClick;
-import butterknife.Optional;
import butterknife.Unbinder;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.PreferencesActivity;
@@ -44,35 +43,17 @@ import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
import info.nightscout.androidaps.plugins.Insulin.InsulinOrefRapidActingPlugin;
import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin;
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
-import info.nightscout.androidaps.plugins.SensitivityOref0.SensitivityOref0Plugin;
+import info.nightscout.androidaps.plugins.Sensitivity.SensitivityOref0Plugin;
import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.PasswordProtection;
public class ConfigBuilderFragment extends SubscriberFragment {
- private List pluginViews = new ArrayList<>();
+ private List pluginViewHolders = new ArrayList<>();
- @BindView(R.id.profile_plugins)
- LinearLayout profilePlugins;
- @BindView(R.id.insulin_plugins)
- LinearLayout insulinPlugins;
- @BindView(R.id.bgsource_plugins)
- LinearLayout bgSourcePlugins;
- @BindView(R.id.pump_plugins)
- LinearLayout pumpPlugins;
- @BindView(R.id.sensitivity_plugins)
- LinearLayout sensitivityPlugins;
- @BindView(R.id.aps_plugins)
- LinearLayout apsPlugins;
- @BindView(R.id.loop_plugins)
- LinearLayout loopPlugins;
- @BindView(R.id.constraints_plugins)
- LinearLayout constraintsPlugins;
- @BindView(R.id.treatments_plugins)
- LinearLayout treatmentsPlugins;
- @BindView(R.id.general_plugins)
- LinearLayout generalPlugins;
+ @BindView(R.id.categories)
+ LinearLayout categories;
@BindView(R.id.main_layout)
ScrollView mainLayout;
@@ -111,34 +92,40 @@ public class ConfigBuilderFragment extends SubscriberFragment {
@Override
public void onDestroyView() {
super.onDestroyView();
- for (PluginView pluginView : pluginViews) pluginView.unbind();
- pluginViews.clear();
+ for (PluginViewHolder pluginViewHolder : pluginViewHolders) pluginViewHolder.unbind();
+ pluginViewHolders.clear();
}
@Override
protected void updateGUI() {
- for (PluginView pluginView : pluginViews) pluginView.update();
+ for (PluginViewHolder pluginViewHolder : pluginViewHolders) pluginViewHolder.update();
}
private void createViews() {
- createViewsForPlugins(profilePlugins, MainApp.getSpecificPluginsVisibleInListByInterface(ProfileInterface.class, PluginType.PROFILE));
- createViewsForPlugins(insulinPlugins, MainApp.getSpecificPluginsVisibleInListByInterface(InsulinInterface.class, PluginType.INSULIN));
- createViewsForPlugins(bgSourcePlugins, MainApp.getSpecificPluginsVisibleInListByInterface(BgSourceInterface.class, PluginType.BGSOURCE));
- createViewsForPlugins(pumpPlugins, MainApp.getSpecificPluginsVisibleInList(PluginType.PUMP));
- createViewsForPlugins(sensitivityPlugins, MainApp.getSpecificPluginsVisibleInListByInterface(SensitivityInterface.class, PluginType.SENSITIVITY));
- createViewsForPlugins(apsPlugins, MainApp.getSpecificPluginsVisibleInList(PluginType.APS));
- createViewsForPlugins(loopPlugins, MainApp.getSpecificPluginsVisibleInList(PluginType.LOOP));
- createViewsForPlugins(constraintsPlugins, MainApp.getSpecificPluginsVisibleInListByInterface(ConstraintsInterface.class, PluginType.CONSTRAINTS));
- createViewsForPlugins(treatmentsPlugins, MainApp.getSpecificPluginsVisibleInList(PluginType.TREATMENT));
- createViewsForPlugins(generalPlugins, MainApp.getSpecificPluginsVisibleInList(PluginType.GENERAL));
+ createViewsForPlugins(R.string.configbuilder_profile, R.string.configbuilder_profile_description, PluginType.PROFILE, MainApp.getSpecificPluginsVisibleInListByInterface(ProfileInterface.class, PluginType.PROFILE));
+ createViewsForPlugins(R.string.configbuilder_insulin, R.string.configbuilder_insulin_description, PluginType.INSULIN, MainApp.getSpecificPluginsVisibleInListByInterface(InsulinInterface.class, PluginType.INSULIN));
+ createViewsForPlugins(R.string.configbuilder_bgsource, R.string.configbuilder_bgsource_description, PluginType.BGSOURCE, MainApp.getSpecificPluginsVisibleInListByInterface(BgSourceInterface.class, PluginType.BGSOURCE));
+ createViewsForPlugins(R.string.configbuilder_pump, R.string.configbuilder_pump_description, PluginType.PUMP, MainApp.getSpecificPluginsVisibleInList(PluginType.PUMP));
+ createViewsForPlugins(R.string.configbuilder_sensitivity, R.string.configbuilder_sensitivity_description, PluginType.SENSITIVITY, MainApp.getSpecificPluginsVisibleInListByInterface(SensitivityInterface.class, PluginType.SENSITIVITY));
+ createViewsForPlugins(R.string.configbuilder_aps, R.string.configbuilder_aps_description, PluginType.APS, MainApp.getSpecificPluginsVisibleInList(PluginType.APS));
+ createViewsForPlugins(R.string.configbuilder_loop, R.string.configbuilder_loop_description, PluginType.LOOP, MainApp.getSpecificPluginsVisibleInList(PluginType.LOOP));
+ createViewsForPlugins(R.string.constraints, R.string.configbuilder_constraints_description, PluginType.CONSTRAINTS, MainApp.getSpecificPluginsVisibleInListByInterface(ConstraintsInterface.class, PluginType.CONSTRAINTS));
+ createViewsForPlugins(R.string.configbuilder_treatments, R.string.configbuilder_treatments_description, PluginType.TREATMENT, MainApp.getSpecificPluginsVisibleInList(PluginType.TREATMENT));
+ createViewsForPlugins(R.string.configbuilder_general, R.string.configbuilder_general_description, PluginType.GENERAL, MainApp.getSpecificPluginsVisibleInList(PluginType.GENERAL));
}
- private void createViewsForPlugins(LinearLayout parent, List plugins) {
+ private void createViewsForPlugins(@StringRes int title, @StringRes int description, PluginType pluginType, List plugins) {
+ if (plugins.size() == 0) return;
+ LinearLayout parent = (LinearLayout) getLayoutInflater().inflate(R.layout.configbuilder_single_category, null);
+ ((TextView) parent.findViewById(R.id.category_title)).setText(MainApp.gs(title));
+ ((TextView) parent.findViewById(R.id.category_description)).setText(MainApp.gs(description));
+ LinearLayout pluginContainer = parent.findViewById(R.id.category_plugins);
for (PluginBase plugin: plugins) {
- PluginView pluginView = new PluginView(plugin);
- parent.addView(pluginView.getBaseView());
- pluginViews.add(pluginView);
+ PluginViewHolder pluginViewHolder = new PluginViewHolder(pluginType, plugin);
+ pluginContainer.addView(pluginViewHolder.getBaseView());
+ pluginViewHolders.add(pluginViewHolder);
}
+ categories.addView(parent);
}
private boolean areMultipleSelectionsAllowed(PluginType type) {
@@ -200,9 +187,10 @@ public class ConfigBuilderFragment extends SubscriberFragment {
}
}
- class PluginView {
+ public class PluginViewHolder {
private Unbinder unbinder;
+ private PluginType pluginType;
private PluginBase plugin;
LinearLayout baseView;
@@ -219,7 +207,8 @@ public class ConfigBuilderFragment extends SubscriberFragment {
@BindView(R.id.plugin_visibility)
CheckBox pluginVisibility;
- public PluginView(PluginBase plugin) {
+ public PluginViewHolder(PluginType pluginType, PluginBase plugin) {
+ this.pluginType = pluginType;
this.plugin = plugin;
baseView = (LinearLayout) getLayoutInflater().inflate(R.layout.configbuilder_single_plugin, null);
unbinder = ButterKnife.bind(this, baseView);
@@ -231,10 +220,10 @@ public class ConfigBuilderFragment extends SubscriberFragment {
}
public void update() {
- enabledExclusive.setVisibility(areMultipleSelectionsAllowed(plugin.getType()) ? View.GONE : View.VISIBLE);
- enabledInclusive.setVisibility(areMultipleSelectionsAllowed(plugin.getType()) ? View.VISIBLE : View.GONE);
- enabledExclusive.setChecked(plugin.isEnabled(plugin.getType()));
- enabledInclusive.setChecked(plugin.isEnabled(plugin.getType()));
+ enabledExclusive.setVisibility(areMultipleSelectionsAllowed(pluginType) ? View.GONE : View.VISIBLE);
+ enabledInclusive.setVisibility(areMultipleSelectionsAllowed(pluginType) ? View.VISIBLE : View.GONE);
+ enabledExclusive.setChecked(plugin.isEnabled(pluginType));
+ enabledInclusive.setChecked(plugin.isEnabled(pluginType));
enabledInclusive.setEnabled(!plugin.pluginDescription.alwaysEnabled);
enabledExclusive.setEnabled(!plugin.pluginDescription.alwaysEnabled);
pluginName.setText(plugin.getName());
@@ -243,15 +232,15 @@ public class ConfigBuilderFragment extends SubscriberFragment {
pluginDescription.setVisibility(View.VISIBLE);
pluginDescription.setText(plugin.getDescription());
}
- pluginPreferences.setVisibility(plugin.getPreferencesId() == -1 || !plugin.isEnabled(plugin.getType()) ? View.INVISIBLE : View.VISIBLE);
+ pluginPreferences.setVisibility(plugin.getPreferencesId() == -1 || !plugin.isEnabled(pluginType) ? View.INVISIBLE : View.VISIBLE);
pluginVisibility.setVisibility(plugin.hasFragment() ? View.VISIBLE : View.INVISIBLE);
- pluginVisibility.setEnabled(!(plugin.pluginDescription.neverVisible || plugin.pluginDescription.alwayVisible) && plugin.isEnabled(plugin.getType()));
+ pluginVisibility.setEnabled(!(plugin.pluginDescription.neverVisible || plugin.pluginDescription.alwayVisible) && plugin.isEnabled(pluginType));
pluginVisibility.setChecked(plugin.isFragmentVisible());
}
@OnClick(R.id.plugin_visibility)
void onVisibilityChanged() {
- plugin.setFragmentVisible(plugin.getType(), pluginVisibility.isChecked());
+ plugin.setFragmentVisible(pluginType, pluginVisibility.isChecked());
ConfigBuilderPlugin.getPlugin().storeSettings("CheckedCheckboxVisible");
MainApp.bus().post(new EventRefreshGui());
ConfigBuilderPlugin.getPlugin().logPluginStatus();
@@ -259,16 +248,7 @@ public class ConfigBuilderFragment extends SubscriberFragment {
@OnClick({R.id.plugin_enabled_exclusive, R.id.plugin_enabled_inclusive})
void onEnabledChanged() {
- boolean enabled = enabledExclusive.getVisibility() == View.VISIBLE ? enabledExclusive.isChecked() : enabledInclusive.isChecked();
- plugin.setPluginEnabled(plugin.getType(), enabled);
- plugin.setFragmentVisible(plugin.getType(), enabled);
- processOnEnabledCategoryChanged(plugin, plugin.getType());
- updateGUI();
- ConfigBuilderPlugin.getPlugin().storeSettings("CheckedCheckboxEnabled");
- MainApp.bus().post(new EventRefreshGui());
- MainApp.bus().post(new EventConfigBuilderChange());
- ConfigBuilderPlugin.getPlugin().logPluginStatus();
- FabricPrivacy.getInstance().logCustom(new CustomEvent("ConfigurationChange"));
+ plugin.switchAllowed(new PluginSwitcher(), getActivity());
}
@OnClick(R.id.plugin_preferences)
@@ -284,6 +264,23 @@ public class ConfigBuilderFragment extends SubscriberFragment {
unbinder.unbind();
}
- }
+ public class PluginSwitcher {
+ public void invoke() {
+ boolean enabled = enabledExclusive.getVisibility() == View.VISIBLE ? enabledExclusive.isChecked() : enabledInclusive.isChecked();
+ plugin.setPluginEnabled(pluginType, enabled);
+ plugin.setFragmentVisible(pluginType, enabled);
+ processOnEnabledCategoryChanged(plugin, pluginType);
+ updateGUI();
+ ConfigBuilderPlugin.getPlugin().storeSettings("CheckedCheckboxEnabled");
+ MainApp.bus().post(new EventRefreshGui());
+ MainApp.bus().post(new EventConfigBuilderChange());
+ ConfigBuilderPlugin.getPlugin().logPluginStatus();
+ FabricPrivacy.getInstance().logCustom(new CustomEvent("ConfigurationChange"));
+ }
+ public void cancel(){
+ updateGUI();
+ }
+ }
+ }
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java
index 1911f588b1..886eeb3db7 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java
@@ -43,7 +43,7 @@ import info.nightscout.androidaps.plugins.Loop.APSResult;
import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity;
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
-import info.nightscout.androidaps.plugins.SensitivityOref0.SensitivityOref0Plugin;
+import info.nightscout.androidaps.plugins.Sensitivity.SensitivityOref0Plugin;
import info.nightscout.androidaps.queue.Callback;
import info.nightscout.androidaps.queue.CommandQueue;
import info.nightscout.utils.FabricPrivacy;
@@ -113,9 +113,17 @@ public class ConfigBuilderPlugin extends PluginBase {
pluginList = MainApp.getPluginsList();
upgradeSettings();
loadSettings();
+ setAlwaysEnabledPluginsEnabled();
MainApp.bus().post(new EventAppInitialized());
}
+ private void setAlwaysEnabledPluginsEnabled() {
+ for (PluginBase plugin : pluginList) {
+ if (plugin.pluginDescription.alwaysEnabled) plugin.setPluginEnabled(plugin.getType(), true);
+ }
+ storeSettings("setAlwaysEnabledPluginsEnabled");
+ }
+
public void storeSettings(String from) {
if (pluginList != null) {
if (Config.logPrefsChange)
@@ -520,6 +528,7 @@ public class ConfigBuilderPlugin extends PluginBase {
// deliver SMB
DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
+ detailedBolusInfo.lastKnownBolusTime = activeTreatments.getLastBolusTime();
detailedBolusInfo.eventType = CareportalEvent.CORRECTIONBOLUS;
detailedBolusInfo.insulin = request.smb;
detailedBolusInfo.isSMB = true;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesFragment.java
index 4f2cfa65e0..2f896ba91b 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesFragment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesFragment.java
@@ -1,12 +1,18 @@
package info.nightscout.androidaps.plugins.ConstraintsObjectives;
+import android.animation.LayoutTransition;
import android.app.Activity;
-import android.content.Context;
import android.os.Bundle;
-import android.support.v4.app.Fragment;
+import android.os.Handler;
+import android.os.Looper;
+import android.support.annotation.NonNull;
+import android.support.v4.content.ContextCompat;
import android.support.v7.widget.CardView;
import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.LinearSmoothScroller;
import android.support.v7.widget.RecyclerView;
+import android.text.Html;
+import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -16,199 +22,40 @@ import android.widget.LinearLayout;
import android.widget.TextView;
+import com.squareup.otto.Subscribe;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
-import java.util.List;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.events.EventConfigBuilderChange;
+import info.nightscout.androidaps.events.EventNewBG;
+import info.nightscout.androidaps.events.EventProfileSwitchChange;
+import info.nightscout.androidaps.events.EventTreatmentChange;
import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
+import info.nightscout.androidaps.plugins.ConstraintsObjectives.events.EventObjectivesSaved;
+import info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives.Objective;
import info.nightscout.utils.FabricPrivacy;
-import info.nightscout.utils.T;
public class ObjectivesFragment extends SubscriberFragment {
private static Logger log = LoggerFactory.getLogger(ObjectivesFragment.class);
RecyclerView recyclerView;
- LinearLayoutManager llm;
CheckBox enableFake;
- LinearLayout fake_layout;
TextView reset;
+ ObjectivesAdapter objectivesAdapter = new ObjectivesAdapter();
+ Handler handler = new Handler(Looper.getMainLooper());
- public class RecyclerViewAdapter extends RecyclerView.Adapter {
-
- List objectives;
-
- RecyclerViewAdapter(List objectives) {
- this.objectives = objectives;
- }
-
+ private Runnable objectiveUpdater = new Runnable() {
@Override
- public ObjectiveViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
- View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.objectives_item, viewGroup, false);
- return new ObjectiveViewHolder(v);
+ public void run() {
+ handler.postDelayed(this, 60 * 1000);
+ updateGUI();
}
-
- @Override
- public void onBindViewHolder(ObjectiveViewHolder holder, int position) {
- ObjectivesPlugin.Objective o = objectives.get(position);
- ObjectivesPlugin.RequirementResult requirementsMet = ObjectivesPlugin.getPlugin().requirementsMet(position);
- Context context = MainApp.instance().getApplicationContext();
- holder.position.setText(String.valueOf(position + 1));
- holder.objective.setText(o.objective);
- holder.gate.setText(o.gate);
- holder.duration.setText(MainApp.gs(R.string.objectives_minimalduration) + " " + o.durationInDays + " " + MainApp.gs(R.string.days));
- holder.progress.setText(requirementsMet.comment);
- holder.started.setText(o.started.toLocaleString());
- holder.accomplished.setText(o.accomplished.toLocaleString());
-
- holder.startButton.setTag(o);
- holder.verifyButton.setTag(o);
-
- holder.startButton.setOnClickListener(v -> {
- ObjectivesPlugin.Objective o1 = (ObjectivesPlugin.Objective) v.getTag();
- o1.started = new Date();
- updateGUI();
- ObjectivesPlugin.saveProgress();
- });
- holder.verifyButton.setOnClickListener(v -> {
- ObjectivesPlugin.Objective o12 = (ObjectivesPlugin.Objective) v.getTag();
- if (ObjectivesPlugin.getPlugin().requirementsMet(o12.num).done || enableFake.isChecked()) {
- o12.accomplished = new Date();
- updateGUI();
- ObjectivesPlugin.saveProgress();
- }
- });
-
- long prevObjectiveAccomplishedTime = position > 0 ?
- objectives.get(position - 1).accomplished.getTime() : -1;
-
- int phase = modifyVisibility(position, prevObjectiveAccomplishedTime,
- o.started.getTime(), o.durationInDays,
- o.accomplished.getTime(), requirementsMet.done, enableFake.isChecked());
-
- switch (phase) {
- case 0:
- // Phase 0: previous not completed
- holder.startedLayout.setVisibility(View.GONE);
- holder.durationLayout.setVisibility(View.GONE);
- holder.progressLayout.setVisibility(View.GONE);
- holder.verifyLayout.setVisibility(View.GONE);
- break;
- case 1:
- // Phase 1: not started
- holder.durationLayout.setVisibility(View.GONE);
- holder.progressLayout.setVisibility(View.GONE);
- holder.verifyLayout.setVisibility(View.GONE);
- holder.started.setVisibility(View.GONE);
- break;
- case 2:
- // Phase 2: started, waiting for duration and met requirements
- holder.startButton.setEnabled(false);
- holder.verifyLayout.setVisibility(View.GONE);
- break;
- case 3:
- // Phase 3: started, after duration, requirements met
- holder.startButton.setEnabled(false);
- holder.accomplished.setVisibility(View.INVISIBLE);
- break;
- case 4:
- // Phase 4: verified
- holder.gateLayout.setVisibility(View.GONE);
- holder.startedLayout.setVisibility(View.GONE);
- holder.durationLayout.setVisibility(View.GONE);
- holder.progressLayout.setVisibility(View.GONE);
- holder.verifyButton.setVisibility(View.INVISIBLE);
- break;
- default:
- // should not happen
- }
- }
-
-
- @Override
- public int getItemCount() {
- return objectives.size();
- }
-
- @Override
- public void onAttachedToRecyclerView(RecyclerView recyclerView) {
- super.onAttachedToRecyclerView(recyclerView);
- }
-
- public class ObjectiveViewHolder extends RecyclerView.ViewHolder {
- CardView cv;
- TextView position;
- TextView objective;
- LinearLayout gateLayout;
- TextView gate;
- TextView duration;
- LinearLayout durationLayout;
- TextView progress;
- LinearLayout progressLayout;
- TextView started;
- Button startButton;
- LinearLayout startedLayout;
- TextView accomplished;
- Button verifyButton;
- LinearLayout verifyLayout;
-
- ObjectiveViewHolder(View itemView) {
- super(itemView);
- cv = (CardView) itemView.findViewById(R.id.objectives_cardview);
- position = (TextView) itemView.findViewById(R.id.objectives_position);
- objective = (TextView) itemView.findViewById(R.id.objectives_objective);
- durationLayout = (LinearLayout) itemView.findViewById(R.id.objectives_duration_linearlayout);
- duration = (TextView) itemView.findViewById(R.id.objectives_duration);
- progressLayout = (LinearLayout) itemView.findViewById(R.id.objectives_progresslayout);
- progress = (TextView) itemView.findViewById(R.id.objectives_progress);
- gateLayout = (LinearLayout) itemView.findViewById(R.id.objectives_gate_linearlayout);
- gate = (TextView) itemView.findViewById(R.id.objectives_gate);
- startedLayout = (LinearLayout) itemView.findViewById(R.id.objectives_start_linearlayout);
- started = (TextView) itemView.findViewById(R.id.objectives_started);
- startButton = (Button) itemView.findViewById(R.id.objectives_start);
- verifyLayout = (LinearLayout) itemView.findViewById(R.id.objectives_verify_linearlayout);
- accomplished = (TextView) itemView.findViewById(R.id.objectives_accomplished);
- verifyButton = (Button) itemView.findViewById(R.id.objectives_verify);
- }
- }
- }
-
- /**
- * returns an int, which represents the phase the current objective is at.
- *
- * this is mainly used for unit-testing the conditions
- *
- * @param currentPosition
- * @param prevObjectiveAccomplishedTime
- * @param objectiveStartedTime
- * @param durationInDays
- * @param objectiveAccomplishedTime
- * @param requirementsMet
- * @return
- */
- public int modifyVisibility(int currentPosition,
- long prevObjectiveAccomplishedTime,
- long objectiveStartedTime, int durationInDays,
- long objectiveAccomplishedTime, boolean requirementsMet,
- boolean enableFakeValue) {
- Long now = System.currentTimeMillis();
- if (currentPosition > 0 && prevObjectiveAccomplishedTime == 0) {
- return 0;
- } else if (objectiveStartedTime == 0) {
- return 1;
- } else if (objectiveStartedTime > 0 && !enableFakeValue
- && objectiveAccomplishedTime == 0
- && !(objectiveStartedTime + T.days(durationInDays).msecs() < now && requirementsMet)) {
- return 2;
- } else if (objectiveAccomplishedTime == 0) {
- return 3;
- } else {
- return 4;
- }
- }
+ };
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
@@ -216,45 +63,20 @@ public class ObjectivesFragment extends SubscriberFragment {
try {
View view = inflater.inflate(R.layout.objectives_fragment, container, false);
- recyclerView = (RecyclerView) view.findViewById(R.id.objectives_recyclerview);
- recyclerView.setHasFixedSize(true);
- llm = new LinearLayoutManager(view.getContext());
- recyclerView.setLayoutManager(llm);
- enableFake = (CheckBox) view.findViewById(R.id.objectives_fake);
- fake_layout = (LinearLayout) view.findViewById(R.id.objectives_fake_layout);
- reset = (TextView) view.findViewById(R.id.objectives_reset);
- enableFake.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- updateGUI();
- }
+ recyclerView = view.findViewById(R.id.objectives_recyclerview);
+ recyclerView.setLayoutManager(new LinearLayoutManager(view.getContext()));
+ recyclerView.setAdapter(objectivesAdapter);
+ enableFake = view.findViewById(R.id.objectives_fake);
+ reset = view.findViewById(R.id.objectives_reset);
+ enableFake.setOnClickListener(v -> updateGUI());
+ reset.setOnClickListener(v -> {
+ ObjectivesPlugin.getPlugin().reset();
+ ObjectivesPlugin.saveProgress();
+ recyclerView.getAdapter().notifyDataSetChanged();
+ scrollToCurrentObjective();
});
- reset.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- ObjectivesPlugin.getPlugin().initializeData();
- ObjectivesPlugin.saveProgress();
- updateGUI();
- }
- });
-
- // Add correct translations to array after app is initialized
- ObjectivesPlugin.objectives.get(0).objective = MainApp.gs(R.string.objectives_0_objective);
- ObjectivesPlugin.objectives.get(1).objective = MainApp.gs(R.string.objectives_1_objective);
- ObjectivesPlugin.objectives.get(2).objective = MainApp.gs(R.string.objectives_2_objective);
- ObjectivesPlugin.objectives.get(3).objective = MainApp.gs(R.string.objectives_3_objective);
- ObjectivesPlugin.objectives.get(4).objective = MainApp.gs(R.string.objectives_4_objective);
- ObjectivesPlugin.objectives.get(5).objective = MainApp.gs(R.string.objectives_5_objective);
- ObjectivesPlugin.objectives.get(6).objective = MainApp.gs(R.string.objectives_6_objective);
- ObjectivesPlugin.objectives.get(7).objective = MainApp.gs(R.string.objectives_7_objective);
- ObjectivesPlugin.objectives.get(0).gate = MainApp.gs(R.string.objectives_0_gate);
- ObjectivesPlugin.objectives.get(1).gate = MainApp.gs(R.string.objectives_1_gate);
- ObjectivesPlugin.objectives.get(2).gate = MainApp.gs(R.string.objectives_2_gate);
- ObjectivesPlugin.objectives.get(3).gate = MainApp.gs(R.string.objectives_3_gate);
- ObjectivesPlugin.objectives.get(4).gate = MainApp.gs(R.string.objectives_4_gate);
- ObjectivesPlugin.objectives.get(5).gate = MainApp.gs(R.string.objectives_5_gate);
- ObjectivesPlugin.objectives.get(7).gate = MainApp.gs(R.string.objectives_7_gate);
-
- updateGUI();
-
+ scrollToCurrentObjective();
+ startUpdateTimer();
return view;
} catch (Exception e) {
FabricPrivacy.logException(e);
@@ -263,13 +85,142 @@ public class ObjectivesFragment extends SubscriberFragment {
return null;
}
+ @Override
+ public synchronized void onDestroyView() {
+ super.onDestroyView();
+ handler.removeCallbacks(objectiveUpdater);
+ }
+
+ private void startUpdateTimer() {
+ handler.removeCallbacks(objectiveUpdater);
+ for (Objective objective : ObjectivesPlugin.getObjectives()) {
+ if (objective.isStarted() && !objective.isAccomplished()) {
+ long timeTillNextMinute = (System.currentTimeMillis() - objective.getStartedOn().getTime()) % (60 * 1000);
+ handler.postDelayed(objectiveUpdater, timeTillNextMinute);
+ break;
+ }
+ }
+ }
+
+ private void scrollToCurrentObjective() {
+ for (int i = 0; i < ObjectivesPlugin.getObjectives().size(); i++) {
+ Objective objective = ObjectivesPlugin.getObjectives().get(i);
+ if (!objective.isStarted() || !objective.isAccomplished()) {
+ RecyclerView.SmoothScroller smoothScroller = new LinearSmoothScroller(getContext()) {
+ @Override
+ protected int getVerticalSnapPreference() {
+ return LinearSmoothScroller.SNAP_TO_START;
+ }
+
+ @Override
+ protected int calculateTimeForScrolling(int dx) {
+ return super.calculateTimeForScrolling(dx) * 4;
+ }
+ };
+ smoothScroller.setTargetPosition(i);
+ recyclerView.getLayoutManager().startSmoothScroll(smoothScroller);
+ break;
+ }
+ }
+ }
+
+ private class ObjectivesAdapter extends RecyclerView.Adapter {
+
+ @NonNull
+ @Override
+ public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.objectives_item, parent, false));
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
+ Objective objective = ObjectivesPlugin.getObjectives().get(position);
+ holder.title.setText(MainApp.gs(R.string.nth_objective, position + 1));
+ if (objective.getObjective() != 0) {
+ holder.objective.setVisibility(View.VISIBLE);
+ holder.objective.setText(MainApp.gs(objective.getObjective()));
+ } else holder.objective.setVisibility(View.GONE);
+ if (objective.getGate() != 0) {
+ holder.gate.setVisibility(View.VISIBLE);
+ holder.gate.setText(MainApp.gs(objective.getGate()));
+ } else holder.gate.setVisibility(View.GONE);
+ if (!objective.isStarted()) {
+ holder.gate.setTextColor(0xFFFFFFFF);
+ holder.verify.setVisibility(View.GONE);
+ holder.progress.setVisibility(View.GONE);
+ if (position == 0 || ObjectivesPlugin.getObjectives().get(position - 1).isAccomplished())
+ holder.start.setVisibility(View.VISIBLE);
+ else holder.start.setVisibility(View.GONE);
+ } else if (objective.isAccomplished()) {
+ holder.gate.setTextColor(0xFF4CAF50);
+ holder.verify.setVisibility(View.GONE);
+ holder.progress.setVisibility(View.GONE);
+ holder.start.setVisibility(View.GONE);
+ } else if (objective.isStarted()) {
+ holder.gate.setTextColor(0xFFFFFFFF);
+ holder.verify.setVisibility(View.VISIBLE);
+ holder.verify.setEnabled(objective.isCompleted() || enableFake.isChecked());
+ holder.start.setVisibility(View.GONE);
+ holder.progress.setVisibility(View.VISIBLE);
+ holder.progress.removeAllViews();
+ for (Objective.Task task : objective.getTasks()) {
+ if (task.shouldBeIgnored()) continue;
+ TextView textView = new TextView(holder.progress.getContext());
+ textView.setTextColor(0xFFFFFFFF);
+ String basicHTML = "%2$s: %3$s";
+ String formattedHTML = String.format(basicHTML, task.isCompleted() ? "#4CAF50" : "#FF9800", MainApp.gs(task.getTask()), task.getProgress());
+ textView.setText(Html.fromHtml(formattedHTML));
+ holder.progress.addView(textView, LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
+ }
+ }
+ holder.verify.setOnClickListener((view) -> {
+ objective.setAccomplishedOn(new Date());
+ notifyDataSetChanged();
+ scrollToCurrentObjective();
+ startUpdateTimer();
+ });
+ holder.start.setOnClickListener((view) -> {
+ objective.setStartedOn(new Date());
+ notifyDataSetChanged();
+ scrollToCurrentObjective();
+ startUpdateTimer();
+ });
+ }
+
+ @Override
+ public int getItemCount() {
+ return ObjectivesPlugin.getObjectives().size();
+ }
+
+ public class ViewHolder extends RecyclerView.ViewHolder {
+
+ public CardView cardView;
+ public TextView title;
+ public TextView objective;
+ public TextView gate;
+ public LinearLayout progress;
+ public Button verify;
+ public Button start;
+
+ public ViewHolder(View itemView) {
+ super(itemView);
+ cardView = (CardView) itemView;
+ title = itemView.findViewById(R.id.objective_title);
+ objective = itemView.findViewById(R.id.objective_objective);
+ gate = itemView.findViewById(R.id.objective_gate);
+ progress = itemView.findViewById(R.id.objective_progress);
+ verify = itemView.findViewById(R.id.objective_verify);
+ start = itemView.findViewById(R.id.objective_start);
+ }
+ }
+ }
+
@Override
public void updateGUI() {
Activity activity = getActivity();
if (activity != null)
activity.runOnUiThread(() -> {
- RecyclerViewAdapter adapter = new RecyclerViewAdapter(ObjectivesPlugin.objectives);
- recyclerView.setAdapter(adapter);
+ objectivesAdapter.notifyDataSetChanged();
});
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesPlugin.java
index 010bb1277a..a67f694eb8 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesPlugin.java
@@ -1,20 +1,14 @@
package info.nightscout.androidaps.plugins.ConstraintsObjectives;
-import android.content.SharedPreferences;
-import android.preference.PreferenceManager;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
-import java.util.Date;
import java.util.List;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
-import info.nightscout.androidaps.db.DatabaseHelper;
-import info.nightscout.androidaps.interfaces.APSInterface;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
@@ -23,12 +17,15 @@ import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.ConstraintsObjectives.events.EventObjectivesSaved;
-import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyPlugin;
-import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
-import info.nightscout.androidaps.plugins.NSClientInternal.NSClientPlugin;
-import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
-import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
-import info.nightscout.utils.DateUtil;
+import info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives.Objective;
+import info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives.Objective1;
+import info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives.Objective2;
+import info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives.Objective3;
+import info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives.Objective4;
+import info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives.Objective5;
+import info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives.Objective6;
+import info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives.Objective7;
+import info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives.Objective8;
import info.nightscout.utils.SP;
/**
@@ -39,6 +36,11 @@ public class ObjectivesPlugin extends PluginBase implements ConstraintsInterface
private static ObjectivesPlugin objectivesPlugin;
+ public static List objectives = new ArrayList<>();
+ public static boolean bgIsAvailableInNS = false;
+ public static boolean pumpStatusIsAvailableInNS = false;
+ public static Integer manualEnacts = 0;
+
public static ObjectivesPlugin getPlugin() {
if (objectivesPlugin == null) {
objectivesPlugin = new ObjectivesPlugin();
@@ -46,8 +48,6 @@ public class ObjectivesPlugin extends PluginBase implements ConstraintsInterface
return objectivesPlugin;
}
- public static List objectives;
-
private ObjectivesPlugin() {
super(new PluginDescription()
.mainType(PluginType.CONSTRAINTS)
@@ -58,7 +58,7 @@ public class ObjectivesPlugin extends PluginBase implements ConstraintsInterface
.shortName(R.string.objectives_shortname)
.description(R.string.description_objectives)
);
- initializeData();
+ setupObjectives();
loadProgress();
}
@@ -68,187 +68,38 @@ public class ObjectivesPlugin extends PluginBase implements ConstraintsInterface
return pump == null || pump.getPumpDescription().isTempBasalCapable;
}
- public class Objective {
- Integer num;
- String objective;
- String gate;
- Date started;
- Integer durationInDays;
- Date accomplished;
-
- Objective(Integer num, String objective, String gate, Date started, Integer durationInDays, Date accomplished) {
- this.num = num;
- this.objective = objective;
- this.gate = gate;
- this.started = started;
- this.durationInDays = durationInDays;
- this.accomplished = accomplished;
- }
-
- public void setStarted(Date started) {
- this.started = started;
- }
-
- public boolean isStarted() {
- return started.getTime() > 0;
- }
-
- boolean isFinished() {
- return accomplished.getTime() != 0;
- }
+ private void setupObjectives() {
+ objectives.add(new Objective1());
+ objectives.add(new Objective2());
+ objectives.add(new Objective3());
+ objectives.add(new Objective4());
+ objectives.add(new Objective5());
+ objectives.add(new Objective6());
+ objectives.add(new Objective7());
+ objectives.add(new Objective8());
}
- // Objective 0
- public static boolean bgIsAvailableInNS = false;
- public static boolean pumpStatusIsAvailableInNS = false;
- // Objective 1
- public static Integer manualEnacts = 0;
- private static final Integer manualEnactsNeeded = 20;
-
- class RequirementResult {
- boolean done = false;
- String comment = "";
-
- RequirementResult(boolean done, String comment) {
- this.done = done;
- this.comment = comment;
+ public void reset() {
+ for (Objective objective : objectives) {
+ objective.setStartedOn(null);
+ objective.setAccomplishedOn(null);
}
- }
-
- private String yesOrNo(boolean yes) {
- if (yes) return "☺";
- else return "---";
- }
-
- RequirementResult requirementsMet(Integer objNum) {
- switch (objNum) {
- case 0:
- boolean isVirtualPump = VirtualPumpPlugin.getPlugin().isEnabled(PluginType.PUMP);
- boolean vpUploadEnabled = SP.getBoolean("virtualpump_uploadstatus", false);
- boolean vpUploadNeeded = !isVirtualPump || vpUploadEnabled;
- boolean hasBGData = DatabaseHelper.lastBg() != null;
-
- boolean apsEnabled = false;
- APSInterface usedAPS = ConfigBuilderPlugin.getActiveAPS();
- if (usedAPS != null && ((PluginBase) usedAPS).isEnabled(PluginType.APS))
- apsEnabled = true;
-
- boolean profileSwitchExists = TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(DateUtil.now()) != null;
-
- return new RequirementResult(hasBGData && bgIsAvailableInNS && pumpStatusIsAvailableInNS && NSClientPlugin.getPlugin().hasWritePermission() && LoopPlugin.getPlugin().isEnabled(PluginType.LOOP) && apsEnabled && vpUploadNeeded && profileSwitchExists,
- MainApp.gs(R.string.objectives_bgavailableinns) + ": " + yesOrNo(bgIsAvailableInNS)
- + "\n" + MainApp.gs(R.string.nsclienthaswritepermission) + ": " + yesOrNo(NSClientPlugin.getPlugin().hasWritePermission())
- + (isVirtualPump ? "\n" + MainApp.gs(R.string.virtualpump_uploadstatus_title) + ": " + yesOrNo(vpUploadEnabled) : "")
- + "\n" + MainApp.gs(R.string.objectives_pumpstatusavailableinns) + ": " + yesOrNo(pumpStatusIsAvailableInNS)
- + "\n" + MainApp.gs(R.string.hasbgdata) + ": " + yesOrNo(hasBGData)
- + "\n" + MainApp.gs(R.string.loopenabled) + ": " + yesOrNo(LoopPlugin.getPlugin().isEnabled(PluginType.LOOP))
- + "\n" + MainApp.gs(R.string.apsselected) + ": " + yesOrNo(apsEnabled)
- + "\n" + MainApp.gs(R.string.activate_profile) + ": " + yesOrNo(profileSwitchExists)
- );
- case 1:
- return new RequirementResult(manualEnacts >= manualEnactsNeeded,
- MainApp.gs(R.string.objectives_manualenacts) + ": " + manualEnacts + "/" + manualEnactsNeeded);
- case 2:
- return new RequirementResult(true, "");
- case 3:
- Constraint closedLoopEnabled = new Constraint<>(true);
- SafetyPlugin.getPlugin().isClosedLoopAllowed(closedLoopEnabled);
- return new RequirementResult(closedLoopEnabled.value(), MainApp.gs(R.string.closedmodeenabled) + ": " + yesOrNo(closedLoopEnabled.value()));
- case 4:
- double maxIOB = MainApp.getConstraintChecker().getMaxIOBAllowed().value();
- boolean maxIobSet = maxIOB > 0;
- return new RequirementResult(maxIobSet, MainApp.gs(R.string.maxiobset) + ": " + yesOrNo(maxIobSet));
- default:
- return new RequirementResult(true, "");
- }
- }
-
-
- void initializeData() {
bgIsAvailableInNS = false;
pumpStatusIsAvailableInNS = false;
manualEnacts = 0;
-
- objectives = new ArrayList<>();
- objectives.add(new Objective(0,
- MainApp.gs(R.string.objectives_0_objective),
- MainApp.gs(R.string.objectives_0_gate),
- new Date(0),
- 0, // 0 day
- new Date(0)));
- objectives.add(new Objective(1,
- MainApp.gs(R.string.objectives_1_objective),
- MainApp.gs(R.string.objectives_1_gate),
- new Date(0),
- 7, // 7 days
- new Date(0)));
- objectives.add(new Objective(2,
- MainApp.gs(R.string.objectives_2_objective),
- MainApp.gs(R.string.objectives_2_gate),
- new Date(0),
- 0, // 0 days
- new Date(0)));
- objectives.add(new Objective(3,
- MainApp.gs(R.string.objectives_3_objective),
- MainApp.gs(R.string.objectives_3_gate),
- new Date(0),
- 5, // 5 days
- new Date(0)));
- objectives.add(new Objective(4,
- MainApp.gs(R.string.objectives_4_objective),
- MainApp.gs(R.string.objectives_4_gate),
- new Date(0),
- 1,
- new Date(0)));
- objectives.add(new Objective(5,
- MainApp.gs(R.string.objectives_5_objective),
- MainApp.gs(R.string.objectives_5_gate),
- new Date(0),
- 7,
- new Date(0)));
- objectives.add(new Objective(6,
- MainApp.gs(R.string.objectives_6_objective),
- "",
- new Date(0),
- 28,
- new Date(0)));
- objectives.add(new Objective(7,
- MainApp.gs(R.string.objectives_7_objective),
- "",
- new Date(0),
- 28,
- new Date(0)));
+ saveProgress();
}
public static void saveProgress() {
- if (objectives != null) {
- SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
- SharedPreferences.Editor editor = settings.edit();
- for (int num = 0; num < objectives.size(); num++) {
- Objective o = objectives.get(num);
- editor.putString("Objectives" + num + "started", Long.toString(o.started.getTime()));
- editor.putString("Objectives" + num + "accomplished", Long.toString(o.accomplished.getTime()));
- }
- editor.putBoolean("Objectives" + "bgIsAvailableInNS", bgIsAvailableInNS);
- editor.putBoolean("Objectives" + "pumpStatusIsAvailableInNS", pumpStatusIsAvailableInNS);
- editor.putString("Objectives" + "manualEnacts", Integer.toString(manualEnacts));
- editor.apply();
- if (Config.logPrefsChange)
- log.debug("Objectives stored");
- MainApp.bus().post(new EventObjectivesSaved());
- }
+ SP.putBoolean("Objectives" + "bgIsAvailableInNS", bgIsAvailableInNS);
+ SP.putBoolean("Objectives" + "pumpStatusIsAvailableInNS", pumpStatusIsAvailableInNS);
+ SP.putString("Objectives" + "manualEnacts", Integer.toString(manualEnacts));
+ if (Config.logPrefsChange)
+ log.debug("Objectives stored");
+ MainApp.bus().post(new EventObjectivesSaved());
}
private void loadProgress() {
- for (int num = 0; num < objectives.size(); num++) {
- Objective o = objectives.get(num);
- try {
- o.started = new Date(SP.getLong("Objectives" + num + "started", 0L));
- o.accomplished = new Date(SP.getLong("Objectives" + num + "accomplished", 0L));
- } catch (Exception e) {
- log.error("Unhandled exception", e);
- }
- }
bgIsAvailableInNS = SP.getBoolean("Objectives" + "bgIsAvailableInNS", false);
pumpStatusIsAvailableInNS = SP.getBoolean("Objectives" + "pumpStatusIsAvailableInNS", false);
try {
@@ -260,11 +111,15 @@ public class ObjectivesPlugin extends PluginBase implements ConstraintsInterface
log.debug("Objectives loaded");
}
+ public static List getObjectives() {
+ return objectives;
+ }
+
/**
* Constraints interface
**/
@Override
- public Constraint isLoopInvokationAllowed(Constraint value) {
+ public Constraint isLoopInvocationAllowed(Constraint value) {
if (!objectives.get(0).isStarted())
value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 1), this);
return value;
@@ -300,7 +155,7 @@ public class ObjectivesPlugin extends PluginBase implements ConstraintsInterface
@Override
public Constraint applyMaxIOBConstraints(Constraint maxIob) {
- if (objectives.get(3).isStarted() && !objectives.get(3).isFinished())
+ if (objectives.get(3).isStarted() && !objectives.get(3).isAccomplished())
maxIob.set(0d, String.format(MainApp.gs(R.string.objectivenotfinished), 4), this);
return maxIob;
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective.java
new file mode 100644
index 0000000000..bba29c5201
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective.java
@@ -0,0 +1,140 @@
+package info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives;
+
+import android.support.annotation.StringRes;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.utils.SP;
+
+public abstract class Objective {
+
+ private int number;
+ @StringRes
+ private int objective;
+ @StringRes
+ private int gate;
+ private Date startedOn;
+ private Date accomplishedOn;
+ private List tasks = new ArrayList<>();
+
+ public Objective(int number, @StringRes int objective, @StringRes int gate) {
+ this.number = number;
+ this.objective = objective;
+ this.gate = gate;
+ startedOn = new Date(SP.getLong("Objectives" + number + "started", 0L));
+ if (startedOn.getTime() == 0L) startedOn = null;
+ accomplishedOn = new Date(SP.getLong("Objectives" + number + "accomplished", 0L));
+ if (accomplishedOn.getTime() == 0L) accomplishedOn = null;
+ setupTasks(tasks);
+ for (Task task : tasks) task.objective = this;
+ }
+
+ public boolean isCompleted() {
+ for (Task task : tasks) {
+ if (!task.shouldBeIgnored() && !task.isCompleted())
+ return false;
+ }
+ return true;
+ }
+
+ public boolean isAccomplished() {
+ return accomplishedOn != null;
+ }
+
+ public boolean isStarted() {
+ return startedOn != null;
+ }
+
+ public Date getStartedOn() {
+ return startedOn;
+ }
+
+ public int getObjective() {
+ return objective;
+ }
+
+ public int getGate() {
+ return gate;
+ }
+
+ public void setStartedOn(Date startedOn) {
+ this.startedOn = startedOn;
+ SP.putLong("Objectives" + number + "started", startedOn == null ? 0 : startedOn.getTime());
+ }
+
+ public void setAccomplishedOn(Date accomplishedOn) {
+ this.accomplishedOn = accomplishedOn;
+ SP.putLong("Objectives" + number + "accomplished", accomplishedOn == null ? 0 : accomplishedOn.getTime());
+ }
+
+ protected void setupTasks(List tasks) {
+
+ }
+
+ public List getTasks() {
+ return tasks;
+ }
+
+ public abstract class Task {
+ @StringRes
+ private int task;
+ private Objective objective;
+
+ public Task(@StringRes int task) {
+ this.task = task;
+ }
+
+ public int getTask() {
+ return task;
+ }
+
+ protected Objective getObjective() {
+ return objective;
+ }
+
+ public abstract boolean isCompleted();
+
+ public String getProgress() {
+ return MainApp.gs(isCompleted() ? R.string.completed_well_done : R.string.not_completed_yet);
+ }
+
+ public boolean shouldBeIgnored() {
+ return false;
+ }
+ }
+
+ public class MinimumDurationTask extends Task {
+
+ private long minimumDuration;
+
+ public MinimumDurationTask(long minimumDuration) {
+ super(R.string.time_elapsed);
+ this.minimumDuration = minimumDuration;
+ }
+
+ @Override
+ public boolean isCompleted() {
+ return getObjective().isStarted() && System.currentTimeMillis() - getObjective().getStartedOn().getTime() >= minimumDuration;
+ }
+
+ @Override
+ public String getProgress() {
+ return getDurationText(System.currentTimeMillis() - getObjective().getStartedOn().getTime())
+ + " / " + getDurationText(minimumDuration);
+ }
+
+ private String getDurationText(long duration) {
+ int days = (int) Math.floor((double) duration / (24D * 60D * 60D * 1000D));
+ int hours = (int) Math.floor((double) duration / (60D * 60D * 1000D));
+ int minutes = (int) Math.floor((double) duration / (60D * 1000D));
+ if (days > 0) return MainApp.gq(R.plurals.objective_days, days, days);
+ else if (hours > 0) return MainApp.gq(R.plurals.objective_hours, hours, hours);
+ else return MainApp.gq(R.plurals.objective_minutes, minutes, minutes);
+ }
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective1.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective1.java
new file mode 100644
index 0000000000..e374126b11
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective1.java
@@ -0,0 +1,84 @@
+package info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives;
+
+import java.util.List;
+
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.db.DatabaseHelper;
+import info.nightscout.androidaps.interfaces.APSInterface;
+import info.nightscout.androidaps.interfaces.PluginBase;
+import info.nightscout.androidaps.interfaces.PluginType;
+import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
+import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin;
+import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
+import info.nightscout.androidaps.plugins.NSClientInternal.NSClientPlugin;
+import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
+import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
+import info.nightscout.utils.DateUtil;
+import info.nightscout.utils.SP;
+
+public class Objective1 extends Objective {
+
+ public Objective1() {
+ super(0, R.string.objectives_0_objective, R.string.objectives_0_gate);
+ }
+
+ @Override
+ protected void setupTasks(List tasks) {
+ tasks.add(new Task(R.string.objectives_bgavailableinns) {
+ @Override
+ public boolean isCompleted() {
+ return ObjectivesPlugin.bgIsAvailableInNS;
+ }
+ });
+ tasks.add(new Task(R.string.nsclienthaswritepermission) {
+ @Override
+ public boolean isCompleted() {
+ return NSClientPlugin.getPlugin().hasWritePermission();
+ }
+ });
+ tasks.add(new Task(R.string.virtualpump_uploadstatus_title) {
+ @Override
+ public boolean isCompleted() {
+ return SP.getBoolean("virtualpump_uploadstatus", false);
+ }
+
+ @Override
+ public boolean shouldBeIgnored() {
+ return !VirtualPumpPlugin.getPlugin().isEnabled(PluginType.PUMP);
+ }
+ });
+ tasks.add(new Task(R.string.objectives_pumpstatusavailableinns) {
+ @Override
+ public boolean isCompleted() {
+ return ObjectivesPlugin.pumpStatusIsAvailableInNS;
+ }
+ });
+ tasks.add(new Task(R.string.hasbgdata) {
+ @Override
+ public boolean isCompleted() {
+ return DatabaseHelper.lastBg() != null;
+ }
+ });
+ tasks.add(new Task(R.string.loopenabled) {
+ @Override
+ public boolean isCompleted() {
+ return LoopPlugin.getPlugin().isEnabled(PluginType.LOOP);
+ }
+ });
+ tasks.add(new Task(R.string.apsselected) {
+ @Override
+ public boolean isCompleted() {
+ APSInterface usedAPS = ConfigBuilderPlugin.getActiveAPS();
+ if (usedAPS != null && ((PluginBase) usedAPS).isEnabled(PluginType.APS))
+ return true;
+ return false;
+ }
+ });
+ tasks.add(new Task(R.string.activate_profile) {
+ @Override
+ public boolean isCompleted() {
+ return TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(DateUtil.now()) != null;
+ }
+ });
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective2.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective2.java
new file mode 100644
index 0000000000..305f00ec6f
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective2.java
@@ -0,0 +1,33 @@
+package info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives;
+
+import java.util.List;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin;
+
+public class Objective2 extends Objective {
+
+ public static final int MANUAL_ENACTS_NEEDED = 20;
+
+ public Objective2() {
+ super(1, R.string.objectives_1_objective, R.string.objectives_1_gate);
+ }
+
+ @Override
+ protected void setupTasks(List tasks) {
+ tasks.add(new MinimumDurationTask(7L * 24L * 60L * 60L * 1000L));
+ tasks.add(new Task(R.string.objectives_manualenacts) {
+ @Override
+ public boolean isCompleted() {
+ return ObjectivesPlugin.manualEnacts >= MANUAL_ENACTS_NEEDED;
+ }
+
+ @Override
+ public String getProgress() {
+ if (ObjectivesPlugin.manualEnacts >= MANUAL_ENACTS_NEEDED) return MainApp.gs(R.string.completed_well_done);
+ else return ObjectivesPlugin.manualEnacts + " / " + MANUAL_ENACTS_NEEDED;
+ }
+ });
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective3.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective3.java
new file mode 100644
index 0000000000..8a84e3c83c
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective3.java
@@ -0,0 +1,10 @@
+package info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives;
+
+import info.nightscout.androidaps.R;
+
+public class Objective3 extends Objective {
+
+ public Objective3() {
+ super(2, R.string.objectives_2_objective, R.string.objectives_2_gate);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective4.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective4.java
new file mode 100644
index 0000000000..7700c94cb6
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective4.java
@@ -0,0 +1,27 @@
+package info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives;
+
+import java.util.List;
+
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.interfaces.Constraint;
+import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyPlugin;
+
+public class Objective4 extends Objective {
+
+ public Objective4() {
+ super(3, R.string.objectives_3_objective, R.string.objectives_4_gate);
+ }
+
+ @Override
+ protected void setupTasks(List tasks) {
+ tasks.add(new MinimumDurationTask(5L * 24L * 60L * 60L * 1000L));
+ tasks.add(new Task(R.string.closedmodeenabled) {
+ @Override
+ public boolean isCompleted() {
+ Constraint closedLoopEnabled = new Constraint<>(true);
+ SafetyPlugin.getPlugin().isClosedLoopAllowed(closedLoopEnabled);
+ return closedLoopEnabled.value();
+ }
+ });
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective5.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective5.java
new file mode 100644
index 0000000000..563a114e05
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective5.java
@@ -0,0 +1,25 @@
+package info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives;
+
+import java.util.List;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+
+public class Objective5 extends Objective {
+
+ public Objective5() {
+ super(4, R.string.objectives_4_objective, R.string.objectives_4_gate);
+ }
+
+ @Override
+ protected void setupTasks(List tasks) {
+ tasks.add(new MinimumDurationTask(24L * 60L * 60L * 1000L));
+ tasks.add(new Task(R.string.maxiobset) {
+ @Override
+ public boolean isCompleted() {
+ double maxIOB = MainApp.getConstraintChecker().getMaxIOBAllowed().value();
+ return maxIOB > 0;
+ }
+ });
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective6.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective6.java
new file mode 100644
index 0000000000..7106d7522b
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective6.java
@@ -0,0 +1,17 @@
+package info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives;
+
+import java.util.List;
+
+import info.nightscout.androidaps.R;
+
+public class Objective6 extends Objective {
+
+ public Objective6() {
+ super(5, R.string.objectives_5_objective, R.string.objectives_5_gate);
+ }
+
+ @Override
+ protected void setupTasks(List tasks) {
+ tasks.add(new MinimumDurationTask(7L * 24L * 60L * 60L * 1000L));
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective7.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective7.java
new file mode 100644
index 0000000000..cfd041bf13
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective7.java
@@ -0,0 +1,17 @@
+package info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives;
+
+import java.util.List;
+
+import info.nightscout.androidaps.R;
+
+public class Objective7 extends Objective {
+
+ public Objective7() {
+ super(6, R.string.objectives_6_objective, 0);
+ }
+
+ @Override
+ protected void setupTasks(List tasks) {
+ tasks.add(new MinimumDurationTask(28L * 24L * 60L * 60L * 1000L));
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective8.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective8.java
new file mode 100644
index 0000000000..70d75fd900
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective8.java
@@ -0,0 +1,17 @@
+package info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives;
+
+import java.util.List;
+
+import info.nightscout.androidaps.R;
+
+public class Objective8 extends Objective {
+
+ public Objective8() {
+ super(7, R.string.objectives_7_objective, 0);
+ }
+
+ @Override
+ protected void setupTasks(List tasks) {
+ tasks.add(new MinimumDurationTask(28L * 24L * 60L * 60L * 1000L));
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPlugin.java
index 6a9613e92a..3d17970edc 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPlugin.java
@@ -49,7 +49,7 @@ public class SafetyPlugin extends PluginBase implements ConstraintsInterface {
* Constraints interface
**/
@Override
- public Constraint isLoopInvokationAllowed(Constraint value) {
+ public Constraint isLoopInvocationAllowed(Constraint value) {
if (!ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable)
value.set(false, MainApp.gs(R.string.pumpisnottempbasalcapable), this);
return value;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/AutosensData.java b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/AutosensData.java
index 79ab63e2ac..c826b70437 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/AutosensData.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/AutosensData.java
@@ -16,8 +16,8 @@ import info.nightscout.androidaps.plugins.OpenAPSSMB.SMBDefaults;
import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface;
import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries;
import info.nightscout.androidaps.plugins.Overview.graphExtensions.Scale;
-import info.nightscout.androidaps.plugins.SensitivityAAPS.SensitivityAAPSPlugin;
-import info.nightscout.androidaps.plugins.SensitivityWeightedAverage.SensitivityWeightedAveragePlugin;
+import info.nightscout.androidaps.plugins.Sensitivity.SensitivityAAPSPlugin;
+import info.nightscout.androidaps.plugins.Sensitivity.SensitivityWeightedAveragePlugin;
import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.utils.SP;
@@ -56,11 +56,11 @@ public class AutosensData implements DataPointWithLabelInterface {
}
public long time = 0L;
- long chartTime;
+ public double bg = 0; // mgdl
+ private long chartTime;
public String pastSensitivity = "";
public double deviation = 0d;
- boolean nonCarbsDeviation = false;
- public boolean nonEqualDeviation = false;
+ public boolean validDeviation = false;
List activeCarbsList = new ArrayList<>();
double absorbed = 0d;
public double carbsFromBolus = 0d;
@@ -76,6 +76,14 @@ public class AutosensData implements DataPointWithLabelInterface {
public double usedMinCarbsImpact = 0d;
public boolean failoverToMinAbsorbtionRate = false;
+ // Oref1
+ public boolean absorbing = false;
+ public double mealCarbs = 0;
+ public int mealStartCounter = 999;
+ public String type = "";
+ public boolean uam = false;
+ public List extraDeviation = new ArrayList<>();
+
@Override
public String toString() {
return "AutosensData: " + new Date(time).toLocaleString() + " " + pastSensitivity + " Delta=" + delta + " avgDelta=" + avgDelta + " Bgi=" + bgi + " Deviation=" + deviation + " avgDeviation=" + avgDeviation + " Absorbed=" + absorbed + " CarbsFromBolus=" + carbsFromBolus + " COB=" + cob + " autosensRatio=" + autosensRatio + " slopeFromMaxDeviation=" + slopeFromMaxDeviation + " slopeFromMinDeviation =" + slopeFromMinDeviation;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/AutosensResult.java b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/AutosensResult.java
index 4e0f8ef107..6602038fb4 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/AutosensResult.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/AutosensResult.java
@@ -32,4 +32,8 @@ public class AutosensResult {
return ret;
}
+ @Override
+ public String toString() {
+ return json().toString();
+ }
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorPlugin.java
index 2e8e16a226..d6fc244eef 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorPlugin.java
@@ -35,6 +35,7 @@ import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData;
import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin;
+import info.nightscout.androidaps.plugins.Sensitivity.SensitivityOref1Plugin;
import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.utils.DateUtil;
@@ -68,7 +69,7 @@ public class IobCobCalculatorPlugin extends PluginBase {
final Object dataLock = new Object();
boolean stopCalculationTrigger = false;
- private IobCobThread thread = null;
+ private Thread thread = null;
public IobCobCalculatorPlugin() {
super(new PluginDescription()
@@ -387,10 +388,6 @@ public class IobCobCalculatorPlugin extends PluginBase {
//log.debug(">>> getAutosensData Cache hit " + data.log(time));
return data;
} else {
- if (time > now) {
- // data may not be calculated yet, use last data
- return getLastAutosensData("getAutosensData");
- }
//log.debug(">>> getAutosensData Cache miss " + new Date(time).toLocaleString());
return null;
}
@@ -541,7 +538,10 @@ public class IobCobCalculatorPlugin extends PluginBase {
public void runCalculation(String from, long start, boolean bgDataReload, Event cause) {
log.debug("Starting calculation thread: " + from);
if (thread == null || thread.getState() == Thread.State.TERMINATED) {
- thread = new IobCobThread(this, from, start, bgDataReload, cause);
+ if (SensitivityOref1Plugin.getPlugin().isEnabled(PluginType.SENSITIVITY))
+ thread = new IobCobOref1Thread(this, from, start, bgDataReload, cause);
+ else
+ thread = new IobCobThread(this, from, start, bgDataReload, cause);
thread.start();
}
}
@@ -580,7 +580,9 @@ public class IobCobCalculatorPlugin extends PluginBase {
ev.isChanged(R.string.key_age) ||
ev.isChanged(R.string.key_absorption_maxtime) ||
ev.isChanged(R.string.key_openapsama_min_5m_carbimpact) ||
- ev.isChanged(R.string.key_absorption_cutoff)
+ ev.isChanged(R.string.key_absorption_cutoff) ||
+ ev.isChanged(R.string.key_openapsama_autosens_max) ||
+ ev.isChanged(R.string.key_openapsama_autosens_min)
) {
stopCalculation("onEventPreferenceChange");
synchronized (dataLock) {
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobOref1Thread.java b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobOref1Thread.java
new file mode 100644
index 0000000000..725cfab741
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobOref1Thread.java
@@ -0,0 +1,354 @@
+package info.nightscout.androidaps.plugins.IobCobCalculator;
+
+import android.content.Context;
+import android.os.PowerManager;
+import android.support.v4.util.LongSparseArray;
+
+import com.crashlytics.android.answers.CustomEvent;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.List;
+
+import info.nightscout.androidaps.BuildConfig;
+import info.nightscout.androidaps.Config;
+import info.nightscout.androidaps.Constants;
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.data.IobTotal;
+import info.nightscout.androidaps.data.Profile;
+import info.nightscout.androidaps.db.BgReading;
+import info.nightscout.androidaps.db.TempTarget;
+import info.nightscout.androidaps.events.Event;
+import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished;
+import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventIobCalculationProgress;
+import info.nightscout.androidaps.plugins.OpenAPSSMB.SMBDefaults;
+import info.nightscout.androidaps.plugins.Treatments.Treatment;
+import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
+import info.nightscout.utils.DateUtil;
+import info.nightscout.utils.FabricPrivacy;
+import info.nightscout.utils.SP;
+
+import static info.nightscout.utils.DateUtil.now;
+import static java.util.Calendar.MINUTE;
+
+/**
+ * Created by mike on 23.01.2018.
+ */
+
+public class IobCobOref1Thread extends Thread {
+ private static Logger log = LoggerFactory.getLogger(IobCobOref1Thread.class);
+ private final Event cause;
+
+ private IobCobCalculatorPlugin iobCobCalculatorPlugin;
+ private boolean bgDataReload;
+ private String from;
+ private long start;
+
+ private PowerManager.WakeLock mWakeLock;
+
+ public IobCobOref1Thread(IobCobCalculatorPlugin plugin, String from, long start, boolean bgDataReload, Event cause) {
+ super();
+
+ this.iobCobCalculatorPlugin = plugin;
+ this.bgDataReload = bgDataReload;
+ this.from = from;
+ this.cause = cause;
+ this.start = start;
+
+ PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE);
+ mWakeLock = powerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "iobCobThread");
+ }
+
+ @Override
+ public final void run() {
+ mWakeLock.acquire();
+ try {
+ if (MainApp.getConfigBuilder() == null) {
+ log.debug("Aborting calculation thread (ConfigBuilder not ready): " + from);
+ return; // app still initializing
+ }
+ if (!MainApp.getConfigBuilder().isProfileValid("IobCobThread")) {
+ log.debug("Aborting calculation thread (No profile): " + from);
+ return; // app still initializing
+ }
+ //log.debug("Locking calculateSensitivityData");
+
+ long oldestTimeWithData = iobCobCalculatorPlugin.oldestDataAvailable();
+
+ synchronized (iobCobCalculatorPlugin.dataLock) {
+ if (bgDataReload) {
+ iobCobCalculatorPlugin.loadBgData(start);
+ iobCobCalculatorPlugin.createBucketedData();
+ }
+ List bucketed_data = iobCobCalculatorPlugin.getBucketedData();
+ LongSparseArray autosensDataTable = IobCobCalculatorPlugin.getPlugin().getAutosensDataTable();
+
+ if (bucketed_data == null || bucketed_data.size() < 3) {
+ log.debug("Aborting calculation thread (No bucketed data available): " + from);
+ return;
+ }
+
+ long prevDataTime = IobCobCalculatorPlugin.roundUpTime(bucketed_data.get(bucketed_data.size() - 3).date);
+ log.debug("Prev data time: " + new Date(prevDataTime).toLocaleString());
+ AutosensData previous = autosensDataTable.get(prevDataTime);
+ // start from oldest to be able sub cob
+ for (int i = bucketed_data.size() - 4; i >= 0; i--) {
+ String progress = i + (MainApp.isDev() ? " (" + from + ")" : "");
+ MainApp.bus().post(new EventIobCalculationProgress(progress));
+
+ if (iobCobCalculatorPlugin.stopCalculationTrigger) {
+ iobCobCalculatorPlugin.stopCalculationTrigger = false;
+ log.debug("Aborting calculation thread (trigger): " + from);
+ return;
+ }
+ // check if data already exists
+ long bgTime = bucketed_data.get(i).date;
+ bgTime = IobCobCalculatorPlugin.roundUpTime(bgTime);
+ if (bgTime > IobCobCalculatorPlugin.roundUpTime(now()))
+ continue;
+
+ AutosensData existing;
+ if ((existing = autosensDataTable.get(bgTime)) != null) {
+ previous = existing;
+ continue;
+ }
+
+ Profile profile = MainApp.getConfigBuilder().getProfile(bgTime);
+ if (profile == null) {
+ log.debug("Aborting calculation thread (no profile): " + from);
+ return; // profile not set yet
+ }
+
+ if (Config.logAutosensData)
+ log.debug("Processing calculation thread: " + from + " (" + i + "/" + bucketed_data.size() + ")");
+
+ double sens = Profile.toMgdl(profile.getIsf(bgTime), profile.getUnits());
+
+ AutosensData autosensData = new AutosensData();
+ autosensData.time = bgTime;
+ if (previous != null)
+ autosensData.activeCarbsList = new ArrayList<>(previous.activeCarbsList);
+ else
+ autosensData.activeCarbsList = new ArrayList<>();
+
+ //console.error(bgTime , bucketed_data[i].glucose);
+ double bg;
+ double avgDelta;
+ double delta;
+ bg = bucketed_data.get(i).value;
+ if (bg < 39 || bucketed_data.get(i + 3).value < 39) {
+ log.error("! value < 39");
+ continue;
+ }
+ autosensData.bg = bg;
+ delta = (bg - bucketed_data.get(i + 1).value);
+ avgDelta = (bg - bucketed_data.get(i + 3).value) / 3;
+
+ IobTotal iob = iobCobCalculatorPlugin.calculateFromTreatmentsAndTemps(bgTime, profile);
+
+ double bgi = -iob.activity * sens * 5;
+ double deviation = delta - bgi;
+ double avgDeviation = Math.round((avgDelta - bgi) * 1000) / 1000;
+
+ double slopeFromMaxDeviation = 0;
+ double slopeFromMinDeviation = 999;
+ double maxDeviation = 0;
+ double minDeviation = 999;
+
+ // https://github.com/openaps/oref0/blob/master/lib/determine-basal/cob-autosens.js#L169
+ if (i < bucketed_data.size() - 16) { // we need 1h of data to calculate minDeviationSlope
+ long hourago = bgTime + 10 * 1000 - 60 * 60 * 1000L;
+ AutosensData hourAgoData = IobCobCalculatorPlugin.getPlugin().getAutosensData(hourago);
+ if (hourAgoData != null) {
+ int initialIndex = autosensDataTable.indexOfKey(hourAgoData.time);
+ if (Config.logAutosensData)
+ log.debug(">>>>> bucketed_data.size()=" + bucketed_data.size() + " i=" + i + "hourAgoData=" + hourAgoData.toString());
+ int past = 1;
+ try {
+ for (; past < 12; past++) {
+ AutosensData ad = autosensDataTable.valueAt(initialIndex + past);
+ double deviationSlope = (ad.avgDeviation - avgDeviation) / (ad.time - bgTime) * 1000 * 60 * 5;
+ if (ad.avgDeviation > maxDeviation) {
+ slopeFromMaxDeviation = Math.min(0, deviationSlope);
+ maxDeviation = ad.avgDeviation;
+ }
+ if (ad.avgDeviation < minDeviation) {
+ slopeFromMinDeviation = Math.max(0, deviationSlope);
+ minDeviation = ad.avgDeviation;
+ }
+
+ //if (Config.logAutosensData)
+ // log.debug("Deviations: " + new Date(bgTime) + new Date(ad.time) + " avgDeviation=" + avgDeviation + " deviationSlope=" + deviationSlope + " slopeFromMaxDeviation=" + slopeFromMaxDeviation + " slopeFromMinDeviation=" + slopeFromMinDeviation);
+ }
+ } catch (Exception e) {
+ log.error("Unhandled exception", e);
+ FabricPrivacy.logException(e);
+ FabricPrivacy.getInstance().logCustom(new CustomEvent("CatchedError")
+ .putCustomAttribute("buildversion", BuildConfig.BUILDVERSION)
+ .putCustomAttribute("version", BuildConfig.VERSION)
+ .putCustomAttribute("autosensDataTable", iobCobCalculatorPlugin.getAutosensDataTable().toString())
+ .putCustomAttribute("for_data", ">>>>> bucketed_data.size()=" + bucketed_data.size() + " i=" + i + "hourAgoData=" + hourAgoData.toString())
+ .putCustomAttribute("past", past)
+ );
+ }
+ }
+ }
+
+ List recentTreatments = TreatmentsPlugin.getPlugin().getTreatments5MinBackFromHistory(bgTime);
+ for (int ir = 0; ir < recentTreatments.size(); ir++) {
+ autosensData.carbsFromBolus += recentTreatments.get(ir).carbs;
+ autosensData.activeCarbsList.add(new AutosensData.CarbsInPast(recentTreatments.get(ir)));
+ }
+
+
+ // if we are absorbing carbs
+ if (previous != null && previous.cob > 0) {
+ // calculate sum of min carb impact from all active treatments
+ double totalMinCarbsImpact = 0d;
+// if (SensitivityAAPSPlugin.getPlugin().isEnabled(PluginType.SENSITIVITY) || SensitivityWeightedAveragePlugin.getPlugin().isEnabled(PluginType.SENSITIVITY)) {
+ //when the impact depends on a max time, sum them up as smaller carb sizes make them smaller
+// for (int ii = 0; ii < autosensData.activeCarbsList.size(); ++ii) {
+// AutosensData.CarbsInPast c = autosensData.activeCarbsList.get(ii);
+// totalMinCarbsImpact += c.min5minCarbImpact;
+// }
+// } else {
+ //Oref sensitivity
+ totalMinCarbsImpact = SP.getDouble(R.string.key_openapsama_min_5m_carbimpact, SMBDefaults.min_5m_carbimpact);
+// }
+
+ // figure out how many carbs that represents
+ // but always assume at least 3mg/dL/5m (default) absorption per active treatment
+ double ci = Math.max(deviation, totalMinCarbsImpact);
+ if (ci != deviation)
+ autosensData.failoverToMinAbsorbtionRate = true;
+ autosensData.absorbed = ci * profile.getIc(bgTime) / sens;
+ // and add that to the running total carbsAbsorbed
+ autosensData.cob = Math.max(previous.cob - autosensData.absorbed, 0d);
+ autosensData.mealCarbs = previous.mealCarbs;
+ autosensData.substractAbosorbedCarbs();
+ autosensData.usedMinCarbsImpact = totalMinCarbsImpact;
+ autosensData.absorbing = previous.absorbing;
+ autosensData.mealStartCounter = previous.mealStartCounter;
+ autosensData.type = previous.type;
+ autosensData.uam = previous.uam;
+ }
+
+ autosensData.removeOldCarbs(bgTime);
+ autosensData.cob += autosensData.carbsFromBolus;
+ autosensData.mealCarbs += autosensData.carbsFromBolus;
+ autosensData.deviation = deviation;
+ autosensData.bgi = bgi;
+ autosensData.delta = delta;
+ autosensData.avgDelta = avgDelta;
+ autosensData.avgDeviation = avgDeviation;
+ autosensData.slopeFromMaxDeviation = slopeFromMaxDeviation;
+ autosensData.slopeFromMinDeviation = slopeFromMinDeviation;
+
+
+ // If mealCOB is zero but all deviations since hitting COB=0 are positive, exclude from autosens
+ if (autosensData.cob > 0 || autosensData.absorbing || autosensData.mealCarbs > 0) {
+ if (deviation > 0)
+ autosensData.absorbing = true;
+ else
+ autosensData.absorbing = false;
+ // stop excluding positive deviations as soon as mealCOB=0 if meal has been absorbing for >5h
+ if (autosensData.mealStartCounter > 60 && autosensData.cob < 0.5) {
+ autosensData.absorbing = false;
+ }
+ if (!autosensData.absorbing && autosensData.cob < 0.5) {
+ autosensData.mealCarbs = 0;
+ }
+ // check previous "type" value, and if it wasn't csf, set a mealAbsorption start flag
+ if (!autosensData.type.equals("csf")) {
+// process.stderr.write("(");
+ autosensData.mealStartCounter = 0;
+ }
+ autosensData.mealStartCounter++;
+ autosensData.type = "csf";
+ } else {
+ // check previous "type" value, and if it was csf, set a mealAbsorption end flag
+ if (autosensData.type.equals("csf")) {
+// process.stderr.write(")");
+ }
+
+ double currentBasal = profile.getBasal(bgTime);
+ // always exclude the first 45m after each carb entry
+ //if (iob.iob > currentBasal || uam ) {
+ if (iob.iob > 2 * currentBasal || autosensData.uam || autosensData.mealStartCounter < 9) {
+ autosensData.mealStartCounter++;
+ if (deviation > 0)
+ autosensData.uam = true;
+ else
+ autosensData.uam = false;
+ if (!autosensData.type.equals("uam")) {
+// process.stderr.write("u(");
+ }
+ autosensData.type = "uam";
+ } else {
+ if (autosensData.type.equals("uam")) {
+// process.stderr.write(")");
+ }
+ autosensData.type = "non-meal";
+ }
+ }
+
+ // Exclude meal-related deviations (carb absorption) from autosens
+ if (autosensData.type.equals("non-meal")) {
+ if (Math.abs(deviation) < Constants.DEVIATION_TO_BE_EQUAL) {
+ autosensData.pastSensitivity = "=";
+ autosensData.validDeviation = true;
+ } else if (deviation > 0) {
+ autosensData.pastSensitivity = "+";
+ autosensData.validDeviation = true;
+ } else {
+ autosensData.pastSensitivity = "-";
+ autosensData.validDeviation = true;
+ }
+ } else if (autosensData.type.equals("uam")) {
+ autosensData.pastSensitivity = "u";
+ } else {
+ autosensData.pastSensitivity = "x";
+ }
+ //log.debug("TIME: " + new Date(bgTime).toString() + " BG: " + bg + " SENS: " + sens + " DELTA: " + delta + " AVGDELTA: " + avgDelta + " IOB: " + iob.iob + " ACTIVITY: " + iob.activity + " BGI: " + bgi + " DEVIATION: " + deviation);
+
+ // add an extra negative deviation if a high temptarget is running and exercise mode is set
+ if (SP.getBoolean(R.string.key_high_temptarget_raises_sensitivity, SMBDefaults.high_temptarget_raises_sensitivity)) {
+ TempTarget tempTarget = TreatmentsPlugin.getPlugin().getTempTargetFromHistory(bgTime);
+ if (tempTarget != null && tempTarget.target() >= 100) {
+ autosensData.extraDeviation.add(-(tempTarget.target() - 100) / 20);
+ }
+ }
+
+ // add one neutral deviation every 2 hours to help decay over long exclusion periods
+ GregorianCalendar calendar = new GregorianCalendar();
+ calendar.setTimeInMillis(bgTime);
+ int min = calendar.get(MINUTE);
+ int hours = calendar.get(Calendar.HOUR_OF_DAY);
+ if (min >= 0 && min < 5 && hours % 2 == 0)
+ autosensData.extraDeviation.add(0d);
+
+ previous = autosensData;
+ if (bgTime < now())
+ autosensDataTable.put(bgTime, autosensData);
+ if (Config.logAutosensData)
+ log.debug("Running detectSensitivity from: " + DateUtil.dateAndTimeString(oldestTimeWithData) + " to: " + DateUtil.dateAndTimeString(bgTime));
+ autosensData.autosensRatio = iobCobCalculatorPlugin.detectSensitivity(oldestTimeWithData, bgTime).ratio;
+ if (Config.logAutosensData)
+ log.debug(autosensData.toString());
+ }
+ }
+ MainApp.bus().post(new EventAutosensCalculationFinished(cause));
+ log.debug("Finishing calculation thread: " + from);
+ } finally {
+ mWakeLock.release();
+ MainApp.bus().post(new EventIobCalculationProgress(""));
+ }
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobThread.java b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobThread.java
index 9818ed17e4..2ba476996f 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobThread.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobThread.java
@@ -26,8 +26,8 @@ import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventIobCalculationProgress;
import info.nightscout.androidaps.plugins.OpenAPSSMB.SMBDefaults;
-import info.nightscout.androidaps.plugins.SensitivityAAPS.SensitivityAAPSPlugin;
-import info.nightscout.androidaps.plugins.SensitivityWeightedAverage.SensitivityWeightedAveragePlugin;
+import info.nightscout.androidaps.plugins.Sensitivity.SensitivityAAPSPlugin;
+import info.nightscout.androidaps.plugins.Sensitivity.SensitivityWeightedAveragePlugin;
import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.utils.DateUtil;
@@ -145,6 +145,7 @@ public class IobCobThread extends Thread {
log.error("! value < 39");
continue;
}
+ autosensData.bg = bg;
delta = (bg - bucketed_data.get(i + 1).value);
avgDelta = (bg - bucketed_data.get(i + 3).value) / 3;
@@ -245,26 +246,29 @@ public class IobCobThread extends Thread {
// calculate autosens only without COB
if (autosensData.cob <= 0) {
if (Math.abs(deviation) < Constants.DEVIATION_TO_BE_EQUAL) {
- autosensData.pastSensitivity += "=";
- autosensData.nonEqualDeviation = true;
+ autosensData.pastSensitivity = "=";
+ autosensData.validDeviation = true;
} else if (deviation > 0) {
- autosensData.pastSensitivity += "+";
- autosensData.nonEqualDeviation = true;
+ autosensData.pastSensitivity = "+";
+ autosensData.validDeviation = true;
} else {
- autosensData.pastSensitivity += "-";
- autosensData.nonEqualDeviation = true;
+ autosensData.pastSensitivity = "-";
+ autosensData.validDeviation = true;
}
- autosensData.nonCarbsDeviation = true;
} else {
- autosensData.pastSensitivity += "C";
+ autosensData.pastSensitivity = "C";
}
//log.debug("TIME: " + new Date(bgTime).toString() + " BG: " + bg + " SENS: " + sens + " DELTA: " + delta + " AVGDELTA: " + avgDelta + " IOB: " + iob.iob + " ACTIVITY: " + iob.activity + " BGI: " + bgi + " DEVIATION: " + deviation);
previous = autosensData;
- autosensDataTable.put(bgTime, autosensData);
+ if (bgTime < now())
+ autosensDataTable.put(bgTime, autosensData);
if (Config.logAutosensData)
log.debug("Running detectSensitivity from: " + DateUtil.dateAndTimeString(oldestTimeWithData) + " to: " + DateUtil.dateAndTimeString(bgTime));
- autosensData.autosensRatio = iobCobCalculatorPlugin.detectSensitivity(oldestTimeWithData, bgTime).ratio;
+ AutosensResult sensitivity = iobCobCalculatorPlugin.detectSensitivity(oldestTimeWithData, bgTime);
+ if (Config.logAutosensData)
+ log.debug("Sensitivity result: " + sensitivity.toString());
+ autosensData.autosensRatio = sensitivity.ratio;
if (Config.logAutosensData)
log.debug(autosensData.toString());
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/APSResult.java b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/APSResult.java
index 87e55c7dc6..ce63ad67e5 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/APSResult.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/APSResult.java
@@ -10,7 +10,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
-import java.util.Date;
import java.util.List;
import info.nightscout.androidaps.MainApp;
@@ -28,7 +27,7 @@ import info.nightscout.utils.DecimalFormatter;
public class APSResult {
private static Logger log = LoggerFactory.getLogger(APSResult.class);
- public Date date;
+ public long date = 0;
public String reason;
public double rate;
public int duration;
@@ -133,8 +132,8 @@ public class APSResult {
public List getPredictions() {
List array = new ArrayList<>();
try {
- long startTime = date.getTime();
- if (json.has("predBGs")) {
+ long startTime = date;
+ if (json != null && json.has("predBGs")) {
JSONObject predBGs = json.getJSONObject("predBGs");
if (predBGs.has("IOB")) {
JSONArray iob = predBGs.getJSONArray("IOB");
@@ -196,8 +195,8 @@ public class APSResult {
public long getLatestPredictionsTime() {
long latest = 0;
try {
- long startTime = date != null ? date.getTime() : 0;
- if (json.has("predBGs")) {
+ long startTime = date;
+ if (json != null && json.has("predBGs")) {
JSONObject predBGs = json.getJSONObject("predBGs");
if (predBGs.has("IOB")) {
JSONArray iob = predBGs.getJSONArray("IOB");
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopFragment.java
index 4ad35c0d02..7fa810f8c0 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopFragment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopFragment.java
@@ -80,7 +80,7 @@ public class LoopFragment extends SubscriberFragment {
clearGUI();
final Activity activity = getActivity();
if (activity != null)
- activity.runOnUiThread(() -> lastRunView.setText(ev.text));
+ activity.runOnUiThread(() -> { synchronized (LoopFragment.this) { if (lastRunView != null) lastRunView.setText(ev.text); } });
}
@@ -89,26 +89,29 @@ public class LoopFragment extends SubscriberFragment {
Activity activity = getActivity();
if (activity != null)
activity.runOnUiThread(() -> {
- LoopPlugin.LastRun lastRun = LoopPlugin.lastRun;
- if (lastRun != null) {
- requestView.setText(lastRun.request != null ? lastRun.request.toSpanned() : "");
- constraintsProcessedView.setText(lastRun.constraintsProcessed != null ? lastRun.constraintsProcessed.toSpanned() : "");
- sourceView.setText(lastRun.source != null ? lastRun.source : "");
- lastRunView.setText(lastRun.lastAPSRun != null && lastRun.lastAPSRun.getTime() != 0 ? lastRun.lastAPSRun.toLocaleString() : "");
- lastEnactView.setText(lastRun.lastEnact != null && lastRun.lastEnact.getTime() != 0 ? lastRun.lastEnact.toLocaleString() : "");
- tbrSetByPumpView.setText(lastRun.tbrSetByPump != null ? Html.fromHtml(lastRun.tbrSetByPump.toHtml()) : "");
- smbSetByPumpView.setText(lastRun.smbSetByPump != null ? Html.fromHtml(lastRun.smbSetByPump.toHtml()) : "");
+ synchronized (LoopFragment.this) {
+ if (!isBound()) return;
+ LoopPlugin.LastRun lastRun = LoopPlugin.lastRun;
+ if (lastRun != null) {
+ requestView.setText(lastRun.request != null ? lastRun.request.toSpanned() : "");
+ constraintsProcessedView.setText(lastRun.constraintsProcessed != null ? lastRun.constraintsProcessed.toSpanned() : "");
+ sourceView.setText(lastRun.source != null ? lastRun.source : "");
+ lastRunView.setText(lastRun.lastAPSRun != null && lastRun.lastAPSRun.getTime() != 0 ? lastRun.lastAPSRun.toLocaleString() : "");
+ lastEnactView.setText(lastRun.lastEnact != null && lastRun.lastEnact.getTime() != 0 ? lastRun.lastEnact.toLocaleString() : "");
+ tbrSetByPumpView.setText(lastRun.tbrSetByPump != null ? Html.fromHtml(lastRun.tbrSetByPump.toHtml()) : "");
+ smbSetByPumpView.setText(lastRun.smbSetByPump != null ? Html.fromHtml(lastRun.smbSetByPump.toHtml()) : "");
- String constraints = "";
- if (lastRun.constraintsProcessed != null) {
- Constraint allConstraints = new Constraint<>(0d);
- if (lastRun.constraintsProcessed.rateConstraint != null)
- allConstraints.copyReasons(lastRun.constraintsProcessed.rateConstraint);
- if (lastRun.constraintsProcessed.smbConstraint != null)
- allConstraints.copyReasons(lastRun.constraintsProcessed.smbConstraint);
- constraints = allConstraints.getMostLimitedReasons();
+ String constraints = "";
+ if (lastRun.constraintsProcessed != null) {
+ Constraint allConstraints = new Constraint<>(0d);
+ if (lastRun.constraintsProcessed.rateConstraint != null)
+ allConstraints.copyReasons(lastRun.constraintsProcessed.rateConstraint);
+ if (lastRun.constraintsProcessed.smbConstraint != null)
+ allConstraints.copyReasons(lastRun.constraintsProcessed.smbConstraint);
+ constraints = allConstraints.getMostLimitedReasons();
+ }
+ constraintsView.setText(constraints);
}
- constraintsView.setText(constraints);
}
});
}
@@ -117,13 +120,29 @@ public class LoopFragment extends SubscriberFragment {
Activity activity = getActivity();
if (activity != null)
activity.runOnUiThread(() -> {
- requestView.setText("");
- constraintsProcessedView.setText("");
- sourceView.setText("");
- lastRunView.setText("");
- lastEnactView.setText("");
- tbrSetByPumpView.setText("");
- smbSetByPumpView.setText("");
+ synchronized (LoopFragment.this) {
+ if (isBound()) {
+ requestView.setText("");
+ constraintsProcessedView.setText("");
+ sourceView.setText("");
+ lastRunView.setText("");
+ lastEnactView.setText("");
+ tbrSetByPumpView.setText("");
+ smbSetByPumpView.setText("");
+ }
+ }
});
}
+
+ boolean isBound() {
+ return requestView != null
+ && constraintsProcessedView != null
+ && sourceView != null
+ && lastRunView != null
+ && lastEnactView != null
+ && tbrSetByPumpView != null
+ && smbSetByPumpView != null
+ && constraintsView != null
+ && runNowButton != null;
+ }
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java
index c01cf0a641..480646ccfc 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java
@@ -46,6 +46,7 @@ import info.nightscout.androidaps.plugins.Loop.events.EventLoopUpdateGui;
import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.androidaps.queue.Callback;
+import info.nightscout.androidaps.queue.commands.Command;
import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.NSUpload;
import info.nightscout.utils.SP;
@@ -332,7 +333,9 @@ public class LoopPlugin extends PluginBase {
Constraint closedLoopEnabled = MainApp.getConstraintChecker().isClosedLoopAllowed();
if (closedLoopEnabled.value()) {
- if (result.isChangeRequested()) {
+ if (result.isChangeRequested()
+ && !ConfigBuilderPlugin.getCommandQueue().bolusInQueue()
+ && !ConfigBuilderPlugin.getCommandQueue().isRunning(Command.CommandType.BOLUS)) {
final PumpEnactResult waiting = new PumpEnactResult();
waiting.queued = true;
if (resultAfterConstraints.tempBasalRequested)
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/NsClientReceiverDelegate.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/NsClientReceiverDelegate.java
index 04b587ca24..ba6ec2c80b 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/NsClientReceiverDelegate.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/NsClientReceiverDelegate.java
@@ -122,7 +122,8 @@ class NsClientReceiverDelegate {
boolean newAllowedState = true;
if (ev.wifiConnected) {
- if (!allowedSSIDs.trim().isEmpty() && !allowedSSIDs.contains(ev.ssid)) {
+ if (!allowedSSIDs.trim().isEmpty() &&
+ (!allowedSSIDs.contains(ev.getSsid()) && !allowedSSIDs.contains(ev.ssid))) {
newAllowedState = false;
}
} else {
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSDeviceStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSDeviceStatus.java
index d1755dd4c1..29d1b33467 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSDeviceStatus.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSDeviceStatus.java
@@ -13,6 +13,7 @@ import java.util.Iterator;
import java.util.Map;
import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.plugins.Loop.APSResult;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.Round;
import info.nightscout.utils.SP;
@@ -374,7 +375,7 @@ public class NSDeviceStatus {
public String getUploaderStatus() {
Iterator iter = uploaders.entrySet().iterator();
int minBattery = 100;
- while(iter.hasNext()) {
+ while (iter.hasNext()) {
Map.Entry pair = (Map.Entry) iter.next();
Uploader uploader = (Uploader) pair.getValue();
if (minBattery > uploader.battery)
@@ -388,7 +389,7 @@ public class NSDeviceStatus {
StringBuilder string = new StringBuilder();
Iterator iter = uploaders.entrySet().iterator();
- while(iter.hasNext()) {
+ while (iter.hasNext()) {
Map.Entry pair = (Map.Entry) iter.next();
Uploader uploader = (Uploader) pair.getValue();
String device = (String) pair.getKey();
@@ -398,4 +399,11 @@ public class NSDeviceStatus {
return Html.fromHtml(string.toString());
}
+ public static APSResult getAPSResult() {
+ APSResult result = new APSResult();
+ result.json = deviceStatusOpenAPSData.suggested;
+ result.date = deviceStatusOpenAPSData.clockSuggested;
+ return result;
+ }
+
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalResultAMA.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalResultAMA.java
index cb2b4a0091..ac7a7c2b49 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalResultAMA.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalResultAMA.java
@@ -6,19 +6,18 @@ import org.mozilla.javascript.NativeObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.Date;
-
import info.nightscout.androidaps.plugins.Loop.APSResult;
+import info.nightscout.utils.DateUtil;
public class DetermineBasalResultAMA extends APSResult {
private static Logger log = LoggerFactory.getLogger(DetermineBasalResultAMA.class);
- public double eventualBG;
- public double snoozeBG;
+ private double eventualBG;
+ private double snoozeBG;
- public DetermineBasalResultAMA(NativeObject result, JSONObject j) {
+ DetermineBasalResultAMA(NativeObject result, JSONObject j) {
this();
- date = new Date();
+ date = DateUtil.now();
json = j;
if (result.containsKey("error")) {
reason = result.get("error").toString();
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/DetermineBasalAdapterSMBJS.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/DetermineBasalAdapterSMBJS.java
index 396338efa4..48a4c16ccd 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/DetermineBasalAdapterSMBJS.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/DetermineBasalAdapterSMBJS.java
@@ -234,8 +234,8 @@ public class DetermineBasalAdapterSMBJS {
mProfile.put("max_daily_safety_multiplier", SP.getInt(R.string.key_openapsama_max_daily_safety_multiplier, 3));
mProfile.put("current_basal_safety_multiplier", SP.getDouble(R.string.key_openapsama_current_basal_safety_multiplier, 4d));
- mProfile.put("high_temptarget_raises_sensitivity", SMBDefaults.high_temptarget_raises_sensitivity);
- mProfile.put("low_temptarget_lowers_sensitivity", SMBDefaults.low_temptarget_lowers_sensitivity);
+ mProfile.put("high_temptarget_raises_sensitivity", SP.getBoolean(R.string.key_high_temptarget_raises_sensitivity, SMBDefaults.high_temptarget_raises_sensitivity));
+ mProfile.put("low_temptarget_lowers_sensitivity", SP.getBoolean(R.string.key_low_temptarget_lowers_sensitivity, SMBDefaults.low_temptarget_lowers_sensitivity));
mProfile.put("sensitivity_raises_target", SMBDefaults.sensitivity_raises_target);
mProfile.put("resistance_lowers_target", SMBDefaults.resistance_lowers_target);
mProfile.put("adv_target_adjustments", SMBDefaults.adv_target_adjustments);
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/DetermineBasalResultSMB.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/DetermineBasalResultSMB.java
index 59c1dd95e3..d5f108bf4f 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/DetermineBasalResultSMB.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/DetermineBasalResultSMB.java
@@ -5,22 +5,20 @@ import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.Date;
-
import info.nightscout.androidaps.plugins.Loop.APSResult;
import info.nightscout.utils.DateUtil;
public class DetermineBasalResultSMB extends APSResult {
private static final Logger log = LoggerFactory.getLogger(DetermineBasalResultSMB.class);
- public double eventualBG;
- public double snoozeBG;
- public double insulinReq;
- public double carbsReq;
+ private double eventualBG;
+ private double snoozeBG;
+ //public double insulinReq;
+ //public double carbsReq;
- public DetermineBasalResultSMB(JSONObject result) {
+ DetermineBasalResultSMB(JSONObject result) {
this();
- date = new Date();
+ date = DateUtil.now();
json = result;
try {
if (result.has("error")) {
@@ -31,8 +29,8 @@ public class DetermineBasalResultSMB extends APSResult {
reason = result.getString("reason");
if (result.has("eventualBG")) eventualBG = result.getDouble("eventualBG");
if (result.has("snoozeBG")) snoozeBG = result.getDouble("snoozeBG");
- if (result.has("insulinReq")) insulinReq = result.getDouble("insulinReq");
- if (result.has("carbsReq")) carbsReq = result.getDouble("carbsReq");
+ //if (result.has("insulinReq")) insulinReq = result.getDouble("insulinReq");
+ //if (result.has("carbsReq")) carbsReq = result.getDouble("carbsReq");
if (result.has("rate") && result.has("duration")) {
tempBasalRequested = true;
@@ -64,7 +62,7 @@ public class DetermineBasalResultSMB extends APSResult {
}
}
- public DetermineBasalResultSMB() {
+ private DetermineBasalResultSMB() {
hasPredictions = true;
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBFragment.java
index 724bfcf86c..20ccd46b40 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBFragment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBFragment.java
@@ -87,34 +87,37 @@ public class OpenAPSSMBFragment extends SubscriberFragment {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
- OpenAPSSMBPlugin plugin = OpenAPSSMBPlugin.getPlugin();
- DetermineBasalResultSMB lastAPSResult = plugin.lastAPSResult;
- if (lastAPSResult != null) {
- resultView.setText(JSONFormatter.format(lastAPSResult.json));
- requestView.setText(lastAPSResult.toSpanned());
- }
- DetermineBasalAdapterSMBJS determineBasalAdapterSMBJS = plugin.lastDetermineBasalAdapterSMBJS;
- if (determineBasalAdapterSMBJS != null) {
- glucoseStatusView.setText(JSONFormatter.format(determineBasalAdapterSMBJS.getGlucoseStatusParam()).toString().trim());
- currentTempView.setText(JSONFormatter.format(determineBasalAdapterSMBJS.getCurrentTempParam()).toString().trim());
- try {
- JSONArray iobArray = new JSONArray(determineBasalAdapterSMBJS.getIobDataParam());
- iobDataView.setText((String.format(MainApp.gs(R.string.array_of_elements), iobArray.length()) + "\n" + JSONFormatter.format(iobArray.getString(0))).trim());
- } catch (JSONException e) {
- log.error("Unhandled exception", e);
- iobDataView.setText("JSONException see log for details");
+ synchronized (OpenAPSSMBFragment.this) {
+ if (!isBound()) return;
+ OpenAPSSMBPlugin plugin = OpenAPSSMBPlugin.getPlugin();
+ DetermineBasalResultSMB lastAPSResult = plugin.lastAPSResult;
+ if (lastAPSResult != null) {
+ resultView.setText(JSONFormatter.format(lastAPSResult.json));
+ requestView.setText(lastAPSResult.toSpanned());
+ }
+ DetermineBasalAdapterSMBJS determineBasalAdapterSMBJS = plugin.lastDetermineBasalAdapterSMBJS;
+ if (determineBasalAdapterSMBJS != null) {
+ glucoseStatusView.setText(JSONFormatter.format(determineBasalAdapterSMBJS.getGlucoseStatusParam()).toString().trim());
+ currentTempView.setText(JSONFormatter.format(determineBasalAdapterSMBJS.getCurrentTempParam()).toString().trim());
+ try {
+ JSONArray iobArray = new JSONArray(determineBasalAdapterSMBJS.getIobDataParam());
+ iobDataView.setText((String.format(MainApp.gs(R.string.array_of_elements), iobArray.length()) + "\n" + JSONFormatter.format(iobArray.getString(0))).trim());
+ } catch (JSONException e) {
+ log.error("Unhandled exception", e);
+ iobDataView.setText("JSONException see log for details");
+ }
+ profileView.setText(JSONFormatter.format(determineBasalAdapterSMBJS.getProfileParam()).toString().trim());
+ mealDataView.setText(JSONFormatter.format(determineBasalAdapterSMBJS.getMealDataParam()).toString().trim());
+ scriptdebugView.setText(determineBasalAdapterSMBJS.getScriptDebug().trim());
+ if (lastAPSResult != null && lastAPSResult.inputConstraints != null)
+ constraintsView.setText(lastAPSResult.inputConstraints.getReasons().trim());
+ }
+ if (plugin.lastAPSRun != null) {
+ lastRunView.setText(plugin.lastAPSRun.toLocaleString().trim());
+ }
+ if (plugin.lastAutosensResult != null) {
+ autosensDataView.setText(JSONFormatter.format(plugin.lastAutosensResult.json()).toString().trim());
}
- profileView.setText(JSONFormatter.format(determineBasalAdapterSMBJS.getProfileParam()).toString().trim());
- mealDataView.setText(JSONFormatter.format(determineBasalAdapterSMBJS.getMealDataParam()).toString().trim());
- scriptdebugView.setText(determineBasalAdapterSMBJS.getScriptDebug().trim());
- if (lastAPSResult != null && lastAPSResult.inputConstraints != null)
- constraintsView.setText(lastAPSResult.inputConstraints.getReasons().trim());
- }
- if (plugin.lastAPSRun != null) {
- lastRunView.setText(plugin.lastAPSRun.toLocaleString().trim());
- }
- if (plugin.lastAutosensResult != null) {
- autosensDataView.setText(JSONFormatter.format(plugin.lastAutosensResult.json()).toString().trim());
}
}
});
@@ -126,17 +129,36 @@ public class OpenAPSSMBFragment extends SubscriberFragment {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
- resultView.setText(text);
- glucoseStatusView.setText("");
- currentTempView.setText("");
- iobDataView.setText("");
- profileView.setText("");
- mealDataView.setText("");
- autosensDataView.setText("");
- scriptdebugView.setText("");
- requestView.setText("");
- lastRunView.setText("");
+ synchronized (OpenAPSSMBFragment.this) {
+ if (isBound()) {
+ resultView.setText(text);
+ glucoseStatusView.setText("");
+ currentTempView.setText("");
+ iobDataView.setText("");
+ profileView.setText("");
+ mealDataView.setText("");
+ autosensDataView.setText("");
+ scriptdebugView.setText("");
+ requestView.setText("");
+ lastRunView.setText("");
+ }
+ }
}
});
}
+
+ private boolean isBound() {
+ return run != null
+ && lastRunView != null
+ && constraintsView != null
+ && glucoseStatusView != null
+ && currentTempView != null
+ && iobDataView != null
+ && profileView != null
+ && mealDataView != null
+ && autosensDataView != null
+ && resultView != null
+ && scriptdebugView != null
+ && requestView != null;
+ }
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java
index e89a040316..2e8dea0662 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java
@@ -25,14 +25,11 @@ import android.text.style.ForegroundColorSpan;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.ContextMenu;
-import android.view.HapticFeedbackConstants;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.CheckBox;
-import android.widget.CompoundButton;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -89,10 +86,12 @@ import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialo
import info.nightscout.androidaps.plugins.Careportal.OptionsToShow;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin;
+import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult;
import info.nightscout.androidaps.plugins.IobCobCalculator.CobInfo;
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventIobCalculationProgress;
+import info.nightscout.androidaps.plugins.Loop.APSResult;
import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSDeviceStatus;
@@ -104,7 +103,6 @@ import info.nightscout.androidaps.plugins.Overview.Dialogs.NewInsulinDialog;
import info.nightscout.androidaps.plugins.Overview.Dialogs.NewTreatmentDialog;
import info.nightscout.androidaps.plugins.Overview.Dialogs.WizardDialog;
import info.nightscout.androidaps.plugins.Overview.activities.QuickWizardListActivity;
-import info.nightscout.androidaps.plugins.Overview.events.EventSetWakeLock;
import info.nightscout.androidaps.plugins.Overview.graphData.GraphData;
import info.nightscout.androidaps.plugins.Overview.notifications.NotificationRecyclerViewAdapter;
import info.nightscout.androidaps.plugins.Overview.notifications.NotificationStore;
@@ -116,6 +114,7 @@ import info.nightscout.androidaps.queue.Callback;
import info.nightscout.utils.BolusWizard;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter;
+import info.nightscout.utils.DefaultValueHelper;
import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.NSUpload;
import info.nightscout.utils.OKDialog;
@@ -124,14 +123,19 @@ import info.nightscout.utils.SP;
import info.nightscout.utils.SingleClickButton;
import info.nightscout.utils.ToastUtils;
+import static info.nightscout.utils.DateUtil.now;
+
public class OverviewFragment extends Fragment implements View.OnClickListener, View.OnLongClickListener {
private static Logger log = LoggerFactory.getLogger(OverviewFragment.class);
TextView timeView;
TextView bgView;
TextView arrowView;
+ TextView sensitivityView;
TextView timeAgoView;
+ TextView timeAgoShortView;
TextView deltaView;
+ TextView deltaShortView;
TextView avgdeltaView;
TextView baseBasalView;
TextView extendedBolusView;
@@ -177,8 +181,6 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
SingleClickButton cgmButton;
SingleClickButton quickWizardButton;
- CheckBox lockScreen;
-
boolean smallWidth;
boolean smallHeight;
@@ -235,8 +237,11 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
if (smallWidth) {
arrowView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 35);
}
+ sensitivityView = (TextView) view.findViewById(R.id.overview_sensitivity);
timeAgoView = (TextView) view.findViewById(R.id.overview_timeago);
+ timeAgoShortView = (TextView) view.findViewById(R.id.overview_timeagoshort);
deltaView = (TextView) view.findViewById(R.id.overview_delta);
+ deltaShortView = (TextView) view.findViewById(R.id.overview_deltashort);
avgdeltaView = (TextView) view.findViewById(R.id.overview_avgdelta);
baseBasalView = (TextView) view.findViewById(R.id.overview_basebasal);
extendedBolusView = (TextView) view.findViewById(R.id.overview_extendedbolus);
@@ -323,7 +328,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
iobGraph.getGridLabelRenderer().setHorizontalLabelsVisible(false);
bgGraph.getGridLabelRenderer().setLabelVerticalWidth(axisWidth);
iobGraph.getGridLabelRenderer().setLabelVerticalWidth(axisWidth);
- iobGraph.getGridLabelRenderer().setNumVerticalLabels(5);
+ iobGraph.getGridLabelRenderer().setNumVerticalLabels(3);
rangeToDisplay = SP.getInt(R.string.key_rangetodisplay, 6);
@@ -340,18 +345,6 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
setupChartMenu(view);
- lockScreen = (CheckBox) view.findViewById(R.id.overview_lockscreen);
- if (lockScreen != null) {
- lockScreen.setChecked(SP.getBoolean("lockscreen", false));
- lockScreen.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
- @Override
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- SP.putBoolean("lockscreen", isChecked);
- MainApp.bus().post(new EventSetWakeLock(isChecked));
- }
- });
- }
-
return view;
} catch (Exception e) {
FabricPrivacy.logException(e);
@@ -367,7 +360,13 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
@Override
public void onClick(View v) {
final LoopPlugin.LastRun finalLastRun = LoopPlugin.lastRun;
- final boolean predictionsAvailable = finalLastRun != null && finalLastRun.request.hasPredictions;
+ boolean predictionsAvailable;
+ if (Config.APS)
+ predictionsAvailable = finalLastRun != null && finalLastRun.request.hasPredictions;
+ else if (Config.NSCLIENT)
+ predictionsAvailable = true;
+ else
+ predictionsAvailable = false;
MenuItem item;
CharSequence title;
@@ -504,6 +503,15 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
if (MainApp.getConfigBuilder().getActiveProfileInterface().getProfile() != null) {
menu.add(MainApp.gs(R.string.careportal_profileswitch));
}
+ } else if (v == tempTargetView) {
+ menu.setHeaderTitle(MainApp.gs(R.string.careportal_temporarytarget));
+ menu.add(MainApp.gs(R.string.custom));
+ menu.add(MainApp.gs(R.string.eatingsoon));
+ menu.add(MainApp.gs(R.string.activity));
+ menu.add(MainApp.gs(R.string.hypo));
+ if (TreatmentsPlugin.getPlugin().getTempTargetFromHistory() != null) {
+ menu.add(MainApp.gs(R.string.cancel));
+ }
}
}
@@ -594,6 +602,53 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
ProfileViewerDialog pvd = ProfileViewerDialog.newInstance(System.currentTimeMillis());
FragmentManager manager = getFragmentManager();
pvd.show(manager, "ProfileViewDialog");
+ } else if (item.getTitle().equals(MainApp.gs(R.string.eatingsoon))) {
+ DefaultValueHelper defHelper = new DefaultValueHelper();
+ double target = defHelper.determineEatingSoonTT(profile.getUnits());
+ TempTarget tempTarget = new TempTarget()
+ .date(System.currentTimeMillis())
+ .duration(defHelper.determineEatingSoonTTDuration())
+ .reason(MainApp.gs(R.string.eatingsoon))
+ .source(Source.USER)
+ .low(target)
+ .high(target);
+ TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget);
+ } else if (item.getTitle().equals(MainApp.gs(R.string.activity))) {
+ DefaultValueHelper defHelper = new DefaultValueHelper();
+ double target = defHelper.determineActivityTT(profile.getUnits());
+ TempTarget tempTarget = new TempTarget()
+ .date(now())
+ .duration(defHelper.determineActivityTTDuration())
+ .reason(MainApp.gs(R.string.activity))
+ .source(Source.USER)
+ .low(target)
+ .high(target);
+ TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget);
+ } else if (item.getTitle().equals(MainApp.gs(R.string.hypo))) {
+ DefaultValueHelper defHelper = new DefaultValueHelper();
+ double target = defHelper.determineHypoTT(profile.getUnits());
+ TempTarget tempTarget = new TempTarget()
+ .date(now())
+ .duration(defHelper.determineHypoTTDuration())
+ .reason(MainApp.gs(R.string.activity))
+ .source(Source.USER)
+ .low(target)
+ .high(target);
+ TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget);
+ } else if (item.getTitle().equals(MainApp.gs(R.string.custom))) {
+ NewNSTreatmentDialog newTTDialog = new NewNSTreatmentDialog();
+ final OptionsToShow temptarget = CareportalFragment.TEMPTARGET;
+ temptarget.executeTempTarget = true;
+ newTTDialog.setOptions(temptarget, R.string.careportal_temporarytarget);
+ newTTDialog.show(getFragmentManager(), "NewNSTreatmentDialog");
+ } else if (item.getTitle().equals(MainApp.gs(R.string.cancel))) {
+ TempTarget tempTarget = new TempTarget()
+ .source(Source.USER)
+ .date(now())
+ .duration(0)
+ .low(0)
+ .high(0);
+ TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget);
}
return super.onContextItemSelected(item);
@@ -859,6 +914,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
sLoopHandler.removeCallbacksAndMessages(null);
unregisterForContextMenu(apsModeView);
unregisterForContextMenu(activeProfileView);
+ unregisterForContextMenu(tempTargetView);
}
@Override
@@ -872,6 +928,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
sLoopHandler.postDelayed(sRefreshLoop, 60 * 1000L);
registerForContextMenu(apsModeView);
registerForContextMenu(activeProfileView);
+ registerForContextMenu(tempTargetView);
updateGUI("onResume");
}
@@ -1043,12 +1100,18 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
arrowView.setTextColor(color);
GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
if (glucoseStatus != null) {
- deltaView.setText("Δ " + Profile.toUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units) + " " + units);
+ if (deltaView != null)
+ deltaView.setText("Δ " + Profile.toUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units) + " " + units);
+ if (deltaShortView != null)
+ deltaShortView.setText(Profile.toSignedUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units));
if (avgdeltaView != null)
avgdeltaView.setText("øΔ15m: " + Profile.toUnitsString(glucoseStatus.short_avgdelta, glucoseStatus.short_avgdelta * Constants.MGDL_TO_MMOLL, units) +
" øΔ40m: " + Profile.toUnitsString(glucoseStatus.long_avgdelta, glucoseStatus.long_avgdelta * Constants.MGDL_TO_MMOLL, units));
} else {
- deltaView.setText("Δ " + MainApp.gs(R.string.notavailable));
+ if (deltaView != null)
+ deltaView.setText("Δ " + MainApp.gs(R.string.notavailable));
+ if (deltaShortView != null)
+ deltaShortView.setText("---");
if (avgdeltaView != null)
avgdeltaView.setText("");
}
@@ -1204,7 +1267,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
extendedBolusView.setText(extendedBolusText);
}
if (extendedBolusText.equals(""))
- extendedBolusView.setVisibility(View.GONE);
+ extendedBolusView.setVisibility(shorttextmode ? View.INVISIBLE : View.GONE);
else
extendedBolusView.setVisibility(View.VISIBLE);
}
@@ -1218,17 +1281,6 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
activeProfileView.setTextColor(MainApp.gc(R.color.ribbonTextDefault));
}
- tempTargetView.setOnLongClickListener(view -> {
- view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
- NewNSTreatmentDialog newTTDialog = new NewNSTreatmentDialog();
- final OptionsToShow temptarget = CareportalFragment.TEMPTARGET;
- temptarget.executeTempTarget = true;
- newTTDialog.setOptions(temptarget, R.string.careportal_temporarytarget);
- newTTDialog.show(getFragmentManager(), "NewNSTreatmentDialog");
- return true;
- });
- tempTargetView.setLongClickable(true);
-
// QuickWizard button
QuickWizardEntry quickWizardEntry = OverviewPlugin.getPlugin().quickWizard.getActive();
if (quickWizardEntry != null && lastBG != null && pump.isInitialized() && !pump.isSuspended()) {
@@ -1288,7 +1340,10 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
flag &= ~Paint.STRIKE_THRU_TEXT_FLAG;
bgView.setPaintFlags(flag);
- timeAgoView.setText(DateUtil.minAgo(lastBG.date));
+ if (timeAgoView != null)
+ timeAgoView.setText(DateUtil.minAgo(lastBG.date));
+ if (timeAgoShortView != null)
+ timeAgoShortView.setText("(" + DateUtil.minAgoShort(lastBG.date) + ")");
// iob
TreatmentsPlugin.getPlugin().updateTotalIOBTreatments();
@@ -1379,7 +1434,15 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
}
}
- final boolean predictionsAvailable = finalLastRun != null && finalLastRun.request.hasPredictions;
+ boolean predictionsAvailable;
+ if (Config.APS)
+ predictionsAvailable = finalLastRun != null && finalLastRun.request.hasPredictions;
+ else if (Config.NSCLIENT)
+ predictionsAvailable = true;
+ else
+ predictionsAvailable = false;
+ final boolean finalPredictionsAvailable = predictionsAvailable;
+
// pump status from ns
if (pumpDeviceStatusView != null) {
pumpDeviceStatusView.setText(NSDeviceStatus.getInstance().getPumpStatus());
@@ -1398,6 +1461,15 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
uploaderDeviceStatusView.setOnClickListener(v -> OKDialog.show(getActivity(), MainApp.gs(R.string.uploader), NSDeviceStatus.getInstance().getExtendedUploaderStatus(), null));
}
+ // Sensitivity
+ if (sensitivityView != null) {
+ AutosensResult lastAutosensResult = IobCobCalculatorPlugin.getPlugin().detectSensitivityWithLock(IobCobCalculatorPlugin.getPlugin().oldestDataAvailable(), System.currentTimeMillis());
+ if (lastAutosensResult != null)
+ sensitivityView.setText(String.format("%.0f%%", lastAutosensResult.ratio * 100));
+ else
+ sensitivityView.setText("");
+ }
+
// ****** GRAPH *******
new Thread(() -> {
@@ -1413,8 +1485,15 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
final long toTime;
final long fromTime;
final long endTime;
- if (predictionsAvailable && SP.getBoolean("showprediction", false)) {
- int predHours = (int) (Math.ceil(finalLastRun.constraintsProcessed.getLatestPredictionsTime() - System.currentTimeMillis()) / (60 * 60 * 1000));
+
+ APSResult apsResult = null;
+
+ if (finalPredictionsAvailable && SP.getBoolean("showprediction", false)) {
+ if (Config.APS)
+ apsResult = finalLastRun.constraintsProcessed;
+ else
+ apsResult = NSDeviceStatus.getAPSResult();
+ int predHours = (int) (Math.ceil(apsResult.getLatestPredictionsTime() - System.currentTimeMillis()) / (60 * 60 * 1000));
predHours = Math.min(2, predHours);
predHours = Math.max(0, predHours);
hoursToFetch = rangeToDisplay - predHours;
@@ -1440,9 +1519,9 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
graphData.addInRangeArea(fromTime, endTime, lowLine, highLine);
// **** BG ****
- if (predictionsAvailable && SP.getBoolean("showprediction", false))
+ if (finalPredictionsAvailable && SP.getBoolean("showprediction", false))
graphData.addBgReadings(fromTime, toTime, lowLine, highLine,
- finalLastRun.constraintsProcessed.getPredictions());
+ apsResult.getPredictions());
else
graphData.addBgReadings(fromTime, toTime, lowLine, highLine, null);
@@ -1494,7 +1573,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
secondGraphData.addDeviations(fromTime, now, useDevForScale, 1d);
if (SP.getBoolean("showratios", false))
secondGraphData.addRatio(fromTime, now, useRatioForScale, 1d);
- if (SP.getBoolean("showdevslope", false))
+ if (SP.getBoolean("showdevslope", false) && MainApp.devBranch)
secondGraphData.addDeviationSlope(fromTime, now, useDSForScale, 1d);
// **** NOW line ****
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventSetWakeLock.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventSetWakeLock.java
deleted file mode 100644
index 49ccf9fbfb..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventSetWakeLock.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package info.nightscout.androidaps.plugins.Overview.events;
-
-import info.nightscout.androidaps.events.Event;
-
-/**
- * Created by mike on 02.07.2017.
- */
-
-public class EventSetWakeLock extends Event {
- public boolean lock = false;
-
- public EventSetWakeLock(boolean val) {
- lock = val;
- }
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphData/GraphData.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphData/GraphData.java
index 30e2ad97e4..24ba8c1cea 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphData/GraphData.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphData/GraphData.java
@@ -49,7 +49,8 @@ import info.nightscout.utils.Round;
public class GraphData {
private GraphView graph;
- public double maxY = 0;
+ public double maxY = Double.MIN_VALUE;
+ public double minY = Double.MAX_VALUE;
private List bgReadingsArray;
private String units;
private List series = new ArrayList<>();
@@ -63,7 +64,7 @@ public class GraphData {
}
public void addBgReadings(long fromTime, long toTime, double lowLine, double highLine, List predictions) {
- double maxBgValue = 0d;
+ double maxBgValue = Double.MIN_VALUE;
bgReadingsArray = MainApp.getDbHelper().getBgreadingsDataFromTime(fromTime, true);
List bgListArray = new ArrayList<>();
@@ -93,10 +94,8 @@ public class GraphData {
maxY = maxBgValue;
+ minY = 0;
// set manual y bounds to have nice steps
- graph.getViewport().setMaxY(maxY);
- graph.getViewport().setMinY(0);
- graph.getViewport().setYAxisBoundsManual(true);
graph.getGridLabelRenderer().setNumVerticalLabels(numOfVertLines);
addSeries(new PointsWithLabelGraphSeries<>(bg));
@@ -335,7 +334,7 @@ public class GraphData {
public void addIob(long fromTime, long toTime, boolean useForScale, double scale) {
FixedLineGraphSeries iobSeries;
List iobArray = new ArrayList<>();
- Double maxIobValueFound = 0d;
+ Double maxIobValueFound = Double.MIN_VALUE;
double lastIob = 0;
Scale iobScale = new Scale();
@@ -361,8 +360,10 @@ public class GraphData {
iobSeries.setColor(MainApp.gc(R.color.iob));
iobSeries.setThickness(3);
- if (useForScale)
+ if (useForScale) {
maxY = maxIobValueFound;
+ minY = -maxIobValueFound;
+ }
iobScale.setMultiplier(maxY * scale / maxIobValueFound);
@@ -406,8 +407,10 @@ public class GraphData {
cobSeries.setColor(MainApp.gc(R.color.cob));
cobSeries.setThickness(3);
- if (useForScale)
+ if (useForScale) {
maxY = maxCobValueFound;
+ minY = 0;
+ }
cobScale.setMultiplier(maxY * scale / maxCobValueFound);
@@ -438,9 +441,18 @@ public class GraphData {
AutosensData autosensData = IobCobCalculatorPlugin.getPlugin().getAutosensData(time);
if (autosensData != null) {
int color = MainApp.gc(R.color.deviationblack); // "="
- if (autosensData.pastSensitivity.equals("C")) color = MainApp.gc(R.color.deviationgrey);
- if (autosensData.pastSensitivity.equals("+")) color = MainApp.gc(R.color.deviationgreen);
- if (autosensData.pastSensitivity.equals("-")) color = MainApp.gc(R.color.deviationred);
+ if (autosensData.type.equals("") || autosensData.type.equals("non-meal")) {
+ if (autosensData.pastSensitivity.equals("C"))
+ color = MainApp.gc(R.color.deviationgrey);
+ if (autosensData.pastSensitivity.equals("+"))
+ color = MainApp.gc(R.color.deviationgreen);
+ if (autosensData.pastSensitivity.equals("-"))
+ color = MainApp.gc(R.color.deviationred);
+ } else if (autosensData.type.equals("uam")) {
+ color = MainApp.gc(R.color.uam);
+ } else if (autosensData.type.equals("csf")) {
+ color = MainApp.gc(R.color.deviationgrey);
+ }
devArray.add(new DeviationDataPoint(time, autosensData.deviation, color, devScale));
maxDevValueFound = Math.max(maxDevValueFound, Math.abs(autosensData.deviation));
}
@@ -457,8 +469,10 @@ public class GraphData {
}
});
- if (useForScale)
+ if (useForScale) {
maxY = maxDevValueFound;
+ minY = -maxY;
+ }
devScale.setMultiplier(maxY * scale / maxDevValueFound);
@@ -469,14 +483,16 @@ public class GraphData {
public void addRatio(long fromTime, long toTime, boolean useForScale, double scale) {
LineGraphSeries ratioSeries;
List ratioArray = new ArrayList<>();
- Double maxRatioValueFound = 0d;
- Scale ratioScale = new Scale(-1d);
+ Double maxRatioValueFound = Double.MIN_VALUE;
+ Double minRatioValueFound = Double.MAX_VALUE;
+ Scale ratioScale = new Scale();
for (long time = fromTime; time <= toTime; time += 5 * 60 * 1000L) {
AutosensData autosensData = IobCobCalculatorPlugin.getPlugin().getAutosensData(time);
if (autosensData != null) {
- ratioArray.add(new ScaledDataPoint(time, autosensData.autosensRatio, ratioScale));
- maxRatioValueFound = Math.max(maxRatioValueFound, Math.abs(autosensData.autosensRatio));
+ ratioArray.add(new ScaledDataPoint(time, autosensData.autosensRatio - 1, ratioScale));
+ maxRatioValueFound = Math.max(maxRatioValueFound, autosensData.autosensRatio - 1);
+ minRatioValueFound = Math.min(minRatioValueFound, autosensData.autosensRatio - 1);
}
}
@@ -487,8 +503,10 @@ public class GraphData {
ratioSeries.setColor(MainApp.gc(R.color.ratio));
ratioSeries.setThickness(3);
- if (useForScale)
+ if (useForScale) {
maxY = maxRatioValueFound;
+ minY = minRatioValueFound;
+ }
ratioScale.setMultiplier(maxY * scale / maxRatioValueFound);
@@ -529,8 +547,10 @@ public class GraphData {
dsMinSeries.setColor(MainApp.gc(R.color.devslopeneg));
dsMinSeries.setThickness(3);
- if (useForScale)
+ if (useForScale) {
maxY = Math.max(maxFromMaxValueFound, maxFromMinValueFound);
+ minY = -maxY;
+ }
dsMaxScale.setMultiplier(maxY * scale / maxFromMaxValueFound);
dsMinScale.setMultiplier(maxY * scale / maxFromMinValueFound);
@@ -584,6 +604,10 @@ public class GraphData {
}
}
+ graph.getViewport().setMaxY(Round.ceilTo(maxY, 1d));
+ graph.getViewport().setMinY(Round.floorTo(minY, 1d));
+ graph.getViewport().setYAxisBoundsManual(true);
+
// draw it
graph.onDataChanged(false, false);
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/PointsWithLabelGraphSeries.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/PointsWithLabelGraphSeries.java
index 5f39cedafe..4a87a8508e 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/PointsWithLabelGraphSeries.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/PointsWithLabelGraphSeries.java
@@ -312,20 +312,20 @@ public class PointsWithLabelGraphSeries e
mPaint.setStrokeWidth(5);
canvas.drawRect(px - 3, bounds.top + py - 3, xpluslength + 3, bounds.bottom + py + 3, mPaint);
}
- } else if (value.getShape() == Shape.OPENAPSOFFLINE) {
+ } else if (value.getShape() == Shape.OPENAPSOFFLINE && value.getDuration() != 0) {
mPaint.setStrokeWidth(0);
if (value.getLabel() != null) {
- mPaint.setStrokeWidth(0);
- mPaint.setTextSize(scaledTextSize);
- mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));
+ //mPaint.setStrokeWidth(0);
+ //mPaint.setTextSize(scaledTextSize);
+ //mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));
Rect bounds = new Rect();
- mPaint.getTextBounds(value.getLabel(), 0, value.getLabel().length(), bounds);
- mPaint.setStyle(Paint.Style.STROKE);
+ //mPaint.getTextBounds(value.getLabel(), 0, value.getLabel().length(), bounds);
+ mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
float px = endX;
float py = graphTop + 50;
- canvas.drawText(value.getLabel(), px, py, mPaint);
+ //canvas.drawText(value.getLabel(), px, py, mPaint);
mPaint.setStrokeWidth(5);
- canvas.drawRect(px - 3, bounds.top + py - 3, xpluslength + 3, bounds.bottom + py + 3, mPaint);
+ canvas.drawRect(px - 3, graphTop, xpluslength + 3, graphTop + graphHeight, mPaint);
}
} else if (value.getShape() == Shape.GENERALWITHDURATION) {
mPaint.setStrokeWidth(0);
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Persistentnotification/DummyService.java b/app/src/main/java/info/nightscout/androidaps/plugins/Persistentnotification/DummyService.java
new file mode 100644
index 0000000000..fad1147dfc
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Persistentnotification/DummyService.java
@@ -0,0 +1,31 @@
+package info.nightscout.androidaps.plugins.Persistentnotification;
+
+import android.app.Notification;
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+import android.support.annotation.Nullable;
+
+/**
+ * Keeps AndroidAPS in foreground state, so it won't be terminated by Android nor get restricted by the background execution limits
+ */
+public class DummyService extends Service {
+ @Nullable
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ Notification notification = PersistentNotificationPlugin.getPlugin().updateNotification();
+ if (notification != null)
+ startForeground(PersistentNotificationPlugin.ONGOING_NOTIFICATION_ID, notification);
+ return START_STICKY;
+ }
+
+ @Override
+ public void onDestroy() {
+ stopForeground(true);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Persistentnotification/PersistentNotificationPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Persistentnotification/PersistentNotificationPlugin.java
index 5f6d50273a..3fc7371311 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Persistentnotification/PersistentNotificationPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Persistentnotification/PersistentNotificationPlugin.java
@@ -1,6 +1,7 @@
package info.nightscout.androidaps.plugins.Persistentnotification;
import android.annotation.SuppressLint;
+import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
@@ -35,7 +36,6 @@ import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
-import info.nightscout.androidaps.plugins.IobCobCalculator.CobInfo;
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.utils.DecimalFormatter;
@@ -46,9 +46,16 @@ import info.nightscout.utils.DecimalFormatter;
public class PersistentNotificationPlugin extends PluginBase {
+ private static PersistentNotificationPlugin plugin;
+
+ public static PersistentNotificationPlugin getPlugin() {
+ if (plugin == null) plugin = new PersistentNotificationPlugin(MainApp.instance());
+ return plugin;
+ }
+
public static final String CHANNEL_ID = "AndroidAPS-Ongoing";
- private static final int ONGOING_NOTIFICATION_ID = 4711;
+ public static final int ONGOING_NOTIFICATION_ID = 4711;
private final Context ctx;
public PersistentNotificationPlugin(Context ctx) {
@@ -57,6 +64,7 @@ public class PersistentNotificationPlugin extends PluginBase {
.neverVisible(true)
.pluginName(R.string.ongoingnotificaction)
.enableByDefault(true)
+ .alwaysEnabled(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
.description(R.string.description_persistent_notification)
);
this.ctx = ctx;
@@ -66,7 +74,7 @@ public class PersistentNotificationPlugin extends PluginBase {
protected void onStart() {
MainApp.bus().register(this);
createNotificationChannel();
- updateNotification();
+ triggerNotificationUpdate();
super.onStart();
}
@@ -85,20 +93,22 @@ public class PersistentNotificationPlugin extends PluginBase {
@Override
protected void onStop() {
MainApp.bus().unregister(this);
- NotificationManager mNotificationManager =
- (NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE);
- mNotificationManager.cancel(ONGOING_NOTIFICATION_ID);
+ MainApp.instance().stopService(new Intent(MainApp.instance(), DummyService.class));
}
- private void updateNotification() {
+ private void triggerNotificationUpdate() {
+ MainApp.instance().startService(new Intent(MainApp.instance(), DummyService.class));
+ }
+
+ Notification updateNotification() {
if (!isEnabled(PluginType.GENERAL)) {
- return;
+ return null;
}
String line1 = "";
if (MainApp.getConfigBuilder().getActiveProfileInterface() == null || !MainApp.getConfigBuilder().isProfileValid("Notificiation"))
- return;
+ return null;
String units = MainApp.getConfigBuilder().getProfileUnits();
@@ -166,7 +176,7 @@ public class PersistentNotificationPlugin extends PluginBase {
android.app.Notification notification = builder.build();
mNotificationManager.notify(ONGOING_NOTIFICATION_ID, notification);
-
+ return notification;
}
private String deltastring(double deltaMGDL, double deltaMMOL, String units) {
@@ -188,42 +198,42 @@ public class PersistentNotificationPlugin extends PluginBase {
@Subscribe
public void onStatusEvent(final EventPreferenceChange ev) {
- updateNotification();
+ triggerNotificationUpdate();
}
@Subscribe
public void onStatusEvent(final EventTreatmentChange ev) {
- updateNotification();
+ triggerNotificationUpdate();
}
@Subscribe
public void onStatusEvent(final EventTempBasalChange ev) {
- updateNotification();
+ triggerNotificationUpdate();
}
@Subscribe
public void onStatusEvent(final EventExtendedBolusChange ev) {
- updateNotification();
+ triggerNotificationUpdate();
}
@Subscribe
public void onStatusEvent(final EventNewBG ev) {
- updateNotification();
+ triggerNotificationUpdate();
}
@Subscribe
public void onStatusEvent(final EventNewBasalProfile ev) {
- updateNotification();
+ triggerNotificationUpdate();
}
@Subscribe
public void onStatusEvent(final EventInitializationChanged ev) {
- updateNotification();
+ triggerNotificationUpdate();
}
@Subscribe
public void onStatusEvent(final EventRefreshOverview ev) {
- updateNotification();
+ triggerNotificationUpdate();
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfileFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfileFragment.java
index 39d0f9829d..18060ba1ec 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfileFragment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfileFragment.java
@@ -132,7 +132,7 @@ public class LocalProfileFragment extends SubscriberFragment {
LocalProfilePlugin.getPlugin().loadSettings();
mgdlView.setChecked(LocalProfilePlugin.getPlugin().mgdl);
mmolView.setChecked(LocalProfilePlugin.getPlugin().mmol);
- diaView.setParams(LocalProfilePlugin.getPlugin().dia, 2d, 48d, 0.1d, new DecimalFormat("0.0"), false, textWatch);
+ diaView.setParams(LocalProfilePlugin.getPlugin().dia, 5d, 12d, 0.1d, new DecimalFormat("0.0"), false, textWatch);
icView = new TimeListEdit(getContext(), layout, R.id.localprofile_ic, MainApp.gs(R.string.nsprofileview_ic_label) + ":", LocalProfilePlugin.getPlugin().ic, null, 0.5, 50d, 0.1d, new DecimalFormat("0.0"), save);
isfView = new TimeListEdit(getContext(), layout, R.id.localprofile_isf, MainApp.gs(R.string.nsprofileview_isf_label) + ":", LocalProfilePlugin.getPlugin().isf, null, 0.5, 500d, 0.1d, new DecimalFormat("0.0"), save);
basalView = new TimeListEdit(getContext(), layout, R.id.localprofile_basal, MainApp.gs(R.string.nsprofileview_basal_label) + ": " + getSumLabel(), LocalProfilePlugin.getPlugin().basal, null, pumpDescription.basalMinimumRate, 10, 0.01d, new DecimalFormat("0.00"), save);
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfileFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfileFragment.java
index dca9b183a3..6cc9fdf98e 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfileFragment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfileFragment.java
@@ -79,11 +79,14 @@ public class NSProfileFragment extends SubscriberFragment {
public void onStatusEvent(final EventNSProfileUpdateGUI ev) {
Activity activity = getActivity();
if (activity != null)
- activity.runOnUiThread(() -> updateGUI());
+ activity.runOnUiThread(() -> { synchronized (NSProfileFragment.this) { updateGUI(); } });
}
@Override
protected void updateGUI() {
+ if (noProfile == null || profileSpinner == null)
+ return;
+
ProfileStore profileStore = NSProfilePlugin.getPlugin().getProfile();
if (profileStore != null) {
ArrayList profileList = profileStore.getProfileList();
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java
index d4aa0d7da8..2555eac427 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java
@@ -1,8 +1,11 @@
package info.nightscout.androidaps.plugins.PumpCombo;
+import android.content.DialogInterface;
import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
+import android.support.v4.app.FragmentActivity;
+import android.support.v7.app.AlertDialog;
import com.crashlytics.android.answers.CustomEvent;
@@ -28,6 +31,7 @@ import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TDD;
import info.nightscout.androidaps.db.TemporaryBasal;
+import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment;
import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.androidaps.events.EventInitializationChanged;
import info.nightscout.androidaps.events.EventRefreshOverview;
@@ -194,6 +198,32 @@ public class ComboPlugin extends PluginBase implements PumpInterface, Constraint
return MainApp.gs(R.string.combo_pump_state_running);
}
+ @Override
+ public void switchAllowed(ConfigBuilderFragment.PluginViewHolder.PluginSwitcher pluginSwitcher, FragmentActivity context) {
+ boolean allowHardwarePump = SP.getBoolean("allow_hardware_pump", false);
+ if (allowHardwarePump || context == null){
+ pluginSwitcher.invoke();
+ } else {
+ AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setMessage(R.string.allow_hardware_pump_text)
+ .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ pluginSwitcher.invoke();
+ SP.putBoolean("allow_hardware_pump", true);
+ log.debug("First time HW pump allowed!");
+ }
+ })
+ .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ pluginSwitcher.cancel();
+ log.debug("User does not allow switching to HW pump!");
+ }
+ });
+ builder.create().show();
+ }
+ }
+
+
@Override
public boolean isInitialized() {
return pump.initialized;
@@ -354,6 +384,11 @@ public class ComboPlugin extends PluginBase implements PumpInterface, Constraint
// trigger a connect, which will update state and check history
CommandResult stateResult = runCommand(null, 1, ruffyScripter::readPumpState);
+ if (stateResult.invalidSetup) {
+ MainApp.bus().post(new EventNewNotification(
+ new Notification(Notification.COMBO_PUMP_ALARM, MainApp.gs(R.string.combo_invalid_setup), Notification.URGENT)));
+ return;
+ }
if (!stateResult.success) {
return;
}
@@ -1374,7 +1409,7 @@ public class ComboPlugin extends PluginBase implements PumpInterface, Constraint
private boolean validBasalRateProfileSelectedOnPump = true;
@Override
- public Constraint isLoopInvokationAllowed(Constraint value) {
+ public Constraint isLoopInvocationAllowed(Constraint value) {
if (!validBasalRateProfileSelectedOnPump)
value.set(false, MainApp.gs(R.string.novalidbasalrate), this);
return value;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ruffyscripter/CommandResult.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ruffyscripter/CommandResult.java
index 9da5d4d6fa..b595d13d28 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ruffyscripter/CommandResult.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ruffyscripter/CommandResult.java
@@ -5,10 +5,11 @@ import android.support.annotation.Nullable;
import java.util.LinkedList;
import java.util.List;
-import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.Bolus;
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.PumpHistory;
public class CommandResult {
+ /** True if a condition indicating a broken pump setup/configuration is detected */
+ public boolean invalidSetup;
/** Whether the command was executed successfully. */
public boolean success;
/** State of the pump *after* command execution. */
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ruffyscripter/RuffyScripter.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ruffyscripter/RuffyScripter.java
index 1e7e542e5f..5b569e479e 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ruffyscripter/RuffyScripter.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ruffyscripter/RuffyScripter.java
@@ -281,10 +281,10 @@ public class RuffyScripter implements RuffyCommands {
log.debug("Executing " + cmd + " took " + (cmdEndTime - cmdStartTime) + "ms");
} catch (CommandException e) {
log.error("CommandException running command", e);
- activeCmd.getResult().success = false;
+ cmd.getResult().success = false;
} catch (Exception e) {
log.error("Unexpected exception running cmd", e);
- activeCmd.getResult().success = false;
+ cmd.getResult().success = false;
}
}, cmd.getClass().getSimpleName());
long executionStart = System.currentTimeMillis();
@@ -328,6 +328,7 @@ public class RuffyScripter implements RuffyCommands {
if (unparsableMenuEncountered) {
log.error("UnparsableMenuEncountered flagged, aborting command");
cmdThread.interrupt();
+ activeCmd.getResult().invalidSetup = true;
activeCmd.getResult().success = false;
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ruffyscripter/commands/ReadQuickInfoCommand.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ruffyscripter/commands/ReadQuickInfoCommand.java
index e55fb4d010..654861fddb 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ruffyscripter/commands/ReadQuickInfoCommand.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ruffyscripter/commands/ReadQuickInfoCommand.java
@@ -39,17 +39,19 @@ public class ReadQuickInfoCommand extends BaseCommand {
// read bolus records
int totalRecords = (int) scripter.getCurrentMenu().getAttribute(MenuAttribute.TOTAL_RECORD);
int record = (int) scripter.getCurrentMenu().getAttribute(MenuAttribute.CURRENT_RECORD);
- while (true) {
- bolusHistory.add(readBolusRecord());
- if (bolusHistory.size() == numberOfBolusRecordsToRetrieve || record == totalRecords) {
- break;
+ if (record > 0) {
+ while (true) {
+ bolusHistory.add(readBolusRecord());
+ if (bolusHistory.size() == numberOfBolusRecordsToRetrieve || record == totalRecords) {
+ break;
+ }
+ // advance to next record
+ scripter.pressDownKey();
+ while (record == (int) scripter.getCurrentMenu().getAttribute(MenuAttribute.CURRENT_RECORD)) {
+ scripter.waitForScreenUpdate();
+ }
+ record = (int) scripter.getCurrentMenu().getAttribute(MenuAttribute.CURRENT_RECORD);
}
- // advance to next record
- scripter.pressDownKey();
- while (record == (int) scripter.getCurrentMenu().getAttribute(MenuAttribute.CURRENT_RECORD)) {
- scripter.waitForScreenUpdate();
- }
- record = (int) scripter.getCurrentMenu().getAttribute(MenuAttribute.CURRENT_RECORD);
}
if (log.isDebugEnabled()) {
if (!result.history.bolusHistory.isEmpty()) {
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRFragment.java
index 8d18ca4f04..7288602d65 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRFragment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRFragment.java
@@ -216,74 +216,96 @@ public class DanaRFragment extends SubscriberFragment {
@SuppressLint("SetTextI18n")
@Override
public void run() {
- DanaRPump pump = DanaRPump.getInstance();
- if (pump.lastConnection != 0) {
- Long agoMsec = System.currentTimeMillis() - pump.lastConnection;
- int agoMin = (int) (agoMsec / 60d / 1000d);
- lastConnectionView.setText(DateUtil.timeString(pump.lastConnection) + " (" + String.format(MainApp.gs(R.string.minago), agoMin) + ")");
- SetWarnColor.setColor(lastConnectionView, agoMin, 16d, 31d);
- }
- if (pump.lastBolusTime.getTime() != 0) {
- Long agoMsec = System.currentTimeMillis() - pump.lastBolusTime.getTime();
- double agoHours = agoMsec / 60d / 60d / 1000d;
- if (agoHours < 6) // max 6h back
- lastBolusView.setText(DateUtil.timeString(pump.lastBolusTime) + " " + DateUtil.sinceString(pump.lastBolusTime.getTime()) + " " + DecimalFormatter.to2Decimal(DanaRPump.getInstance().lastBolusAmount) + " U");
- else lastBolusView.setText("");
- }
+ synchronized(DanaRFragment.this) {
+ if (!isBound()) return;
- dailyUnitsView.setText(DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits + " U");
- SetWarnColor.setColor(dailyUnitsView, pump.dailyTotalUnits, pump.maxDailyTotalUnits * 0.75d, pump.maxDailyTotalUnits * 0.9d);
- basaBasalRateView.setText("( " + (pump.activeProfile + 1) + " ) " + DecimalFormatter.to2Decimal(ConfigBuilderPlugin.getActivePump().getBaseBasalRate()) + " U/h");
- // DanaRPlugin, DanaRKoreanPlugin
- if (ConfigBuilderPlugin.getActivePump().isFakingTempsByExtendedBoluses()) {
- if (TreatmentsPlugin.getPlugin().isInHistoryRealTempBasalInProgress()) {
- tempBasalView.setText(TreatmentsPlugin.getPlugin().getRealTempBasalFromHistory(System.currentTimeMillis()).toStringFull());
- } else {
- tempBasalView.setText("");
+ DanaRPump pump = DanaRPump.getInstance();
+ if (pump.lastConnection != 0) {
+ Long agoMsec = System.currentTimeMillis() - pump.lastConnection;
+ int agoMin = (int) (agoMsec / 60d / 1000d);
+ lastConnectionView.setText(DateUtil.timeString(pump.lastConnection) + " (" + String.format(MainApp.gs(R.string.minago), agoMin) + ")");
+ SetWarnColor.setColor(lastConnectionView, agoMin, 16d, 31d);
}
- } else {
- // v2 plugin
- if (TreatmentsPlugin.getPlugin().isTempBasalInProgress()) {
- tempBasalView.setText(TreatmentsPlugin.getPlugin().getTempBasalFromHistory(System.currentTimeMillis()).toStringFull());
- } else {
- tempBasalView.setText("");
+ if (pump.lastBolusTime.getTime() != 0) {
+ Long agoMsec = System.currentTimeMillis() - pump.lastBolusTime.getTime();
+ double agoHours = agoMsec / 60d / 60d / 1000d;
+ if (agoHours < 6) // max 6h back
+ lastBolusView.setText(DateUtil.timeString(pump.lastBolusTime) + " " + DateUtil.sinceString(pump.lastBolusTime.getTime()) + " " + DecimalFormatter.to2Decimal(DanaRPump.getInstance().lastBolusAmount) + " U");
+ else lastBolusView.setText("");
}
- }
- ExtendedBolus activeExtendedBolus = TreatmentsPlugin.getPlugin().getExtendedBolusFromHistory(System.currentTimeMillis());
- if (activeExtendedBolus != null) {
- extendedBolusView.setText(activeExtendedBolus.toString());
- } else {
- extendedBolusView.setText("");
- }
- reservoirView.setText(DecimalFormatter.to0Decimal(pump.reservoirRemainingUnits) + " / 300 U");
- SetWarnColor.setColorInverse(reservoirView, pump.reservoirRemainingUnits, 50d, 20d);
- batteryView.setText("{fa-battery-" + (pump.batteryRemaining / 25) + "}");
- SetWarnColor.setColorInverse(batteryView, pump.batteryRemaining, 51d, 26d);
- iobView.setText(pump.iob + " U");
- if (pump.model != 0 || pump.protocol != 0 || pump.productCode != 0) {
- firmwareView.setText(String.format(MainApp.gs(R.string.danar_model), pump.model, pump.protocol, pump.productCode));
- } else {
- firmwareView.setText("OLD");
- }
- basalStepView.setText("" + pump.basalStep);
- bolusStepView.setText("" + pump.bolusStep);
- serialNumberView.setText("" + pump.serialNumber);
- if (queueView != null) {
- Spanned status = ConfigBuilderPlugin.getCommandQueue().spannedStatus();
- if (status.toString().equals("")) {
- queueView.setVisibility(View.GONE);
+
+ dailyUnitsView.setText(DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits + " U");
+ SetWarnColor.setColor(dailyUnitsView, pump.dailyTotalUnits, pump.maxDailyTotalUnits * 0.75d, pump.maxDailyTotalUnits * 0.9d);
+ basaBasalRateView.setText("( " + (pump.activeProfile + 1) + " ) " + DecimalFormatter.to2Decimal(ConfigBuilderPlugin.getActivePump().getBaseBasalRate()) + " U/h");
+ // DanaRPlugin, DanaRKoreanPlugin
+ if (ConfigBuilderPlugin.getActivePump().isFakingTempsByExtendedBoluses()) {
+ if (TreatmentsPlugin.getPlugin().isInHistoryRealTempBasalInProgress()) {
+ tempBasalView.setText(TreatmentsPlugin.getPlugin().getRealTempBasalFromHistory(System.currentTimeMillis()).toStringFull());
+ } else {
+ tempBasalView.setText("");
+ }
} else {
- queueView.setVisibility(View.VISIBLE);
- queueView.setText(status);
+ // v2 plugin
+ if (TreatmentsPlugin.getPlugin().isTempBasalInProgress()) {
+ tempBasalView.setText(TreatmentsPlugin.getPlugin().getTempBasalFromHistory(System.currentTimeMillis()).toStringFull());
+ } else {
+ tempBasalView.setText("");
+ }
+ }
+ ExtendedBolus activeExtendedBolus = TreatmentsPlugin.getPlugin().getExtendedBolusFromHistory(System.currentTimeMillis());
+ if (activeExtendedBolus != null) {
+ extendedBolusView.setText(activeExtendedBolus.toString());
+ } else {
+ extendedBolusView.setText("");
+ }
+ reservoirView.setText(DecimalFormatter.to0Decimal(pump.reservoirRemainingUnits) + " / 300 U");
+ SetWarnColor.setColorInverse(reservoirView, pump.reservoirRemainingUnits, 50d, 20d);
+ batteryView.setText("{fa-battery-" + (pump.batteryRemaining / 25) + "}");
+ SetWarnColor.setColorInverse(batteryView, pump.batteryRemaining, 51d, 26d);
+ iobView.setText(pump.iob + " U");
+ if (pump.model != 0 || pump.protocol != 0 || pump.productCode != 0) {
+ firmwareView.setText(String.format(MainApp.gs(R.string.danar_model), pump.model, pump.protocol, pump.productCode));
+ } else {
+ firmwareView.setText("OLD");
+ }
+ basalStepView.setText("" + pump.basalStep);
+ bolusStepView.setText("" + pump.bolusStep);
+ serialNumberView.setText("" + pump.serialNumber);
+ if (queueView != null) {
+ Spanned status = ConfigBuilderPlugin.getCommandQueue().spannedStatus();
+ if (status.toString().equals("")) {
+ queueView.setVisibility(View.GONE);
+ } else {
+ queueView.setVisibility(View.VISIBLE);
+ queueView.setText(status);
+ }
+ }
+ //hide user options button if not an RS pump
+ boolean isKorean = MainApp.getSpecificPlugin(DanaRKoreanPlugin.class) != null && MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).isEnabled(PluginType.PUMP);
+ if (isKorean) {
+ danar_user_options.setVisibility(View.GONE);
}
- }
- //hide user options button if not an RS pump
- boolean isKorean = MainApp.getSpecificPlugin(DanaRKoreanPlugin.class) != null && MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).isEnabled(PluginType.PUMP);
- if (isKorean ) {
- danar_user_options.setVisibility(View.GONE);
}
}
});
}
+ private boolean isBound() {
+ return lastConnectionView != null
+ && lastBolusView != null
+ && dailyUnitsView != null
+ && basaBasalRateView != null
+ && tempBasalView != null
+ && extendedBolusView != null
+ && reservoirView != null
+ && batteryView != null
+ && iobView != null
+ && firmwareView != null
+ && basalStepView != null
+ && bolusStepView != null
+ && serialNumberView != null
+ && danar_user_options != null
+ && queueView != null;
+ }
+
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java
index b1b0f3d9ce..77146738d9 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java
@@ -2,9 +2,12 @@ package info.nightscout.androidaps.plugins.PumpDanaR;
import android.content.ComponentName;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
+import android.support.v4.app.FragmentActivity;
+import android.support.v7.app.AlertDialog;
import com.squareup.otto.Subscribe;
@@ -18,6 +21,7 @@ import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.TemporaryBasal;
+import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStartWithSpeed;
import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.androidaps.events.EventAppExit;
@@ -78,6 +82,31 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
pumpDescription.needsManualTDDLoad = true;
}
+ @Override
+ public void switchAllowed(ConfigBuilderFragment.PluginViewHolder.PluginSwitcher pluginSwitcher, FragmentActivity context) {
+ boolean allowHardwarePump = SP.getBoolean("allow_hardware_pump", false);
+ if (allowHardwarePump || context == null){
+ pluginSwitcher.invoke();
+ } else {
+ AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setMessage(R.string.allow_hardware_pump_text)
+ .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ pluginSwitcher.invoke();
+ SP.putBoolean("allow_hardware_pump", true);
+ log.debug("First time HW pump allowed!");
+ }
+ })
+ .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ pluginSwitcher.cancel();
+ log.debug("User does not allow switching to HW pump!");
+ }
+ });
+ builder.create().show();
+ }
+ }
+
@Override
protected void onStart() {
Context context = MainApp.instance().getApplicationContext();
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPlugin.java
index b7b100a3a6..9ce1a6409a 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPlugin.java
@@ -2,9 +2,12 @@ package info.nightscout.androidaps.plugins.PumpDanaRKorean;
import android.content.ComponentName;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
+import android.support.v4.app.FragmentActivity;
+import android.support.v7.app.AlertDialog;
import com.squareup.otto.Subscribe;
@@ -23,6 +26,7 @@ import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.interfaces.PumpDescription;
+import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment;
import info.nightscout.androidaps.plugins.PumpDanaR.AbstractDanaRPlugin;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStart;
import info.nightscout.androidaps.plugins.PumpDanaRKorean.services.DanaRKoreanExecutionService;
@@ -45,7 +49,8 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
}
public DanaRKoreanPlugin() {
- super();
+ pluginDescription.description(R.string.description_pump_dana_r_korean);
+
log = LoggerFactory.getLogger(DanaRKoreanPlugin.class);
useExtendedBoluses = SP.getBoolean("danar_useextended", false);
@@ -79,6 +84,32 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
pumpDescription.needsManualTDDLoad = true;
}
+ @Override
+ public void switchAllowed(ConfigBuilderFragment.PluginViewHolder.PluginSwitcher pluginSwitcher, FragmentActivity context) {
+ boolean allowHardwarePump = SP.getBoolean("allow_hardware_pump", false);
+ if (allowHardwarePump || context == null){
+ pluginSwitcher.invoke();
+ } else {
+ AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setMessage(R.string.allow_hardware_pump_text)
+ .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ pluginSwitcher.invoke();
+ SP.putBoolean("allow_hardware_pump", true);
+ log.debug("First time HW pump allowed!");
+ }
+ })
+ .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ pluginSwitcher.cancel();
+ log.debug("User does not allow switching to HW pump!");
+ }
+ });
+ builder.create().show();
+ }
+ }
+
+
@Override
protected void onStart() {
Context context = MainApp.instance().getApplicationContext();
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPlugin.java
index c2c438b50c..96b6f393cd 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPlugin.java
@@ -2,10 +2,13 @@ package info.nightscout.androidaps.plugins.PumpDanaRS;
import android.content.ComponentName;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.annotation.Nullable;
+import android.support.v4.app.FragmentActivity;
+import android.support.v7.app.AlertDialog;
import com.squareup.otto.Subscribe;
@@ -36,6 +39,7 @@ import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.interfaces.ProfileInterface;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface;
+import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment;
import info.nightscout.androidaps.plugins.ConfigBuilder.DetailedBolusInfoStorage;
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
@@ -147,6 +151,31 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
MainApp.bus().unregister(this);
}
+ @Override
+ public void switchAllowed(ConfigBuilderFragment.PluginViewHolder.PluginSwitcher pluginSwitcher, FragmentActivity context) {
+ boolean allowHardwarePump = SP.getBoolean("allow_hardware_pump", false);
+ if (allowHardwarePump || context == null){
+ pluginSwitcher.invoke();
+ } else {
+ AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setMessage(R.string.allow_hardware_pump_text)
+ .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ pluginSwitcher.invoke();
+ SP.putBoolean("allow_hardware_pump", true);
+ log.debug("First time HW pump allowed!");
+ }
+ })
+ .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ pluginSwitcher.cancel();
+ log.debug("User does not allow switching to HW pump!");
+ }
+ });
+ builder.create().show();
+ }
+ }
+
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceDisconnected(ComponentName name) {
@@ -494,8 +523,12 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
// Convert duration from minutes to hours
if (Config.logPumpActions)
log.debug("setTempBasalAbsolute: Setting temp basal " + percentRate + "% for " + durationInMinutes + " mins (doLowTemp || doHighTemp)");
- // use special APS temp basal call ... 100+/15min .... 100-/30min
- result = setHighTempBasalPercent(percentRate);
+ if (percentRate == 0 && durationInMinutes > 30) {
+ result = setTempBasalPercent(percentRate, durationInMinutes, profile, false);
+ } else {
+ // use special APS temp basal call ... 100+/15min .... 100-/30min
+ result = setHighTempBasalPercent(percentRate);
+ }
if (!result.success) {
log.error("setTempBasalAbsolute: Failed to set hightemp basal");
return result;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/BLEComm.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/BLEComm.java
index b552026279..5b6afb8089 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/BLEComm.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/BLEComm.java
@@ -20,8 +20,6 @@ import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import info.nightscout.androidaps.MainApp;
@@ -45,11 +43,11 @@ public class BLEComm {
private static final long WRITE_DELAY_MILLIS = 50;
- public static String UART_READ_UUID = "0000fff1-0000-1000-8000-00805f9b34fb";
- public static String UART_WRITE_UUID = "0000fff2-0000-1000-8000-00805f9b34fb";
+ private static String UART_READ_UUID = "0000fff1-0000-1000-8000-00805f9b34fb";
+ private static String UART_WRITE_UUID = "0000fff2-0000-1000-8000-00805f9b34fb";
- private byte PACKET_START_BYTE = (byte) 0xA5;
- private byte PACKET_END_BYTE = (byte) 0x5A;
+ private final byte PACKET_START_BYTE = (byte) 0xA5;
+ private final byte PACKET_END_BYTE = (byte) 0x5A;
private static BLEComm instance = null;
public static BLEComm getInstance(DanaRSService service) {
@@ -58,16 +56,13 @@ public class BLEComm {
return instance;
}
- private final ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor();
private ScheduledFuture> scheduledDisconnection = null;
private DanaRS_Packet processsedMessage = null;
- private ArrayList mSendQueue = new ArrayList<>();
+ private final ArrayList mSendQueue = new ArrayList<>();
private BluetoothManager mBluetoothManager = null;
private BluetoothAdapter mBluetoothAdapter = null;
- private BluetoothDevice mBluetoothDevice = null;
- private String mBluetoothDeviceAddress = null;
private String mBluetoothDeviceName = null;
private BluetoothGatt mBluetoothGatt = null;
@@ -79,7 +74,7 @@ public class BLEComm {
private DanaRSService service;
- BLEComm(DanaRSService service) {
+ private BLEComm(DanaRSService service) {
this.service = service;
initialize();
}
@@ -138,15 +133,13 @@ public class BLEComm {
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
if (device == null) {
- log.debug("Device not found. Unable to connect.");
+ log.debug("Device not found. Unable to connect from: " + from);
return false;
}
- log.debug("Trying to create a new connection.");
+ log.debug("Trying to create a new connection from: " + from);
mBluetoothGatt = device.connectGatt(service.getApplicationContext(), false, mGattCallback);
setCharacteristicNotification(getUARTReadBTGattChar(), true);
- mBluetoothDevice = device;
- mBluetoothDeviceAddress = address;
mBluetoothDeviceName = device.getName();
return true;
}
@@ -174,7 +167,7 @@ public class BLEComm {
SystemClock.sleep(2000);
}
- public void close() {
+ public synchronized void close() {
log.debug("BluetoothAdapter close");
if (mBluetoothGatt == null) {
return;
@@ -184,15 +177,8 @@ public class BLEComm {
mBluetoothGatt = null;
}
- public BluetoothDevice getConnectDevice() {
- return mBluetoothDevice;
- }
- public String getConnectDeviceAddress() {
- return mBluetoothDeviceAddress;
- }
-
- public String getConnectDeviceName() {
+ private String getConnectDeviceName() {
return mBluetoothDeviceName;
}
@@ -229,33 +215,25 @@ public class BLEComm {
public void onCharacteristicChanged(BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
log.debug("onCharacteristicChanged" + (characteristic != null ? ":" + DanaRS_Packet.toHexString(characteristic.getValue()) : ""));
addToReadBuffer(characteristic.getValue());
- new Thread(new Runnable() {
- @Override
- public void run() {
- readDataParsing();
- }
- }).start();
+ new Thread(() -> readDataParsing()).start();
}
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
log.debug("onCharacteristicWrite" + (characteristic != null ? ":" + DanaRS_Packet.toHexString(characteristic.getValue()) : ""));
- new Thread(new Runnable() {
- @Override
- public void run() {
- synchronized (mSendQueue) {
- // after message sent, check if there is the rest of the message waiting and send it
- if (mSendQueue.size() > 0) {
- byte[] bytes = mSendQueue.get(0);
- mSendQueue.remove(0);
- writeCharacteristic_NO_RESPONSE(getUARTWriteBTGattChar(), bytes);
- }
+ new Thread(() -> {
+ synchronized (mSendQueue) {
+ // after message sent, check if there is the rest of the message waiting and send it
+ if (mSendQueue.size() > 0) {
+ byte[] bytes = mSendQueue.get(0);
+ mSendQueue.remove(0);
+ writeCharacteristic_NO_RESPONSE(getUARTWriteBTGattChar(), bytes);
}
}
}).start();
}
};
- public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) {
+ private synchronized void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) {
log.debug("setCharacteristicNotification");
if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
log.debug("BluetoothAdapter not initialized_ERROR");
@@ -266,7 +244,7 @@ public class BLEComm {
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
}
- public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
+ public synchronized void readCharacteristic(BluetoothGattCharacteristic characteristic) {
log.debug("readCharacteristic");
if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
log.debug("BluetoothAdapter not initialized_ERROR");
@@ -277,41 +255,39 @@ public class BLEComm {
mBluetoothGatt.readCharacteristic(characteristic);
}
- public void writeCharacteristic_NO_RESPONSE(final BluetoothGattCharacteristic characteristic, final byte[] data) {
- new Thread(new Runnable() {
- public void run() {
- SystemClock.sleep(WRITE_DELAY_MILLIS);
+ private synchronized void writeCharacteristic_NO_RESPONSE(final BluetoothGattCharacteristic characteristic, final byte[] data) {
+ new Thread(() -> {
+ SystemClock.sleep(WRITE_DELAY_MILLIS);
- if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
- log.debug("BluetoothAdapter not initialized_ERROR");
- isConnecting = false;
- isConnected = false;
- return;
- }
-
- characteristic.setValue(data);
- characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
- log.debug("writeCharacteristic:" + DanaRS_Packet.toHexString(data));
- mBluetoothGatt.writeCharacteristic(characteristic);
+ if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
+ log.debug("BluetoothAdapter not initialized_ERROR");
+ isConnecting = false;
+ isConnected = false;
+ return;
}
+
+ characteristic.setValue(data);
+ characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
+ log.debug("writeCharacteristic:" + DanaRS_Packet.toHexString(data));
+ mBluetoothGatt.writeCharacteristic(characteristic);
}).start();
}
- public BluetoothGattCharacteristic getUARTReadBTGattChar() {
+ private BluetoothGattCharacteristic getUARTReadBTGattChar() {
if (UART_Read == null) {
UART_Read = new BluetoothGattCharacteristic(UUID.fromString(UART_READ_UUID), BluetoothGattCharacteristic.PROPERTY_READ | BluetoothGattCharacteristic.PROPERTY_NOTIFY, 0);
}
return UART_Read;
}
- public BluetoothGattCharacteristic getUARTWriteBTGattChar() {
+ private BluetoothGattCharacteristic getUARTWriteBTGattChar() {
if (UART_Write == null) {
UART_Write = new BluetoothGattCharacteristic(UUID.fromString(UART_WRITE_UUID), BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE, 0);
}
return UART_Write;
}
- public List getSupportedGattServices() {
+ private List getSupportedGattServices() {
log.debug("getSupportedGattServices");
if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
log.debug("BluetoothAdapter not initialized_ERROR");
@@ -329,7 +305,7 @@ public class BLEComm {
if (gattServices == null) {
return;
}
- String uuid = null;
+ String uuid;
for (BluetoothGattService gattService : gattServices) {
List gattCharacteristics = gattService.getCharacteristics();
@@ -346,7 +322,7 @@ public class BLEComm {
}
}
- private byte[] readBuffer = new byte[1024];
+ private final byte[] readBuffer = new byte[1024];
private int bufferLength = 0;
private void addToReadBuffer(byte[] buffer) {
@@ -634,7 +610,7 @@ public class BLEComm {
writeCharacteristic_NO_RESPONSE(getUARTWriteBTGattChar(), bytes);
}
- protected void SendPumpCheck() {
+ private void SendPumpCheck() {
// 1st message sent to pump after connect
byte[] bytes = BleCommandUtil.getInstance().getEncryptedPacket(BleCommandUtil.DANAR_PACKET__OPCODE_ENCRYPTION__PUMP_CHECK, null, getConnectDeviceName());
log.debug(">>>>> " + "ENCRYPTION__PUMP_CHECK (0x00)" + " " + DanaRS_Packet.toHexString(bytes));
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/DanaRSService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/DanaRSService.java
index 63035d64d0..ff4203fd7b 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/DanaRSService.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/DanaRSService.java
@@ -19,6 +19,7 @@ import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
+import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity;
import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Option_Get_User_Option;
import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.androidaps.events.EventAppExit;
@@ -135,6 +136,37 @@ public class DanaRSService extends Service {
bleComm.sendMessage(new DanaRS_Packet_Bolus_Get_Step_Bolus_Information()); // last bolus, bolusStep, maxBolus
MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingtempbasalstatus)));
bleComm.sendMessage(new DanaRS_Packet_Basal_Get_Temporary_Basal_State());
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumptime)));
+ bleComm.sendMessage(new DanaRS_Packet_Option_Get_Pump_Time());
+
+ long timeDiff = (danaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L;
+ log.debug("Pump time difference: " + timeDiff + " seconds");
+ if (Math.abs(timeDiff) > 3) {
+ if (Math.abs(timeDiff) > 60*60*1.5) {
+ log.debug("Pump time difference: " + timeDiff + " seconds - large difference");
+ //If time-diff is very large, warn user until we can synchronize history readings properly
+ Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
+ i.putExtra("soundid", R.raw.error);
+ i.putExtra("status", MainApp.gs(R.string.largetimediff));
+ i.putExtra("title", MainApp.gs(R.string.largetimedifftitle));
+ i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ MainApp.instance().startActivity(i);
+
+ //deinitialize pump
+ danaRPump.lastConnection = 0;
+ MainApp.bus().post(new EventDanaRNewStatus());
+ MainApp.bus().post(new EventInitializationChanged());
+ return;
+ } else {
+ waitForWholeMinute(); // Dana can set only whole minute
+ // add 10sec to be sure we are over minute (will be cutted off anyway)
+ bleComm.sendMessage(new DanaRS_Packet_Option_Set_Pump_Time(new Date(DateUtil.now() + T.secs(10).msecs())));
+ bleComm.sendMessage(new DanaRS_Packet_Option_Get_Pump_Time());
+ timeDiff = (danaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L;
+ log.debug("Pump time difference: " + timeDiff + " seconds");
+ }
+ }
+ danaRPump.lastConnection = System.currentTimeMillis();
long now = System.currentTimeMillis();
if (danaRPump.lastSettingsRead + 60 * 60 * 1000L < now || !MainApp.getSpecificPlugin(DanaRSPlugin.class).isInitialized()) {
@@ -146,19 +178,7 @@ public class DanaRSService extends Service {
bleComm.sendMessage(new DanaRS_Packet_Basal_Get_Basal_Rate()); // basal profile, basalStep, maxBasal
bleComm.sendMessage(new DanaRS_Packet_Bolus_Get_Calculation_Information()); // target
bleComm.sendMessage(new DanaRS_Packet_Bolus_Get_CIR_CF_Array());
- MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumptime)));
- bleComm.sendMessage(new DanaRS_Packet_Option_Get_Pump_Time());
bleComm.sendMessage(new DanaRS_Packet_Option_Get_User_Option()); // Getting user options
- long timeDiff = (danaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L;
- log.debug("Pump time difference: " + timeDiff + " seconds");
- if (Math.abs(timeDiff) > 3) {
- waitForWholeMinute(); // Dana can set only whole minute
- // add 10sec to be sure we are over minute (will be cutted off anyway)
- bleComm.sendMessage(new DanaRS_Packet_Option_Set_Pump_Time(new Date(DateUtil.now() + T.secs(10).msecs())));
- bleComm.sendMessage(new DanaRS_Packet_Option_Get_Pump_Time());
- timeDiff = (danaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L;
- log.debug("Pump time difference: " + timeDiff + " seconds");
- }
danaRPump.lastSettingsRead = now;
}
@@ -183,6 +203,13 @@ public class DanaRSService extends Service {
}
public PumpEnactResult loadEvents() {
+
+ if(!MainApp.getSpecificPlugin(DanaRSPlugin.class).isInitialized()){
+ PumpEnactResult result = new PumpEnactResult().success(false);
+ result.comment = "pump not initialized";
+ return result;
+ }
+
DanaRS_Packet_APS_History_Events msg;
if (lastHistoryFetched == 0) {
msg = new DanaRS_Packet_APS_History_Events(0);
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java
index b4004fecb3..c88d62ecc7 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java
@@ -2,9 +2,12 @@ package info.nightscout.androidaps.plugins.PumpDanaRv2;
import android.content.ComponentName;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
+import android.support.v4.app.FragmentActivity;
+import android.support.v7.app.AlertDialog;
import com.squareup.otto.Subscribe;
@@ -20,6 +23,7 @@ import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.events.EventAppExit;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.PumpDescription;
+import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment;
import info.nightscout.androidaps.plugins.ConfigBuilder.DetailedBolusInfoStorage;
import info.nightscout.androidaps.plugins.PumpDanaR.AbstractDanaRPlugin;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStartWithSpeed;
@@ -44,6 +48,8 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin {
}
private DanaRv2Plugin() {
+ pluginDescription.description(R.string.description_pump_dana_r_v2);
+
log = LoggerFactory.getLogger(DanaRv2Plugin.class);
useExtendedBoluses = false;
@@ -138,6 +144,31 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin {
return pump.lastConnection > 0 && pump.maxBasal > 0;
}
+ @Override
+ public void switchAllowed(ConfigBuilderFragment.PluginViewHolder.PluginSwitcher pluginSwitcher, FragmentActivity context) {
+ boolean allowHardwarePump = SP.getBoolean("allow_hardware_pump", false);
+ if (allowHardwarePump || context == null){
+ pluginSwitcher.invoke();
+ } else {
+ AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setMessage(R.string.allow_hardware_pump_text)
+ .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ pluginSwitcher.invoke();
+ SP.putBoolean("allow_hardware_pump", true);
+ log.debug("First time HW pump allowed!");
+ }
+ })
+ .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ pluginSwitcher.cancel();
+ log.debug("User does not allow switching to HW pump!");
+ }
+ });
+ builder.create().show();
+ }
+ }
+
// Pump interface
@Override
public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) {
@@ -266,8 +297,12 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin {
// Convert duration from minutes to hours
if (Config.logPumpActions)
log.debug("setTempBasalAbsolute: Setting temp basal " + percentRate + "% for " + durationInMinutes + " mins (doLowTemp || doHighTemp)");
- // use special APS temp basal call ... 100+/15min .... 100-/30min
- result = setHighTempBasalPercent(percentRate);
+ if (percentRate == 0 && durationInMinutes > 30) {
+ result = setTempBasalPercent(percentRate, durationInMinutes, profile, false);
+ } else {
+ // use special APS temp basal call ... 100+/15min .... 100-/30min
+ result = setHighTempBasalPercent(percentRate);
+ }
if (!result.success) {
log.error("setTempBasalAbsolute: Failed to set hightemp basal");
return result;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/services/DanaRv2ExecutionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/services/DanaRv2ExecutionService.java
index 1ada4c629d..6977139395 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/services/DanaRv2ExecutionService.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/services/DanaRv2ExecutionService.java
@@ -1,6 +1,7 @@
package info.nightscout.androidaps.plugins.PumpDanaRv2.services;
import android.bluetooth.BluetoothDevice;
+import android.content.Intent;
import android.content.IntentFilter;
import android.os.Binder;
import android.os.SystemClock;
@@ -18,6 +19,7 @@ import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
+import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingUserOptions;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetUserOptions;
import info.nightscout.androidaps.plugins.Treatments.Treatment;
@@ -187,6 +189,36 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
mSerialIOThread.sendMessage(tempStatusMsg);
MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingextendedbolusstatus)));
mSerialIOThread.sendMessage(exStatusMsg);
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumptime)));
+ mSerialIOThread.sendMessage(new MsgSettingPumpTime());
+ long timeDiff = (mDanaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L;
+ log.debug("Pump time difference: " + timeDiff + " seconds");
+ if (Math.abs(timeDiff) > 3) {
+ if (Math.abs(timeDiff) > 60*60*1.5) {
+ log.debug("Pump time difference: " + timeDiff + " seconds - large difference");
+ //If time-diff is very large, warn user until we can synchronize history readings properly
+ Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
+ i.putExtra("soundid", R.raw.error);
+ i.putExtra("status", MainApp.gs(R.string.largetimediff));
+ i.putExtra("title", MainApp.gs(R.string.largetimedifftitle));
+ i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ MainApp.instance().startActivity(i);
+
+ //deinitialize pump
+ mDanaRPump.lastConnection = 0;
+ MainApp.bus().post(new EventDanaRNewStatus());
+ MainApp.bus().post(new EventInitializationChanged());
+ return;
+ } else {
+ waitForWholeMinute(); // Dana can set only whole minute
+ // add 10sec to be sure we are over minute (will be cutted off anyway)
+ mSerialIOThread.sendMessage(new MsgSetTime(new Date(DateUtil.now() + T.secs(10).msecs())));
+ mSerialIOThread.sendMessage(new MsgSettingPumpTime());
+ timeDiff = (mDanaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L;
+ log.debug("Pump time difference: " + timeDiff + " seconds");
+ }
+ }
+ mDanaRPump.lastConnection = System.currentTimeMillis();
long now = System.currentTimeMillis();
if (mDanaRPump.lastSettingsRead + 60 * 60 * 1000L < now || !MainApp.getSpecificPlugin(DanaRv2Plugin.class).isInitialized()) {
@@ -202,18 +234,6 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
mSerialIOThread.sendMessage(new MsgSettingProfileRatios());
mSerialIOThread.sendMessage(new MsgSettingUserOptions());
mSerialIOThread.sendMessage(new MsgSettingProfileRatiosAll());
- MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumptime)));
- mSerialIOThread.sendMessage(new MsgSettingPumpTime());
- long timeDiff = (mDanaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L;
- log.debug("Pump time difference: " + timeDiff + " seconds");
- if (Math.abs(timeDiff) > 3) {
- waitForWholeMinute(); // Dana can set only whole minute
- // add 10sec to be sure we are over minute (will be cutted off anyway)
- mSerialIOThread.sendMessage(new MsgSetTime(new Date(DateUtil.now() + T.secs(10).msecs())));
- mSerialIOThread.sendMessage(new MsgSettingPumpTime());
- timeDiff = (mDanaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L;
- log.debug("Pump time difference: " + timeDiff + " seconds");
- }
mDanaRPump.lastSettingsRead = now;
}
@@ -425,6 +445,14 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
}
public PumpEnactResult loadEvents() {
+
+ if(!MainApp.getSpecificPlugin(DanaRv2Plugin.class).isInitialized()){
+ PumpEnactResult result = new PumpEnactResult().success(false);
+ result.comment = "pump not initialized";
+ return result;
+ }
+
+
if (!isConnected())
return new PumpEnactResult().success(false);
SystemClock.sleep(300);
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPlugin.java
index 2b31e4e3d7..a0e0199c79 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPlugin.java
@@ -1,5 +1,9 @@
package info.nightscout.androidaps.plugins.PumpInsight;
+import android.content.DialogInterface;
+import android.support.v4.app.FragmentActivity;
+import android.support.v7.app.AlertDialog;
+
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
@@ -27,6 +31,7 @@ import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface;
+import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment;
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress;
@@ -203,6 +208,31 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
return result;
}
+ @Override
+ public void switchAllowed(ConfigBuilderFragment.PluginViewHolder.PluginSwitcher pluginSwitcher, FragmentActivity context) {
+ boolean allowHardwarePump = SP.getBoolean("allow_hardware_pump", false);
+ if (allowHardwarePump || context == null){
+ pluginSwitcher.invoke();
+ } else {
+ AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setMessage(R.string.allow_hardware_pump_text)
+ .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ pluginSwitcher.invoke();
+ SP.putBoolean("allow_hardware_pump", true);
+ log.debug("First time HW pump allowed!");
+ }
+ })
+ .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ pluginSwitcher.cancel();
+ log.debug("User does not allow switching to HW pump!");
+ }
+ });
+ builder.create().show();
+ }
+ }
+
@Override
public boolean isInitialized() {
return initialized;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/AbstractSensitivityPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/AbstractSensitivityPlugin.java
new file mode 100644
index 0000000000..f05cea1b9d
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/AbstractSensitivityPlugin.java
@@ -0,0 +1,68 @@
+package info.nightscout.androidaps.plugins.Sensitivity;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.interfaces.PluginBase;
+import info.nightscout.androidaps.interfaces.PluginDescription;
+import info.nightscout.androidaps.interfaces.SensitivityInterface;
+import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult;
+import info.nightscout.utils.Round;
+import info.nightscout.utils.SP;
+import info.nightscout.utils.SafeParse;
+
+public abstract class AbstractSensitivityPlugin extends PluginBase implements SensitivityInterface {
+
+ private static final Logger log = LoggerFactory.getLogger(SensitivityInterface.class);
+
+ public AbstractSensitivityPlugin(PluginDescription pluginDescription) {
+ super(pluginDescription);
+ }
+
+ @Override
+ public abstract AutosensResult detectSensitivity(long fromTime, long toTime);
+
+ public AutosensResult fillResult(double ratio, double carbsAbsorbed, String pastSensitivity,
+ String ratioLimit, String sensResult, int deviationsArraySize) {
+ return this.fillResult(ratio, carbsAbsorbed, pastSensitivity, ratioLimit, sensResult,
+ deviationsArraySize,
+ SafeParse.stringToDouble(SP.getString(R.string.key_openapsama_autosens_min, "0.7")),
+ SafeParse.stringToDouble(SP.getString(R.string.key_openapsama_autosens_max, "1.2")));
+ }
+
+ public AutosensResult fillResult(double ratio, double carbsAbsorbed, String pastSensitivity,
+ String ratioLimit, String sensResult, int deviationsArraySize,
+ double ratioMin, double ratioMax) {
+ double rawRatio = ratio;
+ ratio = Math.max(ratio, ratioMin);
+ ratio = Math.min(ratio, ratioMax);
+
+ //If not-excluded data <= MIN_HOURS -> don't do Autosens
+ //If not-excluded data >= MIN_HOURS_FULL_AUTOSENS -> full Autosens
+ //Between MIN_HOURS and MIN_HOURS_FULL_AUTOSENS: gradually increase autosens
+ double autosensContrib = (Math.min(Math.max(MIN_HOURS, deviationsArraySize / 12d),
+ MIN_HOURS_FULL_AUTOSENS) - MIN_HOURS) / (MIN_HOURS_FULL_AUTOSENS - MIN_HOURS);
+ ratio = autosensContrib * (ratio - 1) + 1;
+
+ if (autosensContrib != 1d) {
+ ratioLimit += "(" + deviationsArraySize + " of " + MIN_HOURS_FULL_AUTOSENS * 12 + " values) ";
+ }
+
+ if (ratio != rawRatio) {
+ ratioLimit += "Ratio limited from " + rawRatio + " to " + ratio;
+ log.debug(ratioLimit);
+ }
+
+ AutosensResult output = new AutosensResult();
+ output.ratio = Round.roundTo(ratio, 0.01);
+ output.carbsAbsorbed = Round.roundTo(carbsAbsorbed, 0.01);
+ output.pastSensitivity = pastSensitivity;
+ output.ratioLimit = ratioLimit;
+ output.sensResult = sensResult;
+ return output;
+ }
+
+
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityAAPS/SensitivityAAPSPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/SensitivityAAPSPlugin.java
similarity index 79%
rename from app/src/main/java/info/nightscout/androidaps/plugins/SensitivityAAPS/SensitivityAAPSPlugin.java
rename to app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/SensitivityAAPSPlugin.java
index d7421a3aa2..fdf85c064e 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityAAPS/SensitivityAAPSPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/SensitivityAAPSPlugin.java
@@ -1,11 +1,10 @@
-package info.nightscout.androidaps.plugins.SensitivityAAPS;
+package info.nightscout.androidaps.plugins.Sensitivity;
import android.support.v4.util.LongSparseArray;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
@@ -15,6 +14,7 @@ import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
+import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
@@ -30,7 +30,7 @@ import info.nightscout.utils.SafeParse;
* Created by mike on 24.06.2017.
*/
-public class SensitivityAAPSPlugin extends PluginBase implements SensitivityInterface {
+public class SensitivityAAPSPlugin extends AbstractSensitivityPlugin {
private static Logger log = LoggerFactory.getLogger(SensitivityAAPSPlugin.class);
static SensitivityAAPSPlugin plugin = null;
@@ -81,6 +81,8 @@ public class SensitivityAAPSPlugin extends PluginBase implements SensitivityInte
}
+ List siteChanges = MainApp.getDbHelper().getCareportalEventsFromTime(fromTime, CareportalEvent.SITECHANGE, true);
+
List deviationsArray = new ArrayList<>();
String pastSensitivity = "";
int index = 0;
@@ -97,8 +99,21 @@ public class SensitivityAAPSPlugin extends PluginBase implements SensitivityInte
continue;
}
- if (autosensData.time > toTime - hoursForDetection * 60 * 60 * 1000L)
- deviationsArray.add(autosensData.nonEqualDeviation ? autosensData.deviation : 0d);
+ // reset deviations after site change
+ if (CareportalEvent.isEvent5minBack(siteChanges, autosensData.time)) {
+ deviationsArray.clear();
+ pastSensitivity += "(SITECHANGE)";
+ }
+
+ double deviation = autosensData.deviation;
+
+ //set positive deviations to zero if bg < 80
+ if (autosensData.bg < 80 && deviation > 0)
+ deviation = 0;
+
+ if (autosensData.validDeviation)
+ if (autosensData.time > toTime - hoursForDetection * 60 * 60 * 1000L)
+ deviationsArray.add(deviation);
if (deviationsArray.size() > hoursForDetection * 60 / 5)
deviationsArray.remove(0);
@@ -139,26 +154,16 @@ public class SensitivityAAPSPlugin extends PluginBase implements SensitivityInte
if (Config.logAutosensData)
log.debug(sensResult);
- double rawRatio = ratio;
- ratio = Math.max(ratio, SafeParse.stringToDouble(SP.getString(R.string.key_openapsama_autosens_min, "0.7")));
- ratio = Math.min(ratio, SafeParse.stringToDouble(SP.getString(R.string.key_openapsama_autosens_max, "1.2")));
-
- if (ratio != rawRatio) {
- ratioLimit = "Ratio limited from " + rawRatio + " to " + ratio;
- log.debug(ratioLimit);
- }
+ AutosensResult output = fillResult(ratio, current.cob, pastSensitivity, ratioLimit,
+ sensResult, deviationsArray.size());
if (Config.logAutosensData) {
- log.debug("Sensitivity to: " + new Date(toTime).toLocaleString() + " percentile: " + percentile + " ratio: " + ratio + " mealCOB: " + current.cob);
+ log.debug("Sensitivity to: {}, percentile: {} ratio: {} mealCOB: ",
+ new Date(toTime).toLocaleString(),
+ percentile, output.ratio, ratio, current.cob);
log.debug("Sensitivity to: deviations " + Arrays.toString(deviations));
}
- AutosensResult output = new AutosensResult();
- output.ratio = Round.roundTo(ratio, 0.01);
- output.carbsAbsorbed = Round.roundTo(current.cob, 0.01);
- output.pastSensitivity = pastSensitivity;
- output.ratioLimit = ratioLimit;
- output.sensResult = sensResult;
return output;
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityOref0/SensitivityOref0Plugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/SensitivityOref0Plugin.java
similarity index 76%
rename from app/src/main/java/info/nightscout/androidaps/plugins/SensitivityOref0/SensitivityOref0Plugin.java
rename to app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/SensitivityOref0Plugin.java
index e4bf00be99..cfe5dd28f6 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityOref0/SensitivityOref0Plugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/SensitivityOref0Plugin.java
@@ -1,4 +1,4 @@
-package info.nightscout.androidaps.plugins.SensitivityOref0;
+package info.nightscout.androidaps.plugins.Sensitivity;
import android.support.v4.util.LongSparseArray;
@@ -14,6 +14,7 @@ import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
+import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
@@ -29,7 +30,7 @@ import info.nightscout.utils.SafeParse;
* Created by mike on 24.06.2017.
*/
-public class SensitivityOref0Plugin extends PluginBase implements SensitivityInterface {
+public class SensitivityOref0Plugin extends AbstractSensitivityPlugin {
private static Logger log = LoggerFactory.getLogger(IobCobCalculatorPlugin.class);
static SensitivityOref0Plugin plugin = null;
@@ -54,12 +55,7 @@ public class SensitivityOref0Plugin extends PluginBase implements SensitivityInt
public AutosensResult detectSensitivity(long fromTime, long toTime) {
LongSparseArray autosensDataTable = IobCobCalculatorPlugin.getPlugin().getAutosensDataTable();
- String age = SP.getString(R.string.key_age, "");
- int defaultHours = 24;
- if (age.equals(MainApp.gs(R.string.key_adult))) defaultHours = 24;
- if (age.equals(MainApp.gs(R.string.key_teenage))) defaultHours = 24;
- if (age.equals(MainApp.gs(R.string.key_child))) defaultHours = 24;
- int hoursForDetection = SP.getInt(R.string.key_openapsama_autosens_period, defaultHours);
+ int hoursForDetection = 24;
long now = System.currentTimeMillis();
Profile profile = MainApp.getConfigBuilder().getProfile();
@@ -81,6 +77,8 @@ public class SensitivityOref0Plugin extends PluginBase implements SensitivityInt
}
+ List siteChanges = MainApp.getDbHelper().getCareportalEventsFromTime(fromTime, CareportalEvent.SITECHANGE, true);
+
List deviationsArray = new ArrayList<>();
String pastSensitivity = "";
int index = 0;
@@ -97,8 +95,21 @@ public class SensitivityOref0Plugin extends PluginBase implements SensitivityInt
continue;
}
- if (autosensData.time > toTime - hoursForDetection * 60 * 60 * 1000L)
- deviationsArray.add(autosensData.nonEqualDeviation ? autosensData.deviation : 0d);
+ // reset deviations after site change
+ if (CareportalEvent.isEvent5minBack(siteChanges, autosensData.time)) {
+ deviationsArray.clear();
+ pastSensitivity += "(SITECHANGE)";
+ }
+
+ double deviation = autosensData.deviation;
+
+ //set positive deviations to zero if bg < 80
+ if (autosensData.bg < 80 && deviation > 0)
+ deviation = 0;
+
+ if (autosensData.validDeviation)
+ if (autosensData.time > toTime - hoursForDetection * 60 * 60 * 1000L)
+ deviationsArray.add(deviation);
if (deviationsArray.size() > hoursForDetection * 60 / 5)
deviationsArray.remove(0);
@@ -150,24 +161,13 @@ public class SensitivityOref0Plugin extends PluginBase implements SensitivityInt
ratio = 1 + (basalOff / profile.getMaxDailyBasal());
- double rawRatio = ratio;
- ratio = Math.max(ratio, SafeParse.stringToDouble(SP.getString(R.string.key_openapsama_autosens_min, "0.7")));
- ratio = Math.min(ratio, SafeParse.stringToDouble(SP.getString(R.string.key_openapsama_autosens_max, "1.2")));
-
- if (ratio != rawRatio) {
- ratioLimit = "Ratio limited from " + rawRatio + " to " + ratio;
- log.debug(ratioLimit);
- }
+ AutosensResult output = fillResult(ratio, current.cob, pastSensitivity, ratioLimit,
+ sensResult, deviationsArray.size());
if (Config.logAutosensData)
- log.debug("Sensitivity to: " + new Date(toTime).toLocaleString() + " ratio: " + ratio + " mealCOB: " + current.cob);
+ log.debug("Sensitivity to: {} ratio: {} mealCOB: {}",
+ new Date(toTime).toLocaleString(), output.ratio, current.cob);
- AutosensResult output = new AutosensResult();
- output.ratio = Round.roundTo(ratio, 0.01);
- output.carbsAbsorbed = Round.roundTo(current.cob, 0.01);
- output.pastSensitivity = pastSensitivity;
- output.ratioLimit = ratioLimit;
- output.sensResult = sensResult;
return output;
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/SensitivityOref1Plugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/SensitivityOref1Plugin.java
new file mode 100644
index 0000000000..f6d5a4ef2a
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/SensitivityOref1Plugin.java
@@ -0,0 +1,187 @@
+package info.nightscout.androidaps.plugins.Sensitivity;
+
+import android.support.v4.util.LongSparseArray;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+
+import info.nightscout.androidaps.Config;
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.data.Profile;
+import info.nightscout.androidaps.db.CareportalEvent;
+import info.nightscout.androidaps.interfaces.PluginBase;
+import info.nightscout.androidaps.interfaces.PluginDescription;
+import info.nightscout.androidaps.interfaces.PluginType;
+import info.nightscout.androidaps.interfaces.SensitivityInterface;
+import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData;
+import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult;
+import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
+import info.nightscout.utils.Round;
+import info.nightscout.utils.SP;
+import info.nightscout.utils.SafeParse;
+
+/**
+ * Created by mike on 19.06.2018.
+ */
+
+public class SensitivityOref1Plugin extends AbstractSensitivityPlugin {
+ private static Logger log = LoggerFactory.getLogger(IobCobCalculatorPlugin.class);
+
+ static SensitivityOref1Plugin plugin = null;
+
+ public static SensitivityOref1Plugin getPlugin() {
+ if (plugin == null)
+ plugin = new SensitivityOref1Plugin();
+ return plugin;
+ }
+
+ public SensitivityOref1Plugin() {
+ super(new PluginDescription()
+ .mainType(PluginType.SENSITIVITY)
+ .pluginName(R.string.sensitivityoref1)
+ .shortName(R.string.sensitivity_shortname)
+ .preferencesId(R.xml.pref_absorption_oref1)
+ .description(R.string.description_sensitivity_oref1)
+ );
+ }
+
+ @Override
+ public AutosensResult detectSensitivity(long fromTime, long toTime) {
+ LongSparseArray autosensDataTable = IobCobCalculatorPlugin.getPlugin().getAutosensDataTable();
+
+ Profile profile = MainApp.getConfigBuilder().getProfile();
+
+ if (profile == null) {
+ log.debug("No profile");
+ return new AutosensResult();
+ }
+
+ if (autosensDataTable == null || autosensDataTable.size() < 4) {
+ log.debug("No autosens data available");
+ return new AutosensResult();
+ }
+
+ AutosensData current = IobCobCalculatorPlugin.getPlugin().getAutosensData(toTime); // this is running inside lock already
+ if (current == null) {
+ log.debug("No current autosens data available");
+ return new AutosensResult();
+ }
+
+ List siteChanges = MainApp.getDbHelper().getCareportalEventsFromTime(fromTime, CareportalEvent.SITECHANGE, true);
+
+ List deviationsArray = new ArrayList<>();
+ String pastSensitivity = "";
+ int index = 0;
+ while (index < autosensDataTable.size()) {
+ AutosensData autosensData = autosensDataTable.valueAt(index);
+
+ if (autosensData.time < fromTime) {
+ index++;
+ continue;
+ }
+
+ if (autosensData.time > toTime) {
+ index++;
+ continue;
+ }
+
+ // reset deviations after site change
+ if (CareportalEvent.isEvent5minBack(siteChanges, autosensData.time)) {
+ deviationsArray.clear();
+ pastSensitivity += "(SITECHANGE)";
+ }
+
+ double deviation = autosensData.deviation;
+
+ //set positive deviations to zero if bg < 80
+ if (autosensData.bg < 80 && deviation > 0)
+ deviation = 0;
+
+ if (autosensData.validDeviation)
+ deviationsArray.add(deviation);
+
+ for (int i = 0; i < autosensData.extraDeviation.size(); i++)
+ deviationsArray.add(autosensData.extraDeviation.get(i));
+ if (deviationsArray.size() > 96)
+ deviationsArray.remove(0);
+
+ pastSensitivity += autosensData.pastSensitivity;
+ int secondsFromMidnight = Profile.secondsFromMidnight(autosensData.time);
+ if (secondsFromMidnight % 3600 < 2.5 * 60 || secondsFromMidnight % 3600 > 57.5 * 60) {
+ pastSensitivity += "(" + Math.round(secondsFromMidnight / 3600d) + ")";
+ }
+ index++;
+ }
+
+ // when we have less than 8h worth of deviation data, add up to 90m of zero deviations
+ // this dampens any large sensitivity changes detected based on too little data, without ignoring them completely
+ log.debug("Using most recent " + deviationsArray.size() + " deviations");
+ if (deviationsArray.size() < 96) {
+ int pad = Math.round((1 - deviationsArray.size() / 96) * 18);
+ log.debug("Adding " + pad + " more zero deviations");
+ for (int d = 0; d < pad; d++) {
+ //process.stderr.write(".");
+ deviationsArray.add(0d);
+ }
+ }
+
+ Double[] deviations = new Double[deviationsArray.size()];
+ deviations = deviationsArray.toArray(deviations);
+
+ double sens = profile.getIsf();
+
+ double ratio = 1;
+ String ratioLimit = "";
+ String sensResult = "";
+
+ if (Config.logAutosensData)
+ log.debug("Records: " + index + " " + pastSensitivity);
+
+ Arrays.sort(deviations);
+
+ for (double i = 0.9; i > 0.1; i = i - 0.01) {
+ if (IobCobCalculatorPlugin.percentile(deviations, (i + 0.01)) >= 0 && IobCobCalculatorPlugin.percentile(deviations, i) < 0) {
+ if (Config.logAutosensData)
+ log.debug(Math.round(100 * i) + "% of non-meal deviations negative (>50% = sensitivity)");
+ }
+ if (IobCobCalculatorPlugin.percentile(deviations, (i + 0.01)) > 0 && IobCobCalculatorPlugin.percentile(deviations, i) <= 0) {
+ if (Config.logAutosensData)
+ log.debug(Math.round(100 * i) + "% of non-meal deviations negative (>50% = resistance)");
+ }
+ }
+ double pSensitive = IobCobCalculatorPlugin.percentile(deviations, 0.50);
+ double pResistant = IobCobCalculatorPlugin.percentile(deviations, 0.50);
+
+ double basalOff = 0;
+
+ if (pSensitive < 0) { // sensitive
+ basalOff = pSensitive * (60 / 5) / Profile.toMgdl(sens, profile.getUnits());
+ sensResult = "Excess insulin sensitivity detected";
+ } else if (pResistant > 0) { // resistant
+ basalOff = pResistant * (60 / 5) / Profile.toMgdl(sens, profile.getUnits());
+ sensResult = "Excess insulin resistance detected";
+ } else {
+ sensResult = "Sensitivity normal";
+ }
+
+ if (Config.logAutosensData)
+ log.debug(sensResult);
+
+ ratio = 1 + (basalOff / profile.getMaxDailyBasal());
+
+ AutosensResult output = fillResult(ratio, current.cob, pastSensitivity, ratioLimit,
+ sensResult, deviationsArray.size());
+
+ if (Config.logAutosensData)
+ log.debug("Sensitivity to: {} ratio: {} mealCOB: {}",
+ new Date(toTime).toLocaleString(), output.ratio, current.cob);
+
+ return output;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityWeightedAverage/SensitivityWeightedAveragePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/SensitivityWeightedAveragePlugin.java
similarity index 81%
rename from app/src/main/java/info/nightscout/androidaps/plugins/SensitivityWeightedAverage/SensitivityWeightedAveragePlugin.java
rename to app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/SensitivityWeightedAveragePlugin.java
index 3d33b5ae14..ed185e88f9 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityWeightedAverage/SensitivityWeightedAveragePlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/SensitivityWeightedAveragePlugin.java
@@ -1,4 +1,4 @@
-package info.nightscout.androidaps.plugins.SensitivityWeightedAverage;
+package info.nightscout.androidaps.plugins.Sensitivity;
import android.support.v4.util.LongSparseArray;
@@ -6,11 +6,13 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
+import java.util.List;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
+import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
@@ -26,7 +28,7 @@ import info.nightscout.utils.SafeParse;
* Created by mike on 24.06.2017.
*/
-public class SensitivityWeightedAveragePlugin extends PluginBase implements SensitivityInterface {
+public class SensitivityWeightedAveragePlugin extends AbstractSensitivityPlugin {
private static Logger log = LoggerFactory.getLogger(SensitivityWeightedAveragePlugin.class);
private static SensitivityWeightedAveragePlugin plugin = null;
@@ -79,6 +81,8 @@ public class SensitivityWeightedAveragePlugin extends PluginBase implements Sens
return new AutosensResult();
}
+ List siteChanges = MainApp.getDbHelper().getCareportalEventsFromTime(fromTime, CareportalEvent.SITECHANGE, true);
+
String pastSensitivity = "";
int index = 0;
LongSparseArray data = new LongSparseArray<>();
@@ -101,11 +105,24 @@ public class SensitivityWeightedAveragePlugin extends PluginBase implements Sens
continue;
}
+ // reset deviations after site change
+ if (CareportalEvent.isEvent5minBack(siteChanges, autosensData.time)) {
+ data.clear();
+ pastSensitivity += "(SITECHANGE)";
+ }
+
+ double deviation = autosensData.deviation;
+
+ //set positive deviations to zero if bg < 80
+ if (autosensData.bg < 80 && deviation > 0)
+ deviation = 0;
+
//data.append(autosensData.time);
long reverseWeight = (toTime - autosensData.time) / (5 * 60 * 1000L);
- data.append(reverseWeight, autosensData.nonEqualDeviation ? autosensData.deviation : 0d);
+ if (autosensData.validDeviation)
+ data.append(reverseWeight, deviation);
//weights += reverseWeight;
- //weightedsum += reverseWeight * (autosensData.nonEqualDeviation ? autosensData.deviation : 0d);
+ //weightedsum += reverseWeight * (autosensData.validDeviation ? autosensData.deviation : 0d);
pastSensitivity += autosensData.pastSensitivity;
@@ -159,25 +176,13 @@ public class SensitivityWeightedAveragePlugin extends PluginBase implements Sens
if (Config.logAutosensData)
log.debug(sensResult);
- double rawRatio = ratio;
- ratio = Math.max(ratio, SafeParse.stringToDouble(SP.getString(R.string.key_openapsama_autosens_min, "0.7")));
- ratio = Math.min(ratio, SafeParse.stringToDouble(SP.getString(R.string.key_openapsama_autosens_max, "1.2")));
-
- if (ratio != rawRatio) {
- ratioLimit = "Ratio limited from " + rawRatio + " to " + ratio;
- if (Config.logAutosensData)
- log.debug(ratioLimit);
- }
+ AutosensResult output = fillResult(ratio, current.cob, pastSensitivity, ratioLimit,
+ sensResult, data.size());
if (Config.logAutosensData)
- log.debug("Sensitivity to: " + new Date(toTime).toLocaleString() + " weightedaverage: " + average + " ratio: " + ratio + " mealCOB: " + current.cob);
+ log.debug("Sensitivity to: {} weightedaverage: {} ratio: {} mealCOB: {}", new Date(toTime).toLocaleString(),
+ average, output.ratio, current.cob);
- AutosensResult output = new AutosensResult();
- output.ratio = Round.roundTo(ratio, 0.01);
- output.carbsAbsorbed = Round.roundTo(current.cob, 0.01);
- output.pastSensitivity = pastSensitivity;
- output.ratioLimit = ratioLimit;
- output.sensResult = sensResult;
return output;
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java
index 8e1dd06d2f..847ead4482 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java
@@ -2,6 +2,7 @@ package info.nightscout.androidaps.plugins.SmsCommunicator;
import android.content.Intent;
import android.content.pm.ResolveInfo;
+import android.os.SystemClock;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
@@ -47,6 +48,7 @@ import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.NSUpload;
import info.nightscout.utils.SP;
import info.nightscout.utils.SafeParse;
+import info.nightscout.utils.T;
import info.nightscout.utils.XdripCalibrations;
/**
@@ -450,12 +452,14 @@ public class SmsCommunicatorPlugin extends PluginBase {
public void run() {
PumpInterface pump = MainApp.getConfigBuilder().getActivePump();
if (result.success) {
+ SystemClock.sleep(T.secs(15).msecs()); // wait some time to get history
String reply = String.format(MainApp.gs(R.string.smscommunicator_bolusdelivered), result.bolusDelivered);
if (pump != null)
reply += "\n" + pump.shortStatus(true);
lastRemoteBolusTime = new Date();
sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply, new Date()));
} else {
+ SystemClock.sleep(T.secs(60).msecs()); // wait some time to get history
String reply = MainApp.gs(R.string.smscommunicator_bolusfailed);
if (pump != null)
reply += "\n" + pump.shortStatus(true);
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceNSClientPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceNSClientPlugin.java
index e3c4181c05..c99fbcb9bb 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceNSClientPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceNSClientPlugin.java
@@ -20,6 +20,9 @@ public class SourceNSClientPlugin extends PluginBase implements BgSourceInterfac
return plugin;
}
+ private long lastBGTimeStamp = 0;
+ private boolean isAdvancedFilteringEnabled = false;
+
private SourceNSClientPlugin() {
super(new PluginDescription()
.mainType(PluginType.BGSOURCE)
@@ -33,6 +36,16 @@ public class SourceNSClientPlugin extends PluginBase implements BgSourceInterfac
@Override
public boolean advancedFilteringSupported() {
- return false;
+ return isAdvancedFilteringEnabled;
+ }
+
+ public void detectSource(String source, long timeStamp) {
+ if (timeStamp > lastBGTimeStamp) {
+ if (source.contains("G5 Native") || source.contains("AndroidAPS-DexcomG5"))
+ isAdvancedFilteringEnabled = true;
+ else
+ isAdvancedFilteringEnabled = false;
+ lastBGTimeStamp = timeStamp;
+ }
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsPlugin.java
index a754b7dcfa..461f204f84 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsPlugin.java
@@ -40,8 +40,8 @@ import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData;
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
-import info.nightscout.androidaps.plugins.SensitivityAAPS.SensitivityAAPSPlugin;
-import info.nightscout.androidaps.plugins.SensitivityWeightedAverage.SensitivityWeightedAveragePlugin;
+import info.nightscout.androidaps.plugins.Sensitivity.SensitivityAAPSPlugin;
+import info.nightscout.androidaps.plugins.Sensitivity.SensitivityWeightedAveragePlugin;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.NSUpload;
import info.nightscout.utils.SP;
@@ -78,7 +78,6 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
.fragmentClass(TreatmentsFragment.class.getName())
.pluginName(R.string.treatments)
.shortName(R.string.treatments_shortname)
- .preferencesId(R.xml.pref_absorption_oref0)
.alwaysEnabled(true)
.description(R.string.description_treatments)
);
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsBolusFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsBolusFragment.java
index 57ad6833a9..0faceb2382 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsBolusFragment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsBolusFragment.java
@@ -43,6 +43,8 @@ import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.NSUpload;
import info.nightscout.utils.SP;
+import static info.nightscout.utils.DateUtil.now;
+
public class TreatmentsBolusFragment extends SubscriberFragment implements View.OnClickListener {
private static Logger log = LoggerFactory.getLogger(TreatmentsBolusFragment.class);
@@ -52,6 +54,7 @@ public class TreatmentsBolusFragment extends SubscriberFragment implements View.
TextView iobTotal;
TextView activityTotal;
Button refreshFromNS;
+ Button deleteFutureTreatments;
Context context;
@@ -89,7 +92,7 @@ public class TreatmentsBolusFragment extends SubscriberFragment implements View.
holder.iob.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.colorActive));
else
holder.iob.setTextColor(holder.carbs.getCurrentTextColor());
- if (t.date > DateUtil.now())
+ if (t.date > now())
holder.date.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.colorScheduled));
else
holder.date.setTextColor(holder.carbs.getCurrentTextColor());
@@ -189,6 +192,9 @@ public class TreatmentsBolusFragment extends SubscriberFragment implements View.
refreshFromNS = (Button) view.findViewById(R.id.treatments_reshreshfromnightscout);
refreshFromNS.setOnClickListener(this);
+ deleteFutureTreatments = (Button) view.findViewById(R.id.treatments_delete_future_treatments);
+ deleteFutureTreatments.setOnClickListener(this);
+
boolean nsUploadOnly = SP.getBoolean(R.string.key_ns_upload_only, false);
if (nsUploadOnly)
refreshFromNS.setVisibility(View.GONE);
@@ -201,17 +207,37 @@ public class TreatmentsBolusFragment extends SubscriberFragment implements View.
@Override
public void onClick(View view) {
+ AlertDialog.Builder builder;
switch (view.getId()) {
case R.id.treatments_reshreshfromnightscout:
- AlertDialog.Builder builder = new AlertDialog.Builder(this.getContext());
+ builder = new AlertDialog.Builder(this.getContext());
builder.setTitle(MainApp.gs(R.string.confirmation));
builder.setMessage(MainApp.gs(R.string.refresheventsfromnightscout) + "?");
- builder.setPositiveButton(MainApp.gs(R.string.ok), new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- TreatmentsPlugin.getPlugin().getService().resetTreatments();
- Intent restartNSClient = new Intent(Intents.ACTION_RESTART);
- MainApp.instance().getApplicationContext().sendBroadcast(restartNSClient);
+ builder.setPositiveButton(MainApp.gs(R.string.ok), (dialog, id) -> {
+ TreatmentsPlugin.getPlugin().getService().resetTreatments();
+ Intent restartNSClient = new Intent(Intents.ACTION_RESTART);
+ MainApp.instance().getApplicationContext().sendBroadcast(restartNSClient);
+ });
+ builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
+ builder.show();
+ break;
+ case R.id.treatments_delete_future_treatments:
+ builder = new AlertDialog.Builder(this.getContext());
+ builder.setTitle(MainApp.gs(R.string.confirmation));
+ builder.setMessage(MainApp.gs(R.string.deletefuturetreatments) + "?");
+ builder.setPositiveButton(MainApp.gs(R.string.ok), (dialog, id) -> {
+ final List futureTreatments = TreatmentsPlugin.getPlugin().getService()
+ .getTreatmentDataFromTime(now() + 1000, true);
+ for (Treatment treatment : futureTreatments) {
+ final String _id = treatment._id;
+ if (NSUpload.isIdValid(_id)) {
+ NSUpload.removeCareportalEntryFromNS(_id);
+ } else {
+ UploadQueue.removeID("dbAdd", _id);
+ }
+ TreatmentsPlugin.getPlugin().getService().delete(treatment);
}
+ updateGUI();
});
builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
builder.show();
@@ -233,14 +259,16 @@ public class TreatmentsBolusFragment extends SubscriberFragment implements View.
protected void updateGUI() {
Activity activity = getActivity();
if (activity != null)
- activity.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- recyclerView.swapAdapter(new RecyclerViewAdapter(TreatmentsPlugin.getPlugin().getTreatmentsFromHistory()), false);
- if (TreatmentsPlugin.getPlugin().getLastCalculationTreatments() != null) {
- iobTotal.setText(DecimalFormatter.to2Decimal(TreatmentsPlugin.getPlugin().getLastCalculationTreatments().iob) + " U");
- activityTotal.setText(DecimalFormatter.to3Decimal(TreatmentsPlugin.getPlugin().getLastCalculationTreatments().activity) + " U");
- }
+ activity.runOnUiThread(() -> {
+ recyclerView.swapAdapter(new RecyclerViewAdapter(TreatmentsPlugin.getPlugin().getTreatmentsFromHistory()), false);
+ if (TreatmentsPlugin.getPlugin().getLastCalculationTreatments() != null) {
+ iobTotal.setText(DecimalFormatter.to2Decimal(TreatmentsPlugin.getPlugin().getLastCalculationTreatments().iob) + " " + MainApp.gs(R.string.insulin_unit_shortname));
+ activityTotal.setText(DecimalFormatter.to3Decimal(TreatmentsPlugin.getPlugin().getLastCalculationTreatments().activity) + " " + MainApp.gs(R.string.insulin_unit_shortname));
+ }
+ if (!TreatmentsPlugin.getPlugin().getService().getTreatmentDataFromTime(now() + 1000, true).isEmpty()) {
+ deleteFutureTreatments.setVisibility(View.VISIBLE);
+ } else {
+ deleteFutureTreatments.setVisibility(View.GONE);
}
});
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsCareportalFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsCareportalFragment.java
index 97c3a05274..7e69883a3d 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsCareportalFragment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsCareportalFragment.java
@@ -107,16 +107,14 @@ public class TreatmentsCareportalFragment extends SubscriberFragment implements
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(MainApp.gs(R.string.confirmation));
builder.setMessage(MainApp.gs(R.string.removerecord) + "\n" + DateUtil.dateAndTimeString(careportalEvent.date));
- builder.setPositiveButton(MainApp.gs(R.string.ok), new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- final String _id = careportalEvent._id;
- if (NSUpload.isIdValid(_id)) {
- NSUpload.removeCareportalEntryFromNS(_id);
- } else {
- UploadQueue.removeID("dbAdd", _id);
- }
- MainApp.getDbHelper().delete(careportalEvent);
+ builder.setPositiveButton(MainApp.gs(R.string.ok), (dialog, id) -> {
+ final String _id = careportalEvent._id;
+ if (NSUpload.isIdValid(_id)) {
+ NSUpload.removeCareportalEntryFromNS(_id);
+ } else {
+ UploadQueue.removeID("dbAdd", _id);
}
+ MainApp.getDbHelper().delete(careportalEvent);
});
builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
builder.show();
@@ -136,12 +134,14 @@ public class TreatmentsCareportalFragment extends SubscriberFragment implements
llm = new LinearLayoutManager(view.getContext());
recyclerView.setLayoutManager(llm);
- RecyclerViewAdapter adapter = new RecyclerViewAdapter(MainApp.getDbHelper().getCareportalEventsFromTime(false));
+ RecyclerViewAdapter adapter = new RecyclerViewAdapter(MainApp.getDbHelper().getCareportalEvents(false));
recyclerView.setAdapter(adapter);
refreshFromNS = (Button) view.findViewById(R.id.careportal_refreshfromnightscout);
refreshFromNS.setOnClickListener(this);
+ view.findViewById(R.id.careportal_removeandroidapsstartedevents).setOnClickListener(this);
+
context = getContext();
boolean nsUploadOnly = SP.getBoolean(R.string.key_ns_upload_only, false);
@@ -169,6 +169,16 @@ public class TreatmentsCareportalFragment extends SubscriberFragment implements
builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
builder.show();
break;
+ case R.id.careportal_removeandroidapsstartedevents:
+ builder = new AlertDialog.Builder(context);
+ builder.setTitle(MainApp.gs(R.string.confirmation));
+ builder.setMessage(MainApp.gs(R.string.careportal_removestartedevents));
+ builder.setPositiveButton(MainApp.gs(R.string.ok), (dialog, id) -> {
+ removeAndroidAPSStatedEvents();
+ });
+ builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
+ builder.show();
+ break;
}
}
@@ -185,8 +195,24 @@ public class TreatmentsCareportalFragment extends SubscriberFragment implements
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
- recyclerView.swapAdapter(new RecyclerViewAdapter(MainApp.getDbHelper().getCareportalEventsFromTime(false)), false);
+ recyclerView.swapAdapter(new RecyclerViewAdapter(MainApp.getDbHelper().getCareportalEvents(false)), false);
}
});
}
+
+ private void removeAndroidAPSStatedEvents() {
+ List events = MainApp.getDbHelper().getCareportalEvents(false);
+ for (int i = 0; i < events.size(); i++) {
+ CareportalEvent careportalEvent = events.get(i);
+ if (careportalEvent.json.contains(MainApp.gs(R.string.androidaps_start))) {
+ final String _id = careportalEvent._id;
+ if (NSUpload.isIdValid(_id)) {
+ NSUpload.removeCareportalEntryFromNS(_id);
+ } else {
+ UploadQueue.removeID("dbAdd", _id);
+ }
+ MainApp.getDbHelper().delete(careportalEvent);
+ }
+ }
+ }
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/wearintegration/WatchUpdaterService.java b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/wearintegration/WatchUpdaterService.java
index 696b8b0b57..b5d30ad071 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/wearintegration/WatchUpdaterService.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/wearintegration/WatchUpdaterService.java
@@ -738,11 +738,14 @@ public class WatchUpdaterService extends WearableListenerService implements
public static int getBatteryLevel(Context context) {
Intent batteryIntent = context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
- int level = batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
- int scale = batteryIntent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
- if (level == -1 || scale == -1) {
- return 50;
+ if (batteryIntent != null) {
+ int level = batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
+ int scale = batteryIntent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
+ if (level == -1 || scale == -1) {
+ return 50;
+ }
+ return (int) (((float) level / (float) scale) * 100.0f);
}
- return (int) (((float) level / (float) scale) * 100.0f);
+ return 50;
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java b/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java
index 9f2fdf7eee..47fe4acd6a 100644
--- a/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java
+++ b/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java
@@ -26,6 +26,7 @@ import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressHelperAc
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
+import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.androidaps.queue.commands.Command;
import info.nightscout.androidaps.queue.commands.CommandBolus;
import info.nightscout.androidaps.queue.commands.CommandCancelExtendedBolus;
@@ -177,6 +178,18 @@ public class CommandQueue {
public synchronized boolean bolus(DetailedBolusInfo detailedBolusInfo, Callback callback) {
Command.CommandType type = detailedBolusInfo.isSMB ? Command.CommandType.SMB_BOLUS : Command.CommandType.BOLUS;
+ if (type == Command.CommandType.SMB_BOLUS) {
+ if (isRunning(Command.CommandType.BOLUS) || bolusInQueue()) {
+ log.debug("Rejecting SMB since a bolus is queue/running");
+ return false;
+ }
+ if (detailedBolusInfo.lastKnownBolusTime < TreatmentsPlugin.getPlugin().getLastBolusTime()) {
+ log.debug("Rejecting bolus, another bolus was issued since request time");
+ return false;
+ }
+ }
+
+
if(type.equals(Command.CommandType.BOLUS) && detailedBolusInfo.carbs > 0 && detailedBolusInfo.insulin == 0){
type = Command.CommandType.CARBS_ONLY_TREATMENT;
//Carbs only can be added in parallel as they can be "in the future".
diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.java
index 0e7ba0e623..a8402dc1a5 100644
--- a/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.java
+++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.java
@@ -98,14 +98,7 @@ public class SWDefinition {
add(new SWScreen(R.string.nav_setupwizard)
.add(new SWInfotext()
.label(R.string.welcometosetupwizard))
- .add(new SWButton()
- .text(R.string.nav_import)
- .action(() -> ImportExportPrefs.importSharedPreferences(getActivity()))
- .visibility(ImportExportPrefs.file::exists))
- .add(new SWInfotext()
- .label(R.string.backupismissing)
- .visibility(() -> !ImportExportPrefs.file.exists()))
- )
+ )
.add(new SWScreen(R.string.language)
.skippable(false)
.add(new SWRadioButton()
@@ -169,6 +162,15 @@ public class SWDefinition {
.visibility(() -> Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE))
.validator(() -> !(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)))
)
+ .add(new SWScreen(R.string.nav_import)
+ .add(new SWInfotext()
+ .label(R.string.storedsettingsfound))
+ .add(new SWBreak())
+ .add(new SWButton()
+ .text(R.string.nav_import)
+ .action(() -> ImportExportPrefs.importSharedPreferences(getActivity())))
+ .visibility(() -> ImportExportPrefs.file.exists() && !(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)))
+ )
.add(new SWScreen(R.string.nsclientinternal_title)
.skippable(true)
.add(new SWInfotext()
@@ -223,21 +225,14 @@ public class SWDefinition {
)
.add(new SWScreen(R.string.configbuilder_insulin)
.skippable(false)
- .add(new SWInfotext()
- .label(MainApp.gs(R.string.rapid_acting_oref) + ": " + MainApp.gs(R.string.fastactinginsulincomment)))
- .add(new SWInfotext()
- .label(MainApp.gs(R.string.ultrarapid_oref) + ": " + MainApp.gs(R.string.ultrafastactinginsulincomment)))
- .add(new SWInfotext()
- .label(MainApp.gs(R.string.free_peak_oref) + ": " + MainApp.gs(R.string.free_peak_oref_description)))
+ .add(new SWPlugin()
+ .option(PluginType.INSULIN, R.string.configbuilder_insulin_description)
+ .makeVisible(false)
+ .label(R.string.configbuilder_insulin))
.add(new SWBreak())
.add(new SWInfotext()
.label(R.string.diawarning))
.add(new SWBreak())
- .add(new SWPlugin()
- .option(PluginType.INSULIN)
- .makeVisible(false)
- .label(R.string.configbuilder_insulin))
- .add(new SWBreak())
.add(new SWButton()
.text(R.string.insulinsourcesetup)
.action(() -> {
@@ -253,10 +248,8 @@ public class SWDefinition {
)
.add(new SWScreen(R.string.configbuilder_bgsource)
.skippable(false)
- .add(new SWInfotext()
- .label(R.string.setupwizard_bgsource_description))
.add(new SWPlugin()
- .option(PluginType.BGSOURCE)
+ .option(PluginType.BGSOURCE, R.string.configbuilder_bgsource_description)
.label(R.string.configbuilder_bgsource))
.add(new SWBreak())
.add(new SWButton()
@@ -278,7 +271,7 @@ public class SWDefinition {
.label(R.string.setupwizard_profile_description))
.add(new SWBreak())
.add(new SWPlugin()
- .option(PluginType.PROFILE)
+ .option(PluginType.PROFILE, R.string.configbuilder_profile_description)
.label(R.string.configbuilder_profile))
.validator(() -> MainApp.getConfigBuilder().getActiveProfileInterface() != null)
)
@@ -324,8 +317,9 @@ public class SWDefinition {
.add(new SWScreen(R.string.configbuilder_pump)
.skippable(false)
.add(new SWPlugin()
- .option(PluginType.PUMP)
+ .option(PluginType.PUMP, R.string.configbuilder_pump_description)
.label(R.string.configbuilder_pump))
+ .add(new SWBreak())
.add(new SWButton()
.text(R.string.pumpsetup)
.action(() -> {
@@ -360,7 +354,7 @@ public class SWDefinition {
.label("https://openaps.readthedocs.io/en/latest/"))
.add(new SWBreak())
.add(new SWPlugin()
- .option(PluginType.APS)
+ .option(PluginType.APS, R.string.configbuilder_aps_description)
.label(R.string.configbuilder_aps))
.add(new SWButton()
.text(R.string.apssetup)
@@ -402,7 +396,7 @@ public class SWDefinition {
.label(R.string.setupwizard_sensitivity_url))
.add(new SWBreak())
.add(new SWPlugin()
- .option(PluginType.SENSITIVITY)
+ .option(PluginType.SENSITIVITY, R.string.configbuilder_sensitivity_description)
.label(R.string.configbuilder_sensitivity))
.add(new SWBreak())
.add(new SWButton()
@@ -454,13 +448,6 @@ public class SWDefinition {
add(new SWScreen(R.string.nav_setupwizard)
.add(new SWInfotext()
.label(R.string.welcometosetupwizard))
- .add(new SWButton()
- .text(R.string.nav_import)
- .action(() -> ImportExportPrefs.importSharedPreferences(getActivity()))
- .visibility(ImportExportPrefs.file::exists))
- .add(new SWInfotext()
- .label(R.string.backupismissing)
- .visibility(() -> !ImportExportPrefs.file.exists()))
)
.add(new SWScreen(R.string.language)
.skippable(false)
@@ -513,6 +500,15 @@ public class SWDefinition {
.visibility(() -> Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE))
.validator(() -> !(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)))
)
+ .add(new SWScreen(R.string.nav_import)
+ .add(new SWInfotext()
+ .label(R.string.storedsettingsfound))
+ .add(new SWBreak())
+ .add(new SWButton()
+ .text(R.string.nav_import)
+ .action(() -> ImportExportPrefs.importSharedPreferences(getActivity())))
+ .visibility(() -> ImportExportPrefs.file.exists() && !(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)))
+ )
.add(new SWScreen(R.string.nsclientinternal_title)
.skippable(true)
.add(new SWInfotext()
@@ -567,21 +563,14 @@ public class SWDefinition {
)
.add(new SWScreen(R.string.configbuilder_insulin)
.skippable(false)
- .add(new SWInfotext()
- .label(MainApp.gs(R.string.rapid_acting_oref) + ": " + MainApp.gs(R.string.fastactinginsulincomment)))
- .add(new SWInfotext()
- .label(MainApp.gs(R.string.ultrarapid_oref) + ": " + MainApp.gs(R.string.ultrafastactinginsulincomment)))
- .add(new SWInfotext()
- .label(MainApp.gs(R.string.free_peak_oref) + ": " + MainApp.gs(R.string.free_peak_oref_description)))
+ .add(new SWPlugin()
+ .option(PluginType.INSULIN, R.string.configbuilder_insulin_description)
+ .makeVisible(false)
+ .label(R.string.configbuilder_insulin))
.add(new SWBreak())
.add(new SWInfotext()
.label(R.string.diawarning))
.add(new SWBreak())
- .add(new SWPlugin()
- .option(PluginType.INSULIN)
- .makeVisible(false)
- .label(R.string.configbuilder_insulin))
- .add(new SWBreak())
.add(new SWButton()
.text(R.string.insulinsourcesetup)
.action(() -> {
@@ -603,7 +592,7 @@ public class SWDefinition {
.label(R.string.setupwizard_sensitivity_url))
.add(new SWBreak())
.add(new SWPlugin()
- .option(PluginType.SENSITIVITY)
+ .option(PluginType.SENSITIVITY, R.string.configbuilder_sensitivity_description)
.label(R.string.configbuilder_sensitivity))
.add(new SWBreak())
.add(new SWButton()
diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/SWEventListener.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWEventListener.java
index 40979a3efd..487a80d91c 100644
--- a/app/src/main/java/info/nightscout/androidaps/setupwizard/SWEventListener.java
+++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWEventListener.java
@@ -46,11 +46,11 @@ public class SWEventListener extends SWItem {
}
@Override
- public void generateDialog(View view, LinearLayout layout) {
- Context context = view.getContext();
+ public void generateDialog(LinearLayout layout) {
+ Context context = layout.getContext();
textView = new TextView(context);
- textView.setId(view.generateViewId());
+ textView.setId(layout.generateViewId());
textView.setText((textLabel != 0 ? MainApp.gs(textLabel) : "") + " " + status);
layout.addView(textView);
if (listener != null)
diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.java
index 523970d6df..5102e36ac6 100644
--- a/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.java
+++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.java
@@ -129,7 +129,7 @@ public class SetupWizardActivity extends AppCompatActivity {
LinearLayout layout = SWItem.generateLayout(this.findViewById(R.id.sw_content_fields));
for (int i = 0; i < currentScreen.items.size(); i++) {
SWItem currentItem = currentScreen.items.get(i);
- currentItem.generateDialog(this.findViewById(R.id.sw_content_fields), layout);
+ currentItem.generateDialog(layout);
}
scrollView.smoothScrollTo(0,0);
}
diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWBreak.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWBreak.java
index f513cccf4e..c6a9cf3f86 100644
--- a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWBreak.java
+++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWBreak.java
@@ -27,8 +27,8 @@ public class SWBreak extends SWItem {
}
@Override
- public void generateDialog(View view, LinearLayout layout) {
- Context context = view.getContext();
+ public void generateDialog(LinearLayout layout) {
+ Context context = layout.getContext();
l = new TextView(context);
l.setId(View.generateViewId());
diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWButton.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWButton.java
index 4f22720091..afa28c1803 100644
--- a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWButton.java
+++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWButton.java
@@ -39,8 +39,8 @@ public class SWButton extends SWItem {
}
@Override
- public void generateDialog(View view, LinearLayout layout) {
- Context context = view.getContext();
+ public void generateDialog(LinearLayout layout) {
+ Context context = layout.getContext();
button = new Button(context);
button.setText(buttonText);
@@ -50,7 +50,7 @@ public class SWButton extends SWItem {
});
processVisibility();
layout.addView(button);
- super.generateDialog(view, layout);
+ super.generateDialog(layout);
}
@Override
diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWCheckbox.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWCheckbox.java
index 816fb79a97..ed96b37944 100644
--- a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWCheckbox.java
+++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWCheckbox.java
@@ -40,8 +40,8 @@ public class SWCheckbox extends SWItem {
}
@Override
- public void generateDialog(View view, LinearLayout layout) {
- Context context = view.getContext();
+ public void generateDialog(LinearLayout layout) {
+ Context context = layout.getContext();
// Get if there is already value in SP
Boolean previousValue;
previousValue = SP.getBoolean(preferenceId, false);
@@ -68,7 +68,7 @@ public class SWCheckbox extends SWItem {
}
});
layout.addView(checkBox);
- super.generateDialog(view, layout);
+ super.generateDialog(layout);
}
public void save(boolean value){
SP.putBoolean(preferenceID, value);
diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWEditString.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWEditString.java
index b464ae6316..d02f10acf0 100644
--- a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWEditString.java
+++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWEditString.java
@@ -27,28 +27,28 @@ public class SWEditString extends SWItem {
}
@Override
- public void generateDialog(View view, LinearLayout layout) {
- Context context = view.getContext();
+ public void generateDialog(LinearLayout layout) {
+ Context context = layout.getContext();
TextView l = new TextView(context);
- l.setId(view.generateViewId());
+ l.setId(layout.generateViewId());
l.setText(label);
l.setTypeface(l.getTypeface(), Typeface.BOLD);
layout.addView(l);
TextView c = new TextView(context);
- c.setId(view.generateViewId());
+ c.setId(layout.generateViewId());
c.setText(comment);
c.setTypeface(c.getTypeface(), Typeface.ITALIC);
layout.addView(c);
EditText editText = new EditText(context);
- editText.setId(view.generateViewId());
+ editText.setId(layout.generateViewId());
editText.setInputType(InputType.TYPE_CLASS_TEXT);
editText.setMaxLines(1);
editText.setText(SP.getString(preferenceId, ""));
layout.addView(editText);
- super.generateDialog(view, layout);
+ super.generateDialog(layout);
editText.addTextChangedListener(new TextWatcher() {
@Override
diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWEditUrl.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWEditUrl.java
index 6039577bff..04b02a5bc2 100644
--- a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWEditUrl.java
+++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWEditUrl.java
@@ -27,8 +27,8 @@ public class SWEditUrl extends SWItem {
}
@Override
- public void generateDialog(View view, LinearLayout layout) {
- Context context = view.getContext();
+ public void generateDialog(LinearLayout layout) {
+ Context context = layout.getContext();
TextView l = new TextView(context);
l.setId(View.generateViewId());
@@ -48,7 +48,7 @@ public class SWEditUrl extends SWItem {
editText.setMaxLines(1);
editText.setText(SP.getString(preferenceId, ""));
layout.addView(editText);
- super.generateDialog(view, layout);
+ super.generateDialog(layout);
editText.addTextChangedListener(new TextWatcher() {
@Override
diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWFragment.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWFragment.java
index 9e470fa687..a061f57eb6 100644
--- a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWFragment.java
+++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWFragment.java
@@ -27,7 +27,7 @@ public class SWFragment extends SWItem {
}
@Override
- public void generateDialog(View view, LinearLayout layout) {
+ public void generateDialog(LinearLayout layout) {
definition.getActivity().getSupportFragmentManager().beginTransaction().add(layout.getId(), fragment, fragment.getTag()).commit();
}
diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWHtmlLink.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWHtmlLink.java
index 1ee27be6ae..fd4ffdd524 100644
--- a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWHtmlLink.java
+++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWHtmlLink.java
@@ -39,8 +39,8 @@ public class SWHtmlLink extends SWItem {
}
@Override
- public void generateDialog(View view, LinearLayout layout) {
- Context context = view.getContext();
+ public void generateDialog(LinearLayout layout) {
+ Context context = layout.getContext();
l = new TextView(context);
l.setId(View.generateViewId());
diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWInfotext.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWInfotext.java
index f98fbee82f..91e5c2da2d 100644
--- a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWInfotext.java
+++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWInfotext.java
@@ -38,8 +38,8 @@ public class SWInfotext extends SWItem {
}
@Override
- public void generateDialog(View view, LinearLayout layout) {
- Context context = view.getContext();
+ public void generateDialog(LinearLayout layout) {
+ Context context = layout.getContext();
l = new TextView(context);
l.setId(View.generateViewId());
diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWItem.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWItem.java
index c82d4f5683..4f454b843d 100644
--- a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWItem.java
+++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWItem.java
@@ -78,7 +78,7 @@ public class SWItem {
return layout;
}
- public void generateDialog(View view, LinearLayout layout) {
+ public void generateDialog(LinearLayout layout) {
}
public void processVisibility() {
diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWPlugin.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWPlugin.java
index 06735ee72e..80f60eb678 100644
--- a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWPlugin.java
@@ -2,9 +2,11 @@ package info.nightscout.androidaps.setupwizard.elements;
import android.content.Context;
import android.view.View;
+import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
+import android.widget.TextView;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -24,6 +26,7 @@ public class SWPlugin extends SWItem {
private PluginType pType;
private RadioGroup radioGroup;
+ private int pluginDescription;
private boolean makeVisible = true;
@@ -31,8 +34,9 @@ public class SWPlugin extends SWItem {
super(Type.PLUGIN);
}
- public SWPlugin option(PluginType pType) {
+ public SWPlugin option(PluginType pType, int pluginDescription) {
this.pType = pType;
+ this.pluginDescription = pluginDescription;
return this;
}
@@ -42,8 +46,9 @@ public class SWPlugin extends SWItem {
}
@Override
- public void generateDialog(View view, LinearLayout layout) {
- Context context = view.getContext();
+ public void generateDialog(LinearLayout layout) {
+
+ Context context = layout.getContext();
radioGroup = new RadioGroup(context);
radioGroup.clearCheck();
@@ -52,6 +57,13 @@ public class SWPlugin extends SWItem {
radioGroup.setOrientation(LinearLayout.VERTICAL);
radioGroup.setVisibility(View.VISIBLE);
+ TextView pdesc = new TextView(context);
+ pdesc.setText(pluginDescription);
+ LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ params.setMargins(0, 0, 0, 40);
+ pdesc.setLayoutParams(params);
+ layout.addView(pdesc);
+
for (int i = 0; i < pluginsInCategory.size(); i++) {
RadioButton rdbtn = new RadioButton(context);
PluginBase p = pluginsInCategory.get(i);
@@ -61,6 +73,12 @@ public class SWPlugin extends SWItem {
rdbtn.setChecked(true);
rdbtn.setTag(p);
radioGroup.addView(rdbtn);
+ params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ params.setMargins(80, 0, 0, 0);
+ TextView desc = new TextView(context);
+ desc.setText(p.getDescription());
+ desc.setLayoutParams(params);
+ radioGroup.addView(desc);
}
radioGroup.setOnCheckedChangeListener((group, checkedId) -> {
@@ -74,6 +92,6 @@ public class SWPlugin extends SWItem {
MainApp.bus().post(new EventSWUpdate());
});
layout.addView(radioGroup);
- super.generateDialog(view, layout);
+ super.generateDialog(layout);
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWRadioButton.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWRadioButton.java
index e034e86ba8..80346c433c 100644
--- a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWRadioButton.java
+++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWRadioButton.java
@@ -38,8 +38,8 @@ public class SWRadioButton extends SWItem {
}
@Override
- public void generateDialog(View view, LinearLayout layout) {
- Context context = view.getContext();
+ public void generateDialog(LinearLayout layout) {
+ Context context = layout.getContext();
// Get if there is already value in SP
String previousValue = SP.getString(preferenceId, "none");
radioGroup = new RadioGroup(context);
@@ -62,7 +62,7 @@ public class SWRadioButton extends SWItem {
save(values()[i]);
});
layout.addView(radioGroup);
- super.generateDialog(view, layout);
+ super.generateDialog(layout);
}
public SWRadioButton preferenceId(int preferenceId) {
diff --git a/app/src/main/java/info/nightscout/utils/DateUtil.java b/app/src/main/java/info/nightscout/utils/DateUtil.java
index 441449e8ee..7d7db3f5a7 100644
--- a/app/src/main/java/info/nightscout/utils/DateUtil.java
+++ b/app/src/main/java/info/nightscout/utils/DateUtil.java
@@ -135,6 +135,11 @@ public class DateUtil {
return MainApp.gs(R.string.minago, mins);
}
+ public static String minAgoShort(long time) {
+ Integer mins = (int) ((time - now()) / 1000 / 60);
+ return (mins > 0 ? "+" : "") + mins.toString();
+ }
+
public static String hourAgo(long time) {
double hours = (now() - time) / 1000d / 60 / 60;
return MainApp.gs(R.string.hoursago, hours);
diff --git a/app/src/main/java/info/nightscout/utils/PercentageSplitter.java b/app/src/main/java/info/nightscout/utils/PercentageSplitter.java
index 53e50466b5..40dfdf2455 100644
--- a/app/src/main/java/info/nightscout/utils/PercentageSplitter.java
+++ b/app/src/main/java/info/nightscout/utils/PercentageSplitter.java
@@ -8,14 +8,23 @@ import java.util.regex.Pattern;
*/
public class PercentageSplitter {
+ // "Profile name (200%,2h)"
+ private static final Pattern percentagePattern = Pattern.compile("(.+)\\(\\d+%,\\d+h\\)");
+ // "Profile name (200%)"
+ private static final Pattern percentageShiftPattern = Pattern.compile("(.+)\\(\\d+%\\)");
+
+ /** Removes the suffix for percentage and timeshift from a profile name. */
public static String pureName(String name) {
- String newName = name;
- String s = "(.*)\\((\\d+)\\%\\)";
- Pattern r = Pattern.compile(s);
- Matcher m = r.matcher(name);
- if (m.find()) {
- newName = m.group(1);
+ Matcher percentageMatch = percentagePattern.matcher(name);
+ if (percentageMatch.find()) {
+ return percentageMatch.group(1).trim();
}
- return newName;
+
+ Matcher percentageShiftMatch = percentageShiftPattern.matcher(name);
+ if (percentageShiftMatch.find()) {
+ return percentageShiftMatch.group(1).trim();
+ }
+
+ return name;
}
}
diff --git a/app/src/main/java/info/nightscout/utils/StringUtils.java b/app/src/main/java/info/nightscout/utils/StringUtils.java
new file mode 100644
index 0000000000..de16f7964e
--- /dev/null
+++ b/app/src/main/java/info/nightscout/utils/StringUtils.java
@@ -0,0 +1,20 @@
+package info.nightscout.utils;
+
+/**
+ * class contains useful String functions
+ */
+public class StringUtils {
+
+ private StringUtils() {
+ // this constructor is private, since this class should not get instantiated
+ }
+
+ public static String removeSurroundingQuotes(String string) {
+ if (string.length() >= 2 && string.charAt(0) == '"'
+ && string.charAt(string.length() - 1) == '"') {
+ string = string.substring(1, string.length() - 1);
+ }
+
+ return string;
+ }
+}
diff --git a/app/src/main/res/layout/configbuilder_fragment.xml b/app/src/main/res/layout/configbuilder_fragment.xml
index e02b30b2c8..bb5da61cfd 100644
--- a/app/src/main/res/layout/configbuilder_fragment.xml
+++ b/app/src/main/res/layout/configbuilder_fragment.xml
@@ -18,420 +18,10 @@
android:layout_height="match_parent">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:padding="16dp" />
\ No newline at end of file
diff --git a/app/src/main/res/layout/configbuilder_single_category.xml b/app/src/main/res/layout/configbuilder_single_category.xml
new file mode 100644
index 0000000000..4c7d9787de
--- /dev/null
+++ b/app/src/main/res/layout/configbuilder_single_category.xml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/objectives_fragment.xml b/app/src/main/res/layout/objectives_fragment.xml
index ea2028f5b4..8f984be622 100644
--- a/app/src/main/res/layout/objectives_fragment.xml
+++ b/app/src/main/res/layout/objectives_fragment.xml
@@ -1,46 +1,41 @@
-
+ android:layout_height="wrap_content"
+ android:gravity="center_vertical"
+ android:orientation="horizontal"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
+ android:paddingTop="16dp"
+ android:visibility="gone">
-
+ android:layout_marginRight="16dp"
+ android:layout_weight="1"
+ android:text="Enable fake time and progress" />
-
-
-
-
-
-
-
-
+
-
-
+
+
diff --git a/app/src/main/res/layout/objectives_item.xml b/app/src/main/res/layout/objectives_item.xml
index 977a6f8f93..b6029e5842 100644
--- a/app/src/main/res/layout/objectives_item.xml
+++ b/app/src/main/res/layout/objectives_item.xml
@@ -1,162 +1,70 @@
+ android:layout_marginLeft="16dp"
+ android:layout_marginRight="16dp"
+ android:layout_marginTop="16dp"
+ app:cardBackgroundColor="@color/colorPrimary"
+ app:cardCornerRadius="2dp"
+ app:cardUseCompatPadding="true"
+ app:contentPadding="16dp">
+
+
+
+
+
+
+ android:layout_marginTop="8dp"
+ android:orientation="vertical" />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:text="@string/objectives_button_verify" />
+
diff --git a/app/src/main/res/layout/overview_fragment_nsclient.xml b/app/src/main/res/layout/overview_fragment_nsclient.xml
index edb624e97c..ad97d201a7 100644
--- a/app/src/main/res/layout/overview_fragment_nsclient.xml
+++ b/app/src/main/res/layout/overview_fragment_nsclient.xml
@@ -62,9 +62,9 @@
android:layout_gravity="right"
android:layout_weight="1"
android:gravity="center_vertical|center_horizontal"
- android:text="TempTarget"
android:paddingBottom="3dp"
android:paddingTop="3dp"
+ android:text="TempTarget"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="@color/mdtp_white" />
@@ -83,9 +83,9 @@
android:layout_height="match_parent"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
+ android:gravity="center_vertical|center_horizontal"
android:paddingBottom="3dp"
android:paddingTop="3dp"
- android:gravity="center_vertical|center_horizontal"
android:text="@string/initializing"
android:textAppearance="?android:attr/textAppearanceSmall" />
@@ -100,77 +100,61 @@
android:id="@+id/overview_bg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="top|left"
- android:gravity="center_vertical"
+ android:layout_gravity="center_vertical"
android:text="00.0"
- android:textSize="70dp"
+ android:textSize="40dp"
android:textStyle="bold" />
-
+ android:layout_gravity="center_vertical"
+ android:text="-0.5"
+ android:textSize="20sp"
+ android:textStyle="bold" />
-
-
-
-
-
-
-
-
+ android:layout_gravity="center_vertical"
+ android:layout_weight="0.5"
+ android:gravity="center_vertical|center_horizontal"
+ android:text="100%"
+ android:textSize="20sp"
+ android:textStyle="bold" />
-
+
-
-
+
@@ -519,8 +503,8 @@
+ android:orientation="horizontal"
+ android:paddingRight="5dp">
@@ -89,9 +89,9 @@
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
+ android:gravity="center_vertical|center_horizontal"
android:paddingBottom="3dp"
android:paddingTop="3dp"
- android:gravity="center_vertical|center_horizontal"
android:text="@string/initializing"
android:textAppearance="?android:attr/textAppearanceSmall" />
@@ -106,8 +106,7 @@
android:id="@+id/overview_bg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="top|left"
- android:gravity="center_vertical"
+ android:layout_gravity="center_vertical"
android:text="00.0"
android:textSize="90dp"
android:textStyle="bold" />
@@ -116,69 +115,51 @@
android:id="@+id/overview_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="top|left"
+ android:layout_gravity="center_vertical"
android:layout_marginTop="-15dp"
- android:gravity="center_vertical"
android:paddingLeft="-5dp"
android:paddingRight="-5dp"
android:text="→"
- android:textSize="90dp"
+ android:textSize="50sp"
android:textStyle="bold" />
-
+
+
-
-
-
-
-
-
-
-
-
-
+ android:gravity="center_vertical|center_horizontal"
+ android:text="100%"
+ android:textSize="50sp"
+ android:textStyle="bold" />
+
+
@@ -616,8 +597,8 @@
+ android:orientation="horizontal"
+ android:paddingRight="5dp">
-
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
Изчаква резултат от помпата
Разрешени телефонни номера
+XXXXXXXXXX;+YYYYYYYYYY
- За да доставите болус от %.2fЕ отговорете с код %s
- За да изпратите калибрация %.2f отговорете с код %s
+ За да доставите болус от %1$.2fЕ отговорете с код %2$s
+ За да изпратите калибрация %1$.2f отговорете с код %2$s
Болус отказан
Болус %.2fЕд беше подаден успешно
Подава болус %.2fЕ
@@ -292,13 +292,13 @@
Loop has been enabled
Loop is disabled
Loop is enabled
- %.2f ограничен до %.2f
+ %1$.2f ограничен до %2$.2f
Стойността %s е извън границите
Remote basal setting is not allowed
Remote command is not allowed
- To start basal %.2fU/h reply with code %s
- To suspend loop for %d minutes reply with code %s
- Temp basal %.2fU/h for %d min started successfully
+ To start basal %1$.2fU/h reply with code %2$s
+ To suspend loop for %1$d minutes reply with code %2$s
+ Temp basal %1$.2fU/h for %2$d min started successfully
Temp basal start failed
To stop temp basal reply with code %s
Temp basal canceled
@@ -406,7 +406,7 @@
Използвай краткоср. Δ вместо разлика от последната КЗ
Полезно при данни за КЗ с много шум
Разширени настройки
- Модел: %02X Протокол: %02X Код: %02X
+ Модел: %1$02X Протокол: %2$02X Код: %3$02X
Профил
По подразбиране: 3 Това е основен параметър в сигурността на OpenAPS. Той ограничава максималният базал да бъде 3 пъти най-голямата стойност от дневните базали. Не би трябвало да има нужа от промяна, защото от опит сме проверили, че максимумите са “3x от най-високия дневен; 4x от текущия”.
По подразбиране: 4\nТова е другият основен параметър в сигурността на OpenAPS, и другата половина от "3x от най-високия дневен; 4x от текущия". Това означава, че независимо от макс базал настроен в помпата, стойността на базала не може да е по-висока от тази стойност умножена по стойността на базала за текущият час от денонощието. Това е с цел да предпази от прекалено високи стойности на максималния базал преди да разбират как работи алгоритъма. Повечето от Вас няма да имат нужда от смяна на тази стойност и могат да се справят с настойки на другите параметри.
@@ -560,8 +560,6 @@
UPLD
БАЗА
УД.
- Заключен екран
- Закл
Когато включите Autosense feature трябва да въвеждате ВСИЧКИ въглехидрати. В противен случай те ще се изчисляват грешно като повишена чувствителност!!
чрез Среднопретеглената стойност
OK
@@ -584,7 +582,7 @@
Продължителност [мин.]
ПОМПА
Дата
- DIA от %f е твърде кратка - използвай %f вместо това!
+ DIA от %1$f е твърде кратка - използвай %2$f вместо това!
Със свободен пик по Oref
Пик на кривата на IOB
Време на пик [мин.]
@@ -629,7 +627,6 @@
Чете историята на помпата
Настройва базалният профил
Опитва се да възстанови връзката
- Доставянето на болуса и проверката на историята на помпата са неуспешни, моля, проверете помпата и ако е доставен болус го добавете като запис през Careportal
Задайте стъпка на базала 0.01 Е/ч
Dexcom G5 приложение (модифицирано)
Качвай данните за КЗ в NS
@@ -711,13 +708,13 @@
Състояние
Активност
Няма връзка от %d мин.
- %d%% (%d мин. остават)
+ %1$d%% (%2$d мин. остават)
Инициализация
Прекратен поради грешка
Прекратен от потребителя
Изпълнява
Отказва временен базал
- Задава временен базал (%d%% / %d min)
+ Задава временен базал (%1$d%% / %2$d min)
Болус (%.1f U)
Обновява
Исканата операция не се поддържа от помпата
@@ -727,12 +724,12 @@
Сега
Ниско ниво на резервоар на помпа
Батерията на помпата е слаба
- Помпата отчита грешка E%d: %s
+ Помпата отчита грешка E%1$d: %2$s
Необходимо е сверяване на часа в помпата
Отказването на временният базал беше потвърдено
Помпата е недостъпна. Не беше доставен болус.
Болусът беше неуспешен. За да сте сигурни, моля, проверете помпата, за да избегнете повторение на вече доставен болус. За да се избегнат бъгове болусите не се повтарят автоматично.
- Само %.2f U от искания болус от %.2f U е доставен поради грешка. Моля, проверете помпата, за да потвърдите това и да предприемете съответните действия.
+ Само %1$.2f U от искания болус от %2$.2f U е доставен поради грешка. Моля, проверете помпата, за да потвърдите това и да предприемете съответните действия.
Insight
Insight помпа
Статус
@@ -775,7 +772,7 @@
час
ден
седмица
- %ds изтича %s
+ %1$ds изтича %2$s
Статистика
Предварително свързване
Автоматично свързване при отваряне на AndroidAPS, преди връзка с помпата за намаляване на първоначалното забавяне
@@ -824,7 +821,7 @@
Използвате dev версия. Closed loop е деактивиран.
Engineering mode не е активиран и не е release версия
Прочита базалният профил
- "Историята на помпата се промени след извършване на изчислението за болус. Болусът не беше доставен. Моля, преизчислете дали все още е необходим болус. Ако се изисква същото болусно количество, моля, изчакайте две минути, тъй за това време болусите с едно и също количество са блокирани от съображения за безопасност "
+ "Историята на помпата се промени след извършване на изчислението за болус. Болусът не беше доставен. Моля, преизчислете дали все още е необходим болус.
" http://www.androidaps.org facebook: http://facebook.androidaps.org"
Старт на вр.цел за физ. активност
Старт на вр. цел за Eating soon
@@ -837,18 +834,18 @@
Closed loop е забранен в настройките
Аутосенс е забранен в настройките
SMB е забранен в настройките
- Ограничаване на макс. базална стойност до %.2f Е/ч поради %s
+ Ограничаване на макс. базална стойност до %1$.2f Е/ч поради %2$s
лимит на помпата
трябва да бъде положително число
множител на макс. базал
множител на макс. дневен базал
Болус беше доставен през последните 3 мин, пропуска SMB
Базалът е зададен коректно
- Ограничаване на максималната процентна стойност до %d%% поради %s
- Ограничаване на болус до %.1f Е поради %s
- Ограничаване на макс. IOB до %.1f Е поради %s
- Ограничаване на въглехидрати до %d гр. поради %s
- Ограничаване на IOB до %.1f Е поради %s
+ Ограничаване на максималната процентна стойност до %1$d%% поради %2$s
+ Ограничаване на болус до %1$.1f Е поради %2$s
+ Ограничаване на макс. IOB до %1$.1f Е поради %2$s
+ Ограничаване на въглехидрати до %1$d гр. поради %2$s
+ Ограничаване на IOB до %1$.1f Е поради %2$s
макс. стойност в настройките
опасно използване
Четенето на статуса се провали
@@ -870,7 +867,7 @@
Време
нулиране
Тази стойност се нарича Max IOB в контекста на OpenAPS. OpenAPS няма да добавя инсулин, ако текущата IOB е по-голяма от тази стойност
- Поискано: %.2fU Доставено: %.2fU Error code: %d
+ Поискано: %1$.2fU Доставено: %2$.2fU Error code: %3$d
Първо добавяне за инсулин
Второ добавяне за инсулин
Трето добавяне за инсулин
diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml
index e0cd78bd0d..5094c94624 100644
--- a/app/src/main/res/values-cs/strings.xml
+++ b/app/src/main/res/values-cs/strings.xml
@@ -204,7 +204,7 @@
Bolus %.2fU aplikován úspěšně
Chyba při aplikování bolusu
Vzdálený bolus není momentálně povolen
- K potvzení bolusu %.2fU odpověz SMS s kódem %s
+ K potvzení bolusu %1$.2fU odpověz SMS s kódem %2$s
SMS komunikátor
Povolená tel. čísla
+XXXXXXXXXX;+YYYYYYYYYY
@@ -273,12 +273,12 @@
Není vybrán žádný profil
Hodnota %s je mimo přednastavený rozsah
Vzdálené posílání příkazů není povoleno
- Na spuštění bazálu %.2fU/h odpověz SMS s kódem %s
+ Na spuštění bazálu %1$.2fU/h odpověz SMS s kódem %2$s
Na ukončení bazálu odpověz SMS s kódem %s
Dočaný bazál zastaven
Rušení dočasného bazálu selhalo
Spuštění dočasného bazálu selhalo
- Dočasný bazál %.2fU/h na %d minut spuštěn
+ Dočasný bazál %1$.2fU/h na %2$d minut spuštěn
Neznámý příkaz nebo chybná odpověď
Text na tlačítku:
Sacharidy:
@@ -354,7 +354,7 @@
Používat autodetekci senzitivity
Data detekce senzitivity
Ladící informace
- %.2f omezeno na %.2f
+ %1$.2f omezeno na %2$.2f
Odstranit záznam:
Krátkodobý průměr
Obnovit události z NS
@@ -414,7 +414,7 @@
Poslat do xDripu kalibraci %.1f ?
xDrip+ není nainstalován
xDrip nepřijímá kalibrace
- Odeslání kalibrace %.2f potvrďte kódem %s
+ Odeslání kalibrace %1$.2f potvrďte kódem %2$s
Kalibrace odeslána. Příjem musí být v xDripu povolený.
Vzdálené kalibrace nejsou povoleny
Odpojuji
@@ -482,7 +482,7 @@
Smyčka obnovena
Smyčka pozastavena
Vzdálený příkaz není povolen
- K pozastavení smyčky na %d minut odpověz SMS s kódem %s
+ K pozastavení smyčky na %1$d minut odpověz SMS s kódem %2$s
Chybná doba trvání
Zaznamenávat spuštění aplikace do NS
Ukončuji aplikaci, aby se nastavení projevilo.
@@ -525,8 +525,6 @@
hodin
Chybný profil !!!
IOB
- Zámek obrazovky
- Zámek
Zrušit
OK
Nastavení alarmů
@@ -573,7 +571,7 @@
Aktivovat profil
Zobrazovat prodloužený bolus v %
Datum
- DIA %f je příliž krátké - použito %f !
+ DIA %1$f je příliž krátké - použito %2$f !
Čas vrcholu IOB křivky
Vrchol křivky [min]
NEPLATNÝ
@@ -609,7 +607,7 @@
Čekání na spárování na pumpě
Nastavování dočasných cílů a vkládání ošetření na hodinkách Wear
Řízení z hodinek Wear
- Model: %02X Protokol: %02X Kód: %02X
+ Model: %1$02X Protokol: %2$02X Kód: %3$02X
]]>
Výstraha měření glykémie
Vypršel čas připojování
@@ -689,13 +687,13 @@
Stav
Aktivita
Žádné spojení %d min
- %d%% (%d min zbývá)
+ %1$d%% (%2$d min zbývá)
Inicializace
Vypnuto díky chybě
Vypnuto uživatelem
Beží
Rušení dočasného bazálu
- Nastavování doč. bazálu (%d%% / %d min)
+ Nastavování doč. bazálu (%1$d%% / %2$d min)
Bolus (%.1f U)
Obnovování
Požadovaná operace není pumpou podporována
@@ -707,11 +705,10 @@
Nastavení bazálního profilu
V zásobníku je málo inzulínu
Slabá baterie v pumpě
- Pumpa hlásí chybu E%d: %s
+ Pumpa hlásí chybu E%1$d: %2$s
Pokouším se obnovit spojení
- Provádění bolusu a čtení historie selhalo. Zkontrolujte pumpu a zadejte bolus přes péči
Provádění bolusu selhalo. Zdá se, že žádný bolus nebyl podán. Zkontrolujte pumpu a případně pošlete bolus znovu. Jako bezpečnostní opatření podání bolusu není opakováno.
- Pouze %.2f U z bolusu %.2f bylo podáno díky chybě. Zkontrolujte pumpu a proveďte nápravu.
+ Pouze %1$.2f U z bolusu %2$.2f bylo podáno díky chybě. Zkontrolujte pumpu a proveďte nápravu.
Varování o ukončeném dočasném bazálu bylo potvrzeno.
Varování
Prázdný
@@ -776,9 +773,7 @@
Rumunština
Čínština
Dospělý s nízkou citlivostí
- Accu-Chek Combo
- COMBO
- %d vyprší %s
+ %1$d vyprší %2$s
Stav keep-alive
Statistika
Připojování dopředu
@@ -827,7 +822,7 @@
Expertní mód povolen
Expertní mód není povolen a neběží vydaná verze
Načítám bazální profil
- Historie v pumpě se změnila po spočítání bolusu. Bolus nebyl proveden. Prosím spočítejte ho znovu, pokud je to stále potřeba. Pokud bude potřeba bolus stejné velikosti, počkejte 2 minuty, protože bolusy stejné velikosti jsou blokovány z bezpečnostních důvodů.
+ Historie v pumpě se změnila po spočítání bolusu. Bolus nebyl proveden. Prosím spočítejte ho znovu, pokud je to stále potřeba.
Bolus úspěšne podán, ale zápis se nezdařil. To se může stát pokud jsou podány bolusy stejné velikosti během 2 minut. Zkontrolujte historii pumpy a zadejte chybějící položky do ošetření. Ujistěte se, že nezadáváte stejnou velikost v rámci 1 minuty.
Odmítnut vysoký dočasný bazál, protože kalkulace neuvažovala poslední změny v historii pumpy
Obnovuji stav pumpy
@@ -883,18 +878,18 @@
Uzavřená smyčka zakázána v nastavení
Autosens zakázán v nastavení
SMB zakázáno v nastavení
- Max bazál omezen na %.2f U/h: %s
+ Max bazál omezen na %1$.2f U/h: %2$s
limit pumpy
pořadována kladná hodnota
maximální násobek bazálu
mazimální násobek nejvyššího bazálu
Odeslán bolus během posledních 3 minut, SMB přeskočeno
Bazál nastaven správně
- Bazál omezen na %d%%: %s
- Bolus omezen na %.1f U: %s
- Max IOB omezeno na %.1f U: %s
- Sacharidy omezeny na %d g: %s
- IOB omezeno na %.1f U: %s
+ Bazál omezen na %1$d%%: %2$s
+ Bolus omezen na %1$.1f U: %2$s
+ Max IOB omezeno na %1$.1f U: %2$s
+ Sacharidy omezeny na %1$d g: %2$s
+ IOB omezeno na %1$.1f U: %2$s
maximální hodnota v nastavení
pevný limit
nebezpečné použití
@@ -915,7 +910,7 @@
Doba, po které jsou všechny sacharidy považovány za strávené. Zbylé budou oříznuty
Čas
Zobrazovat kolonku poznámky v dialozích ošetření
- Požadováno: %.2fU Doručeno: %.2fU Chyba: %d
+ Požadováno: %1$.2fU Doručeno: %2$.2fU Chyba: %3$d
První přídavek izulínu
Druhý přídavek inzulínu
Třetí přídavek inzulínu
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index 91d8a73a3c..7bacd1afbb 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -212,7 +212,7 @@
Auf Pumpenergebnis warten
Kein Bluetooth-Adapter gefunden
Ferngesteuerter Bolus ist nicht erlaubt
- Um einen Bolus von %.2f IE abzugeben, antworte mit dem Code %s
+ Um einen Bolus von %1$.2f IE abzugeben, antworte mit dem Code %2$s
Korean
Limit erreicht
Falsches Pumpen-Passwort!
@@ -403,7 +403,6 @@
Ungültiges oder defektes Profil!
IOB
Lokales Profil
- Sperrbildschirm
Superbolus (%1$d Min.)
Loop pausiert
Pausiert (%1$d Min.)
@@ -493,7 +492,6 @@
Insgesamt %1$d Einträge erfolgreich hochgeladen
Dauer der Insulinwirkung
INS
- Sperr
%1$s benötigt Batterie-Optimierungs-Whitelisting, um korrekt arbeiten zu können
Veraltete Daten
Veraltete Daten seit [Min.]
@@ -512,7 +510,7 @@
Um die TBR abzubrechen, antworte mit dem Code %s
Bolus %.2f IE erfolgreich abgegeben
xDrip+ hat die Kalbrierung nicht erhalten
- Um die Kalibrierung %.2f zu senden, antworte mit dem Code %s
+ Um die Kalibrierung %1$.2f zu senden, antworte mit dem Code %2$s
Kalibrierung gesendet. Das Empfangen von Kalbrierungen muss in xDrip+ aktiviert sein.
Falsche/ungültige Telefonnummer
Loop wurde deaktiviert
@@ -526,22 +524,22 @@
Ferngesteuerte Kalibrierung ist nicht erlaubt
Ferngesteuerte Befehle sind nicht erlaubt
Erlaube externe Befehle per SMS
- Um das Loopen für %d Minuten zu pausieren, antworte mit dem Code %s
+ Um das Loopen für %1$d Minuten zu pausieren, antworte mit dem Code %2$s
TBR abgebrochen
Das Abbrechen der TBR ist fehlgeschlagen
Das Starten der TBR ist fehlgeschlagen
- TBR mitl %.2f IE/h für %d Min. wurde erfolgreich gestartet
+ TBR mitl %1$.2f IE/h für %2$d Min. wurde erfolgreich gestartet
Unbekannter Befehl oder falsche Antwort
Falsche Dauer
Einstellungen freischalten
- %.2f limitiert auf %.2f
+ %1$.2f limitiert auf %2$.2f
S-Bolus
- Model: %02X Protokoll: %02X Code: %02X
+ Model: %1$02X Protokoll: %2$02X Code: %3$02X
Empfindlichkeitserkennung
COB
Verstehen des Open Loops und der TBR-Empfehlungen
Verwende AMA Autosense
- Um eine BR mit %.2f IE/h zu starten, antworte mit dem Code %s
+ Um eine BR mit %1$.2f IE/h zu starten, antworte mit dem Code %2$s
Fiasp
Ultra-Rapid Oref
Kurzes durchschnittl. Delta
@@ -563,7 +561,7 @@
Peak Time [min]
IOB Curve Peak Time
Free-Peak Oref
- DIA von %f ist zu kurz - AAPS nutzt stattdessen %f!
+ DIA von %1$f ist zu kurz - AAPS nutzt stattdessen %2$f!
Möglicherweise ungenau, wenn zum Befüllen ein Bolus verwendet wurde!
Verhältnis
Aktiviere profil
@@ -681,7 +679,7 @@
Historie wird gelesen
Basalratenprofil wird aktualisiert
Verbindung wird wieder hergestellt
- Der abgegebene Bolus konnte nicht bestätigt werden. Bitte prüfe auf der Pumpe, ob ein Bolus abgegeben wurde und erstelle einen Eintrag im Careportal falls nötig.
+ Der abgegebene Bolus konnte nicht bestätigt werden. Bitte prüfe auf der Pumpe, ob ein Bolus abgegeben wurde. Sofern ein Bolus abgegeben wurde wird dieser zu den Behandlungen hinzugefügt sobald erneut eine Verbindung zur Pumpe zustande kommt.
Die Bolusabgabe ist fehlgeschlagen: Es wurde scheinbar kein Bolus abgegeben. Bitte prüfe auf der Pumpe, ob ein Bolus abgegeben wurde. Um doppelte Boli durch Programmfehler zu vermeiden, werden Boli nicht automatisch wiederholt.
Wegen eines Fehlers wurden nur %1$.2f IE von den angeforderten %2$.2f IE abgegeben. Bitte prüfe den abgegebenen Bolus auf der Pumpe.
Status wird aktualisiert
@@ -695,7 +693,7 @@
Diese Aktion wird von der Pumpe nicht unterstützt
Die Batterie in der Pumpe ist fast leer
Das Reservoir in der Pumpe ist fast leer
- Die Pumpe zeigt einen Fehler an E%d: %s
+ Die Pumpe zeigt einen Fehler an E%1$d: %2$s
Unsichere Verwendung: In der Pumpe ist nicht das erste Basalratenprofil gewählt. Der Loop wird deaktiviert bis dies korrigiert ist.
Unsichere Verwendung: Ein erweiterter oder Multiwave-Bolus ist aktiv. Der Loop wird für die nächsten 6 Stunden kein zusätzliches Insulin abgeben.
Bitte aktualisiere die Uhrzeit der Pumpe
@@ -722,7 +720,7 @@
%.2f IE/h
Keine Verbindung zur Pumpe: Es wurde kein Bolus abgegeben.
Fehler bei der Abgabe eines verlängerten Bolus
- Nach der Berechnung des Bolus hat sich die Pumpenhistorie geändert. Daher wurde kein Bolus abgegeben. Bitte prüfe, ob überhaupt noch ein Bolus benötigt wird. Wenn die gleiche Bolusmenge erforderlich ist, warte zwei Minuten ab, denn es werden aus Sicherheitsgründen keine gleich großen Boli abgegeben, wenn sie innerhalb von zwei Minuten angefordert wurden (unabhängig davon, ob sie verabreicht wurden oder nicht).
+ Nach der Berechnung des Bolus hat sich die Pumpenhistorie geändert. Daher wurde kein Bolus abgegeben. Bitte prüfe, ob überhaupt noch ein Bolus benötigt wird.
Der Bolus wurde erfolgreich abgegeben, aber nicht als Behandlungseintrag gespeichert. Dies kann passieren, wenn zwei kleine, gleich große Boli innerhalb von zwei Minuten verabreicht werden. Bitte überprüfe die Pumpenhistorie und Behandlungseinträge. Verwende das Careportal, um fehlende Einträge hinzuzufügen. Stelle sicher, dass keine Einträge für genau dieselbe Minute und dieselbe Menge hinzugefügt werden.
Status wird aktualisiert
Die Basalrate in der Pumpe hat sich geändert und wird aktualisiert
diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml
index 44f5874e25..cc10da9117 100644
--- a/app/src/main/res/values-el/strings.xml
+++ b/app/src/main/res/values-el/strings.xml
@@ -218,8 +218,8 @@
Περιμέντε για αποτέλεσμα
Επιτρεπτά τηλεφωνικά νούμερα
+XXXXXXXXXX;+YYYYYYYYYY
- "Για έγχυση bolus %.2fU SMS με κώδικα %s "
- "Για αποστολή βαθμονόμησης %.2f SMS με κώδικο %s "
+ "Για έγχυση bolus %1$.2fU SMS με κώδικα %2$s "
+ "Για αποστολή βαθμονόμησης %1$.2f SMS με κώδικο %2$s "
Αποτυχία Bolus
Bolus %.2fU παραδόθηκε επιτυχώς
Πάει να παραδόσει %.2fU
@@ -289,13 +289,13 @@
Το κύκλωμα ενεργοποιήθηκε
Κύκλωμα απενεργοποιημένο
Κύκλωμα ενεργοποιημένο
- %.2f limited to %.2f
+ %1$.2f limited to %2$.2f
Τιμή %s είναι έξω από τα όρια
"Δεν επιτρέπεται η απομακρυσμένη ρύθμιση βασικού ρυθμού "
Δεν επιτρέπεται απομακρυσμένη εντολή
- Για έναρξη βασικού %.2fU/h SMS με κωσικό %s
- Για αναστολή κυκλκώματος για %d λεπτών SMS με κωδικό %s
- Προσ.Ρυθμ.%.2fU/h για %d λεπτά ξεκίνησε επιτυχώς
+ Για έναρξη βασικού %1$.2fU/h SMS με κωσικό %2$s
+ Για αναστολή κυκλκώματος για %1$d λεπτών SMS με κωδικό %2$s
+ Προσ.Ρυθμ.%1$.2fU/h για %2$d λεπτά ξεκίνησε επιτυχώς
"Προσ.Ρυθμ.απέτυχε "
Για να σταματήσετε Προσ.Ρυθμ.SMS με κωδικό %s
Προσ.Ρυθμ.ακυρώθηκε
@@ -403,7 +403,7 @@
Χρησιμοποιείτε πάντα τη βραχυπρόθεσμη μέση γλυκεμική διαφορά αντί της διαφοράς των δύο τελευταίων τιμών
Χρήσιμο όταν δεδομένα από μη φιλτραρισμένες πηγές όπως το xDrip αποκτούν θόρυβο
Ρυθμίσεις για Προχωρημένους
- Model: %02X Protocol: %02X Code: %02X
+ Model: %1$02X Protocol: %2$02X Code: %3$02X
Προφίλ
"Προεπιλεγμένη τιμή: 3 Αυτό είναι ένα κλειδί ασφαλείας OpenAPS.Αυτό περιορίζει την αύξηση του βασικού x3 από την μεγαλύτερη τιμή του.Δεν χρειάζεται να το αλλάξετε "
Μόνο αριθμητικά ψηφία επιτρέπονται.
@@ -558,8 +558,6 @@
UPLD
BAS
EXT
- Κλείδωμα οθόνης
- Κλείδωμα
Ενεργοποιώντας το autosense θυμιθείτε να εισάγετε όλους τους υδατ. Διαφορετικά, οι αποκλίσεις των υδατανθράκων θα εντοπιστούν λανθασμένα ως αλλαγή ευαισθησίας
Σταθμισμένος μέσος όρος ευαισθησίας
OK
@@ -579,7 +577,7 @@
Free-Peak Oref
Γρήγορη δράση - Oref
Έξτρα Γρήγορη δράση - Oref
- "DIA για %f πολύ μικρή - χρησιμοποιήστε %f! "
+ "DIA για %1$f πολύ μικρή - χρησιμοποιήστε %2$f! "
ΕΝΕΡΓΟΠΟΙΗΣΗ ΠΡΟΦΙΛ
Ημερομηνία
ΜΗ ΕΓΚΥΡΟ
diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml
index 8c27102a55..aa5734631d 100644
--- a/app/src/main/res/values-es/strings.xml
+++ b/app/src/main/res/values-es/strings.xml
@@ -221,7 +221,7 @@
Esperando resultado
Números de teléfono permitidos
XXXXXXXXXX +; + YYYYYYYYYY
- Para entregar bolo %.2fU responder con código %s
+ Para entregar bolo %1$.2fU responder con código %2$s
Bolo falló
Bolo %.2fU entregado con éxito
Bolo %.2fU enviado correctamente
@@ -300,8 +300,8 @@
Asistente
Asistente configuración
No permitidos ajustes basales remotos
- Para iniciar basal %.2fU/h responder con código %s
- Basal temporal %.2fU/h para %d min iniciada correctamente
+ Para iniciar basal %1$.2fU/h responder con código %2$s
+ Basal temporal %1$.2fU/h para %2$d min iniciada correctamente
Fallo inicio basal temporal
Para parar basal temporal responder con código %s
Basal temporal cancelada
@@ -334,12 +334,12 @@
Sueco
Max U/h para el perfil base
"Max IOB basal OpenAPs puede emitir "
- Para enviar calibracion %.2f responder con código %s
+ Para enviar calibracion %1$.2f responder con código %2$s
Entregaré %.2fU
Duración de acitividad de insulina
- %.2f limitado a %.2f
+ %1$.2f limitado a %2$.2f
no permitido el mando remoto
- Para cancelar loop por %d minutos responde con código %s
+ Para cancelar loop por %1$d minutos responde con código %2$s
Rellenar/Llenar
Llenar/Rellenar cantidad de insulina estándar
mg/dl
@@ -420,7 +420,7 @@
Usa siempre delta media corto en vez de delta simple
Recomendado si los datos de origen no filtrados como xDrip son inestables.
Ajustes avancados
- Modelo: %02X Protocolo: %02X Codigo: %02X
+ Modelo: %1$02X Protocolo: %2$02X Codigo: %3$02X
Perfiles
"Valor por defecte: 3 Esto es valor de seguridad establecido pos OpenAPS. Limita tu base al máximo de x3 de tu base máxima. No necesitas cambiar esto, pero debes tener en cuenta, que esto se esta discutiento sobre „3 x max diario; 4x actual“ pro razones de seguridad. "
"Ajuste pro defecto: 4 Esto es la otra mitad de los ajustes de seguridad de OpenAPS y la otra mitad de \"3x max diario, 4x actual\". Esto significa, que tu base no puede ser mas alta que el numero que multiplica tu base. Esto es para evitar que las personas se encuentren en situaciones peligrosas por aumentar mucho la base sin entender el algoritmo del sistema. El ajuste por defecto es x4. La mayoría de las personas nunca tendra que cambiar estos ajustes, si no debe modificar otros ajustes en la terapia. "
@@ -577,8 +577,6 @@
UPLD
BAS
EXT
- Bloqueo de pantalla
- Bloqueo
Al activar autosens recuerda editar todos carbohidratos comidos. Si no, sensibilidad será calculada incorrectamente !!!
Sensitivity WeightedAverage
OK
@@ -598,7 +596,7 @@
Free-Peak Oref
Rapid-Acting Oref
Ultra-Rapid Oref
- DIA de %f demasiado corto - usando %f!
+ DIA de %1$f demasiado corto - usando %2$f!
ACTIVAR PERFIL
Fecha
INVALIDO
@@ -692,12 +690,12 @@
Estado
Actividad
Ninguna conexión por %d min
- %d%% (%d min restan)
+ %1$d%% (%2$d min restan)
Apagado por error
Apagado por usario
Funcionando
Cancelando TBR
- Poniendo TBR (%d%% / %d min)
+ Poniendo TBR (%1$d%% / %2$d min)
Emitiendo bolo (%.1f U)
Actualizando
"Acción no disponible en la bomba "
@@ -709,7 +707,7 @@
" Activando perfil base "
"Nivel del deposito bajo "
Bateria casi agotada
- La bomba muesta el error E%d: %s
+ La bomba muesta el error E%1$d: %2$s
Bajo
Vacio
Historial
@@ -718,8 +716,7 @@
Alerta
TBR cancelada, advertencia acceptada
Emisión del bolo fallada. Ningún bolo se ha emitido. Para asegurarse, por favor controle la bomba para evitar bolo doble. Para evitar bugs no se reinician bolos automaticamente.
- "Solo %.2f U del bolo mandado de %.2f U ha sido emitido por causa de un error. Por favorn controla la bomba para confirmar y toma acciones apropiadas. "
- "Fallo de emitir bolo y de controlar historical de la bomba.Por favor controla manualmente y crea un record en Careportal si el bolo ha sido emitido. "
+ "Solo %1$.2f U del bolo mandado de %2$.2f U ha sido emitido por causa de un error. Por favorn controla la bomba para confirmar y toma acciones apropiadas. "
Reestablecido conexión fallada.
"No hay suficiente insulina en el deposito para emitir bolo. "
"Error al emitir bolo prolongado. "
@@ -731,7 +728,7 @@
Actualizando estado bomba
Rechazando temporal alta ya que el calculo no consideró los cambios recientes en el historial de la bomba
El bolus se administró con éxito, pero no se pudo agregar la entrada al tratamiento. Esto puede suceder si se administran dos bolos pequeños del mismo tamaño en los últimos dos minutos. Verifique el historial de la bomba y las entradas de tratamiento y use Careportal para agregar entradas faltantes. Asegúrese de no agregar ninguna entrada para el mismo minuto exacto y la misma cantidad.
- El historial de la bomba ha cambiado después de que se realizó el cálculo del bolo. El bolo no fue entregado. Por favor, vuelva a calcular si aún se necesita un bolo. Si se requiere la misma cantidad de bolo, espere dos minutos ya que los bolos con la misma cantidad se bloquean cuando se solicita con menos de dos minutos entre ellos por seguridad (independientemente de si se administraron o no).
+ El historial de la bomba ha cambiado después de que se realizó el cálculo del bolo. El bolo no fue entregado. Por favor, vuelva a calcular si aún se necesita un bolo.
Leyendo perfil basal
Inicio TT Hipo
Ninguna acción seleccionada, nada sucederá
@@ -776,7 +773,7 @@
Conectar automáticamente cuando se abre AndroidAPS, antes de solicitar ningún comando de bomba, para reducir el retraso de la conexión
Estadísticas
Estado de Mantener-Activo
- %ds expira en %s
+ %1$ds expira en %2$s
Adulto resistente a la insulina
Habilitar SMB durante 6 h después de Carbohidratos, incluso con 0 COB. Solo posible con fuente BG con buen filtrado de datos como G5
Habilitar SMB siempre de forma independiente a los Bolos. Solo posible con fuente BG con buen filtrado de datos como G5
@@ -856,18 +853,18 @@
Loop cerrado desabilitado en preferencias
Autosens desabilitado en preferencias
SMB desabilitado en preferencias
- limitando max basal rate a %.2f U/h debido a %s
+ limitando max basal rate a %1$.2f U/h debido a %2$s
Limite de la bomba
Tiene que ser un valor positivo
Multiplicador basal máximo
Multiplicador diario basal máximo
Un Bolo entregado en los últimos 3 minutos
Basal establecida correctamente
- Limitando porcentaje máximo de tasa a %d%% debido a %s
- "Limitando el bolo a %.1f U debido a %s "
- Limitando max IOB to %.1f U debido a %s
- Limitando carbs to %d g debido a %s
- Limitando IOB to %.1f U debido a %s
+ Limitando porcentaje máximo de tasa a %1$d%% debido a %2$s
+ "Limitando el bolo a %1$.1f U debido a %2$s "
+ Limitando max IOB to %1$.1f U debido a %2$s
+ Limitando carbs to %1$d g debido a %2$s
+ Limitando IOB to %1$.1f U debido a %2$s
Valor máximo en preferencias
Limite estricto
uso no seguro
@@ -887,7 +884,7 @@
"Tiempo en el que cualquier comida se considera absorbida. Los carbohidratos restantes serán cortados. "
Tiempo
Mostrar el campo notas en dialogos de tratamientos
- Solicitado: %.2fU Entregado: %.2fU Codigo de error: %d
+ Solicitado: %1$.2fU Entregado: %2$.2fU Codigo de error: %3$d
Primer incremento insulina
Segundo incremento insulina
Tercer incremento insulina
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index 2bfca7cec0..834b9fe5eb 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -217,8 +217,8 @@
Attente de résultat
Numéros de tél autorisés
+XXXXXXXXXX;+YYYYYYYYYY
- Administrer bolus %.2fU retour avec un code %s
- Envoyer calibrage %.2fU retour avec un code %s
+ Administrer bolus %1$.2fU retour avec un code %2$s
+ Envoyer calibrage %1$.2fU retour avec un code %2$s
Bolus interrompu
Bolus %.2fU administré avec succès
" %.2fU va être administré"
@@ -289,13 +289,13 @@
Loop a été désactivé
"Loop est désactivé "
Loop est activé
- %.2f limité à %.2f
+ %1$.2f limité à %2$.2f
La valeur %s est hors limites strictes
Le réglage du basal à distance n\'est pas autorisé
La commande à distance n\'est pas autorisée
- Lancer le basal %.2fU/h retour avec un code %s
- Suspendre Loop pour %d minutes retour avec un code %s
- Démarrage réussi pour %.2fU/h de basal tempo pour %d min
+ Lancer le basal %1$.2fU/h retour avec un code %2$s
+ Suspendre Loop pour %1$d minutes retour avec un code %2$s
+ Démarrage réussi pour %1$.2fU/h de basal tempo pour %2$d min
Démarage échoué pour basal tempo
Arrêter basal tempo retour avec un code %s
Basal tempo annulé
@@ -403,7 +403,7 @@
Toujours utilisez une moyenne (delta) courte au lieu d’une moyenne normale
Utile quand les données provenant de sources non filtrées lorsque xDrip devient bruyant
Paramètres Avancés
- Modèle: %02X Protocole: %02X Code: %02X
+ Modèle: %1$02X Protocole: %2$02X Code: %3$02X
Profil
Valeur par défaut : true
Seuls les chiffres numériques qui se trouvent dans la fourchette %1$s - %2$s sont autorisés
@@ -556,8 +556,6 @@
UPLD
BAS
EXT
- Écran verrouillé
- verrouiller
En activant la fonction Autosens, n’oubliez pas de rentrer tout les glucides consommés. Sinon les déviations de glucides seront incorrectement identifiées alors que la sensibilité change !!
Sensibilité avec moyenne pondérée
OK
@@ -578,7 +576,7 @@
"Durée du Pic [min] "
"Insuline à Action Rapide Oref "
Insuline à Action Ultra Rapide Oref
- Durée d’Action pour %f trop courte - utiliser %f à la place!
+ Durée d’Action pour %1$f trop courte - utiliser %2$f à la place!
ACTIVER LE PROFIL
" Date"
INVALID
@@ -686,7 +684,7 @@
État
Activité
Pas de connexion depuis %d min
- %d%% (%d min restantes)
+ %1$d%% (%2$d min restantes)
Suspendu pour cause d\'erreur
Suspendu par l\'utilisateur
En cours d\'exécution
@@ -697,7 +695,7 @@
Utiliser les Super Micro Bolus au lieu des débits de base temporaires pour une action rapide
Détection des repas non annoncés
Annulation en cours du TBR
- "Paramétrer TBR (%d%% / %d min) "
+ "Paramétrer TBR (%1$d%% / %2$d min) "
"Administration du bolus en cours (%.1f U) "
Actualisation en cours
L\'opération demandée n\'est pas prise en charge par la pompe
@@ -709,7 +707,7 @@
Définir le profil basal
Niveau cartouche pompe bas
Niveau batterie pompe bas
- La pompe affiche l’erreur E%d: %s
+ La pompe affiche l’erreur E%1$d: %2$s
Bas
Vide
Normal
@@ -717,8 +715,7 @@
Warning
TBR ANNULÉ warning confirmé
Administration bolus échouée. Il semble qu’aucun bolus n’a été administré. Pour être sûr, Veuillez vérifier la pompe pour éviter un double bolus ensuite re bolusez une nouvelle fois
- Seulement %.2f U de %.2f U du bolus demandé a été administré dû à une erreur. Veuillez svp vérifier la pompe pour contrôler cela et prendre les mesures appropriées
- L’administration du bolus et la vérification de l’historique de la pompe ont échoué, Veuillez vérifier la pompe et créez un enregistrement bolus en utilisant Careportal tab si le bolus a été délivré
+ Seulement %1$.2f U de %2$.2f U du bolus demandé a été administré dû à une erreur. Veuillez svp vérifier la pompe pour contrôler cela et prendre les mesures appropriées
"Reconnexion après perte de connexion "
Pas assez d\'insuline restante dans le réservoir pour le bolus
Erreur administration bolus étendu
diff --git a/app/src/main/res/values-ga/strings.xml b/app/src/main/res/values-ga/strings.xml
index 2e44a58f76..f9004721b5 100644
--- a/app/src/main/res/values-ga/strings.xml
+++ b/app/src/main/res/values-ga/strings.xml
@@ -126,7 +126,7 @@
%d nóim ó shin
%.1fu ó shin
%.2f A/u
- %d%% (%d nóim fágtha)
+ %1$d%% (%2$d nóim fágtha)
Gníomhartha
GNÍ
Cuir
@@ -204,7 +204,7 @@
Léigh próifíl bunaidh
Léigh stair caidéil
Cumasaithe
- Socrú BRS (%d%% / %d nóim)
+ Socrú BRS (%1$d%% / %2$d nóim)
Tosaithe
Cealú BRS
Is ceallraí Caidéil íseal
diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml
index 39bdad7cc6..5a0d72f608 100644
--- a/app/src/main/res/values-it/strings.xml
+++ b/app/src/main/res/values-it/strings.xml
@@ -440,8 +440,8 @@
Trattamento
DUR:
Errore di somministrazione basale temporale
- Basale temporanea %.2fU/h for %d min avviata con successo
- Sospendi il loop per %d minuti riprendi %s
+ Basale temporanea %1$.2fU/h for %2$d min avviata con successo
+ Sospendi il loop per %1$d minuti riprendi %2$s
La calibrazione è stata inviata. La ricezione deve essere abilitata in xDrip.
Per interrompere la risposta basale della temperatura con il codice %s
+XXXXXXXXXX;+YYYYYYYYYY
diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml
index b5119364a9..21e0f5701d 100644
--- a/app/src/main/res/values-ko/strings.xml
+++ b/app/src/main/res/values-ko/strings.xml
@@ -224,8 +224,8 @@
결과 기다리는 중
허가된 전화번호
+XXXXXXXXXX;+YYYYYYYYYY
- 식사주입 %.2fU 을 실행하려면 %s 를 입력하고 답장하세요
- 보정값 %.2f을 전송하려면 %s 를 입력하고 답장하세요
+ 식사주입 %1$.2fU 을 실행하려면 %2$s 를 입력하고 답장하세요
+ 보정값 %1$.2f을 전송하려면 %2$s 를 입력하고 답장하세요
Bolus failed
Bolus %.2fU delivered successfully
%.2fU 주입 예정입니다.
@@ -295,13 +295,13 @@
Loop가 실행되었습니다.
Loop가 중지중입니다.
Loop가 실행중입니다.
- %.2f, %.2f으로 제한됨
+ %1$.2f, %2$.2f으로 제한됨
%s값이 하드리밋(Hard Limit)를 벗어났습니다
원격 기초주입설정이 허가되지 않았습니다
원격 명령이 허가되지 않았습니다
- 기초주입 %.2fU/h 을 실행하려면 %s 를 입력하고 답장하세요
- %d분동안 Loop 일시중지하려면 %s 를 입력하고 답장하세요
- Temp basal %.2fU/h for %d min started successfully
+ 기초주입 %1$.2fU/h 을 실행하려면 %2$s 를 입력하고 답장하세요
+ %1$d분동안 Loop 일시중지하려면 %2$s 를 입력하고 답장하세요
+ Temp basal %1$.2fU/h for %2$d min started successfully
Temp basal start failed
임시기초주입을 중지하려면 %s 를 입력하고 답장하세요
Temp basal canceled
@@ -409,7 +409,7 @@
단순델타값 대신 단기평균델타값을 항상 사용합니다.
xDrip의 혈당데이터에 노이즈가 심할경우 유용합니다.
고급 설정
- 모델: %02X 프로토콜: %02X 코드: %02X
+ 모델: %1$02X 프로토콜: %2$02X 코드: %3$02X
프로파일
기본값: 3\n이 값은 중요한 OpenAPS 안전장치입니다. 이 값의 역할은 펌프에 설정되어 있는 최대기초주입량보다 3배를 초과할 수 없게 제한하는 것입니다. 이 값을 변경할 필요는 없을 것이지만, 안전을 위해 "3x max daily; 4x current"이 의미하는 바를 알고 있어야 합니다.
기본값: 4\n이 값은 "3x max daily; 4x current"의 나머지 절반에 해당하는 또 다른 중요한 OpenAPS 안전장치입니다. 이 값은 펌프에 설정된 최대기초주입량과 관계없이, 설정된 현재시간의 기초주입량에 이 값을 곱한 양을 초과할 수 없게됩니다. 이는 알고리즘의 작동 방식을 이해하기 전에 과도하게 높은 최대 기본을 설정하여 위험한 상황에 빠지지 않도록 보호하기 위한 것입니다. 다시한번, 기본 값은 4배인 것을 알아두세요; 일반적으로 이것을 조정할 필요는 전혀 없으며, 대신 이 안전장치를 변경해야할것처럼 생각이 된다면, 다른 설정을 변경해야 할 가능성이 더 큽니다.
@@ -570,8 +570,6 @@
UPLD
BAS
EXT
- 화면 잠금
- 잠금
Autosense 기능을 켜면 모든 섭취된 탄수화물양을 입력하십시오. 그렇지 않으면 탄수화물 편차(deviations)가 민감도 변화로 잘못 인식될것입니다!!
민감도 가중평균
OK
@@ -591,7 +589,7 @@
Free-Peak Oref
Rapid-Acting Oref
Ultra-Rapid Oref
- "DIA %f는 너무 짧습니다. 대신 %f을 사용하세요!"
+ "DIA %1$f는 너무 짧습니다. 대신 %2$f을 사용하세요!"
프로파일 활성화하기
Date
INVALID
diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml
index 191cbc31ad..ed8e526d76 100644
--- a/app/src/main/res/values-nl/strings.xml
+++ b/app/src/main/res/values-nl/strings.xml
@@ -190,20 +190,18 @@
SMS Communicator
Geautoriseerde telefoon nummers
+XXXXXXXXXX;+YYYYYYYYYY
- Om het basaal %.2fU/u te starten antwoord met de code %s
+ Om het basaal %1$.2fU/u te starten antwoord met de code %2$s
Om het tijdelijke basaal te stoppen antwoord met de code %s
Bolus %.2fU succesvol toegediend
Bolus mislukt
- Om de bolus %.2fU toe te dienen antwoord met de code %s
+ Om de bolus %1$.2fU toe te dienen antwoord met de code %2$s
XDrip ontvangt geen callibraties
- Om calibratie %.2f te verzenden antwoord met de code %s
+ Om calibratie %1$.2f te verzenden antwoord met de code %2$s
Kalibratie verzonden. Het ontvangen van kalibraties moet actief zijn in xDrip.
한국어
Taal
Lokaal profiel
LP
- Vergrendel scherm
- Vergrendel
Loop
APS
Berekening met toepassing van limieten
@@ -574,12 +572,12 @@
Standaard waarde: 4 Dit is een combinatie van enerzijds het OpenAPS veiligheid limieten en anderzijds van “3 x max dagelijks basaal ; 4x actueel”. Dit betekent dat het basaal niet hoger kan ingesteld worden dan het ingestelde nummer keer het actueel basaal waarbij de limiet in de pomp geen invloed heeft.Dit is een veiligheidsmaatregel om te vermijden dat patiënten in gevaarlijke laag bereik komen zonder te snappen hoe het algoritme werkt. Nogmaals de standaard waarde is 4x; de meeste zullen deze waarde nooit moeten aanpassen maar zullen eerder andere waardes moeten aanpassen als ze tegen een limiet aanstoten.
Gedurende 1 week succesvol closed loop met KH ingave
ACTIVITIJD & FEEDBACK
- Model: %02X Protokoll: %02X Code: %02X
+ Model: %1$02X Protokoll: %2$02X Code: %3$02X
Verbonden gedurende %d s
Totaal %d gegevens geupload
- %.2f gelimitteerd tot %.2f
- Om de loop te onderbreken voor %d minuten antwoord met de code %s
- Tijdelijk basaal %.2fE/u voor %d minuten succesvol gestart
+ %1$.2f gelimitteerd tot %2$.2f
+ Om de loop te onderbreken voor %1$d minuten antwoord met de code %2$s
+ Tijdelijk basaal %1$.2fE/u voor %2$d minuten succesvol gestart
Gemiddelde gevoeligheid
Dit mag niet gebruikt worden om medische besluiten te trekken. Er is geen garantie voor dit programma voor de werking en het gebruik van dit programma. Tenzij anders beschreven in het copy right. Gebruikers en andere partijen leven dit programma zoals het momenteel is, dit zonder enige garantie.
Standaard waarde: 3.0 Dit is een belangrijke veiligheid parameter van OpenAPS. Dit limiteert je basaal met een max va 3 maal je hoogste basale dosis. Normaal hoef je deze niet te veranderen. Het is echter belangrijk dat je de ingebouwde limieten kent
@@ -587,7 +585,7 @@
Activeer profiel
Datum
Free-Peak Oref
- DIA van %f te kort - %f wordt inplaats gebruikt!\"
+ DIA van %1$f te kort - %2$f wordt inplaats gebruikt!\"
IOB curve piek tijd
Piek tijd [min]
Ongeldig
@@ -686,7 +684,7 @@
Vernieuw
Status
Geen verbinding gedurende %d minuten
- %d%% (%d min resterend)
+ %1$d%% (%2$d min resterend)
Herstel van verbroken verbindng
Waarschuwing
Pomp klok moet bijgesteld worden
@@ -703,15 +701,14 @@
Gestopt door de gebruiker
Actief
Insuline ampul is bijna leeg
- Pomp is in storing, controleer op de pomp: E%d %s
+ Pomp is in storing, controleer op de pomp: E%1$d %2$s
Bolus (%.1f E)
Instellen van basaal profiel
Lezen van pomp historiek
- Maar %.2f E van de gevraagde %.2f E zijn toegediend door een storing. Gelieve op de pomp te controleren en het gepaste gevolg uit te voeren.
- Toedienen en controleren van de bolus in de pomp historiek is mislukt, controleer de pomp en creëer een manuele bolus in het Careportal tabblad
+ Maar %1$.2f E van de gevraagde %2$.2f E zijn toegediend door een storing. Gelieve op de pomp te controleren en het gepaste gevolg uit te voeren.
Bolus toedienen mislukt. Waarschijnlijk is er geen bolus toegediend. Gelieve de pomp te controleren om een dubbele bolus te vermijden. Als bescherming tegen programmeerfouten worden bolussen niet automatisch opnieuw uitgevoerd.
Actie
- Instellen TBR (%d%% / %d min)
+ Instellen TBR (%1$d%% / %2$d min)
Onvoorzichtig gebruik: Vertraagde of multi wave bolussen zijn toegediend in de afgelopen 6 uur op het geselecteerde basaal patroon is niet 1. Loop is onderbroken tot de 6 uur nadat deze bolussen of andere basale patronen zijn gedetecteerd. Alleen normale bolussen en basaal patroon 1 zijn mogelijk binnen basaal patroon 1
Opgelet: verlengde en multi wafe bolussen zijn actief. Loop is naar onderdruk lage waardes enkel overgeschakeld gedurende 6 uur. Alleen gewone bolussen worden onderdsteund in loop modus.
Niet genoeg insuline aanwezig in reservoir voor de bolus
@@ -725,7 +722,7 @@
Ongeldig profiel: %s
Er kon geen verbinding met de pomp gemaakt worden. De Bolus is niet toegediend.
Vertraagde bolus toedien storing
- De pomp historiek is gewijzigd nadat de bolus berend was. De bolus is NIET toegediend. Programmeer een nieuwe bolus indien nodig. Als dezelfde bolus hoeveelheid moet worden toegediend, gelieve 2 minuten te wachten. Gelijke bolussen worden geweigerd om veiligheidsredenen (toegediend of niet).
+ De pomp historiek is gewijzigd nadat de bolus berend was. De bolus is NIET toegediend. Programmeer een nieuwe bolus indien nodig.
Bolus succesvol toegediend, maar toevoegend van de behandeling is gefaald. Dit kan voorvallen wanneer twee kleine bolussen van dezelfde grote gekozen waren gedurende de laatste 2 minuten. Controleer aub de pomphistoriek en de behandelingen, voeg de ontbrekende toe via het careportal. Let op dat je geen 2 dezelfde hoeveelheden hebt op hetzelfde ogenblik.
Tijdelijk basaal geweigerd doordat de berekeningen geen rekening hielden met de recente wijzigingen in de pomp historiek
Vernieuwen van pomp status
@@ -877,7 +874,7 @@
Sta verbinding tijdens roaming toe
Verbindings instellingen
Enkel tijdens opladen
- Gevraagd: %.2fU Afgegeven: %.2fU Storings code: %d
+ Gevraagd: %1$.2fU Afgegeven: %2$.2fU Storings code: %3$d
Românesc
Chinese
Autosens regelt de BG streefwaarde bij
@@ -900,11 +897,11 @@
Closed Loop modus gedeactiveerd in de voorkeuren
SMB gedeactiveerd in de voorkeuren
Ongekend
- Beperken van basaal tot max %.2f E/U wegens de %s
+ Beperken van basaal tot max %1$.2f E/U wegens de %2$s
Pomp limiet
dit moet een positieve waarde zijn
Basaal correct ingesteld
- Begrezen van max procentuele wijzigen tot %d%% want de %s
+ Begrezen van max procentuele wijzigen tot %1$d%% want de %2$s
SMB altijd gedeactiveerd doordat de gekozen BG bron geen optimale filtering toepast
SMB niet toegestaan in Open Loop modus
Niet verbonden (%d m)
@@ -924,7 +921,7 @@
Automatische Careportal gebeurtenissen
resterende van
op voorhand met
- %ds verloopt %s
+ %1$ds verloopt %2$s
" http://www.androidaps.org facebook: http://facebook.androidaps.org"
"Eerste insuline increment"
Tweede insuline increment
@@ -932,12 +929,12 @@
Eerste koolhydraten increment
Tweede koolhydraten increment
Derde koolhydraten increment
- Bolus beperkt tot %.1f E doordat %s
+ Bolus beperkt tot %1$.1f E doordat %2$s
Er is een bolus toegediend gedurende de afgelopen 3 minuten, SMB wordt overgeslagen
- Max IOB wordt beperkt tot %1.f E doordat %s
- Koolhydraten worden beperkt tot %d gr doordat %s
+ Max IOB wordt beperkt tot %1$1.f E doordat %2$s
+ Koolhydraten worden beperkt tot %1$d gr doordat %2$s
Maximum waarde in voorkeuren
- IOB gelimmiteerd tot %.1f E doordat %s
+ IOB gelimmiteerd tot %1$.1f E doordat %2$s
Automatische Insuline, infusieset wissels, batterij wissels en pomp alarmen naar NS uploaden
Tijdspanne waarbinnen elke maaltijd vollezig is opgenomen. Resterende KH worden niet mee gerekend.
Max totaal IOB dat OpenAPS niet kan overschrijden (E)
diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml
index 46ebc8995d..fe895d9232 100644
--- a/app/src/main/res/values-pl/strings.xml
+++ b/app/src/main/res/values-pl/strings.xml
@@ -241,8 +241,8 @@
Oczekiwanie na wynik
Dozwolone numery telefonów
+XXXXXXXXXX;+YYYYYYYYYY
- Aby dostarczyć bolus %.2fU wprowadź kod %s
- Aby wysłać kalibrację %.2f wprowadź kod %s
+ Aby dostarczyć bolus %1$.2fU wprowadź kod %2$s
+ Aby wysłać kalibrację %1$.2f wprowadź kod %2$s
Bolus nieudany
Bolus %.2fU dostarczony
Zamierzam dostarczyć %.2fU
@@ -314,13 +314,13 @@
Pętla (Loop) została włączona
Pętla (Loop) jest wyłączona
Pętla (Loop) jest włączona
- %.2f ograniczone do %.2f
+ %1$.2f ograniczone do %2$.2f
Wartość %s jest poza dopuszczalną granicą
Ustawienie zdalnej bazy nie jest dozwolone
Zdalne komendy nie są dozwolone
- Aby rozpocząć bazę %.2fU/h odpowiedz kodem %s
- Aby wstrzymać pętle na %d minut odpowiedz kodem %s
- Tymczasowa baza %.2fU/h przez %d min rozpoczęta
+ Aby rozpocząć bazę %1$.2fU/h odpowiedz kodem %2$s
+ Aby wstrzymać pętle na %1$d minut odpowiedz kodem %2$s
+ Tymczasowa baza %1$.2fU/h przez %2$d min rozpoczęta
Rozpoczęcie tymczasowej bazy nie powiodło się
Aby zatrzymać bazę tymczasową odpowiedz kodem %s
Baza tymczasowa anulowana
@@ -429,7 +429,7 @@
Zawsze używaj krótkiej średniej delty zamiast prostej delta
Użyteczne, jeżeli dane z niefiltrowanego źródła jak xDrip mają rozrzut.
Ustawienia zaawansowane
- Model: %02X Protocol: %02X Code: %02X
+ Model: %1$02X Protocol: %2$02X Code: %3$02X
Profil
Wartość domyślna: 3 To jest kluczowy współczynnik bezpieczeństwa OpenAPS. Ogranicza dawki bazowe do 3x twojej największej dawki bazowej. Prawdopodobnie nie będziesz musiał tego zmieniać, ale powinieneś być świadomy tego, co się rozumie przez “3x max daily; 4x current” dla współczynników bezpieczeństwa.
Wartość domyślna: 4 To jest drugi kluczowy współczynnik bezpieczeństwa OpenAPS, i druga wartość z “3x max daily; 4x current”. To oznacza, że Twoja dawka bazowa niezależnie od maksymalnej bazy ustawionej na pompie nie może być większ niż ta ustawiona ilość razy twoja aktuialna dawka bazowa. To ma na celu porzestrzec ludzi przed ustawieniem zbyt wysokiej dawki maksymalnej przed zrozumieniem jak działa algorytm. Ponownie, wartość domyślna to 4x; większość ludzi nie będzie potrzebowała tego zmienić i raczej będą potrzebować dostosować inne ustawienia, jeśli czują, że "wpadają" w ten współczynnik bezpieczeństwa.
@@ -594,8 +594,6 @@
UPLD
BAS
EXT
- Zablokuj obraz
- Zablokuj
Przy włączonej funkcji Autosens pamiętaj, żeby wprowadzać wszystkie węglowodany. W innym wypadku odchylenia węglowodanów będą błędnie identyfikowane jako zmiany wrażliwości !!
Wrażliwość ŚredniaWażona
OK
@@ -621,7 +619,7 @@
Swobodny-Pik Oref
Szybko-Działający Oref
Ultra-Szybki Oref
- DIA %f zbyt krótki - przyjmuję %f w zamian!
+ DIA %1$f zbyt krótki - przyjmuję %2$f w zamian!
Aktywuj profil
Data
NIEPRAWIDŁOWY
@@ -721,13 +719,13 @@
Stan
Aktywność
Brak połączenia przez %d min
- %d%% (%d min pozostało)
+ %1$d%% (%2$d min pozostało)
Rozpoczynanie
Wstrzymane z powodu błędu
Wstrzymane przez użytkownika
W działaniu
Anulowanie TBR
- Ustawianie TBR (%d%% / %d min)
+ Ustawianie TBR (%1$d%% / %2$d min)
Podawanie bolusa (%.1f U)
Odświeżanie
Żądana operacja nie jest obsługiwana przez pompę
@@ -740,7 +738,7 @@
Ustawianie profilu bazowego
Poziom zasobnika pompy jest niski
Poziom baterii pompy jest niski
- Pompa wskazuje błąd E%d: %s
+ Pompa wskazuje błąd E%1$d: %2$s
Niski
Pusty
Właściwy
@@ -749,8 +747,7 @@
TBR ANULOWANY ostrzeżenie zostało potwierdzone
Pompa nie została odnaleziona. Nie podano bolusa
Podanie bolusa nie powiodło się. Wygląda na to, że bolus nie został dostarczony. Aby upewnić się, sprawdź pompę, aby uniknąć podwójnego bolusa, a następnie ponownie podaj bolus. Aby uniknąć błędów, bolusy nie są automatycznie ponawiane.
- Only %.2f U z zamierzonego bolusa %.2f U zostało dostarczone z powodu błędu. Sprawdź pompę, aby sięupewnić i podejmij odpowiednie działania.
- Dostarczenie bolusa i sprawdzenie historii pompy nie powiodło się, należy sprawdzić pompę i ręcznie utworzyć zapis bolusa za pomocą zakładki PortalOpieki (CarePortal), jeśli bolus został dostarczony.
+ Only %1$.2f U z zamierzonego bolusa %2$.2f U zostało dostarczone z powodu błędu. Sprawdź pompę, aby sięupewnić i podejmij odpowiednie działania.
Odzyskiwanie po utracie połączenia
Za mało insuliny na bolus pozostało w zbiorniku
Błąd dostarczania bolusa przedłużonego
@@ -794,7 +791,7 @@
dzień
tydzień
s
- %ds wygasa %s
+ %1$ds wygasa %2$s
Status czuwania
Statystyki
Połącz z wyprzedzeniem
@@ -853,7 +850,7 @@
Tryb inżynierski nie włączony i nie pracuje wersja "kandydat do wydania" (RC)
%.2f U/h
Wczytuje profil bazowy
- Historia pompy zmieniła się po wykonaniu obliczenia bolusa. Bolus nie został dostarczony. Proszę, przelicz ponownie, jeśli wciąż potrzebujesz bolusa. If the same bolus amount is required, please wait two minutes since boluses with the same amount are blocked when requested with less than two minutes between them for safety (regardless of whether they were administered or not).
+ Historia pompy zmieniła się po wykonaniu obliczenia bolusa. Bolus nie został dostarczony. Proszę, przelicz ponownie, jeśli wciąż potrzebujesz bolusa.
Bolus został pomyślnie dostarczony, ale dodanie wpisu leczenia nie powiodło się. Może się to zdarzyć, jeśli w ciągu ostatnich dwóch minut podano dwa małe bolusy o tej samej wielkości. Sprawdź historię pompy i leczenie i użyj PortaluOpieki, aby dodać brakujące wpisy. Make sure not to add any entries for the exact same minute and same amount.
Odrzucenie wysokiej dawki tymczasowej ponieważ w obliczeniach nie uwzględniono ostatnio zmienionej historii pompy
Odświeżanie stanu pompy
@@ -874,18 +871,18 @@
Tryb zamkniętej pętli wyłączony w ustawieniach
Autosens wyłączony w ustawieniach
SMB wyłączone w ustawieniach
- Ograniczam maks. dawkę bazową do %.2f U/h z uwagi na %s
+ Ograniczam maks. dawkę bazową do %1$.2f U/h z uwagi na %2$s
ograniczenie pompy
wartość musi być dodatnia
mnożnik maksymalnej dawki bazowej
mnożnik maksymalnej dziennej dawki bazowej
Bolus został podany w ciągu ostatnich 3 minut, opuszczam SMB
Baza ustawiona prawidłowo
- Ograniczam maksymalną wartość w procentach do %d%% z uwagi na %s
- Ograniczam bolus do %.1f U z uwagi na %s
- Ograniczam max IOB do %.1f U z uwagi na %s
- Ograniczam węglow. do %d g z uwagi na %s
- Ograniczam IOB do %.1f U z uwagi na %s
+ Ograniczam maksymalną wartość w procentach do %1$d%% z uwagi na %2$s
+ Ograniczam bolus do %1$.1f U z uwagi na %2$s
+ Ograniczam max IOB do %1$.1f U z uwagi na %2$s
+ Ograniczam węglow. do %1$d g z uwagi na %2$s
+ Ograniczam IOB do %1$.1f U z uwagi na %2$s
maks. wartość w ustawieniach
twarde ograniczenie
niebezpieczne użycie
@@ -909,7 +906,7 @@
Czas, w którym każdy posiłek jest uznany za wchłonięty. Pozostałe węglowodany zostaną odcięte.
Czas
Pokaż pole uwag w oknie leczenia
- Zadano: %.2fU Dostarczono: %.2fU Kod błędu: %d
+ Zadano: %1$.2fU Dostarczono: %2$.2fU Kod błędu: %3$d
Pierwszy stopień przyrostu insuliny
Drugi stopień przyrostu insuliny
Trzeci stopień przyrostu insuliny
diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml
index 50faf76687..3fa72b73e6 100644
--- a/app/src/main/res/values-ro/strings.xml
+++ b/app/src/main/res/values-ro/strings.xml
@@ -195,8 +195,8 @@
Se așteaptă rezultatul
Numere de telefon permise
+XXXXXXXXXX;+YYYYYYYYYY
- Pentru a livra un bolus de %.2fU răspundeți cu codul %s
- Pentru a trimite calibrarea cu %.2f răspundeți cu codul %s
+ Pentru a livra un bolus de %1$.2fU răspundeți cu codul %2$s
+ Pentru a trimite calibrarea cu %1$.2f răspundeți cu codul %2$s
Bolus eșuat
Bolusul de %.2fU livrat cu succes
Se va livra un bolus de %.2fU
@@ -268,9 +268,9 @@
Bucla este activată
Setarea de la distanță a bazalei nu este permisă
Comanda de la distanță nu este permisă
- Pentru pornirea bazalei de %.2fU/h trimiteți codul %s
- Pentru suspendarea buclei pentru %d minute trimiteți codul %s
- Bazala temporară %.2fU/h pentru %d minute a fost trimisă cu succes
+ Pentru pornirea bazalei de %1$.2fU/h trimiteți codul %2$s
+ Pentru suspendarea buclei pentru %1$d minute trimiteți codul %2$s
+ Bazala temporară %1$.2fU/h pentru %2$d minute a fost trimisă cu succes
Trimiterea bazalei temporare a eșuat
Pentru oprirea bazalei temporare trimiteți codul %s
Bazala temporară a fost anulată
@@ -378,7 +378,7 @@
Folosește întotdeauna media scurtă a diferenței în locul diferenței simple
Folositor când datele vin de la surse nefiltrate, ca atunci când xDrip are măsurători zgomotoase.
Setări avansate
- Model: %02X Protocol: %02X Cod: %02X
+ Model: %1$02X Protocol: %2$02X Cod: %3$02X
Profil
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ță.
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.
@@ -389,7 +389,7 @@
Valoare implicită: 3.0\nAceasta este o setare ce privește impactul carbohidraților pe o durată de 5 minute. Valoarea implicită este de așteptat a fi 3mg/dl/5min. Aceasta afectează cât de mult se scade valoarea COB și cât de mare este presupusă a fi absorbția de carbohidrați în calcularea valorii prezise a glicemiei, atunci când glicemia scade cu mai mult decât s-a estimat sau când nu crește așa cum s-a așteptat.
Atenție!\nÎn mod normal nu este nevoie să modificați valorile de mai jos. Vă rog să APĂSAȚI AICI și să CITIȚI textul și să vă asigurați că l-ați ÎNȚELES înainte de a schimba valorile.
Se acceptă numai valori numerice.
- Se acceptă numai valori numerice între %1s - %2s.
+ Se acceptă numai valori numerice între %1$1s - %2$2s.
Acest câmp nu trebuie lăsat necompletat
Numărul de telefon este invalid
Număr de telefon SMS invalid
@@ -539,7 +539,7 @@
Se oprește bolusul
Se activează opțiuni pentru uzul în timpul zilei, cum ar fi SMB
Trebuie sa citiți wiki și măriți maxIOB pentru a obține SMB corect! Un start bun este maxIOB=media bolusurilor + 3x maxima bazalei din zi
- %.2f este limitată la %.2f
+ %1$.2f este limitată la %2$.2f
Valarea %s este mai mare decât limita fizică
Sincronizează cu NS
Hipo
@@ -589,8 +589,6 @@
UPLD
BAZ
EXT
- Ecran blocare
- Blocat
Trebuie introduși toți carbo la pornirea Autosens. În caz contrar, acțiunea carbo va fi percepută ca schimbare a sensibilității!
Mediană sensibilitate
OK
@@ -616,8 +614,7 @@
Oref Fără-Vârf
Oref Insulină-Rapidă
Oref Insulină-UltraRapidă
- Insulină personalizată
- DIA din %f prea scurtă - se folosește %f în schimb!
+ DIA din %1$f prea scurtă - se folosește %2$f în schimb!
Activează profil
Data
INVALID
@@ -717,13 +714,13 @@
Stare
Activitate
Fără conexiune de %d min
- %d%% (%d min rămase)
+ %1$d%% (%2$d min rămase)
Inițializare
Suspendat din cauza unei erori
Suspendat de utilizator
Funcționează
Se oprește TBR
- Se setează TBR (%d%% / %d min)
+ Se setează TBR (%1$d%% / %2$d min)
Bolusare (%.1f U)
Reîncărcare
Operațiunea nu este suportată de pompă
@@ -735,7 +732,7 @@
Se setează profilul bazalei
Nivelul insulinei din pompă este scăzut
Nivelul bateriei pompei este scăzut
- Pompa are eroarea: E%d: %s
+ Pompa are eroarea: E%1$d: %2$s
Scăzut
Gol
Normal
@@ -744,8 +741,7 @@
Alerta RBT ANULATĂ a fost confirmată
Pompa nu poate fi contactată. Nu s-a livrat niciun bolus
Livrare eșuată. Se pare că nu a fost livrat bolusul. Pentru siguranță, verificați în pompă pentru a evita bolusarea dublă. Pentru evitarea greșelilor, bolusurile nu sunt retrimise automat.
- Doar %.2f U din totalul cerut de %.2f U a fost livrat din cauza unei erori. Verificați pompa pentru confirmare și acționați corespunzător.
- Livrarea bolusului și verificarea istoricului pompei a eșuat, verificați pompa și creați manual un bolus folosind Careportal, dacă a fost livrat un bolus.
+ Doar %1$.2f U din totalul cerut de %2$.2f U a fost livrat din cauza unei erori. Verificați pompa pentru confirmare și acționați corespunzător.
Revenire după pierderea conexiunii
Nu este suficientă insulină în rezervor
Eroare de livrare a bolusului extins
@@ -789,7 +785,7 @@
z
săptămână
e
- %ds expiră %s
+ %1$ds expiră %2$s
Stare de menținere
Statistici
Conectare preventivă
@@ -848,7 +844,7 @@
Modul inginer nu este activat și nu este în versiunea lansată
%.2f U/h
Se citește profilul bazal
- Istoricul pompei s-a schimbat după calcularea bolusului. Bolusul nu a fost livrat. Recalculați dacă mai este necesar un bolus. Dacă aceeași cantitate de bolus este necesară, așteptați două minute deoarece două bolusuri cu aceeași valoare nu sunt permise într-un interval mai mic de două minute, din rațiuni de siguranță (indiferent dacă au fost livrate sau nu).
+ Istoricul pompei s-a schimbat după calcularea bolusului. Bolusul nu a fost livrat. Recalculați dacă mai este necesar un bolus.
Bolus livrat, dar nu s-a reușit înregistrarea evenimentului. Aceasta se poate întâmpla când două bolusuri mici de aceeași valoare sunt livrate în mai puțin de două minute. Verificați istoricul pompei și înregistrările tratamentelor și folosiți Careportal pentru adăugarea intrărilor lipsă. Asigurați-vă că nu adăugați intrări duble.
Se respinge temporara mare deoarece calculul nu a luat în calcul istoricul recent schimbat din pompă
Actualizare stare pompă
@@ -887,18 +883,18 @@
Modul buclă închisă dezactivat în preferințe
Autosens dezactivat în preferințe
SMB dezactivat în preferințe
- Se limitează maximul ratei bazale la %.2f U/o datorită %s
+ Se limitează maximul ratei bazale la %1$.2f U/o datorită %2$s
limită pompă
trebuie să fie o valoare pozitivă
maximul multiplicatorului bazalei
maximul zilnic al multiplicatorului bazalei
S-a livrat un bolus în ultimile 3 minute, nu se livrează SMB
Bazala setată corect
- Se limitează procentul ratei maxime la %d%% datorită %s
- Se limitează bolusul la %.1f U datorită %s
- Se limitează max IOB la %.1f U datorită %s
- Se limitează carbohidrații %d g datorită %s
- Se limitează IOB la %.1f U datorită %s
+ Se limitează procentul ratei maxime la %1$d%% datorită %2$s
+ Se limitează bolusul la %1$.1f U datorită %2$s
+ Se limitează max IOB la %1$.1f U datorită %2$s
+ Se limitează carbohidrații %1$d g datorită %2$s
+ Se limitează IOB la %1$.1f U datorită %2$s
valoare maximă în preferințe
folosire nesigură
Citire eșuată a stării
@@ -920,7 +916,7 @@
Timp
reset
Această valoare este denumită Max IOB în contextul OpenAPS, OpenAPS nu va adăuga mai multă insulină dacă IOB este mai mare ca această valoare
- Solicitat: %.2fU Livrat: %.2fU Cod eroare: %d
+ Solicitat: %1$.2fU Livrat: %2$.2fU Cod eroare: %3$d
Primul increment de insulină
Al doilea increment de insulină
Al treilea increment de insulină
@@ -958,12 +954,10 @@
Citire stare
Schimbările trebuie făcute în NS
Ignoră asistentul pentru setări
- Care este sursa de glicemii?
Apăsați butonul pentru a permite AndroidAPS să sugereze/facă schimbări ale bazalei
Apăsați butonul pentru a activa Obiectivele. După terminarea procesului de setare, alegeți fereastra Obiective pentru a face AndroidAPS complet funcțional.
Activați Obiectivele
Configurați plugin APS
- Nu există configurații exportate, decin nu se poate face import de configurații.
Configurați pluginul pentru Sensibilitate
Pluginul Sensibilitate este folosit pentru estimarea sensibilității și calcularea COB. Pentru mai multe info vizitați:
NSClient răspunde de conexiunea cu Nightscout. Puteți ignora această secțiune, dar nu veți putea completa obiectivele până nu îl configurați.
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index 43c3d8988a..c83690ce7a 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -131,7 +131,7 @@
введенные данные неверны
активный инсулин на помпе
предыдущий болюс
- модель: %02X протокол: %02X код: %02X
+ модель: %1$02X протокол: %2$02X код: %3$02X
пароль помпы
настройки помпы DanaR
дозаправка
@@ -337,7 +337,7 @@
результат
выполнить сейчас
отладка скрипта
- %.2f ограничено до %.2f
+ %1$.2f ограничено до %2$.2f
величина %s недопустима
открытый цикл
есть новое предложение
@@ -418,13 +418,13 @@
SMS коммуникатор
разрешенные телефонные номера
+XXXXXXXXXX;+YYYYYYYYYY
- чтобы начать базал %.2fU/h ответьте кодом %s
+ чтобы начать базал %1$.2fU/h ответьте кодом %2$s
чтобы прекратить врем базал ответьте кодом %s
болюс %.2fU доставлен успешно
доставка болюса не состоялась
- чтобы доставить болюс %.2fU ответьте кодом %s
+ чтобы доставить болюс %1$.2fU ответьте кодом %2$s
xdrip не получает калибровок
- чтобы отправить калибровку %.2f ответьте кодом %s
+ чтобы отправить калибровку %1$.2f ответьте кодом %2$s
калибровка отправлена. в xdrip должен быть активирован прием
неверный номер телефона для смс
зцикл был деактивирован
@@ -440,11 +440,11 @@
удаленная команда не разрешена
разрешить команды через смс
SMS
- для приостановки цикла на %d мин ответьте кодом %s
+ для приостановки цикла на %1$d мин ответьте кодом %2$s
врем базал отменен
отмена врем базала не состоялась
неуспех старта врем базала
- врем базал %.2fU/h на %d мин начат успешно
+ врем базал %1$.2fU/h на %2$d мин начат успешно
неизвестная команда или неверный ответ
неверное значение длительности
состояние:
@@ -546,7 +546,7 @@
Просмотреть расширенный болюс %
DanaRv2
дата
- pначение длительности работы инс %f слишком мало - применено %f
+ pначение длительности работы инс %1$f слишком мало - применено %2$f
расширенный болюс
Акуу-Зуфл Щкуа
час
@@ -554,8 +554,6 @@
время пика (в мин.)
НЕВЕРНО
Неверный профиль !!!
- блокировка экрана
- блок
отмена
OK
Голландский
diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml
index 3148682cdd..98edad9381 100644
--- a/app/src/main/res/values-sv/strings.xml
+++ b/app/src/main/res/values-sv/strings.xml
@@ -88,7 +88,6 @@
Konfigurationsverktyg
APS
BG-källa
- Begränsningar
Generella inställningar
Insulin
Loop
@@ -365,11 +364,11 @@
Status:
Fel duration:
Okänt kommando eller fel svar
- Tempbasal %.2f enheter/tim i %d min startad
+ Tempbasal %1$.2f enheter/tim i %2$d min startad
Fel vid start av temp basal
Misslyckades med att avbryta temp basal
Temp basal avbruten
- För att pausa loop i %d minuter, svara med kod %s
+ För att pausa loop i %1$d minuter, svara med kod %2$s
SMS
Tillåt fjärrstyrning via SMS
Kalibrering från andra källor inte tillåtna
@@ -384,13 +383,13 @@
Loop är avstängd
Ogiltigt telefonnummer för SMS
Kalibrering skickad. xDrip måste tillåta att ta emot kalibrering i inställningarna.
- För att skicka kalibrering %.2f, svara med kod %s
+ För att skicka kalibrering %1$.2f, svara med kod %2$s
xDrip tar inte emot kalibreringar
- För att ge bolus %.2f enheter, svara med kod %s
+ För att ge bolus %1$.2f enheter, svara med kod %2$s
Bolus avbruten
Bolus %.2f enheter tillförd
För att stoppa temp basal, svara med kod %s
- För att starta basal %.2f enheter/tim, svara med kod %s
+ För att starta basal %1$.2f enheter/tim, svara med kod %2$s
+XXXXXXXXXX;+YYYYYYYYYY
Godkända telefonnummer
SMS-tjänst
@@ -467,7 +466,7 @@
Ny rekommendation tillgänglig
Open Loop
Värde %s är utanför gränserna
- %.2f begränsad till %.2f
+ %1$.2f begränsad till %2$.2f
Beräkna nu
Beräknat behov
Profil
@@ -538,8 +537,6 @@
Ändra grund-ISF:
MUST NOT BE USED TO MAKE MEDICAL DECISIONS. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
ISF saknas i profilen. Använder standardvärde.
- Lås skärm
- Lås
mmol/l
%d m
mg/dl
@@ -584,7 +581,7 @@
Total grundbasal
Förkorta namnen på flikarna
Deltainställningar
- Modell: %02X Protokoll: %02X Kod: %02X
+ Modell: %1$02X Protokoll: %2$02X Kod: %3$02X
"Standardvärde: 4 Detta är en grundsten i OpenAPS säkerhet. Detta begränsar dina tempbasaler till maximalt 4x din nuvarande basal, oberoende av din max basalhastighet. Detta för att undvika att man av misstag gör farliga inställningar. Om man når taket i denna inställning så kanske ändringar i andra inställningar behövs. De flesta behöver inte ändra denna inställning. "
Standardvärde: 0.7 Med standardvärdet 0.7 kan autosens justera ner dina basaler, kvoter etc med upp till 30% för att kompensera för t ex tillfällig hög insulinkänslighet.
"Det kommer att användas för att ange \"Loggat av: \". "
@@ -606,7 +603,7 @@
Peaktid [min]
Rapid-Acting Oref
Ultra-Rapid Oref
- %s tim DIA är för kort. Använder %s istället!
+ %1$s tim DIA är för kort. Använder %2$s istället!
Aktivera profil
Datum
OGILTIG
@@ -691,14 +688,14 @@
Läge
Aktivitet
Ingen anslutning på %d min
- %d%% (%d min återstår)
+ %1$d%% (%2$d min återstår)
Initierar
Frånkopplad
Pausad pga fel
Pausad av användaren
Körs
Avbryter tempbasal
- Sätter tempbasal (%d%% / %d min)
+ Sätter tempbasal (%1$d%% / %2$d min)
Ger bolus (%.1f enheter)
Uppdaterar
Aldrig
@@ -712,7 +709,7 @@
Sätter basalprofil
Låg nivå i insulinreservoaren
Pumpbatteriet är svagt
- Pumpen visar felet: E%d: %s
+ Pumpen visar felet: E%1$d: %2$s
För att läsa pumpens historik, tryck och håll in ALERTS-knappen. VARNING: detta kan aktivera en bugg som orsakar att pumpen vägrar ansluta och kräver att en knapp trycks in på pumpen för att återgå. Det bör därför undvikas.
"För att läsa pumpens historik, tryck och håll in TDDS-knappen. VARNING: detta kan aktivera en bugg som orsakar att pumpen vägrar ansluta och kräver att en knapp trycks in på pumpen för att återgå. Det bör därför undvikas. "
Minimum: %3.1f enheter
@@ -728,8 +725,7 @@
Är du helt säker på att du vill läsa all pumphistorik och är medveten om konsekvenserna?
Varningen om avbruten tempbasal bekräftad
Bolus avbruten. Det verkar som om ingen bolus gavs. För att vara säker, vänligen kontrollera pumpen för att undvika dubbel bolus och prova sedan vid behov igen. För att förhindra fel orsakade av mjukvaran, försöker inte mjukvaran igen automatiskt.
- Endast %.2f enheter %.2f gavs pga ett fel. Vänligen verifiera på pumpen och vidta nödvändiga åtgärder.
- Leverans av bolus och verifiering av historiken misslyckades. Vänligen kontrollera på pumpen och lägg till bolusen manuellt under Careportal om den gått fram.
+ Endast %1$.2f enheter %2$.2f gavs pga ett fel. Vänligen verifiera på pumpen och vidta nödvändiga åtgärder.
Återansluter efter att ha tappat kontakten
Inte tillräckligt med insulin i reservoaren för att ge bolus
Förlängd bolus misslyckad
@@ -740,7 +736,7 @@
Behandling
Bolus avbruten
Avbryter bolus
- %.2f begränsat till %.2f
+ %1$.2f begränsat till %2$.2f
Värdet %s är utanför hård begränsning
Pumpen kunde inte nås. Bolus ej levererad.
Ändrad
@@ -776,7 +772,7 @@
tim
dag
vecka
- %ds går ut %s
+ %1$ds går ut %2$s
Statistik
Anslut på förhand
Anslut automatiskt när AAPS är öppet, innan något pumpkommando är skickat, för att snabba upp kommunikationen
@@ -832,7 +828,7 @@
Engineering Mode inte aktiverat och appen körs inte som release
%.2f E/h
Läser basalprofil
- Pumphistoriken ändrad efter att boluskalkylen gjordes. Bolusen har inte levererats. Vänligen gör en ny kalkyl vid behov. Om samma mängd insulin krävs, vänligen vänta två minuter eftersom appen begränsar likadana bolusar av säkerhetsskäl.
+ Pumphistoriken ändrad efter att boluskalkylen gjordes. Bolusen har inte levererats. Vänligen gör en ny kalkyl vid behov.
Bolusen levererad, men det gick inte att lägga till den i loggen. Detta kan hända om två små bolusar ges inom två minuter. Vänligen kontrollera pumpens historik och Careportal och lägg till om det saknas. Se till att inte lägga till två bolusar med samma mängd och samma tid.
Avböjer hög tempbasal eftersom kalkylen inte innefattade nyligen ändrad historik
Uppdaterar pumpsstatus
@@ -852,18 +848,18 @@
Closed Loop inaktiverat i Inställningar
Autosens inaktiverat i Inställningar
SMB inaktiverat i Inställningar
- Begränsar max basal till %.2f E/h pga %s
+ Begränsar max basal till %1$.2f E/h pga %2$s
pumpbegränsning
det måste vara ett positivt värde
multiplikator för max basal
multiplikator för daglig max basal
En bolus gavs för mindre än 3 min sedan. Hoppar över SMB
Basal justerad korrekt
- Begränsar max procent hastighet till %d%% pga %s
- Begränsar bolus till %.1f enheter pga %s
- Begränsar max IOB till %.1f pga %s
- Begränsar kolhydrater till %d g pga %s
- Begränsar IOB till %.1f pga %s
+ Begränsar max procent hastighet till %1$d%% pga %2$s
+ Begränsar bolus till %1$.1f enheter pga %2$s
+ Begränsar max IOB till %1$.1f pga %2$s
+ Begränsar kolhydrater till %1$d g pga %2$s
+ Begränsar IOB till %1$.1f pga %2$s
maxvärde i Inställningar
hård begränsning
osäker användning
@@ -887,7 +883,7 @@
Efter denna tid anses alla kolhydrater vara absorberade. Om det fortfarande finns COB, kommer dessa att tas bort ur beräkningen.
Tid
Visa anteckningar i behandlingsdialogerna
- Angivet: %.2f enheter. Levererat: %.2f enheter. Felkod: %d
+ Angivet: %1$.2f enheter. Levererat: %2$.2f enheter. Felkod: %3$d
Första snabbknabben för insulin
Andra snabbknabben för insulin
Tredje snabbknabben för insulin
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 430ba8ebba..f51a4209ca 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,4 +1,4 @@
-
+
Treatments safety
Max allowed bolus [U]
Max allowed carbs [g]
@@ -25,7 +25,7 @@
Synchronizes your data with Nightscout
State of the algorithm in 2016
State of the algorithm in 2017
- Most recent and most stable
+ Most recent algorithm for advanced users
Displays the current state of your loop and buttons for most common actions
Shows an ongoing notification with a short overview of what your loop is doing
Define a profile which is offline available.
@@ -33,12 +33,15 @@
Define a profile with only one time block.
Pump integration for Accu-Chek Combo pumps, requires having ruffy installed
Pump integration for DANA Diabecare R pumps
+ Pump integration for domestic DANA Diabecare R pumps
+ Pump integration for DANA Diabecare R pumps with upgraded firmware
Pump integration for DANA Diabecare RS pumps
Pump integration for Accu-Chek Insight pumps, requires having SightRemote installed
Pump integration for people who do multiple daily injections for their diabetes therapy
Pump integration for pumps which don\'t have any driver yet (Open Loop)
Sensitivity is calculated the same way like Oref0, but you can specify timeframe to the past. Minimal carb absorption is calculated from max carb absorption time from preferences.
Sensitivity is calculated from 24h data in the past and carbs (if not absorbed) are cut after time specified in preferences.
+ Sensitivity is calculated from 8h data in the past and carbs (if not absorbed) are cut after time specified in preferences. Plugin also calculates UAM.
Sensitivity is calculated as a weighted average from deviations. Newer deviations have higher weight. Minimal carb absorption is calculated from max carb absorption time from preferences. This algorithm is the fastest in following sensitivity changes.
Receive BG values from the patched Dexcom G5 app.
Receive BG values from Glimp.
@@ -285,8 +288,8 @@
Waiting for result
Allowed phone numbers
+XXXXXXXXXX;+YYYYYYYYYY
- To deliver bolus %.2fU reply with code %s
- To send calibration %.2f reply with code %s
+ To deliver bolus %1$.2fU reply with code %2$s
+ To send calibration %1$.2f reply with code %2$s
Bolus failed
Bolus %.2fU delivered successfully
Going to deliver %.2fU
@@ -359,13 +362,13 @@
Loop has been enabled
Loop is disabled
Loop is enabled
- %.2f limited to %.2f
+ %1$.2f limited to %2$.2f
Value %s is out of hard limits
Remote basal setting is not allowed
Remote command is not allowed
- To start basal %.2fU/h reply with code %s
- To suspend loop for %d minutes reply with code %s
- Temp basal %.2fU/h for %d min started successfully
+ To start basal %1$.2fU/h reply with code %2$s
+ To suspend loop for %1$d minutes reply with code %2$s
+ Temp basal %1$.2fU/h for %2$d min started successfully
Temp basal start failed
To stop temp basal reply with code %s
Temp basal canceled
@@ -437,6 +440,7 @@
Script debug
Use AMA autosens feature
Refresh events from NS
+ Delete treatments in the future
Eating Soon
Hypo
Activity
@@ -476,7 +480,7 @@
Useful when data from unfiltered sources like xDrip gets noisy.
Advanced Settings
key_advancedsettings
- Model: %02X Protocol: %02X Code: %02X
+ Model: %1$02X Protocol: %2$02X Code: %3$02X
Profile
Default value: 3 This is a key OpenAPS safety cap. What this does is limit your basals to be 3x (in this people) your biggest basal rate. You likely will not need to change this, but you should be aware that’s what is discussed about “3x max daily; 4x current” for safety caps.
Default value: 4 This is the other half of the key OpenAPS safety caps, and the other half of “3x max daily; 4x current” of the safety caps. This means your basal, regardless of max basal set on your pump, cannot be any higher than this number times the current level of your basal. This is to prevent people from getting into dangerous territory by setting excessively high max basals before understanding how the algorithm works. Again, the default is 4x; most people will never need to adjust this and are instead more likely to need to adjust other settings if they feel like they are “running into” this safety cap.
@@ -677,6 +681,7 @@
Which sensitivity algorithm should be used?
SENS
Sensitivity Oref0
+ Sensitivity Oref1
Sensitivity AAPS
Absorption settings
absorption_maxtime
@@ -694,8 +699,8 @@
UPLD
BAS
EXT
- Lock screen
- Lock
+ Keep screen on
+ Prevent Android to turn screen off. It will consume lot of energy when not plugged to power outlet.
By turning on Autosense feature remember to enter all eated carbs. Otherwise carbs deviations will be identified wrong as sensitivity change !!
Sensitivity WeightedAverage
OK
@@ -726,8 +731,7 @@
Free-Peak Oref
Rapid-Acting Oref
Ultra-Rapid Oref
- Custom insulin
- DIA of %f too short - using %f instead!
+ DIA of %1$f too short - using %2$f instead!
Activate profile
Date
INVALID
@@ -851,14 +855,14 @@
State
Activity
No connection for %d min
- %d%% (%d min remaining)
- %.1f %s (%s)
+ %1$d%% (%2$d min remaining)
+ %1$.1f %2$s (%3$s)
Initializing
Suspended due to error
Suspended by user
Running
Cancelling TBR
- Setting TBR (%d%% / %d min)
+ Setting TBR (%1$d%% / %2$d min)
Bolusing (%.1f U)
Refreshing
Requested operation not supported by pump
@@ -871,7 +875,7 @@
Setting basal profile
Pump cartridge level is low
Pump battery is low
- The pump is showing the error E%d: %s
+ The pump is showing the error E%1$d: %2$s
Low
Empty
Normal
@@ -880,8 +884,8 @@
TBR CANCELLED warning was confirmed
The pump could not be reached. No bolus was given
Bolus delivery failed. It appears no bolus was delivered. To be sure, please check the pump to avoid a double bolus and then bolus again. To guard against bugs, boluses are not automatically retried.
- Only %.2f U of the requested bolus of %.2f U was delivered due to an error. Please check the pump to verify this and take appropriate actions.
- Delivering the bolus and verifying the pump\'s history failed, please check the pump and manually create a bolus record using the Careportal tab if a bolus was delivered.
+ Only %1$.2f U of the requested bolus of %2$.2f U was delivered due to an error. Please check the pump to verify this and take appropriate actions.
+ Delivering the bolus and verifying the pump\'s history failed, please check the pump and manually. If a bolus was delivered, it will be added to treatments during the next connection to the pump.
Recovering from connection loss
Not enough insulin for bolus left in reservoir
Extended bolus delivery error
@@ -925,7 +929,7 @@
day
week
s
- %ds expires %s
+ %1$ds expires %2$s
Keep-alive status
Statistics
Connect preemptively
@@ -1005,7 +1009,7 @@
Engineering mode not enabled and not on release branch
%.2f U/h
Reading basal profile
- The pump history has changed after the bolus calculation was performed. The bolus was not delivered. Please recalculate if a bolus is still needed. If the same bolus amount is required, please wait two minutes since boluses with the same amount are blocked when requested with less than two minutes between them for safety (regardless of whether they were administered or not).
+ The pump history has changed after the bolus calculation was performed. The bolus was not delivered. Please recalculate if a bolus is still needed.
Bolus successfully delivered, but adding the treatment entry failed. This can happen if two small boluses of the same size are administered within the last two minutes. Please check the pump history and treatment entries and use the Careportal to add missing entries. Make sure not to add any entries for the exact same minute and same amount.
Rejecting high temp since calculation didn\'t consider recently changed pump history
Refreshing pump state
@@ -1026,7 +1030,7 @@
Closed loop mode disabled in preferences
Autosens disabled in preferences
SMB disabled in preferences
- Limiting max basal rate to %.2f U/h because of %s
+ Limiting max basal rate to %1$.2f U/h because of %2$s
pump limit
openapsma_max_basal
openapsama_current_basal_safety_multiplier
@@ -1037,12 +1041,12 @@
openapsma_max_iob
A bolus was delivered within the last 3 minutes, skipping SMB
Basal set correctly
- Limiting max percent rate to %d%% because of %s
+ Limiting max percent rate to %1$d%% because of %2$s
treatmentssafety_maxbolus
- Limiting bolus to %.1f U because of %s
- Limiting max IOB to %.1f U because of %s
- Limiting carbs to %d g because of %s
- Limiting IOB to %.1f U because of %s
+ Limiting bolus to %1$.1f U because of %2$s
+ Limiting max IOB to %1$.1f U because of %2$s
+ Limiting carbs to %1$d g because of %2$s
+ Limiting IOB to %1$.1f U because of %2$s
max value in preferences
hard limit
treatmentssafety_maxcarbs
@@ -1083,7 +1087,7 @@
Select your language
language
openapsama_min_5m_carbimpact
- Asked: %.2fU Delivered: %.2fU Error code: %d
+ Asked: %1$.2fU Delivered: %2$.2fU Error code: %3$d
First insulin increment
Second insulin increment
Third insulin increment
@@ -1126,12 +1130,10 @@
Read status
Changes must be done in NS
Skip setup wizard
- Where should blood glucose(BG) data be comming from ?\n
Press the button below to enable AndroidAPS to suggest/make basal changes
Press the button below to enable Objectives. Look in the Objectives tab, after you finish this wizard, to make AndroidAPS completely functional.\n
Enable Objectives
Configure APS plugin
- Exported configuration is missing thus import configuration is not possible.\n
startupwizard_processed
Configure Sensitivity plugin
Sensitivity plugin is used for sensitivity detection and COB calculation. For more info visit:
@@ -1140,7 +1142,7 @@
Please remember: new insulin profiles require DIA at least 5h. DIA 5-6h on new profile is equal to DIA 3h on old insulin profiles.
Configure BG source
Please select source of profile. If patient is a child you should use NS profile. If there is nobody following you on Nightscout you will probably prefer Local profile. Please remember that you are only selecting the profile source. To use it you must activate it by executing \"Profile switch\"
- Select one from availables algorithms. They are sorted from oldest to newest. Newer algorithm is usualy more powerfull and more aggresive. Thus if you are new looper you may probably start with AMA and not with latest one. Do not forget to read the OpenAPS documentation and configure it before use.
+ Select one from availables algorithms. They are sorted from oldest to newest. Newer algorithm is usually more powerful and more aggresive. Thus if you are new looper you may probably start with AMA and not with latest one. Do not forget to read the OpenAPS documentation and configure it before use.
Start your first objective
Permission
Ask for permission
@@ -1168,6 +1170,38 @@
Open navigation
Close navigation
Plugin preferences
+ Completed, well done!
+ Not completed yet
+ Time elapsed
+ %1$d. Objective
Poctech
Receive BG values from Poctech app
+ high_temptarget_raises_sensitivity
+ low_temptarget_lowers_sensitivity
+ High temptarget raises sensitivity
+ = 100]]>
+ Low temptarget lowers sensitivity
+
+ Invalid pump setup, check the docs and verify that the Quick Info menu is named "QUICK INFO" using the 360 configuration software.
+ Custom
+ lockscreen
+ Large Time Difference
+ Large time difference:\nTime in pump is off by more than 1.5 hours.\nPlease adjust the time manually on the pump and make sure that reading the history from the pump does not cause unexpected behaviour.\nIf possible, remove the history from the pump before changing the time or disable the closed loop for one DIA after the last wrong history entry but minimum one DIA from now.
+ keep_screen_on
+ Clean AndroidAPS started
+ Stored settings found
+ Attention: If you activate and connect to a hardware pump, AndroidAPS will copy the basal settings from the profile to the pump, overwriting the existing basal rate stored on the pump. Make sure you have the correct basal setting in AndroidAPS. If you are not sure or don\'t want to overwrite the basal settings on your pump, press cancel and repeat switching to the pump at a later time.
+
+
+ - %d day
+ - %d days
+
+
+ - %d hour
+ - %d hours
+
+
+ - %d minute
+ - %d minutes
+
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 1460f9dc65..0bfa713b18 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -27,6 +27,4 @@
-
-
diff --git a/app/src/main/res/xml/pref_absorption_oref1.xml b/app/src/main/res/xml/pref_absorption_oref1.xml
new file mode 100644
index 0000000000..d951366d27
--- /dev/null
+++ b/app/src/main/res/xml/pref_absorption_oref1.xml
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/xml/pref_openapssmb.xml b/app/src/main/res/xml/pref_openapssmb.xml
index c2eee2bc62..e23a364cb8 100644
--- a/app/src/main/res/xml/pref_openapssmb.xml
+++ b/app/src/main/res/xml/pref_openapssmb.xml
@@ -85,6 +85,18 @@
android:summary="@string/enableuam_summary"
android:title="@string/enableuam" />
+
+
+
+
diff --git a/app/src/main/res/xml/pref_overview.xml b/app/src/main/res/xml/pref_overview.xml
index af25a0cf9e..0550143010 100644
--- a/app/src/main/res/xml/pref_overview.xml
+++ b/app/src/main/res/xml/pref_overview.xml
@@ -4,6 +4,12 @@
+
+
c = constraintChecker.isClosedLoopAllowed();
Assert.assertEquals(true, c.getReasonList().size() == 2); // Safety & Objectives
@@ -92,7 +92,7 @@ public class ConstraintsCheckerTest {
@Test
public void isAutosensModeEnabledTest() throws Exception {
- objectivesPlugin.objectives.get(5).setStarted(new Date(0));
+ objectivesPlugin.objectives.get(5).setStartedOn(null);
when(SP.getBoolean(R.string.key_openapsama_useautosens, false)).thenReturn(false);
Constraint c = constraintChecker.isAutosensModeEnabled();
@@ -103,7 +103,7 @@ public class ConstraintsCheckerTest {
@Test
public void isAMAModeEnabledTest() throws Exception {
- objectivesPlugin.objectives.get(6).setStarted(new Date(0));
+ objectivesPlugin.objectives.get(6).setStartedOn(null);
Constraint c = constraintChecker.isAMAModeEnabled();
Assert.assertEquals(true, c.getReasonList().size() == 1); // Objectives
@@ -123,7 +123,7 @@ public class ConstraintsCheckerTest {
@Test
public void isSMBModeEnabledTest() throws Exception {
- objectivesPlugin.objectives.get(7).setStarted(new Date(0));
+ objectivesPlugin.objectives.get(7).setStartedOn(null);
when(SP.getBoolean(R.string.key_use_smb, false)).thenReturn(false);
when(MainApp.getConstraintChecker().isClosedLoopAllowed()).thenReturn(new Constraint<>(true));
diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesFragmentTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesFragmentTest.java
deleted file mode 100644
index ca47477905..0000000000
--- a/app/src/test/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesFragmentTest.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package info.nightscout.androidaps.plugins.ConstraintsObjectives;
-
-import org.junit.Test;
-import static org.junit.Assert.assertEquals;
-
-public class ObjectivesFragmentTest {
-
- @Test
- public void testModifyVisibility() {
-
- ObjectivesFragment fragment = new ObjectivesFragment();
-
- int currentPosition = 1;
- long prevObjectiveAccomplishedTime = 0;
- long objectiveStartedTime = 0;
- int durationInDays = 0;
- long objectiveAccomplishedTime = 0;
- boolean requirementsMet = false;
- boolean enableFakeValue = false;
-
- // previous objective is not accomplished yet
- assertEquals(0, fragment.modifyVisibility(currentPosition, prevObjectiveAccomplishedTime,
- objectiveStartedTime, durationInDays, objectiveAccomplishedTime, requirementsMet, enableFakeValue));
-
- // not started yet
- prevObjectiveAccomplishedTime = 4711;
- assertEquals(1, fragment.modifyVisibility(currentPosition, prevObjectiveAccomplishedTime,
- objectiveStartedTime, durationInDays, objectiveAccomplishedTime, requirementsMet, enableFakeValue));
-
- // started
- // time calculation is true, requirements met is false
- objectiveStartedTime = Long.MAX_VALUE;
- durationInDays = 0;
- assertEquals(2, fragment.modifyVisibility(currentPosition, prevObjectiveAccomplishedTime,
- objectiveStartedTime, durationInDays, objectiveAccomplishedTime, requirementsMet, enableFakeValue));
-
- // started
- // time calculation is true, requirements met is true
- objectiveStartedTime = 10;
- durationInDays = 0;
- requirementsMet = true;
- assertEquals(3, fragment.modifyVisibility(currentPosition, prevObjectiveAccomplishedTime,
- objectiveStartedTime, durationInDays, objectiveAccomplishedTime, requirementsMet, enableFakeValue));
-
- // finished
- objectiveStartedTime = Long.MAX_VALUE;
- durationInDays = 0;
- requirementsMet = true;
- objectiveAccomplishedTime = Long.MAX_VALUE;
- assertEquals(4, fragment.modifyVisibility(currentPosition, prevObjectiveAccomplishedTime,
- objectiveStartedTime, durationInDays, objectiveAccomplishedTime, requirementsMet, enableFakeValue));
-
-
- }
-
-}
\ No newline at end of file
diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesPluginTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesPluginTest.java
index 0b682b3164..d3dbcb3402 100644
--- a/app/src/test/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesPluginTest.java
+++ b/app/src/test/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesPluginTest.java
@@ -13,7 +13,6 @@ import java.util.Date;
import info.AAPSMocker;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.interfaces.Constraint;
-import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.utils.SP;
@@ -28,19 +27,19 @@ public class ObjectivesPluginTest {
ObjectivesPlugin objectivesPlugin;
@Test
- public void notStartedObjectivesShouldLimitLoopInvokation() throws Exception {
- objectivesPlugin.objectives.get(0).setStarted(new Date(0));
+ public void notStartedObjectivesShouldLimitLoopInvocation() throws Exception {
+ objectivesPlugin.objectives.get(0).setStartedOn(null);
Constraint c = new Constraint<>(true);
- c = objectivesPlugin.isLoopInvokationAllowed(c);
+ c = objectivesPlugin.isLoopInvocationAllowed(c);
Assert.assertEquals("Objectives: Objective 1 not started", c.getReasons());
Assert.assertEquals(Boolean.FALSE, c.value());
- objectivesPlugin.objectives.get(0).setStarted(new Date());
+ objectivesPlugin.objectives.get(0).setStartedOn(new Date());
}
@Test
public void notStartedObjective4ShouldLimitClosedLoop() throws Exception {
- objectivesPlugin.objectives.get(3).setStarted(new Date(0));
+ objectivesPlugin.objectives.get(3).setStartedOn(null);
Constraint c = new Constraint<>(true);
c = objectivesPlugin.isClosedLoopAllowed(c);
@@ -50,7 +49,7 @@ public class ObjectivesPluginTest {
@Test
public void notStartedObjective6ShouldLimitAutosensMode() throws Exception {
- objectivesPlugin.objectives.get(5).setStarted(new Date(0));
+ objectivesPlugin.objectives.get(5).setStartedOn(null);
Constraint c = new Constraint<>(true);
c = objectivesPlugin.isAutosensModeEnabled(c);
@@ -60,7 +59,7 @@ public class ObjectivesPluginTest {
@Test
public void notStartedObjective7ShouldLimitAMAMode() throws Exception {
- objectivesPlugin.objectives.get(6).setStarted(new Date(0));
+ objectivesPlugin.objectives.get(6).setStartedOn(null);
Constraint c = new Constraint<>(true);
c = objectivesPlugin.isAMAModeEnabled(c);
@@ -70,7 +69,7 @@ public class ObjectivesPluginTest {
@Test
public void notStartedObjective8ShouldLimitSMBMode() throws Exception {
- objectivesPlugin.objectives.get(7).setStarted(new Date(0));
+ objectivesPlugin.objectives.get(7).setStartedOn(null);
Constraint c = new Constraint<>(true);
c = objectivesPlugin.isSMBModeEnabled(c);
diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPluginTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPluginTest.java
index 76901e5db4..77a91046ab 100644
--- a/app/src/test/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPluginTest.java
+++ b/app/src/test/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPluginTest.java
@@ -19,7 +19,6 @@ import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin;
import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAPlugin;
-import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin;
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
import info.nightscout.androidaps.plugins.Source.SourceGlimpPlugin;
import info.nightscout.utils.SP;
@@ -42,7 +41,7 @@ public class SafetyPluginTest {
pump.getPumpDescription().isTempBasalCapable = false;
Constraint c = new Constraint<>(true);
- c = safetyPlugin.isLoopInvokationAllowed(c);
+ c = safetyPlugin.isLoopInvocationAllowed(c);
Assert.assertEquals("Safety: Pump is not temp basal capable", c.getReasons());
Assert.assertEquals(Boolean.FALSE, c.value());
}
diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/NSClientInternal/NsClientReceiverDelegateTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/NSClientInternal/NsClientReceiverDelegateTest.java
index 70e8d2c9b7..5bb1ca9a44 100644
--- a/app/src/test/java/info/nightscout/androidaps/plugins/NSClientInternal/NsClientReceiverDelegateTest.java
+++ b/app/src/test/java/info/nightscout/androidaps/plugins/NSClientInternal/NsClientReceiverDelegateTest.java
@@ -70,6 +70,14 @@ public class NsClientReceiverDelegateTest {
ev.mobileConnected = true;
ev.wifiConnected = true;
assertTrue(sut.calculateStatus(ev));
+
+ ev.ssid = "test";
+ when(SP.getString(anyInt(), anyString())).thenReturn("\"test\"");
+ assertTrue(sut.calculateStatus(ev));
+
+ ev.ssid = "\"test\"";
+ assertTrue(sut.calculateStatus(ev));
+
ev.wifiConnected = false;
assertTrue(sut.calculateStatus(ev));
diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPluginTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPluginTest.java
index dd648ebab0..8c8653074a 100644
--- a/app/src/test/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPluginTest.java
+++ b/app/src/test/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPluginTest.java
@@ -32,7 +32,7 @@ public class ComboPluginTest {
comboPlugin.setValidBasalRateProfileSelectedOnPump(false);
Constraint c = new Constraint<>(true);
- c = comboPlugin.isLoopInvokationAllowed(c);
+ c = comboPlugin.isLoopInvocationAllowed(c);
Assert.assertEquals("Combo: No valid basal rate read from pump", c.getReasons());
Assert.assertEquals(Boolean.FALSE, c.value());
comboPlugin.setPluginEnabled(PluginType.PUMP, false);
diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/Sensitivity/AbstractSensitivityPluginTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/Sensitivity/AbstractSensitivityPluginTest.java
new file mode 100644
index 0000000000..0a4b01cd64
--- /dev/null
+++ b/app/src/test/java/info/nightscout/androidaps/plugins/Sensitivity/AbstractSensitivityPluginTest.java
@@ -0,0 +1,51 @@
+package info.nightscout.androidaps.plugins.Sensitivity;
+
+import org.junit.Test;
+
+import info.nightscout.androidaps.interfaces.PluginDescription;
+import info.nightscout.androidaps.interfaces.SensitivityInterface;
+import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult;
+
+import static org.junit.Assert.assertEquals;
+
+public class AbstractSensitivityPluginTest {
+
+ private class SensitivityTestClass extends AbstractSensitivityPlugin {
+
+ public SensitivityTestClass() {
+ super(null);
+ }
+
+ public SensitivityTestClass(PluginDescription pluginDescription) {
+ super(pluginDescription);
+ }
+
+ @Override
+ public AutosensResult detectSensitivity(long fromTime, long toTime) {
+ return null;
+ }
+ }
+
+ @Test
+ public void fillResultTest() {
+ SensitivityTestClass sut = new SensitivityTestClass();
+
+ AutosensResult ar = sut.fillResult(1d, 1d, "1",
+ "1.2", "1", 12, 0.7d, 1.2d);
+ assertEquals(1, ar.ratio, 0.01);
+
+ ar = sut.fillResult(1.2d, 1d, "1",
+ "1.2", "1", 40, 0.7d, 1.2d);
+ assertEquals(1.16, ar.ratio, 0.01);
+
+ ar = sut.fillResult(1.2d, 1d, "1",
+ "1.2", "1", 50, 0.7d, 1.2d);
+ assertEquals(1.2, ar.ratio, 0.01);
+
+ ar = sut.fillResult(1.2d, 1d, "1",
+ "1.2", "1", 50, 0.7d, 1.1d);
+ assertEquals(1.1, ar.ratio, 0.01);
+ }
+
+
+}
diff --git a/app/src/test/java/info/nightscout/androidaps/queue/CommandQueueTest.java b/app/src/test/java/info/nightscout/androidaps/queue/CommandQueueTest.java
index dd6493fd66..29c9128186 100644
--- a/app/src/test/java/info/nightscout/androidaps/queue/CommandQueueTest.java
+++ b/app/src/test/java/info/nightscout/androidaps/queue/CommandQueueTest.java
@@ -15,6 +15,8 @@ import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
+import java.util.Date;
+
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.data.ConstraintChecker;
@@ -24,9 +26,11 @@ import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.PumpMDI.MDIPlugin;
+import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.androidaps.queue.commands.Command;
import info.nightscout.utils.ToastUtils;
+import static info.nightscout.utils.DateUtil.now;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -36,7 +40,7 @@ import static org.mockito.Mockito.when;
*/
@RunWith(PowerMockRunner.class)
-@PrepareForTest({MainApp.class, ConfigBuilderPlugin.class, ToastUtils.class, Context.class})
+@PrepareForTest({MainApp.class, ConfigBuilderPlugin.class, ToastUtils.class, Context.class, TreatmentsPlugin.class})
public class CommandQueueTest extends CommandQueue {
String validProfile = "{\"dia\":\"3\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"},{\"time\":\"2:00\",\"value\":\"110\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"0.1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}";
@@ -142,6 +146,11 @@ public class CommandQueueTest extends CommandQueue {
when(MainApp.bus()).thenReturn(bus);
when(MainApp.gs(0)).thenReturn("");
+
+ PowerMockito.mockStatic(TreatmentsPlugin.class);
+ TreatmentsPlugin treatmentsPlugin = mock(TreatmentsPlugin.class);
+ when(TreatmentsPlugin.getPlugin()).thenReturn(treatmentsPlugin);
+ when(treatmentsPlugin.getLastBolusTime()).thenReturn(new Date(100, 0,1 ).getTime());
}
@Override
@@ -159,21 +168,57 @@ public class CommandQueueTest extends CommandQueue {
@Test
public void callingCancelAllBolusesClearsQueue() throws Exception {
+ // given
prepareMock(0d, 0);
-
- // add normal and SMB-bolus to queue
Assert.assertEquals(0, size());
+ DetailedBolusInfo smb = new DetailedBolusInfo();
+ smb.lastKnownBolusTime = now();
+ smb.isSMB = true;
+ bolus(smb, null);
+
+ bolus(new DetailedBolusInfo(), null);
+ Assert.assertEquals(2, size());
+
+ // when
+ cancelAllBoluses();
+
+ // then
+ Assert.assertEquals(0, size());
+ }
+
+ @Test
+ public void smbIsRejectedIfABolusIsQueued() throws Exception {
+ // given
+ prepareMock(0d, 0);
+ Assert.assertEquals(0, size());
+
+ // when
bolus(new DetailedBolusInfo(), null);
DetailedBolusInfo smb = new DetailedBolusInfo();
smb.isSMB = true;
- bolus(smb, null);
+ boolean queued = bolus(smb, null);
- Assert.assertEquals(2, size());
+ // then
+ Assert.assertFalse(queued);
+ Assert.assertEquals(size(), 1);
+ }
- // cancelling all boluses clear all boluses from the queue
- cancelAllBoluses();
+ @Test
+ public void smbIsRejectedIfLastKnownBolusIsOutdated() throws Exception {
+ // given
+ prepareMock(0d, 0);
Assert.assertEquals(0, size());
+
+ // when
+ DetailedBolusInfo bolus = new DetailedBolusInfo();
+ bolus.isSMB = true;
+ bolus.lastKnownBolusTime = 0;
+ boolean queued = bolus(bolus, null);
+
+ // then
+ Assert.assertFalse(queued);
+ Assert.assertEquals(size(), 0);
}
}
diff --git a/app/src/test/java/info/nightscout/utils/PercentageSplitterTest.java b/app/src/test/java/info/nightscout/utils/PercentageSplitterTest.java
index d70edd3a0d..7fa7190d5a 100644
--- a/app/src/test/java/info/nightscout/utils/PercentageSplitterTest.java
+++ b/app/src/test/java/info/nightscout/utils/PercentageSplitterTest.java
@@ -14,7 +14,12 @@ public class PercentageSplitterTest {
}
@Test
- public void pureNameTest() throws Exception {
+ public void pureNameTestPercentageOnly() {
assertEquals("Fiasp", PercentageSplitter.pureName("Fiasp(101%)"));
}
+
+ @Test
+ public void pureNameTestPercentageAndShift() {
+ assertEquals("Fiasp", PercentageSplitter.pureName("Fiasp (101%,2h)"));
+ }
}
diff --git a/app/src/test/java/info/nightscout/utils/StringUtilsTest.java b/app/src/test/java/info/nightscout/utils/StringUtilsTest.java
new file mode 100644
index 0000000000..048ef8ac97
--- /dev/null
+++ b/app/src/test/java/info/nightscout/utils/StringUtilsTest.java
@@ -0,0 +1,22 @@
+package info.nightscout.utils;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class StringUtilsTest {
+
+ @Test
+ public void removeSurroundingQuotesTest() {
+ String compareString = "test";
+
+ assertEquals(compareString, StringUtils.removeSurroundingQuotes(compareString));
+ assertEquals(compareString, StringUtils.removeSurroundingQuotes("\"" + compareString + "\""));
+ assertEquals("\"" + compareString, StringUtils.removeSurroundingQuotes("\"" + compareString));
+
+ compareString = "te\"st";
+ assertEquals(compareString, StringUtils.removeSurroundingQuotes(compareString));
+ assertEquals(compareString, StringUtils.removeSurroundingQuotes("\"" + compareString + "\""));
+ assertEquals("\"" + compareString, StringUtils.removeSurroundingQuotes("\"" + compareString));
+ }
+}
diff --git a/documentation/images/combo-bolus-settings-de.png b/documentation/images/combo-bolus-settings-de.png
deleted file mode 100644
index dbba890b7e..0000000000
Binary files a/documentation/images/combo-bolus-settings-de.png and /dev/null differ
diff --git a/documentation/images/combo-bolus-settings.png b/documentation/images/combo-bolus-settings.png
deleted file mode 100644
index cb69184978..0000000000
Binary files a/documentation/images/combo-bolus-settings.png and /dev/null differ
diff --git a/documentation/images/combo-insulin-settings-de.png b/documentation/images/combo-insulin-settings-de.png
deleted file mode 100644
index 9b45f7107a..0000000000
Binary files a/documentation/images/combo-insulin-settings-de.png and /dev/null differ
diff --git a/documentation/images/combo-insulin-settings.png b/documentation/images/combo-insulin-settings.png
deleted file mode 100644
index c6dd58b51c..0000000000
Binary files a/documentation/images/combo-insulin-settings.png and /dev/null differ
diff --git a/documentation/images/combo-menu-settings-de.png b/documentation/images/combo-menu-settings-de.png
deleted file mode 100644
index cc1d5810c3..0000000000
Binary files a/documentation/images/combo-menu-settings-de.png and /dev/null differ
diff --git a/documentation/images/combo-menu-settings.png b/documentation/images/combo-menu-settings.png
deleted file mode 100644
index 935983089e..0000000000
Binary files a/documentation/images/combo-menu-settings.png and /dev/null differ
diff --git a/documentation/images/combo-pump-options-settings-de.png b/documentation/images/combo-pump-options-settings-de.png
deleted file mode 100644
index f508cc2345..0000000000
Binary files a/documentation/images/combo-pump-options-settings-de.png and /dev/null differ
diff --git a/documentation/images/combo-pump-options-settings.png b/documentation/images/combo-pump-options-settings.png
deleted file mode 100644
index 0323167550..0000000000
Binary files a/documentation/images/combo-pump-options-settings.png and /dev/null differ
diff --git a/documentation/images/combo-tbr-settings-de.png b/documentation/images/combo-tbr-settings-de.png
deleted file mode 100644
index 7b68fe1ef5..0000000000
Binary files a/documentation/images/combo-tbr-settings-de.png and /dev/null differ
diff --git a/documentation/images/combo-tbr-settings.png b/documentation/images/combo-tbr-settings.png
deleted file mode 100644
index ebc6b17177..0000000000
Binary files a/documentation/images/combo-tbr-settings.png and /dev/null differ
diff --git a/wear/build.gradle b/wear/build.gradle
index 584b9a769e..63858c7285 100644
--- a/wear/build.gradle
+++ b/wear/build.gradle
@@ -30,7 +30,7 @@ android {
defaultConfig {
applicationId "info.nightscout.androidaps"
- minSdkVersion 21
+ minSdkVersion 23
targetSdkVersion 23
versionCode 1
versionName "1.0.2"
@@ -67,6 +67,7 @@ dependencies {
implementation "com.google.android.support:wearable:${wearableVersion}"
implementation "com.google.android.gms:play-services-wearable:7.3.0"
implementation(name:"ustwo-clockwise-debug", ext:"aar")
- implementation "com.android.support:support-v4:23.0.1"
+ implementation "com.android.support:support-v4:27.0.1"
+ implementation 'com.android.support:wear:27.0.1'
implementation "me.denley.wearpreferenceactivity:wearpreferenceactivity:0.5.0"
}
diff --git a/wear/src/main/AndroidManifest.xml b/wear/src/main/AndroidManifest.xml
index 01423985d0..e6750c515d 100644
--- a/wear/src/main/AndroidManifest.xml
+++ b/wear/src/main/AndroidManifest.xml
@@ -6,6 +6,8 @@
+
+
+
+
diff --git a/wear/src/main/java/info/nightscout/androidaps/data/ListenerService.java b/wear/src/main/java/info/nightscout/androidaps/data/ListenerService.java
index a827890733..7297d51815 100644
--- a/wear/src/main/java/info/nightscout/androidaps/data/ListenerService.java
+++ b/wear/src/main/java/info/nightscout/androidaps/data/ListenerService.java
@@ -28,6 +28,7 @@ import java.util.concurrent.TimeUnit;
import info.nightscout.androidaps.interaction.AAPSPreferences;
import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.interaction.actions.AcceptActivity;
import info.nightscout.androidaps.interaction.actions.CPPActivity;
import info.nightscout.androidaps.interaction.utils.SafeParse;
@@ -345,45 +346,14 @@ public class ListenerService extends WearableListenerService implements GoogleAp
private void showConfirmationDialog(String title, String message, String actionstring) {
- if(confirmThread != null){
- confirmThread.invalidate();
- }
-
- Intent actionIntent = new Intent(this, ListenerService.class);
- actionIntent.setAction(ACTION_CONFIRMATION);
- actionIntent.putExtra("actionstring", actionstring);
- PendingIntent actionPendingIntent = PendingIntent.getService(this, 0, actionIntent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_UPDATE_CURRENT);;
-
- long[] vibratePattern = new long[]{0, 100, 50, 100, 50};
-
- NotificationCompat.Builder notificationBuilder =
- new NotificationCompat.Builder(this)
- .setSmallIcon(R.drawable.ic_icon)
- .setContentTitle(title)
- .setContentText(message)
- .setContentIntent(actionPendingIntent)
- .setPriority(NotificationCompat.PRIORITY_MAX)
- .setVibrate(vibratePattern)
- .setStyle(new NotificationCompat.BigTextStyle().bigText(message))
- .extend(new NotificationCompat.WearableExtender())
- .addAction(R.drawable.ic_confirm, title, actionPendingIntent);
-
- NotificationManagerCompat notificationManager =
- NotificationManagerCompat.from(this);
-
- notificationManager.notify(CONFIRM_NOTIF_ID, notificationBuilder.build());
-
- // keep the confirmation dialog open for one minute.
- scheduleDismissConfirm(60);
-
- }
-
- private void scheduleDismissConfirm(final int seconds) {
- if(confirmThread != null){
- confirmThread.invalidate();
- }
- confirmThread = new DismissThread(CONFIRM_NOTIF_ID, seconds);
- confirmThread.start();
+ Intent intent = new Intent(this, AcceptActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ Bundle params = new Bundle();
+ params.putString("title", title);
+ params.putString("message", message);
+ params.putString("actionstring", actionstring);
+ intent.putExtras(params);
+ startActivity(intent);
}
private void scheduleDismissBolusprogress(final int seconds) {
@@ -436,6 +406,13 @@ public class ListenerService extends WearableListenerService implements GoogleAp
context.startService(intent);
}
+ public static void confirmAction(Context context, String actionstring) {
+ Intent intent = new Intent(context, ListenerService.class);
+ intent.putExtra("actionstring", actionstring);
+ intent.setAction(ACTION_CONFIRMATION);
+ context.startService(intent);
+ }
+
@Override
public void onConnected(Bundle bundle) {
requestData();
diff --git a/wear/src/main/java/info/nightscout/androidaps/interaction/actions/AcceptActivity.java b/wear/src/main/java/info/nightscout/androidaps/interaction/actions/AcceptActivity.java
new file mode 100644
index 0000000000..f0ae184dfe
--- /dev/null
+++ b/wear/src/main/java/info/nightscout/androidaps/interaction/actions/AcceptActivity.java
@@ -0,0 +1,161 @@
+package info.nightscout.androidaps.interaction.actions;
+
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.os.SystemClock;
+import android.os.Vibrator;
+import android.support.v4.app.NotificationManagerCompat;
+import android.support.wearable.view.DotsPageIndicator;
+import android.support.wearable.view.GridPagerAdapter;
+import android.support.wearable.view.GridViewPager;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.data.ListenerService;
+
+/**
+ * Created by adrian on 09/02/17.
+ */
+
+
+public class AcceptActivity extends ViewSelectorActivity {
+
+
+ String title = "";
+ String message = "";
+ String actionstring = "";
+ private DismissThread dismissThread;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ this.dismissThread = new DismissThread();
+ dismissThread.start();
+
+ Bundle extras = getIntent().getExtras();
+ title = extras.getString("title", "");
+ message = extras.getString("message", "");
+ actionstring = extras.getString("actionstring", "");
+
+ if ("".equals(message) || "".equals(actionstring) ){
+ finish(); return;
+ }
+
+ setContentView(R.layout.grid_layout);
+ final Resources res = getResources();
+ final GridViewPager pager = (GridViewPager) findViewById(R.id.pager);
+
+ pager.setAdapter(new MyGridViewPagerAdapter());
+ DotsPageIndicator dotsPageIndicator = (DotsPageIndicator) findViewById(R.id.page_indicator);
+ dotsPageIndicator.setPager(pager);
+
+ Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
+ long[] vibratePattern = new long[]{0, 100, 50, 100, 50};
+ v.vibrate(vibratePattern, -1);
+ }
+
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ finish();
+ }
+
+
+ private class MyGridViewPagerAdapter extends GridPagerAdapter {
+ @Override
+ public int getColumnCount(int arg0) {
+ return 2;
+ }
+
+ @Override
+ public int getRowCount() {
+ return 1;
+ }
+
+ @Override
+ public Object instantiateItem(ViewGroup container, int row, int col) {
+
+ if(col == 0){
+ final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_confirm_text, container, false);
+ final TextView headingView = (TextView) view.findViewById(R.id.title);
+ headingView.setText(title);
+ final TextView textView = (TextView) view.findViewById(R.id.message);
+ textView.setText(message);
+ container.addView(view);
+ return view;
+ } else {
+ final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_send_item, container, false);
+ final ImageView confirmbutton = (ImageView) view.findViewById(R.id.confirmbutton);
+ confirmbutton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ ListenerService.confirmAction(AcceptActivity.this, actionstring);
+ finish();
+ }
+ });
+ container.addView(view);
+ return view;
+ }
+ }
+
+ @Override
+ public void destroyItem(ViewGroup container, int row, int col, Object view) {
+ // Handle this to get the data before the view is destroyed?
+ // Object should still be kept by this, just setup for reinit?
+ container.removeView((View)view);
+ }
+
+ @Override
+ public boolean isViewFromObject(View view, Object object) {
+ return view==object;
+ }
+
+ }
+
+ @Override
+ public synchronized void onDestroy(){
+ super.onDestroy();
+ if(dismissThread != null){
+ dismissThread.invalidate();
+ }
+
+ }
+
+ private class DismissThread extends Thread{
+ private boolean valid = true;
+
+ public synchronized void invalidate(){
+ valid = false;
+ }
+
+ @Override
+ public void run() {
+ SystemClock.sleep(60 * 1000);
+ synchronized (this) {
+ if(valid) {
+ AcceptActivity.this.finish();
+ }
+ }
+ }
+ }
+
+ @Override
+ protected synchronized void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+ if(dismissThread != null) dismissThread.invalidate();
+ Bundle extras = intent.getExtras();
+ Intent msgIntent = new Intent(this, AcceptActivity.class);
+ msgIntent.putExtras(extras);
+ startActivity(msgIntent);
+ finish();
+ }
+}
\ No newline at end of file
diff --git a/wear/src/main/java/info/nightscout/androidaps/interaction/menus/MainMenuActivity.java b/wear/src/main/java/info/nightscout/androidaps/interaction/menus/MainMenuActivity.java
index fb8bb61e20..0692f273fb 100644
--- a/wear/src/main/java/info/nightscout/androidaps/interaction/menus/MainMenuActivity.java
+++ b/wear/src/main/java/info/nightscout/androidaps/interaction/menus/MainMenuActivity.java
@@ -9,6 +9,7 @@ import java.util.Vector;
import info.nightscout.androidaps.data.ListenerService;
import info.nightscout.androidaps.interaction.AAPSPreferences;
+import info.nightscout.androidaps.interaction.actions.AcceptActivity;
import info.nightscout.androidaps.interaction.actions.BolusActivity;
import info.nightscout.androidaps.interaction.actions.ECarbActivity;
import info.nightscout.androidaps.interaction.actions.TempTargetActivity;
diff --git a/wear/src/main/res/layout/action_confirm_text.xml b/wear/src/main/res/layout/action_confirm_text.xml
new file mode 100644
index 0000000000..291b05116d
--- /dev/null
+++ b/wear/src/main/res/layout/action_confirm_text.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file