@@ -160,6 +154,9 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/assets/OpenAPSAMA/loggerhelper.js b/app/src/main/assets/OpenAPSAMA/loggerhelper.js
index e790f465c8..81c19b5a38 100644
--- a/app/src/main/assets/OpenAPSAMA/loggerhelper.js
+++ b/app/src/main/assets/OpenAPSAMA/loggerhelper.js
@@ -1,12 +1,33 @@
var console = { };
console.error = function error(){
+ var s = '';
for (var i = 0, len = arguments.length; i < len; i++) {
- console2.log(arguments[i]);
+ if (i > 0) s = s + ' ';
+ if (typeof arguments[i] === 'undefined') {
+ s = s + 'undefined';
+ } else if (typeof arguments[i] === 'object') {
+ s = s + JSON.stringify(arguments[i]);
+ } else {
+ s = s + arguments[i].toString();
+ }
}
+ s = s + "\n";
+ console2.log(s);
};
console.log = function log(){
+ var s = '';
for (var i = 0, len = arguments.length; i < len; i++) {
- console2.log(arguments[i]);
+ if (i > 0) s = s + ' ';
+ if (typeof arguments[i] === 'undefined') {
+ s = s + 'undefined';
+ } else if (typeof arguments[i] === 'object') {
+ s = s + JSON.stringify(arguments[i]);
+ } else {
+ s = s + arguments[i].toString();
+ }
+ //console2.log(arguments[i]);
}
+ s = s + "\n";
+ console2.log(s);
};
diff --git a/app/src/main/assets/revoked_certs.txt b/app/src/main/assets/revoked_certs.txt
new file mode 100644
index 0000000000..59a55d9e42
--- /dev/null
+++ b/app/src/main/assets/revoked_certs.txt
@@ -0,0 +1,2 @@
+#Demo certificate
+51:6D:12:67:4C:27:F4:9B:9F:E5:42:9B:01:B3:98:E4:66:2B:85:B7:A8:DD:70:32:B7:6A:D7:97:9A:0D:97:10
\ No newline at end of file
diff --git a/app/src/main/java/com/squareup/otto/LoggingBus.java b/app/src/main/java/com/squareup/otto/LoggingBus.java
deleted file mode 100644
index d9758a9a24..0000000000
--- a/app/src/main/java/com/squareup/otto/LoggingBus.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package com.squareup.otto;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.util.ConcurrentModificationException;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import info.nightscout.androidaps.events.Event;
-import info.nightscout.androidaps.logging.L;
-
-/**
- * Logs events has they're being posted to and dispatched from the event bus.
- *
- * A summary of event-receiver calls that occurred so far is logged
- * after 10s (after startup) and then again every 60s.
- */
-public class LoggingBus extends Bus {
- private static Logger log = LoggerFactory.getLogger(L.EVENTS);
-
- private static long everyMinute = System.currentTimeMillis() + 10 * 1000;
- private Map> event2Receiver = new HashMap<>();
-
- public LoggingBus(ThreadEnforcer enforcer) {
- super(enforcer);
- }
-
- @Override
- public void post(Object event) {
- if (event instanceof DeadEvent) {
- log.debug("Event has no receiver: " + ((DeadEvent) event).event + ", source: " + ((DeadEvent) event).source);
- return;
- }
-
- if (!(event instanceof Event)) {
- log.error("Posted event not an event class: " + event.getClass());
- }
-
- log.debug("<<< " + event);
- try {
- StackTraceElement caller = new Throwable().getStackTrace()[1];
- String className = caller.getClassName();
- className = className.substring(className.lastIndexOf(".") + 1);
- log.debug(" source: " + className + "." + caller.getMethodName() + ":" + caller.getLineNumber());
- } catch (RuntimeException e) {
- log.debug(" source: ");
- }
-
- try {
- super.post(event);
- } catch (IllegalStateException ignored) {
- }
- }
-
- @Override
- protected void dispatch(Object event, EventHandler wrapper) {
- try {
- log.debug(">>> " + event);
- Field methodField = wrapper.getClass().getDeclaredField("method");
- methodField.setAccessible(true);
- Method targetMethod = (Method) methodField.get(wrapper);
- String className = targetMethod.getDeclaringClass().getSimpleName();
- String methodName = targetMethod.getName();
- String receiverMethod = className + "." + methodName;
- log.debug(" receiver: " + receiverMethod);
-
- String key = event.getClass().getSimpleName();
- if (!event2Receiver.containsKey(key)) event2Receiver.put(key, new HashSet());
- event2Receiver.get(key).add(receiverMethod);
- } catch (ReflectiveOperationException e) {
- log.debug(" receiver: ");
- }
-
- try {
- if (everyMinute < System.currentTimeMillis()) {
- log.debug("***************** Event -> receiver pairings seen so far ****************");
- for (Map.Entry> stringSetEntry : event2Receiver.entrySet()) {
- log.debug(" " + stringSetEntry.getKey());
- for (String s : stringSetEntry.getValue()) {
- log.debug(" -> " + s);
- }
- }
- log.debug("*************************************************************************");
- everyMinute = System.currentTimeMillis() + 60 * 1000;
- }
- } catch (ConcurrentModificationException ignored) {
- }
-
- super.dispatch(event, wrapper);
- }
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/Config.java b/app/src/main/java/info/nightscout/androidaps/Config.java
index ae0e14c9b6..bb967cdeb6 100644
--- a/app/src/main/java/info/nightscout/androidaps/Config.java
+++ b/app/src/main/java/info/nightscout/androidaps/Config.java
@@ -12,13 +12,4 @@ public class Config {
public static final boolean PUMPCONTROL = BuildConfig.FLAVOR.equals("pumpcontrol");
public static final boolean PUMPDRIVERS = BuildConfig.FLAVOR.equals("full") || BuildConfig.FLAVOR.equals("pumpcontrol");
-
- public static final boolean ACTION = !NSCLIENT;
- public static final boolean MDI = !NSCLIENT;
- public static final boolean OTHERPROFILES = !NSCLIENT;
- public static final boolean SAFETY = !NSCLIENT;
-
- public static final boolean SMSCOMMUNICATORENABLED = !NSCLIENT;
-
-
}
diff --git a/app/src/main/java/info/nightscout/androidaps/Constants.java b/app/src/main/java/info/nightscout/androidaps/Constants.java
index 2ecabfe965..21a89d8920 100644
--- a/app/src/main/java/info/nightscout/androidaps/Constants.java
+++ b/app/src/main/java/info/nightscout/androidaps/Constants.java
@@ -31,11 +31,13 @@ public class Constants {
public static final long remoteBolusMinDistance = 15 * 60 * 1000L;
// Circadian Percentage Profile
- public static final int CPP_MIN_PERCENTAGE = 50;
+ public static final int CPP_MIN_PERCENTAGE = 30;
public static final int CPP_MAX_PERCENTAGE = 200;
public static final int CPP_MIN_TIMESHIFT = -6;
public static final int CPP_MAX_TIMESHIFT = 23;
+ public static final double MAX_PROFILE_SWITCH_DURATION = 7 * 24 * 60; // [min] ~ 7 days
+
//DanaR
public static final double dailyLimitWarning = 0.95d;
@@ -50,6 +52,11 @@ public class Constants {
public static final double defaultHypoTTmgdl = 120d;
public static final double defaultHypoTTmmol = 6.5d;
+ public static final double MIN_TT_MGDL = 72d;
+ public static final double MAX_TT_MGDL = 180d;
+ public static final double MIN_TT_MMOL = 4d;
+ public static final double MAX_TT_MMOL = 10d;
+
//NSClientInternal
public static final int MAX_LOG_LINES = 100;
diff --git a/app/src/main/java/info/nightscout/androidaps/MainActivity.java b/app/src/main/java/info/nightscout/androidaps/MainActivity.java
index 6779b0a467..64c2656086 100644
--- a/app/src/main/java/info/nightscout/androidaps/MainActivity.java
+++ b/app/src/main/java/info/nightscout/androidaps/MainActivity.java
@@ -6,17 +6,6 @@ import android.content.pm.PackageManager;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.PersistableBundle;
-import android.os.PowerManager;
-import android.support.annotation.Nullable;
-import android.support.design.widget.NavigationView;
-import android.support.design.widget.TabLayout;
-import android.support.v4.app.ActivityCompat;
-import android.support.v4.view.ViewPager;
-import android.support.v4.widget.DrawerLayout;
-import android.support.v7.app.ActionBarDrawerToggle;
-import android.support.v7.app.AlertDialog;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.Toolbar;
import android.text.SpannableString;
import android.text.method.LinkMovementMethod;
import android.text.util.Linkify;
@@ -31,29 +20,40 @@ import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.ActionBarDrawerToggle;
+import androidx.appcompat.app.AlertDialog;
+import androidx.appcompat.widget.Toolbar;
+import androidx.core.app.ActivityCompat;
+import androidx.drawerlayout.widget.DrawerLayout;
+import androidx.viewpager.widget.ViewPager;
+
+import com.google.android.material.navigation.NavigationView;
+import com.google.android.material.tabs.TabLayout;
import com.joanzapata.iconify.Iconify;
import com.joanzapata.iconify.fonts.FontAwesomeModule;
-import com.squareup.otto.Subscribe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.activities.AgreementActivity;
import info.nightscout.androidaps.activities.HistoryBrowseActivity;
+import info.nightscout.androidaps.activities.NoSplashAppCompatActivity;
import info.nightscout.androidaps.activities.PreferencesActivity;
import info.nightscout.androidaps.activities.SingleFragmentActivity;
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.events.EventRebuildTabs;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
+import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
+import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtilsKt;
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus;
-import info.nightscout.androidaps.plugins.general.versionChecker.VersionCheckerUtilsKt;
import info.nightscout.androidaps.setupwizard.SetupWizardActivity;
import info.nightscout.androidaps.tabs.TabPageAdapter;
import info.nightscout.androidaps.utils.AndroidPermission;
@@ -62,25 +62,23 @@ import info.nightscout.androidaps.utils.LocaleHelper;
import info.nightscout.androidaps.utils.OKDialog;
import info.nightscout.androidaps.utils.PasswordProtection;
import info.nightscout.androidaps.utils.SP;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.disposables.CompositeDisposable;
-public class MainActivity extends AppCompatActivity {
+public class MainActivity extends NoSplashAppCompatActivity {
private static Logger log = LoggerFactory.getLogger(L.CORE);
-
- protected PowerManager.WakeLock mWakeLock;
+ private CompositeDisposable disposable = new CompositeDisposable();
private ActionBarDrawerToggle actionBarDrawerToggle;
private MenuItem pluginPreferencesMenuItem;
@Override
- protected void onCreate(Bundle savedInstanceState) {
+ public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- if (L.isEnabled(L.CORE))
- log.debug("onCreate");
-
Iconify.with(new FontAwesomeModule());
- LocaleHelper.onCreate(this, "en");
+ LocaleHelper.INSTANCE.update(getApplicationContext());
setContentView(R.layout.activity_main);
setSupportActionBar(findViewById(R.id.toolbar));
@@ -94,14 +92,10 @@ public class MainActivity extends AppCompatActivity {
actionBarDrawerToggle.syncState();
// initialize screen wake lock
- onEventPreferenceChange(new EventPreferenceChange(R.string.key_keep_screen_on));
+ processPreferenceChange(new EventPreferenceChange(R.string.key_keep_screen_on));
doMigrations();
- registerBus();
- setupTabs();
- setupViews(false);
-
final ViewPager viewPager = findViewById(R.id.pager);
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
@@ -123,6 +117,43 @@ public class MainActivity extends AppCompatActivity {
VersionCheckerUtilsKt.triggerCheckVersion();
FabricPrivacy.setUserStats();
+
+ setupTabs();
+ setupViews();
+
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventRebuildTabs.class)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(event -> {
+ LocaleHelper.INSTANCE.update(getApplicationContext());
+ if (event.getRecreate()) {
+ recreate();
+ } else {
+ setupTabs();
+ setupViews();
+ }
+ setWakeLock();
+ }, FabricPrivacy::logException)
+ );
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventPreferenceChange.class)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(this::processPreferenceChange, FabricPrivacy::logException)
+ );
+
+ if (!SP.getBoolean(R.string.key_setupwizard_processed, false)) {
+ Intent intent = new Intent(this, SetupWizardActivity.class);
+ startActivity(intent);
+ } else {
+ checkEula();
+ }
+
+ AndroidPermission.notifyForStoragePermission(this);
+ AndroidPermission.notifyForBatteryOptimizationPermission(this);
+ if (Config.PUMPDRIVERS) {
+ AndroidPermission.notifyForLocationPermissions(this);
+ AndroidPermission.notifyForSMSPermissions(this);
+ }
}
private void checkPluginPreferences(ViewPager viewPager) {
@@ -138,86 +169,29 @@ public class MainActivity extends AppCompatActivity {
actionBarDrawerToggle.syncState();
}
- @Override
- protected void onResume() {
- super.onResume();
-
- if (L.isEnabled(L.CORE))
- log.debug("onResume");
-
- if (!SP.getBoolean(R.string.key_setupwizard_processed, false)) {
- Intent intent = new Intent(this, SetupWizardActivity.class);
- startActivity(intent);
- } else {
- checkEula();
- }
-
- AndroidPermission.notifyForStoragePermission(this);
- AndroidPermission.notifyForBatteryOptimizationPermission(this);
- if (Config.PUMPDRIVERS) {
- AndroidPermission.notifyForLocationPermissions(this);
- AndroidPermission.notifyForSMSPermissions(this);
- }
-
- MainApp.bus().post(new EventFeatureRunning(EventFeatureRunning.Feature.MAIN));
- }
-
@Override
public void onDestroy() {
- if (L.isEnabled(L.CORE))
- log.debug("onDestroy");
- if (mWakeLock != null)
- if (mWakeLock.isHeld())
- mWakeLock.release();
super.onDestroy();
+ disposable.clear();
}
- @Subscribe
- 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, "AndroidAPS:MainActivity_onEventPreferenceChange");
- if (!mWakeLock.isHeld())
- mWakeLock.acquire();
- } else {
- if (mWakeLock != null && mWakeLock.isHeld())
- mWakeLock.release();
- }
- }
+ private void setWakeLock() {
+ boolean keepScreenOn = 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);
}
- @Subscribe
- public void onStatusEvent(final EventRefreshGui ev) {
- String lang = SP.getString(R.string.key_language, "en");
- LocaleHelper.setLocale(getApplicationContext(), lang);
- runOnUiThread(() -> {
- if (ev.recreate) {
- recreate();
- } else {
- try { // activity may be destroyed
- setupTabs();
- setupViews(true);
- } catch (IllegalStateException e) {
- log.error("Unhandled exception", e);
- }
- }
-
- boolean keepScreenOn = Config.NSCLIENT && 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);
- });
+ public void processPreferenceChange(final EventPreferenceChange ev) {
+ if (ev.isChanged(R.string.key_keep_screen_on))
+ setWakeLock();
}
- private void setupViews(boolean switchToLast) {
+ private void setupViews() {
TabPageAdapter pageAdapter = new TabPageAdapter(getSupportFragmentManager(), this);
NavigationView navigationView = findViewById(R.id.navigation_view);
- navigationView.setNavigationItemSelectedListener(menuItem -> {
- return true;
- });
+ navigationView.setNavigationItemSelectedListener(menuItem -> true);
Menu menu = navigationView.getMenu();
menu.clear();
for (PluginBase p : MainApp.getPluginsList()) {
@@ -236,8 +210,8 @@ public class MainActivity extends AppCompatActivity {
}
ViewPager mPager = findViewById(R.id.pager);
mPager.setAdapter(pageAdapter);
- if (switchToLast)
- mPager.setCurrentItem(pageAdapter.getCount() - 1, false);
+ //if (switchToLast)
+ // mPager.setCurrentItem(pageAdapter.getCount() - 1, false);
checkPluginPreferences(mPager);
}
@@ -263,15 +237,6 @@ public class MainActivity extends AppCompatActivity {
}
}
- private void registerBus() {
- try {
- MainApp.bus().unregister(this);
- } catch (RuntimeException x) {
- // Ignore
- }
- MainApp.bus().register(this);
- }
-
private void checkEula() {
//SP.removeBoolean(R.string.key_i_understand);
boolean IUnderstand = SP.getBoolean(R.string.key_i_understand, false);
@@ -288,10 +253,10 @@ public class MainActivity extends AppCompatActivity {
// guarantee that the unreachable threshold is at least 30 and of type String
// Added in 1.57 at 21.01.2018
- Integer unreachable_threshold = SP.getInt(R.string.key_pump_unreachable_threshold, 30);
+ int unreachable_threshold = SP.getInt(R.string.key_pump_unreachable_threshold, 30);
SP.remove(R.string.key_pump_unreachable_threshold);
if (unreachable_threshold < 30) unreachable_threshold = 30;
- SP.putString(R.string.key_pump_unreachable_threshold, unreachable_threshold.toString());
+ SP.putString(R.string.key_pump_unreachable_threshold, Integer.toString(unreachable_threshold));
}
@@ -307,19 +272,16 @@ public class MainActivity extends AppCompatActivity {
String message = "Target range is changed in current version.\n\nIt's not taken from preferences but from profile.\n\n!!! REVIEW YOUR SETTINGS !!!";
message += "\n\nOld settings: " + oldRange;
message += "\nProfile settings: " + newRange;
- OKDialog.show(this, "Target range change", message, new Runnable() {
- @Override
- public void run() {
- SP.remove("openapsma_min_bg");
- SP.remove("openapsma_max_bg");
- SP.remove("openapsma_target_bg");
- }
+ OKDialog.show(this, "Target range change", message, () -> {
+ SP.remove("openapsma_min_bg");
+ SP.remove("openapsma_max_bg");
+ SP.remove("openapsma_target_bg");
});
}
}
@Override
- public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (permissions.length != 0) {
if (ActivityCompat.checkSelfPermission(this, permissions[0]) == PackageManager.PERMISSION_GRANTED) {
@@ -334,7 +296,7 @@ public class MainActivity extends AppCompatActivity {
case AndroidPermission.CASE_LOCATION:
case AndroidPermission.CASE_SMS:
case AndroidPermission.CASE_BATTERY:
- case AndroidPermission.CASE_PHONESTATE:
+ case AndroidPermission.CASE_PHONE_STATE:
break;
}
}
@@ -404,7 +366,7 @@ public class MainActivity extends AppCompatActivity {
case R.id.nav_exit:
log.debug("Exiting");
MainApp.instance().stopKeepAliveService();
- MainApp.bus().post(new EventAppExit());
+ RxBus.INSTANCE.send(new EventAppExit());
MainApp.closeDbHelper();
finish();
System.runFinalization();
diff --git a/app/src/main/java/info/nightscout/androidaps/MainApp.java b/app/src/main/java/info/nightscout/androidaps/MainApp.java
index 3259483033..379afabddf 100644
--- a/app/src/main/java/info/nightscout/androidaps/MainApp.java
+++ b/app/src/main/java/info/nightscout/androidaps/MainApp.java
@@ -1,19 +1,17 @@
package info.nightscout.androidaps;
import android.app.Application;
+import android.content.BroadcastReceiver;
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 androidx.annotation.PluralsRes;
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import com.crashlytics.android.Crashlytics;
import com.google.firebase.analytics.FirebaseAnalytics;
import com.j256.ormlite.android.apptools.OpenHelperManager;
-import com.squareup.otto.Bus;
-import com.squareup.otto.LoggingBus;
-import com.squareup.otto.ThreadEnforcer;
import net.danlew.android.joda.JodaTimeAndroid;
@@ -37,8 +35,11 @@ import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.constraints.dstHelper.DstHelperPlugin;
import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin;
import info.nightscout.androidaps.plugins.constraints.safety.SafetyPlugin;
+import info.nightscout.androidaps.plugins.constraints.signatureVerifier.SignatureVerifierPlugin;
import info.nightscout.androidaps.plugins.constraints.storage.StorageConstraintPlugin;
-import info.nightscout.androidaps.plugins.general.actions.ActionsFragment;
+import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerPlugin;
+import info.nightscout.androidaps.plugins.general.actions.ActionsPlugin;
+import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin;
import info.nightscout.androidaps.plugins.general.careportal.CareportalPlugin;
import info.nightscout.androidaps.plugins.general.food.FoodPlugin;
import info.nightscout.androidaps.plugins.general.maintenance.LoggerUtils;
@@ -50,7 +51,6 @@ import info.nightscout.androidaps.plugins.general.nsclient.receivers.DBAccessRec
import info.nightscout.androidaps.plugins.general.overview.OverviewPlugin;
import info.nightscout.androidaps.plugins.general.persistentNotification.PersistentNotificationPlugin;
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin;
-import info.nightscout.androidaps.plugins.general.versionChecker.VersionCheckerPlugin;
import info.nightscout.androidaps.plugins.general.wear.WearPlugin;
import info.nightscout.androidaps.plugins.general.xdripStatusline.StatuslinePlugin;
import info.nightscout.androidaps.plugins.insulin.InsulinOrefFreePeakPlugin;
@@ -67,13 +67,13 @@ import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin;
import info.nightscout.androidaps.plugins.pump.danaRv2.DanaRv2Plugin;
import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin;
import info.nightscout.androidaps.plugins.pump.mdi.MDIPlugin;
+import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin;
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin;
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.source.SourceDexcomG5Plugin;
-import info.nightscout.androidaps.plugins.source.SourceDexcomG6Plugin;
+import info.nightscout.androidaps.plugins.source.SourceDexcomPlugin;
import info.nightscout.androidaps.plugins.source.SourceEversensePlugin;
import info.nightscout.androidaps.plugins.source.SourceGlimpPlugin;
import info.nightscout.androidaps.plugins.source.SourceMM640gPlugin;
@@ -85,18 +85,19 @@ import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
import info.nightscout.androidaps.receivers.DataReceiver;
import info.nightscout.androidaps.receivers.KeepAliveReceiver;
import info.nightscout.androidaps.receivers.NSAlarmReceiver;
+import info.nightscout.androidaps.receivers.TimeDateOrTZChangeReceiver;
import info.nightscout.androidaps.services.Intents;
import info.nightscout.androidaps.utils.FabricPrivacy;
+import info.nightscout.androidaps.utils.LocaleHelper;
import io.fabric.sdk.android.Fabric;
-import static info.nightscout.androidaps.plugins.general.versionChecker.VersionCheckerUtilsKt.triggerCheckVersion;
+import static info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtilsKt.triggerCheckVersion;
public class MainApp extends Application {
private static Logger log = LoggerFactory.getLogger(L.CORE);
private static KeepAliveReceiver keepAliveReceiver;
- private static Bus sBus;
private static MainApp sInstance;
public static Resources sResources;
@@ -112,6 +113,8 @@ public class MainApp extends Application {
private static AckAlarmReceiver ackAlarmReciever = new AckAlarmReceiver();
private static DBAccessReceiver dbAccessReciever = new DBAccessReceiver();
private LocalBroadcastManager lbm;
+ BroadcastReceiver btReceiver;
+ TimeDateOrTZChangeReceiver timeDateOrTZChangeReceiver;
public static boolean devBranch;
public static boolean engineeringMode;
@@ -122,9 +125,12 @@ public class MainApp extends Application {
log.debug("onCreate");
sInstance = this;
sResources = getResources();
+ LocaleHelper.INSTANCE.update(this);
sConstraintsChecker = new ConstraintChecker();
sDatabaseHelper = OpenHelperManager.getHelper(sInstance, DatabaseHelper.class);
+ Thread.setDefaultUncaughtExceptionHandler((thread, ex) -> log.error("Uncaught exception crashing app", ex));
+
try {
if (FabricPrivacy.fabricEnabled()) {
Fabric.with(this, new Crashlytics());
@@ -134,6 +140,7 @@ public class MainApp extends Application {
}
mFirebaseAnalytics = FirebaseAnalytics.getInstance(this);
+ mFirebaseAnalytics.setAnalyticsCollectionEnabled(!Boolean.getBoolean("disableFirebase"));
JodaTimeAndroid.init(this);
@@ -145,21 +152,20 @@ public class MainApp extends Application {
File engineeringModeSemaphore = new File(extFilesDir, "engineering_mode");
engineeringMode = engineeringModeSemaphore.exists() && engineeringModeSemaphore.isFile();
- devBranch = BuildConfig.VERSION.contains("dev");
-
- sBus = L.isEnabled(L.EVENTS) && devBranch ? new LoggingBus(ThreadEnforcer.ANY) : new Bus(ThreadEnforcer.ANY);
+ devBranch = BuildConfig.VERSION.contains("-") || BuildConfig.VERSION.matches(".*[a-zA-Z]+.*");
registerLocalBroadcastReceiver();
//trigger here to see the new version on app start after an update
triggerCheckVersion();
+ //setBTReceiver();
if (pluginsList == null) {
pluginsList = new ArrayList<>();
// Register all tabs in app here
- pluginsList.add(OverviewPlugin.getPlugin());
+ pluginsList.add(OverviewPlugin.INSTANCE);
pluginsList.add(IobCobCalculatorPlugin.getPlugin());
- if (Config.ACTION) pluginsList.add(ActionsFragment.getPlugin());
+ if (!Config.NSCLIENT) pluginsList.add(ActionsPlugin.INSTANCE);
pluginsList.add(InsulinOrefRapidActingPlugin.getPlugin());
pluginsList.add(InsulinOrefUltraRapidActingPlugin.getPlugin());
pluginsList.add(InsulinOrefFreePeakPlugin.getPlugin());
@@ -172,39 +178,42 @@ public class MainApp extends Application {
if (Config.PUMPDRIVERS) pluginsList.add(DanaRv2Plugin.getPlugin());
if (Config.PUMPDRIVERS) pluginsList.add(DanaRSPlugin.getPlugin());
if (Config.PUMPDRIVERS) pluginsList.add(LocalInsightPlugin.getPlugin());
- pluginsList.add(CareportalPlugin.getPlugin());
if (Config.PUMPDRIVERS) pluginsList.add(ComboPlugin.getPlugin());
- if (Config.MDI) pluginsList.add(MDIPlugin.getPlugin());
+ if (Config.PUMPDRIVERS) pluginsList.add(MedtronicPumpPlugin.getPlugin());
+ if (!Config.NSCLIENT) pluginsList.add(MDIPlugin.getPlugin());
pluginsList.add(VirtualPumpPlugin.getPlugin());
+ pluginsList.add(CareportalPlugin.getPlugin());
if (Config.APS) pluginsList.add(LoopPlugin.getPlugin());
if (Config.APS) pluginsList.add(OpenAPSMAPlugin.getPlugin());
if (Config.APS) pluginsList.add(OpenAPSAMAPlugin.getPlugin());
if (Config.APS) pluginsList.add(OpenAPSSMBPlugin.getPlugin());
pluginsList.add(NSProfilePlugin.getPlugin());
- if (Config.OTHERPROFILES) pluginsList.add(SimpleProfilePlugin.getPlugin());
- if (Config.OTHERPROFILES) pluginsList.add(LocalProfilePlugin.getPlugin());
+ if (!Config.NSCLIENT) pluginsList.add(SimpleProfilePlugin.getPlugin());
+ if (!Config.NSCLIENT) pluginsList.add(LocalProfilePlugin.getPlugin());
pluginsList.add(TreatmentsPlugin.getPlugin());
- if (Config.SAFETY) pluginsList.add(SafetyPlugin.getPlugin());
- if (Config.SAFETY) pluginsList.add(VersionCheckerPlugin.INSTANCE);
- if (Config.SAFETY) pluginsList.add(StorageConstraintPlugin.getPlugin());
- if (Config.APS) pluginsList.add(ObjectivesPlugin.getPlugin());
+ if (!Config.NSCLIENT) pluginsList.add(SafetyPlugin.getPlugin());
+ if (!Config.NSCLIENT) pluginsList.add(VersionCheckerPlugin.INSTANCE);
+ if (Config.APS) pluginsList.add(StorageConstraintPlugin.getPlugin());
+ if (Config.APS) pluginsList.add(SignatureVerifierPlugin.getPlugin());
+ if (Config.APS) pluginsList.add(ObjectivesPlugin.INSTANCE);
pluginsList.add(SourceXdripPlugin.getPlugin());
pluginsList.add(SourceNSClientPlugin.getPlugin());
pluginsList.add(SourceMM640gPlugin.getPlugin());
pluginsList.add(SourceGlimpPlugin.getPlugin());
- pluginsList.add(SourceDexcomG5Plugin.getPlugin());
- pluginsList.add(SourceDexcomG6Plugin.getPlugin());
+ pluginsList.add(SourceDexcomPlugin.INSTANCE);
pluginsList.add(SourcePoctechPlugin.getPlugin());
pluginsList.add(SourceTomatoPlugin.getPlugin());
pluginsList.add(SourceEversensePlugin.getPlugin());
- if (Config.SMSCOMMUNICATORENABLED) pluginsList.add(SmsCommunicatorPlugin.getPlugin());
+ if (!Config.NSCLIENT) pluginsList.add(SmsCommunicatorPlugin.getPlugin());
pluginsList.add(FoodPlugin.getPlugin());
pluginsList.add(WearPlugin.initPlugin(this));
pluginsList.add(StatuslinePlugin.initPlugin(this));
pluginsList.add(PersistentNotificationPlugin.getPlugin());
pluginsList.add(NSClientPlugin.getPlugin());
+// if (engineeringMode) pluginsList.add(TidepoolPlugin.INSTANCE);
pluginsList.add(MaintenancePlugin.initPlugin(this));
+ pluginsList.add(AutomationPlugin.INSTANCE);
pluginsList.add(ConfigBuilderPlugin.getPlugin());
@@ -252,6 +261,10 @@ public class MainApp extends Application {
//register dbaccess
lbm.registerReceiver(dbAccessReciever, new IntentFilter(Intents.ACTION_DATABASE));
+
+ this.timeDateOrTZChangeReceiver = new TimeDateOrTZChangeReceiver();
+ this.timeDateOrTZChangeReceiver.registerBroadcasts(this);
+
}
private void startKeepAliveService() {
@@ -266,26 +279,6 @@ public class MainApp extends Application {
KeepAliveReceiver.cancelAlarm(this);
}
- public static void subscribe(Object subscriber) {
- try {
- bus().register(subscriber);
- } catch (IllegalArgumentException e) {
- // already registered
- }
- }
-
- public static void unsubscribe(Object subscriber) {
- try {
- bus().unregister(subscriber);
- } catch (IllegalArgumentException e) {
- // already unregistered
- }
- }
-
- public static Bus bus() {
- return sBus;
- }
-
public static String gs(int id) {
return sResources.getString(id);
}
@@ -387,19 +380,6 @@ public class MainApp extends Application {
return newList;
}
- @Nullable
- public static T getSpecificPlugin(Class pluginClass) {
- if (pluginsList != null) {
- for (PluginBase p : pluginsList) {
- if (pluginClass.isAssignableFrom(p.getClass()))
- return (T) p;
- }
- } else {
- log.error("pluginsList=null");
- }
- return null;
- }
-
public static boolean isEngineeringModeOrRelease() {
if (!Config.APS)
return true;
@@ -437,5 +417,19 @@ public class MainApp extends Application {
sDatabaseHelper.close();
sDatabaseHelper = null;
}
+
+ if (btReceiver != null) {
+ unregisterReceiver(btReceiver);
+ }
+
+ if (timeDateOrTZChangeReceiver != null) {
+ unregisterReceiver(timeDateOrTZChangeReceiver);
+ }
+
+ }
+
+ public static int dpToPx(int dp) {
+ float scale = sResources.getDisplayMetrics().density;
+ return (int) (dp * scale + 0.5f);
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/activities/AgreementActivity.java b/app/src/main/java/info/nightscout/androidaps/activities/AgreementActivity.java
index 32352e1371..d3792bbad5 100644
--- a/app/src/main/java/info/nightscout/androidaps/activities/AgreementActivity.java
+++ b/app/src/main/java/info/nightscout/androidaps/activities/AgreementActivity.java
@@ -11,13 +11,13 @@ import info.nightscout.androidaps.MainActivity;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.utils.SP;
-public class AgreementActivity extends Activity {
+public class AgreementActivity extends NoSplashActivity {
boolean IUnderstand;
CheckBox agreeCheckBox;
Button saveButton;
@Override
- protected void onCreate(Bundle savedInstanceState) {
+ public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_agreement);
IUnderstand = SP.getBoolean(R.string.key_i_understand, false);
diff --git a/app/src/main/java/info/nightscout/androidaps/activities/HistoryBrowseActivity.java b/app/src/main/java/info/nightscout/androidaps/activities/HistoryBrowseActivity.java
index c007d1fced..79f3fbf4d4 100644
--- a/app/src/main/java/info/nightscout/androidaps/activities/HistoryBrowseActivity.java
+++ b/app/src/main/java/info/nightscout/androidaps/activities/HistoryBrowseActivity.java
@@ -2,9 +2,6 @@ package info.nightscout.androidaps.activities;
import android.os.Bundle;
import android.os.SystemClock;
-import android.support.v4.content.res.ResourcesCompat;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.PopupMenu;
import android.text.SpannableString;
import android.text.style.ForegroundColorSpan;
import android.view.Menu;
@@ -15,8 +12,10 @@ import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.TextView;
+import androidx.appcompat.widget.PopupMenu;
+import androidx.core.content.res.ResourcesCompat;
+
import com.jjoe64.graphview.GraphView;
-import com.squareup.otto.Subscribe;
import com.wdullaer.materialdatetimepicker.date.DatePickerDialog;
import org.slf4j.Logger;
@@ -25,49 +24,43 @@ import org.slf4j.LoggerFactory;
import java.util.Calendar;
import java.util.Date;
-import butterknife.BindView;
-import butterknife.ButterKnife;
-import butterknife.OnClick;
-import butterknife.OnLongClick;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.events.EventCustomCalculationFinished;
import info.nightscout.androidaps.interfaces.PumpInterface;
+import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
-import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
-import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished;
-import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress;
import info.nightscout.androidaps.plugins.general.overview.OverviewFragment;
import info.nightscout.androidaps.plugins.general.overview.OverviewPlugin;
import info.nightscout.androidaps.plugins.general.overview.graphData.GraphData;
+import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
+import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished;
+import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress;
import info.nightscout.androidaps.utils.DateUtil;
+import info.nightscout.androidaps.utils.FabricPrivacy;
+import info.nightscout.androidaps.utils.SP;
import info.nightscout.androidaps.utils.T;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.disposables.CompositeDisposable;
-public class HistoryBrowseActivity extends AppCompatActivity {
+public class HistoryBrowseActivity extends NoSplashActivity {
private static Logger log = LoggerFactory.getLogger(HistoryBrowseActivity.class);
-
+ private CompositeDisposable disposable = new CompositeDisposable();
ImageButton chartButton;
boolean showBasal = true;
- boolean showIob, showCob, showDev, showRat, showDevslope;
+ boolean showIob, showCob, showDev, showRat, showActPrim, showActSec, showDevslope;
- @BindView(R.id.historybrowse_date)
Button buttonDate;
- @BindView(R.id.historybrowse_zoom)
Button buttonZoom;
- @BindView(R.id.historyybrowse_bggraph)
GraphView bgGraph;
- @BindView(R.id.historybrowse_iobgraph)
GraphView iobGraph;
- @BindView(R.id.historybrowse_seekBar)
SeekBar seekBar;
- @BindView(R.id.historybrowse_noprofile)
TextView noProfile;
- @BindView(R.id.overview_iobcalculationprogess)
TextView iobCalculationProgressView;
private int rangeToDisplay = 24; // for graph
@@ -82,11 +75,83 @@ public class HistoryBrowseActivity extends AppCompatActivity {
}
@Override
- protected void onCreate(Bundle savedInstanceState) {
+ public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_historybrowse);
- ButterKnife.bind(this);
+ buttonDate = findViewById(R.id.historybrowse_date);
+ buttonZoom = findViewById(R.id.historybrowse_zoom);
+ bgGraph = findViewById(R.id.historyybrowse_bggraph);
+ iobGraph = findViewById(R.id.historybrowse_iobgraph);
+ seekBar = findViewById(R.id.historybrowse_seekBar);
+ noProfile = findViewById(R.id.historybrowse_noprofile);
+ iobCalculationProgressView = findViewById(R.id.overview_iobcalculationprogess);
+
+ findViewById(R.id.historybrowse_left).setOnClickListener(v -> {
+ start -= T.hours(rangeToDisplay).msecs();
+ updateGUI("onClickLeft");
+ runCalculation("onClickLeft");
+ });
+
+ findViewById(R.id.historybrowse_right).setOnClickListener(v -> {
+ start += T.hours(rangeToDisplay).msecs();
+ updateGUI("onClickRight");
+ runCalculation("onClickRight");
+ });
+
+ findViewById(R.id.historybrowse_end).setOnClickListener(v -> {
+ Calendar calendar = Calendar.getInstance();
+ calendar.setTimeInMillis(System.currentTimeMillis());
+ calendar.set(Calendar.MILLISECOND, 0);
+ calendar.set(Calendar.SECOND, 0);
+ calendar.set(Calendar.MINUTE, 0);
+ calendar.set(Calendar.HOUR_OF_DAY, 0);
+ start = calendar.getTimeInMillis();
+ updateGUI("onClickEnd");
+ runCalculation("onClickEnd");
+ });
+
+ findViewById(R.id.historybrowse_zoom).setOnClickListener(v -> {
+ rangeToDisplay += 6;
+ rangeToDisplay = rangeToDisplay > 24 ? 6 : rangeToDisplay;
+ updateGUI("rangeChange");
+ });
+
+ findViewById(R.id.historybrowse_zoom).setOnLongClickListener(v -> {
+ Calendar calendar = Calendar.getInstance();
+ calendar.setTimeInMillis(start);
+ calendar.set(Calendar.MILLISECOND, 0);
+ calendar.set(Calendar.SECOND, 0);
+ calendar.set(Calendar.MINUTE, 0);
+ calendar.set(Calendar.HOUR_OF_DAY, 0);
+ start = calendar.getTimeInMillis();
+ updateGUI("resetToMidnight");
+ runCalculation("onLongClickZoom");
+ return true;
+ });
+
+ findViewById(R.id.historybrowse_date).setOnClickListener(v -> {
+ Calendar calendar = Calendar.getInstance();
+ calendar.setTime(new Date(start));
+ DatePickerDialog dpd = DatePickerDialog.newInstance(
+ (view, year, monthOfYear, dayOfMonth) -> {
+ Date date = new Date(0);
+ date.setYear(year - 1900);
+ date.setMonth(monthOfYear);
+ date.setDate(dayOfMonth);
+ date.setHours(0);
+ start = date.getTime();
+ updateGUI("onClickDate");
+ runCalculation("onClickDate");
+ },
+ calendar.get(Calendar.YEAR),
+ calendar.get(Calendar.MONTH),
+ calendar.get(Calendar.DAY_OF_MONTH)
+ );
+ dpd.setThemeDark(true);
+ dpd.dismissOnPause(true);
+ dpd.show(getFragmentManager(), "Datepickerdialog");
+ });
bgGraph.getGridLabelRenderer().setGridColor(MainApp.gc(R.color.graphgrid));
bgGraph.getGridLabelRenderer().reloadStyles();
@@ -103,14 +168,33 @@ public class HistoryBrowseActivity extends AppCompatActivity {
@Override
public void onPause() {
super.onPause();
- MainApp.bus().unregister(this);
+ disposable.clear();
iobCobCalculatorPlugin.stopCalculation("onPause");
}
@Override
public void onResume() {
super.onResume();
- MainApp.bus().register(this);
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventAutosensCalculationFinished.class)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(event -> {
+ if (event.getCause() == eventCustomCalculationFinished) {
+ log.debug("EventAutosensCalculationFinished");
+ synchronized (HistoryBrowseActivity.this) {
+ updateGUI("EventAutosensCalculationFinished");
+ }
+ }
+ }, FabricPrivacy::logException)
+ );
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventIobCalculationProgress.class)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(event -> {
+ if (iobCalculationProgressView != null)
+ iobCalculationProgressView.setText(event.getProgress());
+ }, FabricPrivacy::logException)
+ );
// set start of current day
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
@@ -124,78 +208,6 @@ public class HistoryBrowseActivity extends AppCompatActivity {
updateGUI("onResume");
}
- @OnClick(R.id.historybrowse_left)
- void onClickLeft() {
- start -= T.hours(rangeToDisplay).msecs();
- updateGUI("onClickLeft");
- runCalculation("onClickLeft");
- }
-
- @OnClick(R.id.historybrowse_right)
- void onClickRight() {
- start += T.hours(rangeToDisplay).msecs();
- updateGUI("onClickRight");
- runCalculation("onClickRight");
- }
-
- @OnClick(R.id.historybrowse_end)
- void onClickEnd() {
- Calendar calendar = Calendar.getInstance();
- calendar.setTimeInMillis(System.currentTimeMillis());
- calendar.set(Calendar.MILLISECOND, 0);
- calendar.set(Calendar.SECOND, 0);
- calendar.set(Calendar.MINUTE, 0);
- calendar.set(Calendar.HOUR_OF_DAY, 0);
- start = calendar.getTimeInMillis();
- updateGUI("onClickEnd");
- runCalculation("onClickEnd");
- }
-
- @OnClick(R.id.historybrowse_zoom)
- void onClickZoom() {
- rangeToDisplay += 6;
- rangeToDisplay = rangeToDisplay > 24 ? 6 : rangeToDisplay;
- updateGUI("rangeChange");
- }
-
- @OnLongClick(R.id.historybrowse_zoom)
- boolean onLongClickZoom() {
- Calendar calendar = Calendar.getInstance();
- calendar.setTimeInMillis(start);
- calendar.set(Calendar.MILLISECOND, 0);
- calendar.set(Calendar.SECOND, 0);
- calendar.set(Calendar.MINUTE, 0);
- calendar.set(Calendar.HOUR_OF_DAY, 0);
- start = calendar.getTimeInMillis();
- updateGUI("resetToMidnight");
- runCalculation("onLongClickZoom");
- return true;
- }
-
- @OnClick(R.id.historybrowse_date)
- void onClickDate() {
- Calendar calendar = Calendar.getInstance();
- calendar.setTime(new Date(start));
- DatePickerDialog dpd = DatePickerDialog.newInstance(
- (view, year, monthOfYear, dayOfMonth) -> {
- Date date = new Date(0);
- date.setYear(year - 1900);
- date.setMonth(monthOfYear);
- date.setDate(dayOfMonth);
- date.setHours(0);
- start = date.getTime();
- updateGUI("onClickDate");
- runCalculation("onClickDate");
- },
- calendar.get(Calendar.YEAR),
- calendar.get(Calendar.MONTH),
- calendar.get(Calendar.DAY_OF_MONTH)
- );
- dpd.setThemeDark(true);
- dpd.dismissOnPause(true);
- dpd.show(getFragmentManager(), "Datepickerdialog");
- }
-
private void runCalculation(String from) {
long end = start + T.hours(rangeToDisplay).msecs();
iobCobCalculatorPlugin.stopCalculation(from);
@@ -203,26 +215,6 @@ public class HistoryBrowseActivity extends AppCompatActivity {
iobCobCalculatorPlugin.runCalculation(from, end, true, false, eventCustomCalculationFinished);
}
- @Subscribe
- public void onStatusEvent(final EventAutosensCalculationFinished e) {
- if (e.cause == eventCustomCalculationFinished) {
- log.debug("EventAutosensCalculationFinished");
- runOnUiThread(() -> {
- synchronized (HistoryBrowseActivity.this) {
- updateGUI("EventAutosensCalculationFinished");
- }
- });
- }
- }
-
- @Subscribe
- public void onStatusEvent(final EventIobCalculationProgress e) {
- runOnUiThread(() -> {
- if (iobCalculationProgressView != null)
- iobCalculationProgressView.setText(e.progress);
- });
- }
-
void updateGUI(String from) {
log.debug("updateGUI from: " + from);
@@ -240,14 +232,23 @@ public class HistoryBrowseActivity extends AppCompatActivity {
}
final String units = profile.getUnits();
- final double lowLine = OverviewPlugin.getPlugin().determineLowLine(units);
- final double highLine = OverviewPlugin.getPlugin().determineHighLine(units);
+ final double lowLine = OverviewPlugin.INSTANCE.determineLowLine(units);
+ final double highLine = OverviewPlugin.INSTANCE.determineHighLine(units);
buttonDate.setText(DateUtil.dateAndTimeString(start));
buttonZoom.setText(String.valueOf(rangeToDisplay));
final boolean showPrediction = false;
+ showBasal = SP.getBoolean("hist_showbasals", true);
+ showIob = SP.getBoolean("hist_showiob", true);
+ showCob = SP.getBoolean("hist_showcob", true);
+ showDev = SP.getBoolean("hist_showdeviations", false);
+ showRat = SP.getBoolean("hist_showratios", false);
+ showActPrim = SP.getBoolean("hist_showactivityprimary", false);
+ showActSec = SP.getBoolean("hist_showactivitysecondary", false);
+ showDevslope = SP.getBoolean("hist_showdevslope", false);
+
int hoursToFetch;
final long toTime;
final long fromTime;
@@ -285,6 +286,10 @@ public class HistoryBrowseActivity extends AppCompatActivity {
// set manual x bounds to have nice steps
graphData.formatAxis(fromTime, toTime);
+ if (showActPrim) {
+ graphData.addActivity(fromTime, toTime, false, 1d);
+ }
+
// Treatments
graphData.addTreatments(fromTime, toTime);
@@ -305,6 +310,7 @@ public class HistoryBrowseActivity extends AppCompatActivity {
boolean useCobForScale = false;
boolean useDevForScale = false;
boolean useRatioForScale = false;
+ boolean useIAForScale = false;
boolean useDSForScale = false;
if (showIob) {
@@ -315,18 +321,22 @@ public class HistoryBrowseActivity extends AppCompatActivity {
useDevForScale = true;
} else if (showRat) {
useRatioForScale = true;
+ } else if (showActSec) {
+ useIAForScale = true;
} else if (showDevslope) {
useDSForScale = true;
}
if (showIob)
- secondGraphData.addIob(fromTime, toTime, useIobForScale, 1d);
+ secondGraphData.addIob(fromTime, toTime, useIobForScale, 1d, showPrediction);
if (showCob)
secondGraphData.addCob(fromTime, toTime, useCobForScale, useCobForScale ? 1d : 0.5d);
if (showDev)
secondGraphData.addDeviations(fromTime, toTime, useDevForScale, 1d);
if (showRat)
secondGraphData.addRatio(fromTime, toTime, useRatioForScale, 1d);
+ if (showActSec)
+ secondGraphData.addActivity(fromTime, toTime, useIAForScale, useIAForScale ? 2d : 1d);
if (showDevslope)
secondGraphData.addDeviationSlope(fromTime, toTime, useDSForScale, 1d);
@@ -337,14 +347,14 @@ public class HistoryBrowseActivity extends AppCompatActivity {
// do GUI update
runOnUiThread(() -> {
- if (showIob || showCob || showDev || showRat || showDevslope) {
+ if (showIob || showCob || showDev || showRat || showActSec || showDevslope) {
iobGraph.setVisibility(View.VISIBLE);
} else {
iobGraph.setVisibility(View.GONE);
}
// finally enforce drawing of graphs
graphData.performUpdate();
- if (showIob || showCob || showDev || showRat || showDevslope)
+ if (showIob || showCob || showDev || showRat || showActSec || showDevslope)
secondGraphData.performUpdate();
});
}).start();
@@ -353,22 +363,37 @@ public class HistoryBrowseActivity extends AppCompatActivity {
private void setupChartMenu() {
chartButton = (ImageButton) findViewById(R.id.overview_chartMenuButton);
chartButton.setOnClickListener(v -> {
- MenuItem item;
+ MenuItem item, dividerItem;
CharSequence title;
+ int titleMaxChars = 0;
SpannableString s;
PopupMenu popup = new PopupMenu(v.getContext(), v);
item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.BAS.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_basals));
title = item.getTitle();
+ if (titleMaxChars < title.length()) titleMaxChars = title.length();
s = new SpannableString(title);
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.basal, null)), 0, s.length(), 0);
item.setTitle(s);
item.setCheckable(true);
item.setChecked(showBasal);
+ item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.ACTPRIM.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_activity));
+ title = item.getTitle();
+ if (titleMaxChars < title.length()) titleMaxChars = title.length();
+ s = new SpannableString(title);
+ s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.activity, null)), 0, s.length(), 0);
+ item.setTitle(s);
+ item.setCheckable(true);
+ item.setChecked(showActPrim);
+
+ dividerItem = popup.getMenu().add("");
+ dividerItem.setEnabled(false);
+
item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.IOB.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_iob));
title = item.getTitle();
+ if (titleMaxChars < title.length()) titleMaxChars = title.length();
s = new SpannableString(title);
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.iob, null)), 0, s.length(), 0);
item.setTitle(s);
@@ -377,6 +402,7 @@ public class HistoryBrowseActivity extends AppCompatActivity {
item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.COB.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_cob));
title = item.getTitle();
+ if (titleMaxChars < title.length()) titleMaxChars = title.length();
s = new SpannableString(title);
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.cob, null)), 0, s.length(), 0);
item.setTitle(s);
@@ -385,6 +411,7 @@ public class HistoryBrowseActivity extends AppCompatActivity {
item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.DEV.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_deviations));
title = item.getTitle();
+ if (titleMaxChars < title.length()) titleMaxChars = title.length();
s = new SpannableString(title);
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.deviations, null)), 0, s.length(), 0);
item.setTitle(s);
@@ -393,15 +420,27 @@ public class HistoryBrowseActivity extends AppCompatActivity {
item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.SEN.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_sensitivity));
title = item.getTitle();
+ if (titleMaxChars < title.length()) titleMaxChars = title.length();
s = new SpannableString(title);
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.ratio, null)), 0, s.length(), 0);
item.setTitle(s);
item.setCheckable(true);
item.setChecked(showRat);
+ item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.ACTSEC.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_activity));
+ title = item.getTitle();
+ if (titleMaxChars < title.length()) titleMaxChars = title.length();
+ s = new SpannableString(title);
+ s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.activity, null)), 0, s.length(), 0);
+ item.setTitle(s);
+ item.setCheckable(true);
+ item.setChecked(showActSec);
+
+
if (MainApp.devBranch) {
item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.DEVSLOPE.ordinal(), Menu.NONE, "Deviation slope");
title = item.getTitle();
+ if (titleMaxChars < title.length()) titleMaxChars = title.length();
s = new SpannableString(title);
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.devslopepos, null)), 0, s.length(), 0);
item.setTitle(s);
@@ -409,19 +448,27 @@ public class HistoryBrowseActivity extends AppCompatActivity {
item.setChecked(showDevslope);
}
+ // Fairly good guestimate for required divider text size...
+ title = new String(new char[titleMaxChars + 10]).replace("\0", "_");
+ dividerItem.setTitle(title);
+
popup.setOnMenuItemClickListener(item1 -> {
if (item1.getItemId() == OverviewFragment.CHARTTYPE.BAS.ordinal()) {
- showBasal = !item1.isChecked();
+ SP.putBoolean("hist_showbasals", !item1.isChecked());
} else if (item1.getItemId() == OverviewFragment.CHARTTYPE.IOB.ordinal()) {
- showIob = !item1.isChecked();
+ SP.putBoolean("hist_showiob", !item1.isChecked());
} else if (item1.getItemId() == OverviewFragment.CHARTTYPE.COB.ordinal()) {
- showCob = !item1.isChecked();
+ SP.putBoolean("hist_showcob", !item1.isChecked());
} else if (item1.getItemId() == OverviewFragment.CHARTTYPE.DEV.ordinal()) {
- showDev = !item1.isChecked();
+ SP.putBoolean("hist_showdeviations", !item1.isChecked());
} else if (item1.getItemId() == OverviewFragment.CHARTTYPE.SEN.ordinal()) {
- showRat = !item1.isChecked();
+ SP.putBoolean("hist_showratios", !item1.isChecked());
+ } else if (item1.getItemId() == OverviewFragment.CHARTTYPE.ACTPRIM.ordinal()) {
+ SP.putBoolean("hist_showactivityprimary", !item1.isChecked());
+ } else if (item1.getItemId() == OverviewFragment.CHARTTYPE.ACTSEC.ordinal()) {
+ SP.putBoolean("hist_showactivitysecondary", !item1.isChecked());
} else if (item1.getItemId() == OverviewFragment.CHARTTYPE.DEVSLOPE.ordinal()) {
- showDevslope = !item1.isChecked();
+ SP.putBoolean("hist_showdevslope", !item1.isChecked());
}
updateGUI("onGraphCheckboxesCheckedChanged");
return true;
diff --git a/app/src/main/java/info/nightscout/androidaps/activities/NoSplashActivity.kt b/app/src/main/java/info/nightscout/androidaps/activities/NoSplashActivity.kt
new file mode 100644
index 0000000000..0b7af2bd1d
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/activities/NoSplashActivity.kt
@@ -0,0 +1,13 @@
+package info.nightscout.androidaps.activities
+
+import android.app.Activity
+import android.os.Bundle
+
+import info.nightscout.androidaps.R
+
+open class NoSplashActivity : Activity() {
+ public override fun onCreate(savedInstanceState: Bundle?) {
+ setTheme(R.style.AppTheme_NoActionBar)
+ super.onCreate(savedInstanceState)
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/activities/NoSplashAppCompatActivity.kt b/app/src/main/java/info/nightscout/androidaps/activities/NoSplashAppCompatActivity.kt
new file mode 100644
index 0000000000..e4c8027cd5
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/activities/NoSplashAppCompatActivity.kt
@@ -0,0 +1,12 @@
+package info.nightscout.androidaps.activities
+
+import android.os.Bundle
+import androidx.appcompat.app.AppCompatActivity
+import info.nightscout.androidaps.R
+
+open class NoSplashAppCompatActivity : AppCompatActivity() {
+ public override fun onCreate(savedInstanceState: Bundle?) {
+ setTheme(R.style.AppTheme_NoActionBar)
+ super.onCreate(savedInstanceState)
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/activities/PreferencesActivity.java b/app/src/main/java/info/nightscout/androidaps/activities/PreferencesActivity.java
index aea7bcfca6..367429dbbf 100644
--- a/app/src/main/java/info/nightscout/androidaps/activities/PreferencesActivity.java
+++ b/app/src/main/java/info/nightscout/androidaps/activities/PreferencesActivity.java
@@ -15,12 +15,15 @@ import android.text.TextUtils;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.events.EventPreferenceChange;
-import info.nightscout.androidaps.events.EventRefreshGui;
+import info.nightscout.androidaps.events.EventRebuildTabs;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.plugins.general.careportal.CareportalPlugin;
import info.nightscout.androidaps.plugins.constraints.safety.SafetyPlugin;
+import info.nightscout.androidaps.plugins.general.tidepool.TidepoolPlugin;
+import info.nightscout.androidaps.plugins.general.tidepool.comm.TidepoolUploader;
import info.nightscout.androidaps.plugins.insulin.InsulinOrefFreePeakPlugin;
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin;
@@ -33,24 +36,27 @@ import info.nightscout.androidaps.plugins.pump.danaRKorean.DanaRKoreanPlugin;
import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin;
import info.nightscout.androidaps.plugins.pump.danaRv2.DanaRv2Plugin;
import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin;
+import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin;
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin;
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.general.smsCommunicator.SmsCommunicatorPlugin;
-import info.nightscout.androidaps.plugins.source.SourceDexcomG5Plugin;
import info.nightscout.androidaps.plugins.general.wear.WearPlugin;
import info.nightscout.androidaps.plugins.general.xdripStatusline.StatuslinePlugin;
+import info.nightscout.androidaps.plugins.source.SourceDexcomPlugin;
import info.nightscout.androidaps.utils.LocaleHelper;
import info.nightscout.androidaps.utils.OKDialog;
import info.nightscout.androidaps.utils.SP;
+import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin;
public class PreferencesActivity extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
MyPreferenceFragment myPreferenceFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
+ setTheme(R.style.AppTheme_NoActionBar);
super.onCreate(savedInstanceState);
myPreferenceFragment = new MyPreferenceFragment();
Bundle args = new Bundle();
@@ -62,16 +68,14 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
- MainApp.bus().post(new EventPreferenceChange(key));
+ RxBus.INSTANCE.send(new EventPreferenceChange(key));
if (key.equals("language")) {
- String lang = sharedPreferences.getString("language", "en");
- LocaleHelper.setLocale(getApplicationContext(), lang);
- MainApp.bus().post(new EventRefreshGui(true));
+ RxBus.INSTANCE.send(new EventRebuildTabs(true));
//recreate() does not update language so better close settings
finish();
}
if (key.equals("short_tabtitles")) {
- MainApp.bus().post(new EventRefreshGui());
+ RxBus.INSTANCE.send(new EventRebuildTabs());
}
if (key.equals(MainApp.gs(R.string.key_openapsama_useautosens)) && SP.getBoolean(R.string.key_openapsama_useautosens, false)) {
OKDialog.show(this, MainApp.gs(R.string.configbuilder_sensitivity), MainApp.gs(R.string.sensitivity_warning), null);
@@ -93,7 +97,7 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
} else if (editTextPref.getText() != null) {
((EditTextPreference) pref).setDialogMessage(editTextPref.getDialogMessage());
pref.setSummary(editTextPref.getText());
- } else if (pref.getKey().contains("smscommunicator_allowednumbers") && TextUtils.isEmpty(editTextPref.getText().trim())) {
+ } else if (pref.getKey().contains("smscommunicator_allowednumbers") && (editTextPref.getText() == null || TextUtils.isEmpty(editTextPref.getText().trim()))) {
pref.setSummary(MainApp.gs(R.string.smscommunicator_allowednumbers_summary));
}
}
@@ -144,7 +148,7 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
addPreferencesFromResource(R.xml.pref_overview);
- addPreferencesFromResourceIfEnabled(SourceDexcomG5Plugin.getPlugin(), PluginType.BGSOURCE);
+ addPreferencesFromResourceIfEnabled(SourceDexcomPlugin.INSTANCE, PluginType.BGSOURCE);
addPreferencesFromResourceIfEnabled(CareportalPlugin.getPlugin(), PluginType.GENERAL);
addPreferencesFromResourceIfEnabled(SafetyPlugin.getPlugin(), PluginType.CONSTRAINTS);
if (Config.APS) {
@@ -166,6 +170,7 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
addPreferencesFromResourceIfEnabled(DanaRSPlugin.getPlugin(), PluginType.PUMP);
addPreferencesFromResourceIfEnabled(LocalInsightPlugin.getPlugin(), PluginType.PUMP);
addPreferencesFromResourceIfEnabled(ComboPlugin.getPlugin(), PluginType.PUMP);
+ addPreferencesFromResourceIfEnabled(MedtronicPumpPlugin.getPlugin(), PluginType.PUMP);
if (DanaRPlugin.getPlugin().isEnabled(PluginType.PROFILE)
|| DanaRKoreanPlugin.getPlugin().isEnabled(PluginType.PROFILE)
@@ -182,7 +187,9 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
addPreferencesFromResourceIfEnabled(InsulinOrefFreePeakPlugin.getPlugin(), PluginType.INSULIN);
addPreferencesFromResourceIfEnabled(NSClientPlugin.getPlugin(), PluginType.GENERAL);
+ addPreferencesFromResourceIfEnabled(TidepoolPlugin.INSTANCE, PluginType.GENERAL);
addPreferencesFromResourceIfEnabled(SmsCommunicatorPlugin.getPlugin(), PluginType.GENERAL);
+ addPreferencesFromResourceIfEnabled(AutomationPlugin.INSTANCE, PluginType.GENERAL);
addPreferencesFromResource(R.xml.pref_others);
addPreferencesFromResource(R.xml.pref_datachoices);
@@ -192,17 +199,25 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
}
if (Config.NSCLIENT) {
- PreferenceScreen scrnAdvancedSettings = (PreferenceScreen)findPreference(getString(R.string.key_advancedsettings));
+ PreferenceScreen scrnAdvancedSettings = (PreferenceScreen) findPreference(getString(R.string.key_advancedsettings));
if (scrnAdvancedSettings != null) {
scrnAdvancedSettings.removePreference(getPreference(getString(R.string.key_statuslights_res_warning)));
scrnAdvancedSettings.removePreference(getPreference(getString(R.string.key_statuslights_res_critical)));
scrnAdvancedSettings.removePreference(getPreference(getString(R.string.key_statuslights_bat_warning)));
scrnAdvancedSettings.removePreference(getPreference(getString(R.string.key_statuslights_bat_critical)));
scrnAdvancedSettings.removePreference(getPreference(getString(R.string.key_show_statuslights)));
+ scrnAdvancedSettings.removePreference(getPreference(getString(R.string.key_show_statuslights_extended)));
}
}
initSummary(getPreferenceScreen());
+
+ final Preference tidepoolTestLogin = findPreference(MainApp.gs(R.string.key_tidepool_test_login));
+ if (tidepoolTestLogin != null)
+ tidepoolTestLogin.setOnPreferenceClickListener(preference -> {
+ TidepoolUploader.INSTANCE.testLogin(getActivity());
+ return false;
+ });
}
@Override
diff --git a/app/src/main/java/info/nightscout/androidaps/activities/RequestDexcomPermissionActivity.kt b/app/src/main/java/info/nightscout/androidaps/activities/RequestDexcomPermissionActivity.kt
new file mode 100644
index 0000000000..96a399a299
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/activities/RequestDexcomPermissionActivity.kt
@@ -0,0 +1,19 @@
+package info.nightscout.androidaps.activities
+
+import android.os.Bundle
+import info.nightscout.androidaps.plugins.source.SourceDexcomPlugin
+
+class RequestDexcomPermissionActivity : NoSplashAppCompatActivity() {
+
+ private val requestCode = "AndroidAPS <3".map { it.toInt() }.sum()
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ requestPermissions(arrayOf(SourceDexcomPlugin.PERMISSION), requestCode)
+ }
+
+ override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
+ finish()
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/info/nightscout/androidaps/activities/SingleFragmentActivity.java b/app/src/main/java/info/nightscout/androidaps/activities/SingleFragmentActivity.java
index 2a381cd0a8..688ba82c6a 100644
--- a/app/src/main/java/info/nightscout/androidaps/activities/SingleFragmentActivity.java
+++ b/app/src/main/java/info/nightscout/androidaps/activities/SingleFragmentActivity.java
@@ -2,12 +2,13 @@ package info.nightscout.androidaps.activities;
import android.content.Intent;
import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.support.v4.app.Fragment;
-import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.fragment.app.Fragment;
+
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.PluginBase;
@@ -18,7 +19,7 @@ public class SingleFragmentActivity extends AppCompatActivity {
private PluginBase plugin;
@Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
+ public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_single_fragment);
diff --git a/app/src/main/java/info/nightscout/androidaps/activities/TDDStatsActivity.java b/app/src/main/java/info/nightscout/androidaps/activities/TDDStatsActivity.java
index e42d31d7c0..24cdceada6 100644
--- a/app/src/main/java/info/nightscout/androidaps/activities/TDDStatsActivity.java
+++ b/app/src/main/java/info/nightscout/androidaps/activities/TDDStatsActivity.java
@@ -1,10 +1,8 @@
package info.nightscout.androidaps.activities;
-import android.app.Activity;
import android.graphics.Color;
import android.graphics.Rect;
import android.os.Bundle;
-import android.support.v7.widget.LinearLayoutManager;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.MotionEvent;
@@ -18,7 +16,7 @@ import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
-import com.squareup.otto.Subscribe;
+import androidx.recyclerview.widget.LinearLayoutManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -39,6 +37,7 @@ import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.db.TDD;
import info.nightscout.androidaps.events.EventPumpStatusChanged;
import info.nightscout.androidaps.interfaces.PumpInterface;
+import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPlugin;
@@ -49,11 +48,15 @@ import info.nightscout.androidaps.plugins.pump.danaRv2.DanaRv2Plugin;
import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin;
import info.nightscout.androidaps.queue.Callback;
import info.nightscout.androidaps.utils.DecimalFormatter;
+import info.nightscout.androidaps.utils.FabricPrivacy;
import info.nightscout.androidaps.utils.SP;
import info.nightscout.androidaps.utils.SafeParse;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.disposables.CompositeDisposable;
-public class TDDStatsActivity extends Activity {
+public class TDDStatsActivity extends NoSplashActivity {
private static Logger log = LoggerFactory.getLogger(TDDStatsActivity.class);
+ private CompositeDisposable disposable = new CompositeDisposable();
TextView statusView, statsMessage, totalBaseBasal2;
EditText totalBaseBasal;
@@ -74,13 +77,25 @@ public class TDDStatsActivity extends Activity {
@Override
protected void onResume() {
super.onResume();
- MainApp.bus().register(this);
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventPumpStatusChanged.class)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(event -> statusView.setText(event.getStatus()), FabricPrivacy::logException)
+ );
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventDanaRSyncStatus.class)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(event -> {
+ log.debug("EventDanaRSyncStatus: " + event.getMessage());
+ statusView.setText(event.getMessage());
+ }, FabricPrivacy::logException)
+ );
}
@Override
protected void onPause() {
super.onPause();
- MainApp.bus().unregister(this);
+ disposable.clear();
}
@Override
@@ -99,7 +114,7 @@ public class TDDStatsActivity extends Activity {
}
@Override
- protected void onCreate(Bundle savedInstanceState) {
+ public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.danar_statsactivity);
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
@@ -239,7 +254,7 @@ public class TDDStatsActivity extends Activity {
statsMessage.setText(MainApp.gs(R.string.danar_stats_warning_Message));
}
});
- ConfigBuilderPlugin.getPlugin().getCommandQueue().loadTDDs( new Callback() {
+ ConfigBuilderPlugin.getPlugin().getCommandQueue().loadTDDs(new Callback() {
@Override
public void run() {
loadDataFromDB();
@@ -399,7 +414,7 @@ public class TDDStatsActivity extends Activity {
//cumulative TDDs
for (TDD record : historyList) {
- if(!historyList.isEmpty() && df.format(new Date(record.date)).equals(df.format(new Date()))) {
+ if (!historyList.isEmpty() && df.format(new Date(record.date)).equals(df.format(new Date()))) {
//Today should not be included
continue;
}
@@ -448,7 +463,7 @@ public class TDDStatsActivity extends Activity {
tl.setBackgroundColor(Color.TRANSPARENT);
}
- if(!historyList.isEmpty() && df.format(new Date(historyList.get(0).date)).equals(df.format(new Date()))) {
+ if (!historyList.isEmpty() && df.format(new Date(historyList.get(0).date)).equals(df.format(new Date()))) {
//Today should not be included
historyList.remove(0);
}
@@ -519,42 +534,17 @@ public class TDDStatsActivity extends Activity {
}
}
- @Subscribe
- public void onStatusEvent(final EventDanaRSyncStatus s) {
- log.debug("EventDanaRSyncStatus: " + s.message);
- runOnUiThread(
- new Runnable() {
- @Override
- public void run() {
- statusView.setText(s.message);
- }
- });
- }
-
- @Subscribe
- public void onStatusEvent(final EventPumpStatusChanged c) {
- runOnUiThread(
- new Runnable() {
- @Override
- public void run() {
- statusView.setText(c.textStatus());
- }
- }
- );
- }
-
-
public static boolean isOldData(List historyList) {
Object activePump = ConfigBuilderPlugin.getPlugin().getActivePump();
- PumpInterface dana = MainApp.getSpecificPlugin(DanaRPlugin.class);
- PumpInterface danaRS = MainApp.getSpecificPlugin(DanaRSPlugin.class);
- PumpInterface danaV2 = MainApp.getSpecificPlugin(DanaRv2Plugin.class);
- PumpInterface danaKorean = MainApp.getSpecificPlugin(DanaRKoreanPlugin.class);
- PumpInterface insight = MainApp.getSpecificPlugin(LocalInsightPlugin.class);
+ PumpInterface dana = DanaRPlugin.getPlugin();
+ PumpInterface danaRS = DanaRSPlugin.getPlugin();
+ PumpInterface danaV2 = DanaRv2Plugin.getPlugin();
+ PumpInterface danaKorean = DanaRKoreanPlugin.getPlugin();
+ PumpInterface insight = LocalInsightPlugin.getPlugin();
boolean startsYesterday = activePump == dana || activePump == danaRS || activePump == danaV2 || activePump == danaKorean || activePump == insight;
DateFormat df = new SimpleDateFormat("dd.MM.");
- return (historyList.size() < 3 || !(df.format(new Date(historyList.get(0).date)).equals(df.format(new Date(System.currentTimeMillis() - (startsYesterday?1000 * 60 * 60 * 24:0))))));
+ return (historyList.size() < 3 || !(df.format(new Date(historyList.get(0).date)).equals(df.format(new Date(System.currentTimeMillis() - (startsYesterday ? 1000 * 60 * 60 * 24 : 0))))));
}
}
\ No newline at end of file
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 b1267e81bc..9d7a49493b 100644
--- a/app/src/main/java/info/nightscout/androidaps/data/ConstraintChecker.java
+++ b/app/src/main/java/info/nightscout/androidaps/data/ConstraintChecker.java
@@ -1,11 +1,9 @@
package info.nightscout.androidaps.data;
-import android.support.annotation.NonNull;
+import androidx.annotation.NonNull;
import java.util.ArrayList;
-import javax.annotation.Nonnull;
-
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.interfaces.Constraint;
diff --git a/app/src/main/java/info/nightscout/androidaps/data/Intervals.java b/app/src/main/java/info/nightscout/androidaps/data/Intervals.java
index 66d567d9bd..efb3b76aea 100644
--- a/app/src/main/java/info/nightscout/androidaps/data/Intervals.java
+++ b/app/src/main/java/info/nightscout/androidaps/data/Intervals.java
@@ -1,7 +1,7 @@
package info.nightscout.androidaps.data;
-import android.support.annotation.Nullable;
-import android.support.v4.util.LongSparseArray;
+import androidx.annotation.Nullable;
+import androidx.collection.LongSparseArray;
import java.util.ArrayList;
import java.util.List;
@@ -22,7 +22,7 @@ public abstract class Intervals {
rawData = new LongSparseArray();
}
- public synchronized Intervals reset() {
+ public synchronized Intervals reset() {
rawData = new LongSparseArray();
return this;
}
diff --git a/app/src/main/java/info/nightscout/androidaps/data/IobTotal.java b/app/src/main/java/info/nightscout/androidaps/data/IobTotal.java
index 73f75b9c7d..79885e297f 100644
--- a/app/src/main/java/info/nightscout/androidaps/data/IobTotal.java
+++ b/app/src/main/java/info/nightscout/androidaps/data/IobTotal.java
@@ -9,10 +9,12 @@ import org.slf4j.LoggerFactory;
import java.util.Date;
+import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface;
+import info.nightscout.androidaps.plugins.general.overview.graphExtensions.PointsWithLabelGraphSeries;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.Round;
-public class IobTotal {
+public class IobTotal implements DataPointWithLabelInterface {
private static Logger log = LoggerFactory.getLogger(IobTotal.class);
public double iob;
@@ -133,4 +135,52 @@ public class IobTotal {
return json;
}
+ // DataPoint interface
+
+ int color;
+
+ @Override
+ public double getX() {
+ return time;
+ }
+
+ @Override
+ public double getY() {
+ return iob;
+ }
+
+ @Override
+ public void setY(double y) {
+
+ }
+
+ @Override
+ public String getLabel() {
+ return null;
+ }
+
+ @Override
+ public long getDuration() {
+ return 0;
+ }
+
+ @Override
+ public PointsWithLabelGraphSeries.Shape getShape() {
+ return PointsWithLabelGraphSeries.Shape.IOBPREDICTION;
+ }
+
+ @Override
+ public float getSize() {
+ return 0.5f;
+ }
+
+ @Override
+ public int getColor() {
+ return color;
+ }
+
+ public IobTotal setColor(int color) {
+ this.color = color;
+ return this;
+ }
}
diff --git a/app/src/main/java/info/nightscout/androidaps/data/NonOverlappingIntervals.java b/app/src/main/java/info/nightscout/androidaps/data/NonOverlappingIntervals.java
index 8e0c286e7e..c426aede40 100644
--- a/app/src/main/java/info/nightscout/androidaps/data/NonOverlappingIntervals.java
+++ b/app/src/main/java/info/nightscout/androidaps/data/NonOverlappingIntervals.java
@@ -1,10 +1,8 @@
package info.nightscout.androidaps.data;
-import android.support.annotation.Nullable;
-import android.support.v4.util.LongSparseArray;
+import androidx.annotation.Nullable;
-import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.interfaces.Interval;
/**
@@ -21,7 +19,7 @@ public class NonOverlappingIntervals extends Intervals {
rawData = other.rawData.clone();
}
- protected synchronized void merge() {
+ public synchronized void merge() {
for (int index = 0; index < rawData.size() - 1; index++) {
Interval i = rawData.valueAt(index);
long startOfNewer = rawData.valueAt(index + 1).start();
diff --git a/app/src/main/java/info/nightscout/androidaps/data/OverlappingIntervals.java b/app/src/main/java/info/nightscout/androidaps/data/OverlappingIntervals.java
index 76c2ff3615..5515ea15e1 100644
--- a/app/src/main/java/info/nightscout/androidaps/data/OverlappingIntervals.java
+++ b/app/src/main/java/info/nightscout/androidaps/data/OverlappingIntervals.java
@@ -1,7 +1,7 @@
package info.nightscout.androidaps.data;
-import android.support.annotation.Nullable;
+import androidx.annotation.Nullable;
import info.nightscout.androidaps.interfaces.Interval;
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 23a7e62426..6f18ba7af5 100644
--- a/app/src/main/java/info/nightscout/androidaps/data/Profile.java
+++ b/app/src/main/java/info/nightscout/androidaps/data/Profile.java
@@ -1,6 +1,6 @@
package info.nightscout.androidaps.data;
-import android.support.v4.util.LongSparseArray;
+import androidx.collection.LongSparseArray;
import org.json.JSONArray;
import org.json.JSONException;
@@ -11,11 +11,13 @@ import org.slf4j.LoggerFactory;
import java.text.DecimalFormat;
import java.util.TimeZone;
+import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface;
+import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification;
@@ -165,17 +167,18 @@ public class Profile {
final JSONObject o = array.getJSONObject(index);
long tas = 0;
try {
- tas = getShitfTimeSecs((int) o.getLong("timeAsSeconds"));
- } catch (JSONException e) {
String time = o.getString("time");
tas = getShitfTimeSecs(DateUtil.toSeconds(time));
+ } catch (JSONException e) {
//log.debug(">>>>>>>>>>>> Used recalculated timeAsSecons: " + time + " " + tas);
+ tas = getShitfTimeSecs((int) o.getLong("timeAsSeconds"));
}
double value = o.getDouble("value") * multiplier;
sparse.put(tas, value);
- } catch (JSONException e) {
+ } catch (Exception e) {
log.error("Unhandled exception", e);
log.error(json.toString());
+ FabricPrivacy.logException(e);
}
}
@@ -226,8 +229,10 @@ public class Profile {
for (int index = 0; index < basal_v.size(); index++) {
long secondsFromMidnight = basal_v.keyAt(index);
if (notify && secondsFromMidnight % 3600 != 0) {
- Notification notification = new Notification(Notification.BASAL_PROFILE_NOT_ALIGNED_TO_HOURS, String.format(MainApp.gs(R.string.basalprofilenotaligned), from), Notification.NORMAL);
- MainApp.bus().post(new EventNewNotification(notification));
+ if (Config.APS) {
+ Notification notification = new Notification(Notification.BASAL_PROFILE_NOT_ALIGNED_TO_HOURS, String.format(MainApp.gs(R.string.basalprofilenotaligned), from), Notification.NORMAL);
+ RxBus.INSTANCE.send(new EventNewNotification(notification));
+ }
}
}
}
@@ -258,11 +263,11 @@ public class Profile {
}
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)));
+ RxBus.INSTANCE.send(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)));
+ RxBus.INSTANCE.send(new EventNewNotification(new Notification(Notification.MAXIMUM_BASAL_VALUE_REPLACED, String.format(MainApp.gs(R.string.maximumbasalvaluereplaced), from), Notification.NORMAL)));
}
private void validate(LongSparseArray array) {
@@ -400,6 +405,19 @@ public class Profile {
return getValuesList(isf_v, null, new DecimalFormat("0.0"), getUnits() + MainApp.gs(R.string.profile_per_unit));
}
+ public ProfileValue[] getIsfs() {
+ if (isf_v == null)
+ isf_v = convertToSparseArray(ic);
+ ProfileValue[] ret = new ProfileValue[isf_v.size()];
+
+ for (Integer index = 0; index < isf_v.size(); index++) {
+ Integer tas = (int) isf_v.keyAt(index);
+ double value = isf_v.valueAt(index);
+ ret[index] = new ProfileValue(tas, value);
+ }
+ return ret;
+ }
+
public double getIc() {
return getIcTimeFromMidnight(secondsFromMidnight());
}
@@ -420,6 +438,19 @@ public class Profile {
return getValuesList(ic_v, null, new DecimalFormat("0.0"), MainApp.gs(R.string.profile_carbs_per_unit));
}
+ public ProfileValue[] getIcs() {
+ if (ic_v == null)
+ ic_v = convertToSparseArray(ic);
+ ProfileValue[] ret = new ProfileValue[ic_v.size()];
+
+ for (Integer index = 0; index < ic_v.size(); index++) {
+ Integer tas = (int) ic_v.keyAt(index);
+ double value = ic_v.valueAt(index);
+ ret[index] = new ProfileValue(tas, value);
+ }
+ return ret;
+ }
+
public double getBasal() {
return getBasalTimeFromMidnight(secondsFromMidnight());
}
@@ -438,11 +469,11 @@ public class Profile {
public String getBasalList() {
if (basal_v == null)
basal_v = convertToSparseArray(basal);
- return getValuesList(basal_v, null, new DecimalFormat("0.00"), MainApp.gs(R.string.profile_ins_units_per_hout));
+ return getValuesList(basal_v, null, new DecimalFormat("0.00"), MainApp.gs(R.string.profile_ins_units_per_hour));
}
- public class BasalValue {
- public BasalValue(int timeAsSeconds, double value) {
+ public class ProfileValue {
+ public ProfileValue(int timeAsSeconds, double value) {
this.timeAsSeconds = timeAsSeconds;
this.value = value;
}
@@ -451,15 +482,15 @@ public class Profile {
public double value;
}
- public synchronized BasalValue[] getBasalValues() {
+ public synchronized ProfileValue[] getBasalValues() {
if (basal_v == null)
basal_v = convertToSparseArray(basal);
- BasalValue[] ret = new BasalValue[basal_v.size()];
+ ProfileValue[] ret = new ProfileValue[basal_v.size()];
for (Integer index = 0; index < basal_v.size(); index++) {
Integer tas = (int) basal_v.keyAt(index);
double value = basal_v.valueAt(index);
- ret[index] = new BasalValue(tas, value);
+ ret[index] = new ProfileValue(tas, value);
}
return ret;
}
@@ -500,6 +531,49 @@ public class Profile {
return getValueToTime(targetHigh_v, timeAsSeconds);
}
+ public class TargetValue {
+ public TargetValue(int timeAsSeconds, double low, double high) {
+ this.timeAsSeconds = timeAsSeconds;
+ this.low = low;
+ this.high = high;
+ }
+
+ public int timeAsSeconds;
+ public double low;
+ public double high;
+ }
+
+ public TargetValue[] getTargets() {
+ if (targetLow_v == null)
+ targetLow_v = convertToSparseArray(targetLow);
+ if (targetHigh_v == null)
+ targetHigh_v = convertToSparseArray(targetHigh);
+ TargetValue[] ret = new TargetValue[targetLow_v.size()];
+
+ for (Integer index = 0; index < targetLow_v.size(); index++) {
+ Integer tas = (int) targetLow_v.keyAt(index);
+ double low = targetLow_v.valueAt(index);
+ double high = targetHigh_v.valueAt(index);
+ ret[index] = new TargetValue(tas, low, high);
+ }
+ return ret;
+ }
+
+ public ProfileValue[] getSingleTargets() {
+ if (targetLow_v == null)
+ targetLow_v = convertToSparseArray(targetLow);
+ if (targetHigh_v == null)
+ targetHigh_v = convertToSparseArray(targetHigh);
+ ProfileValue[] ret = new ProfileValue[targetLow_v.size()];
+
+ for (Integer index = 0; index < targetLow_v.size(); index++) {
+ Integer tas = (int) targetLow_v.keyAt(index);
+ double target = (targetLow_v.valueAt(index) + targetHigh_v.valueAt(index)) / 2;
+ ret[index] = new ProfileValue(tas, target);
+ }
+ return ret;
+ }
+
public String getTargetList() {
if (targetLow_v == null)
targetLow_v = convertToSparseArray(targetLow);
diff --git a/app/src/main/java/info/nightscout/androidaps/data/ProfileIntervals.java b/app/src/main/java/info/nightscout/androidaps/data/ProfileIntervals.java
index 8938b53936..37be1dc6e9 100644
--- a/app/src/main/java/info/nightscout/androidaps/data/ProfileIntervals.java
+++ b/app/src/main/java/info/nightscout/androidaps/data/ProfileIntervals.java
@@ -1,7 +1,7 @@
package info.nightscout.androidaps.data;
-import android.support.annotation.Nullable;
-import android.support.v4.util.LongSparseArray;
+import androidx.annotation.Nullable;
+import androidx.collection.LongSparseArray;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -31,7 +31,7 @@ public class ProfileIntervals {
rawData = other.rawData.clone();
}
- public synchronized ProfileIntervals reset() {
+ public synchronized ProfileIntervals reset() {
rawData = new LongSparseArray<>();
return this;
}
diff --git a/app/src/main/java/info/nightscout/androidaps/data/ProfileStore.java b/app/src/main/java/info/nightscout/androidaps/data/ProfileStore.java
index f97d8b5e02..a0b54ec0bb 100644
--- a/app/src/main/java/info/nightscout/androidaps/data/ProfileStore.java
+++ b/app/src/main/java/info/nightscout/androidaps/data/ProfileStore.java
@@ -1,7 +1,7 @@
package info.nightscout.androidaps.data;
-import android.support.annotation.Nullable;
-import android.support.v4.util.ArrayMap;
+import androidx.annotation.Nullable;
+import androidx.collection.ArrayMap;
import org.json.JSONException;
import org.json.JSONObject;
diff --git a/app/src/main/java/info/nightscout/androidaps/data/PumpEnactResult.java b/app/src/main/java/info/nightscout/androidaps/data/PumpEnactResult.java
index d38b355634..461d8faa7b 100644
--- a/app/src/main/java/info/nightscout/androidaps/data/PumpEnactResult.java
+++ b/app/src/main/java/info/nightscout/androidaps/data/PumpEnactResult.java
@@ -45,6 +45,11 @@ public class PumpEnactResult {
return this;
}
+ public PumpEnactResult comment(int comment) {
+ this.comment = MainApp.gs(comment);
+ return this;
+ }
+
public PumpEnactResult duration(int duration) {
this.duration = duration;
return this;
diff --git a/app/src/main/java/info/nightscout/androidaps/data/QuickWizard.java b/app/src/main/java/info/nightscout/androidaps/data/QuickWizard.java
deleted file mode 100644
index 80a6e1b457..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/data/QuickWizard.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package info.nightscout.androidaps.data;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import info.nightscout.androidaps.utils.SP;
-
-/**
- * Created by mike on 12.10.2016.
- */
-
-public class QuickWizard {
- private static Logger log = LoggerFactory.getLogger(QuickWizard.class);
-
- private JSONArray storage = new JSONArray();
-
- public void setData(JSONArray newData) {
- storage = newData;
- }
-
- public void save() {
- SP.putString("QuickWizard", storage.toString());
- }
-
- public int size() {
- return storage.length();
- }
-
- public QuickWizardEntry get(int position) {
- try {
- return new QuickWizardEntry((JSONObject) storage.get(position), position);
- } catch (JSONException e) {
- log.error("Unhandled exception", e);
- }
- return null;
- }
-
- public Boolean isActive() {
- for (int i = 0; i < storage.length(); i++) {
- try {
- if (new QuickWizardEntry((JSONObject) storage.get(i), i).isActive()) return true;
- } catch (JSONException e) {
- log.error("Unhandled exception", e);
- }
- }
- return false;
- }
-
- public QuickWizardEntry getActive() {
- for (int i = 0; i < storage.length(); i++) {
- QuickWizardEntry entry;
- try {
- entry = new QuickWizardEntry((JSONObject) storage.get(i), i);
- } catch (JSONException e) {
- continue;
- }
- if (entry.isActive()) return entry;
- }
- return null;
- }
-
- public QuickWizardEntry newEmptyItem() {
- return new QuickWizardEntry();
- }
-
- public void addOrUpdate(QuickWizardEntry newItem) {
- if (newItem.position == -1)
- storage.put(newItem.storage);
- else {
- try {
- storage.put(newItem.position, newItem.storage);
- } catch (JSONException e) {
- log.error("Unhandled exception", e);
- }
- }
- save();
- }
-
- public void remove(int position) {
- storage.remove(position);
- save();
- }
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/data/QuickWizard.kt b/app/src/main/java/info/nightscout/androidaps/data/QuickWizard.kt
new file mode 100644
index 0000000000..f8bca8c450
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/data/QuickWizard.kt
@@ -0,0 +1,52 @@
+package info.nightscout.androidaps.data
+
+import info.nightscout.androidaps.utils.SP
+import org.json.JSONArray
+import org.json.JSONObject
+
+object QuickWizard {
+ private var storage = JSONArray()
+
+ init {
+ setData(JSONArray(SP.getString("QuickWizard", "[]")))
+ }
+
+ fun getActive(): QuickWizardEntry? {
+ for (i in 0 until storage.length()) {
+ val entry = QuickWizardEntry(storage.get(i) as JSONObject, i)
+ if (entry.isActive) return entry
+ }
+ return null
+ }
+
+ fun setData(newData: JSONArray) {
+ storage = newData
+ }
+
+ fun save() {
+ SP.putString("QuickWizard", storage.toString())
+ }
+
+ fun size(): Int = storage.length()
+
+ operator fun get(position: Int): QuickWizardEntry =
+ QuickWizardEntry(storage.get(position) as JSONObject, position)
+
+
+ fun newEmptyItem(): QuickWizardEntry {
+ return QuickWizardEntry()
+ }
+
+ fun addOrUpdate(newItem: QuickWizardEntry) {
+ if (newItem.position == -1)
+ storage.put(newItem.storage)
+ else
+ storage.put(newItem.position, newItem.storage)
+ save()
+ }
+
+ fun remove(position: Int) {
+ storage.remove(position)
+ save()
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/data/QuickWizardEntry.java b/app/src/main/java/info/nightscout/androidaps/data/QuickWizardEntry.java
index 0bfcbb1002..062f6ae391 100644
--- a/app/src/main/java/info/nightscout/androidaps/data/QuickWizardEntry.java
+++ b/app/src/main/java/info/nightscout/androidaps/data/QuickWizardEntry.java
@@ -50,7 +50,7 @@ public class QuickWizardEntry {
useTemptarget: 0
}
*/
- public QuickWizardEntry() {
+ QuickWizardEntry() {
String emptyData = "{\"buttonText\":\"\",\"carbs\":0,\"validFrom\":0,\"validTo\":86340}";
try {
storage = new JSONObject(emptyData);
@@ -60,18 +60,17 @@ public class QuickWizardEntry {
position = -1;
}
- public QuickWizardEntry(JSONObject entry, int position) {
+ QuickWizardEntry(JSONObject entry, int position) {
storage = entry;
this.position = position;
}
- public Boolean isActive() {
+ Boolean isActive() {
return Profile.secondsFromMidnight() >= validFrom() && Profile.secondsFromMidnight() <= validTo();
}
- public BolusWizard doCalc(Profile profile, TempTarget tempTarget, BgReading lastBG, boolean _synchronized) {
- BolusWizard wizard = new BolusWizard();
-
+ public BolusWizard doCalc(Profile profile, String profileName, BgReading lastBG, boolean _synchronized) {
+ final TempTarget tempTarget = TreatmentsPlugin.getPlugin().getTempTargetFromHistory();
//BG
double bg = 0;
if (lastBG != null && useBG() == YES) {
@@ -86,11 +85,6 @@ public class QuickWizardEntry {
cob = cobInfo.displayCob;
}
- // Temp target
- if (useTempTarget() == NO) {
- tempTarget = null;
- }
-
// Bolus IOB
boolean bolusIOB = false;
if (useBolusIOB() == YES) {
@@ -130,8 +124,7 @@ public class QuickWizardEntry {
trend = true;
}
- wizard.doCalc(profile, tempTarget, carbs(), cob, bg, 0d, bolusIOB, basalIOB, superBolus, trend);
- return wizard;
+ return new BolusWizard(profile, profileName, tempTarget, carbs(), cob, bg, 0d, 100, true, useCOB() == YES, bolusIOB, basalIOB, superBolus, useTempTarget() == YES, trend, "QuickWizard");
}
public String buttonText() {
diff --git a/app/src/main/java/info/nightscout/androidaps/db/BgReading.java b/app/src/main/java/info/nightscout/androidaps/db/BgReading.java
index 6fafdc4b6d..8b206e2c78 100644
--- a/app/src/main/java/info/nightscout/androidaps/db/BgReading.java
+++ b/app/src/main/java/info/nightscout/androidaps/db/BgReading.java
@@ -216,8 +216,8 @@ public class BgReading implements DataPointWithLabelInterface {
@Override
public int getColor() {
String units = ProfileFunctions.getInstance().getProfileUnits();
- Double lowLine = OverviewPlugin.getPlugin().determineLowLine(units);
- Double highLine = OverviewPlugin.getPlugin().determineHighLine(units);
+ Double lowLine = OverviewPlugin.INSTANCE.determineLowLine(units);
+ Double highLine = OverviewPlugin.INSTANCE.determineHighLine(units);
int color = MainApp.gc(R.color.inrange);
if (isPrediction())
return getPredectionColor();
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 f0e70c0a25..40fadff684 100644
--- a/app/src/main/java/info/nightscout/androidaps/db/CareportalEvent.java
+++ b/app/src/main/java/info/nightscout/androidaps/db/CareportalEvent.java
@@ -93,12 +93,22 @@ public class CareportalEvent implements DataPointWithLabelInterface, Interval {
return (System.currentTimeMillis() - date) / (60 * 60 * 1000.0);
}
- public String age() {
+ public String age(boolean useShortText) {
Map diff = computeDiff(date, System.currentTimeMillis());
- if (OverviewFragment.shorttextmode)
- return diff.get(TimeUnit.DAYS) + "d" + diff.get(TimeUnit.HOURS) + "h";
- else
- return diff.get(TimeUnit.DAYS) + " " + MainApp.gs(R.string.days) + " " + diff.get(TimeUnit.HOURS) + " " + MainApp.gs(R.string.hours);
+
+ String days = " " + MainApp.gs(R.string.days) + " ";
+ String hours = " " + MainApp.gs(R.string.hours) + " ";
+
+ if (useShortText) {
+ days = "d";
+ hours = "h";
+ }
+
+ return diff.get(TimeUnit.DAYS) + days + diff.get(TimeUnit.HOURS) + hours;
+ }
+
+ public String age() {
+ return age(OverviewFragment.shorttextmode);
}
public boolean isOlderThan(double hours) {
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 1f071a2f18..d8926fc4c1 100644
--- a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java
+++ b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java
@@ -3,7 +3,7 @@ package info.nightscout.androidaps.db;
import android.content.Context;
import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteDatabase;
-import android.support.annotation.Nullable;
+import androidx.annotation.Nullable;
import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
import com.j256.ormlite.dao.CloseableIterator;
@@ -21,6 +21,8 @@ import org.slf4j.LoggerFactory;
import java.sql.SQLException;
import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
@@ -29,6 +31,7 @@ import java.util.concurrent.TimeUnit;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.data.OverlappingIntervals;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.ProfileStore;
@@ -240,7 +243,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
new java.util.TimerTask() {
@Override
public void run() {
- MainApp.bus().post(new EventRefreshOverview("resetDatabases"));
+ RxBus.INSTANCE.send(new EventRefreshOverview("resetDatabases"));
}
},
3000
@@ -409,7 +412,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public void run() {
if (L.isEnabled(L.DATABASE))
log.debug("Firing EventNewBg");
- MainApp.bus().post(new EventNewBG(bgReading));
+ RxBus.INSTANCE.send(new EventNewBG(bgReading));
scheduledBgPost = null;
}
}
@@ -434,7 +437,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return null;
for (int i = 0; i < bgList.size(); i++)
- if (bgList.get(i).value > 39)
+ if (bgList.get(i).value >= 39)
return bgList.get(i);
return null;
}
@@ -534,6 +537,24 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return tddList;
}
+ public List getTDDsForLastXDays(int days) {
+ List tddList;
+ GregorianCalendar gc = new GregorianCalendar();
+ gc.add(Calendar.DAY_OF_YEAR, (-1) * days);
+
+ try {
+ QueryBuilder queryBuilder = getDaoTDD().queryBuilder();
+ queryBuilder.orderBy("date", false);
+ Where where = queryBuilder.where();
+ where.ge("date", gc.getTimeInMillis());
+ PreparedQuery preparedQuery = queryBuilder.prepare();
+ tddList = getDaoTDD().query(preparedQuery);
+ } catch (SQLException e) {
+ log.error("Unhandled exception", e);
+ tddList = new ArrayList<>();
+ }
+ return tddList;
+ }
// ------------- DbRequests handling -------------------
@@ -596,7 +617,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
}
}
- // -------------------- TREATMENT HANDLING -------------------
+ // -------------------- TEMPTARGET HANDLING -------------------
public static void updateEarliestDataChange(long newDate) {
if (earliestDataChange == null) {
@@ -627,6 +648,23 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return new ArrayList();
}
+ public List getTemptargetsDataFromTime(long from, long to, boolean ascending) {
+ try {
+ Dao daoTempTargets = getDaoTempTargets();
+ List tempTargets;
+ QueryBuilder queryBuilder = daoTempTargets.queryBuilder();
+ queryBuilder.orderBy("date", ascending);
+ Where where = queryBuilder.where();
+ where.between("date", from, to);
+ PreparedQuery preparedQuery = queryBuilder.prepare();
+ tempTargets = daoTempTargets.query(preparedQuery);
+ return tempTargets;
+ } catch (SQLException e) {
+ log.error("Unhandled exception", e);
+ }
+ return new ArrayList();
+ }
+
public boolean createOrUpdate(TempTarget tempTarget) {
try {
TempTarget old;
@@ -699,7 +737,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public void run() {
if (L.isEnabled(L.DATABASE))
log.debug("Firing EventTempTargetChange");
- MainApp.bus().post(new EventTempTargetChange());
+ RxBus.INSTANCE.send(new EventTempTargetChange());
scheduledTemTargetPost = null;
}
}
@@ -852,6 +890,31 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
log.debug("TEMPBASAL: Already exists from: " + Source.getString(tempBasal.source) + " " + tempBasal.toString());
return false;
}
+
+ // search by date (in case its standard record that has become pump record)
+ QueryBuilder queryBuilder2 = getDaoTemporaryBasal().queryBuilder();
+ Where where2 = queryBuilder2.where();
+ where2.eq("date", tempBasal.date);
+ PreparedQuery preparedQuery2 = queryBuilder2.prepare();
+ List trList2 = getDaoTemporaryBasal().query(preparedQuery2);
+
+ if (trList2.size() > 0) {
+ old = trList2.get(0);
+
+ old.copyFromPump(tempBasal);
+ old.source = Source.PUMP;
+
+ if (L.isEnabled(L.DATABASE))
+ log.debug("TEMPBASAL: Updated record with Pump Data : " + Source.getString(tempBasal.source) + " " + tempBasal.toString());
+
+ getDaoTemporaryBasal().update(old);
+
+ updateEarliestDataChange(tempBasal.date);
+ scheduleTemporaryBasalChange();
+
+ return false;
+ }
+
getDaoTemporaryBasal().create(tempBasal);
if (L.isEnabled(L.DATABASE))
log.debug("TEMPBASAL: New record from: " + Source.getString(tempBasal.source) + " " + tempBasal.toString());
@@ -950,15 +1013,31 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return new ArrayList();
}
+ public List getTemporaryBasalsDataFromTime(long from, long to, boolean ascending) {
+ try {
+ List tempbasals;
+ QueryBuilder queryBuilder = getDaoTemporaryBasal().queryBuilder();
+ queryBuilder.orderBy("date", ascending);
+ Where where = queryBuilder.where();
+ where.between("date", from, to);
+ PreparedQuery preparedQuery = queryBuilder.prepare();
+ tempbasals = getDaoTemporaryBasal().query(preparedQuery);
+ return tempbasals;
+ } catch (SQLException e) {
+ log.error("Unhandled exception", e);
+ }
+ return new ArrayList();
+ }
+
private static void scheduleTemporaryBasalChange() {
class PostRunnable implements Runnable {
public void run() {
if (L.isEnabled(L.DATABASE))
log.debug("Firing EventTempBasalChange");
- MainApp.bus().post(new EventReloadTempBasalData());
- MainApp.bus().post(new EventTempBasalChange());
+ RxBus.INSTANCE.send(new EventReloadTempBasalData());
+ RxBus.INSTANCE.send(new EventTempBasalChange());
if (earliestDataChange != null)
- MainApp.bus().post(new EventNewHistoryData(earliestDataChange));
+ RxBus.INSTANCE.send(new EventNewHistoryData(earliestDataChange));
earliestDataChange = null;
scheduledTemBasalsPost = null;
}
@@ -1076,6 +1155,29 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return null;
}
+
+ public TemporaryBasal findTempBasalByPumpId(Long pumpId) {
+ try {
+ QueryBuilder queryBuilder = null;
+ queryBuilder = getDaoTemporaryBasal().queryBuilder();
+ queryBuilder.orderBy("date", false);
+ Where where = queryBuilder.where();
+ where.eq("pumpId", pumpId);
+ PreparedQuery preparedQuery = queryBuilder.prepare();
+ List list = getDaoTemporaryBasal().query(preparedQuery);
+
+ if (list.size() > 0)
+ return list.get(0);
+ else
+ return null;
+
+ } catch (SQLException e) {
+ log.error("Unhandled exception", e);
+ }
+ return null;
+ }
+
+
// ------------ ExtendedBolus handling ---------------
public boolean createOrUpdate(ExtendedBolus extendedBolus) {
@@ -1268,9 +1370,9 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public void run() {
if (L.isEnabled(L.DATABASE))
log.debug("Firing EventExtendedBolusChange");
- MainApp.bus().post(new EventReloadTreatmentData(new EventExtendedBolusChange()));
+ RxBus.INSTANCE.send(new EventReloadTreatmentData(new EventExtendedBolusChange()));
if (earliestDataChange != null)
- MainApp.bus().post(new EventNewHistoryData(earliestDataChange));
+ RxBus.INSTANCE.send(new EventNewHistoryData(earliestDataChange));
earliestDataChange = null;
scheduledExtendedBolusPost = null;
}
@@ -1354,6 +1456,23 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return new ArrayList<>();
}
+ public List getCareportalEvents(long start, long end, boolean ascending) {
+ try {
+ List careportalEvents;
+ QueryBuilder queryBuilder = getDaoCareportalEvents().queryBuilder();
+ queryBuilder.orderBy("date", ascending);
+ Where where = queryBuilder.where();
+ where.between("date", start, end);
+ PreparedQuery preparedQuery = queryBuilder.prepare();
+ careportalEvents = getDaoCareportalEvents().query(preparedQuery);
+ preprocessOpenAPSOfflineEvents(careportalEvents);
+ return careportalEvents;
+ } catch (SQLException e) {
+ log.error("Unhandled exception", e);
+ }
+ return new ArrayList<>();
+ }
+
public void preprocessOpenAPSOfflineEvents(List list) {
OverlappingIntervals offlineEvents = new OverlappingIntervals();
for (int i = 0; i < list.size(); i++) {
@@ -1457,7 +1576,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public void run() {
if (L.isEnabled(L.DATABASE))
log.debug("Firing scheduleCareportalEventChange");
- MainApp.bus().post(new EventCareportalEventChange());
+ RxBus.INSTANCE.send(new EventCareportalEventChange());
scheduledCareportalEventPost = null;
}
}
@@ -1507,6 +1626,24 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return new ArrayList<>();
}
+ public List getProfileSwitchEventsFromTime(long from, long to, boolean ascending) {
+ try {
+ Dao daoProfileSwitch = getDaoProfileSwitch();
+ List profileSwitches;
+ QueryBuilder queryBuilder = daoProfileSwitch.queryBuilder();
+ queryBuilder.orderBy("date", ascending);
+ queryBuilder.limit(100L);
+ Where where = queryBuilder.where();
+ where.between("date", from, to);
+ PreparedQuery preparedQuery = queryBuilder.prepare();
+ profileSwitches = daoProfileSwitch.query(preparedQuery);
+ return profileSwitches;
+ } catch (SQLException e) {
+ log.error("Unhandled exception", e);
+ }
+ return new ArrayList<>();
+ }
+
public boolean createOrUpdate(ProfileSwitch profileSwitch) {
try {
ProfileSwitch old;
@@ -1582,8 +1719,8 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public void run() {
if (L.isEnabled(L.DATABASE))
log.debug("Firing EventProfileNeedsUpdate");
- MainApp.bus().post(new EventReloadProfileSwitchData());
- MainApp.bus().post(new EventProfileNeedsUpdate());
+ RxBus.INSTANCE.send(new EventReloadProfileSwitchData());
+ RxBus.INSTANCE.send(new EventProfileNeedsUpdate());
scheduledProfileSwitchEventPost = null;
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/db/DbObjectBase.java b/app/src/main/java/info/nightscout/androidaps/db/DbObjectBase.java
new file mode 100644
index 0000000000..a0c7f4bd7b
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/db/DbObjectBase.java
@@ -0,0 +1,9 @@
+package info.nightscout.androidaps.db;
+
+public interface DbObjectBase {
+
+ long getDate();
+
+ long getPumpId();
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/db/ExtendedBolus.java b/app/src/main/java/info/nightscout/androidaps/db/ExtendedBolus.java
index 2f11b752c8..25d2c308c1 100644
--- a/app/src/main/java/info/nightscout/androidaps/db/ExtendedBolus.java
+++ b/app/src/main/java/info/nightscout/androidaps/db/ExtendedBolus.java
@@ -18,12 +18,14 @@ import java.util.Objects;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.data.Iob;
import info.nightscout.androidaps.data.IobTotal;
+import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.interfaces.InsulinInterface;
import info.nightscout.androidaps.interfaces.Interval;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface;
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.PointsWithLabelGraphSeries;
+import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult;
import info.nightscout.androidaps.plugins.treatments.Treatment;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.DecimalFormatter;
@@ -219,7 +221,7 @@ public class ExtendedBolus implements Interval, DataPointWithLabelInterface {
IobTotal result = new IobTotal(time);
InsulinInterface insulinInterface = ConfigBuilderPlugin.getPlugin().getActiveInsulin();
- int realDuration = getDurationToTime(time);
+ double realDuration = getDurationToTime(time);
if (realDuration > 0) {
double dia_ago = time - dia * 60 * 60 * 1000;
@@ -247,6 +249,56 @@ public class ExtendedBolus implements Interval, DataPointWithLabelInterface {
return result;
}
+ public IobTotal iobCalc(long time, Profile profile, AutosensResult lastAutosensResult, boolean exercise_mode, int half_basal_exercise_target, boolean isTempTarget) {
+ IobTotal result = new IobTotal(time);
+ InsulinInterface insulinInterface = ConfigBuilderPlugin.getPlugin().getActiveInsulin();
+
+ double realDuration = getDurationToTime(time);
+ double netBasalAmount = 0d;
+
+ double sensitivityRatio = lastAutosensResult.ratio;
+ double normalTarget = 100;
+
+ if (exercise_mode && isTempTarget && profile.getTarget() >= normalTarget + 5) {
+ // w/ target 100, temp target 110 = .89, 120 = 0.8, 140 = 0.67, 160 = .57, and 200 = .44
+ // e.g.: Sensitivity ratio set to 0.8 based on temp target of 120; Adjusting basal from 1.65 to 1.35; ISF from 58.9 to 73.6
+ double c = half_basal_exercise_target - normalTarget;
+ sensitivityRatio = c / (c + profile.getTarget() - normalTarget);
+ }
+
+ if (realDuration > 0) {
+ double netBasalRate;
+ double dia_ago = time - dia * 60 * 60 * 1000;
+ int aboutFiveMinIntervals = (int) Math.ceil(realDuration / 5d);
+ double spacing = realDuration / aboutFiveMinIntervals;
+
+ for (long j = 0L; j < aboutFiveMinIntervals; j++) {
+ // find middle of the interval
+ long calcdate = (long) (date + j * spacing * 60 * 1000 + 0.5d * spacing * 60 * 1000);
+
+ double basalRate = profile.getBasal(calcdate);
+ double basalRateCorrection = basalRate * (sensitivityRatio - 1);
+
+
+ netBasalRate = absoluteRate() - basalRateCorrection;
+
+ if (calcdate > dia_ago && calcdate <= time) {
+ double tempBolusSize = netBasalRate * spacing / 60d;
+
+ Treatment tempBolusPart = new Treatment();
+ tempBolusPart.insulin = tempBolusSize;
+ tempBolusPart.date = calcdate;
+
+ Iob aIOB = insulinInterface.iobCalcForTreatment(tempBolusPart, time, dia);
+ result.iob += aIOB.iobContrib;
+ result.activity += aIOB.activityContrib;
+ result.extendedBolusInsulin += tempBolusPart.insulin;
+ }
+ }
+ }
+ return result;
+ }
+
public int getRealDuration() {
return getDurationToTime(System.currentTimeMillis());
}
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 0e589f0595..62b963e9ef 100644
--- a/app/src/main/java/info/nightscout/androidaps/db/ProfileSwitch.java
+++ b/app/src/main/java/info/nightscout/androidaps/db/ProfileSwitch.java
@@ -1,7 +1,9 @@
package info.nightscout.androidaps.db;
import android.graphics.Color;
-import android.support.annotation.Nullable;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
@@ -18,11 +20,13 @@ import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.interfaces.Interval;
import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface;
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.PointsWithLabelGraphSeries;
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification;
import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin;
+import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.DecimalFormatter;
import info.nightscout.androidaps.utils.T;
@@ -78,12 +82,12 @@ public class ProfileSwitch implements Interval, DataPointWithLabelInterface {
return this;
}
- public ProfileSwitch source(int source) {
+ public ProfileSwitch source(int source) {
this.source = source;
return this;
}
- public ProfileSwitch duration(int duration) {
+ public ProfileSwitch duration(int duration) {
this.durationInMinutes = duration;
return this;
}
@@ -107,7 +111,7 @@ public class ProfileSwitch implements Interval, DataPointWithLabelInterface {
*/
public String getCustomizedName() {
String name = profileName;
- if(LocalProfilePlugin.LOCAL_PROFILE.equals(name)){
+ if (LocalProfilePlugin.LOCAL_PROFILE.equals(name)) {
name = DecimalFormatter.to2Decimal(getProfileObject().percentageBasalSum()) + "U ";
}
if (isCPP) {
@@ -156,7 +160,7 @@ public class ProfileSwitch implements Interval, DataPointWithLabelInterface {
// -------- Interval interface ---------
- Long cuttedEnd = null;
+ private Long cuttedEnd = null;
public long durationInMsec() {
return durationInMinutes * 60 * 1000L;
@@ -212,16 +216,17 @@ public class ProfileSwitch implements Interval, DataPointWithLabelInterface {
@Override
public boolean isValid() {
-
boolean isValid = getProfileObject() != null && getProfileObject().isValid(DateUtil.dateAndTimeString(date));
- if (!isValid)
+ ProfileSwitch active = TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(DateUtil.now());
+ long activeProfileSwitchDate = active != null ? active.date : -1L;
+ if (!isValid && date == activeProfileSwitchDate)
createNotificationInvalidProfile(DateUtil.dateAndTimeString(date));
return isValid;
}
- public void createNotificationInvalidProfile(String detail) {
+ private void createNotificationInvalidProfile(String detail) {
Notification notification = new Notification(Notification.ZERO_VALUE_IN_PROFILE, String.format(MainApp.gs(R.string.zerovalueinprofile), detail), Notification.LOW, 5);
- MainApp.bus().post(new EventNewNotification(notification));
+ RxBus.INSTANCE.send(new EventNewNotification(notification));
}
public static boolean isEvent5minBack(List list, long time, boolean zeroDurationOnly) {
@@ -290,6 +295,7 @@ public class ProfileSwitch implements Interval, DataPointWithLabelInterface {
return Color.CYAN;
}
+ @NonNull
public String toString() {
return "ProfileSwitch{" +
"date=" + date +
diff --git a/app/src/main/java/info/nightscout/androidaps/db/TDD.java b/app/src/main/java/info/nightscout/androidaps/db/TDD.java
index 9ca849b7b6..93a228316c 100644
--- a/app/src/main/java/info/nightscout/androidaps/db/TDD.java
+++ b/app/src/main/java/info/nightscout/androidaps/db/TDD.java
@@ -6,9 +6,8 @@ import com.j256.ormlite.table.DatabaseTable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.Objects;
-
import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil;
/**
* Created by mike on 20.09.2017.
@@ -45,4 +44,16 @@ public class TDD {
this.basal = basal;
this.total = total;
}
+
+
+ @Override
+ public String toString() {
+ return "TDD [" +
+ "date=" + date +
+ "date(str)=" + DateTimeUtil.toStringFromTimeInMillis(date) +
+ ", bolus=" + bolus +
+ ", basal=" + basal +
+ ", total=" + total +
+ ']';
+ }
}
diff --git a/app/src/main/java/info/nightscout/androidaps/db/TempTarget.java b/app/src/main/java/info/nightscout/androidaps/db/TempTarget.java
index a496af802b..ef60d02911 100644
--- a/app/src/main/java/info/nightscout/androidaps/db/TempTarget.java
+++ b/app/src/main/java/info/nightscout/androidaps/db/TempTarget.java
@@ -9,6 +9,9 @@ import org.slf4j.LoggerFactory;
import java.util.Objects;
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.logging.L;
import info.nightscout.androidaps.utils.DateUtil;
@@ -191,4 +194,11 @@ public class TempTarget implements Interval {
'}';
}
+ public String friendlyDescription(String units) {
+ return Profile.toTargetRangeString(low, high, Constants.MGDL, units) +
+ units +
+ "@" + MainApp.gs(R.string.mins, durationInMinutes) +
+ (reason != null && !reason.equals("") ? "(" + reason + ")" : "");
+ }
+
}
diff --git a/app/src/main/java/info/nightscout/androidaps/db/TemporaryBasal.java b/app/src/main/java/info/nightscout/androidaps/db/TemporaryBasal.java
index 336332790a..f2a10cf4a4 100644
--- a/app/src/main/java/info/nightscout/androidaps/db/TemporaryBasal.java
+++ b/app/src/main/java/info/nightscout/androidaps/db/TemporaryBasal.java
@@ -17,6 +17,7 @@ import info.nightscout.androidaps.interfaces.Interval;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
+import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult;
import info.nightscout.androidaps.plugins.treatments.Treatment;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.DecimalFormatter;
@@ -27,7 +28,7 @@ import info.nightscout.androidaps.utils.SP;
*/
@DatabaseTable(tableName = DatabaseHelper.DATABASE_TEMPORARYBASALS)
-public class TemporaryBasal implements Interval {
+public class TemporaryBasal implements Interval, DbObjectBase {
private static Logger log = LoggerFactory.getLogger(L.DATABASE);
@DatabaseField(id = true)
@@ -156,6 +157,14 @@ public class TemporaryBasal implements Interval {
netExtendedRate = t.netExtendedRate;
}
+ public void copyFromPump(TemporaryBasal t) {
+ durationInMinutes = t.durationInMinutes;
+ isAbsolute = t.isAbsolute;
+ percentRate = t.percentRate;
+ absoluteRate = t.absoluteRate;
+ pumpId = t.pumpId;
+ }
+
// -------- Interval interface ---------
Long cuttedEnd = null;
@@ -233,7 +242,7 @@ public class TemporaryBasal implements Interval {
double netBasalAmount = 0d;
if (realDuration > 0) {
- double netBasalRate = 0d;
+ double netBasalRate;
double dia = profile.getDia();
double dia_ago = time - dia * 60 * 60 * 1000;
int aboutFiveMinIntervals = (int) Math.ceil(realDuration / 5d);
@@ -243,10 +252,8 @@ public class TemporaryBasal implements Interval {
// find middle of the interval
long calcdate = (long) (date + j * tempBolusSpacing * 60 * 1000 + 0.5d * tempBolusSpacing * 60 * 1000);
- Double basalRate = profile.getBasal(calcdate);
+ double basalRate = profile.getBasal(calcdate);
- if (basalRate == null)
- continue;
if (isAbsolute) {
netBasalRate = absoluteRate - basalRate;
} else {
@@ -276,6 +283,73 @@ public class TemporaryBasal implements Interval {
return result;
}
+ public IobTotal iobCalc(long time, Profile profile, AutosensResult lastAutosensResult, boolean exercise_mode, int half_basal_exercise_target, boolean isTempTarget) {
+
+ if (isFakeExtended) {
+ log.error("iobCalc should only be called on Extended boluses separately");
+ return new IobTotal(time);
+ }
+
+ IobTotal result = new IobTotal(time);
+ InsulinInterface insulinInterface = ConfigBuilderPlugin.getPlugin().getActiveInsulin();
+
+ double realDuration = getDurationToTime(time);
+ double netBasalAmount = 0d;
+
+ double sensitivityRatio = lastAutosensResult.ratio;
+ double normalTarget = 100;
+
+ if (exercise_mode && isTempTarget && profile.getTarget() >= normalTarget + 5) {
+ // w/ target 100, temp target 110 = .89, 120 = 0.8, 140 = 0.67, 160 = .57, and 200 = .44
+ // e.g.: Sensitivity ratio set to 0.8 based on temp target of 120; Adjusting basal from 1.65 to 1.35; ISF from 58.9 to 73.6
+ double c = half_basal_exercise_target - normalTarget;
+ sensitivityRatio = c / (c + profile.getTarget() - normalTarget);
+ }
+
+ if (realDuration > 0) {
+ double netBasalRate;
+ double dia = profile.getDia();
+ double dia_ago = time - dia * 60 * 60 * 1000;
+ int aboutFiveMinIntervals = (int) Math.ceil(realDuration / 5d);
+ double tempBolusSpacing = realDuration / aboutFiveMinIntervals;
+
+ for (long j = 0L; j < aboutFiveMinIntervals; j++) {
+ // find middle of the interval
+ long calcdate = (long) (date + j * tempBolusSpacing * 60 * 1000 + 0.5d * tempBolusSpacing * 60 * 1000);
+
+ double basalRate = profile.getBasal(calcdate);
+ basalRate *= sensitivityRatio;
+
+ if (isAbsolute) {
+ netBasalRate = absoluteRate - basalRate;
+ } else {
+ double abs = percentRate / 100d * profile.getBasal(calcdate);
+ netBasalRate = abs - basalRate;
+ }
+
+ if (calcdate > dia_ago && calcdate <= time) {
+ double tempBolusSize = netBasalRate * tempBolusSpacing / 60d;
+ netBasalAmount += tempBolusSize;
+
+ Treatment tempBolusPart = new Treatment();
+ tempBolusPart.insulin = tempBolusSize;
+ tempBolusPart.date = calcdate;
+
+ Iob aIOB = insulinInterface.iobCalcForTreatment(tempBolusPart, time, dia);
+ result.basaliob += aIOB.iobContrib;
+ result.activity += aIOB.activityContrib;
+ result.netbasalinsulin += tempBolusPart.insulin;
+ if (tempBolusPart.insulin > 0) {
+ result.hightempinsulin += tempBolusPart.insulin;
+ }
+ }
+ result.netRatio = netBasalRate; // ratio at the end of interval
+ }
+ }
+ result.netInsulin = netBasalAmount;
+ return result;
+ }
+
public int getRealDuration() {
return getDurationToTime(System.currentTimeMillis());
}
@@ -331,8 +405,10 @@ public class TemporaryBasal implements Interval {
if (isFakeExtended) {
Profile profile = ProfileFunctions.getInstance().getProfile();
+ if (profile == null)
+ return "null";
Double currentBasalRate = profile.getBasal();
- double rate = (currentBasalRate == null) ? 0d : (currentBasalRate + netExtendedRate);
+ double rate = currentBasalRate + netExtendedRate;
return getCalcuatedPercentageIfNeeded() + DecimalFormatter.to2Decimal(rate) + "U/h (" + DecimalFormatter.to2Decimal(netExtendedRate) + "E) @" +
DateUtil.timeString(date) +
" " + getRealDuration() + "/" + durationInMinutes + "'";
@@ -350,12 +426,14 @@ public class TemporaryBasal implements Interval {
public String toStringShort() {
if (isAbsolute || isFakeExtended) {
- double rate = 0d;
+ double rate;
if (isFakeExtended) {
Profile profile = ProfileFunctions.getInstance().getProfile();
- Double currentBasalRate = profile.getBasal();
- rate = (currentBasalRate == null) ? 0d : (currentBasalRate + netExtendedRate);
- } else if (isAbsolute) {
+ if (profile == null)
+ return "null";
+ double currentBasalRate = profile.getBasal();
+ rate = currentBasalRate + netExtendedRate;
+ } else {
rate = absoluteRate;
}
@@ -375,24 +453,25 @@ public class TemporaryBasal implements Interval {
}
private String getCalcuatedPercentageIfNeeded() {
+ Profile profile = ProfileFunctions.getInstance().getProfile();
+
+ if (profile == null)
+ return "null";
+
if (isAbsolute || isFakeExtended) {
- double rate = 0d;
+ double rate;
if (isFakeExtended) {
- Profile profile = ProfileFunctions.getInstance().getProfile();
- Double currentBasalRate = profile.getBasal();
- rate = (currentBasalRate == null) ? 0d : (currentBasalRate + netExtendedRate);
- } else if (isAbsolute) {
+ double currentBasalRate = profile.getBasal();
+ rate = currentBasalRate + netExtendedRate;
+ } else {
rate = absoluteRate;
}
if (SP.getBoolean(R.string.key_danar_visualizeextendedaspercentage, false) && SP.getBoolean(R.string.key_danar_useextended, false)) {
- Profile profile = ProfileFunctions.getInstance().getProfile();
- if (profile != null) {
- double basal = profile.getBasal();
- if (basal != 0) {
- return Math.round(rate * 100d / basal) + "% ";
- }
+ double basal = profile.getBasal();
+ if (basal != 0) {
+ return Math.round(rate * 100d / basal) + "% ";
}
}
}
@@ -400,14 +479,18 @@ public class TemporaryBasal implements Interval {
}
public String toStringVeryShort() {
+ Profile profile = ProfileFunctions.getInstance().getProfile();
+
+ if (profile == null)
+ return "null";
+
if (isAbsolute || isFakeExtended) {
- double rate = 0d;
+ double rate;
if (isFakeExtended) {
- Profile profile = ProfileFunctions.getInstance().getProfile();
- Double currentBasalRate = profile.getBasal();
- rate = (currentBasalRate == null) ? 0d : (currentBasalRate + netExtendedRate);
- } else if (isAbsolute) {
+ double currentBasalRate = profile.getBasal();
+ rate = currentBasalRate + netExtendedRate;
+ } else {
rate = absoluteRate;
}
return DecimalFormatter.to2Decimal(rate) + "U/h ";
@@ -416,4 +499,13 @@ public class TemporaryBasal implements Interval {
}
}
+ @Override
+ public long getDate() {
+ return this.date;
+ }
+
+ @Override
+ public long getPumpId() {
+ return this.pumpId;
+ }
}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/Event.java b/app/src/main/java/info/nightscout/androidaps/events/Event.java
deleted file mode 100644
index 864d55d6f7..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/events/Event.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package info.nightscout.androidaps.events;
-
-import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
-import org.apache.commons.lang3.builder.ToStringStyle;
-
-/** Base class for all events posted on the event bus. */
-public abstract class Event {
- static {
- ReflectionToStringBuilder.setDefaultStyle(ToStringStyle.SHORT_PREFIX_STYLE);
- }
-
- @Override
- public String toString() {
- return ReflectionToStringBuilder.toString(this);
- }
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/Event.kt b/app/src/main/java/info/nightscout/androidaps/events/Event.kt
new file mode 100644
index 0000000000..a44f65e836
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/events/Event.kt
@@ -0,0 +1,18 @@
+package info.nightscout.androidaps.events
+
+import org.apache.commons.lang3.builder.ReflectionToStringBuilder
+import org.apache.commons.lang3.builder.ToStringStyle
+
+/** Base class for all events posted on the event bus. */
+abstract class Event {
+
+ override fun toString(): String {
+ return ReflectionToStringBuilder.toString(this)
+ }
+
+ companion object {
+ init {
+ ReflectionToStringBuilder.setDefaultStyle(ToStringStyle.SHORT_PREFIX_STYLE)
+ }
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventAcceptOpenLoopChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventAcceptOpenLoopChange.java
deleted file mode 100644
index 2dfbf9ae35..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/events/EventAcceptOpenLoopChange.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package info.nightscout.androidaps.events;
-
-/** Base class for events to update the UI, mostly a specific tab. */
-public class EventAcceptOpenLoopChange extends Event {
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventAcceptOpenLoopChange.kt b/app/src/main/java/info/nightscout/androidaps/events/EventAcceptOpenLoopChange.kt
new file mode 100644
index 0000000000..552564edfc
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventAcceptOpenLoopChange.kt
@@ -0,0 +1,3 @@
+package info.nightscout.androidaps.events
+
+class EventAcceptOpenLoopChange : Event()
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventAppExit.java b/app/src/main/java/info/nightscout/androidaps/events/EventAppExit.java
deleted file mode 100644
index 9ce91a9a39..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/events/EventAppExit.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package info.nightscout.androidaps.events;
-
-/**
- * Created by mike on 07.07.2016.
- */
-public class EventAppExit extends Event {
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventAppExit.kt b/app/src/main/java/info/nightscout/androidaps/events/EventAppExit.kt
new file mode 100644
index 0000000000..640b586f5f
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventAppExit.kt
@@ -0,0 +1,3 @@
+package info.nightscout.androidaps.events
+
+class EventAppExit : Event()
\ No newline at end of file
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventAppInitialized.java b/app/src/main/java/info/nightscout/androidaps/events/EventAppInitialized.java
deleted file mode 100644
index 17262cfb85..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/events/EventAppInitialized.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package info.nightscout.androidaps.events;
-
-/**
- * Created by mike on 23.01.2018.
- */
-
-public class EventAppInitialized extends Event {
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventAppInitialized.kt b/app/src/main/java/info/nightscout/androidaps/events/EventAppInitialized.kt
new file mode 100644
index 0000000000..293f9698f2
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventAppInitialized.kt
@@ -0,0 +1,3 @@
+package info.nightscout.androidaps.events
+
+class EventAppInitialized : Event()
\ No newline at end of file
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventBolusRequested.java b/app/src/main/java/info/nightscout/androidaps/events/EventBolusRequested.java
deleted file mode 100644
index cb727758bb..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/events/EventBolusRequested.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package info.nightscout.androidaps.events;
-
-/**
- * Created by adrian on 07/02/17.
- */
-
-public class EventBolusRequested extends Event {
- private double amount;
-
- public EventBolusRequested (double amount){
- this.amount = amount;
- }
-
- public double getAmount() {
- return amount;
- }
-
- public void setAmount(double amount) {
- this.amount = amount;
- }
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventBolusRequested.kt b/app/src/main/java/info/nightscout/androidaps/events/EventBolusRequested.kt
new file mode 100644
index 0000000000..a528ef1656
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventBolusRequested.kt
@@ -0,0 +1,3 @@
+package info.nightscout.androidaps.events
+
+class EventBolusRequested(var amount: Double) : Event()
\ No newline at end of file
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventCareportalEventChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventCareportalEventChange.java
deleted file mode 100644
index 9b47ed39cb..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/events/EventCareportalEventChange.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package info.nightscout.androidaps.events;
-
-/**
- * Created by mike on 25.05.2017.
- */
-
-public class EventCareportalEventChange extends Event {
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventCareportalEventChange.kt b/app/src/main/java/info/nightscout/androidaps/events/EventCareportalEventChange.kt
new file mode 100644
index 0000000000..e7d52d86c0
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventCareportalEventChange.kt
@@ -0,0 +1,3 @@
+package info.nightscout.androidaps.events
+
+class EventCareportalEventChange : Event()
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventChargingState.java b/app/src/main/java/info/nightscout/androidaps/events/EventChargingState.java
deleted file mode 100644
index bcd9061133..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/events/EventChargingState.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package info.nightscout.androidaps.events;
-
-public class EventChargingState {
-
- public boolean isCharging = false;
-
- public EventChargingState() {}
-
- public EventChargingState(boolean isCharging) {
- this.isCharging = isCharging;
- }
-
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventChargingState.kt b/app/src/main/java/info/nightscout/androidaps/events/EventChargingState.kt
new file mode 100644
index 0000000000..f9ff60a71d
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventChargingState.kt
@@ -0,0 +1,3 @@
+package info.nightscout.androidaps.events
+
+class EventChargingState(val isCharging: Boolean) : Event()
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventConfigBuilderChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventConfigBuilderChange.java
deleted file mode 100644
index ad5f558fe8..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/events/EventConfigBuilderChange.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package info.nightscout.androidaps.events;
-
-/**
- * Created by mike on 17.02.2017.
- */
-
-public class EventConfigBuilderChange extends Event {
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventConfigBuilderChange.kt b/app/src/main/java/info/nightscout/androidaps/events/EventConfigBuilderChange.kt
new file mode 100644
index 0000000000..b674374fad
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventConfigBuilderChange.kt
@@ -0,0 +1,3 @@
+package info.nightscout.androidaps.events
+
+class EventConfigBuilderChange : Event()
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventCustomActionsChanged.kt b/app/src/main/java/info/nightscout/androidaps/events/EventCustomActionsChanged.kt
new file mode 100644
index 0000000000..d75bf612ce
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventCustomActionsChanged.kt
@@ -0,0 +1,3 @@
+package info.nightscout.androidaps.events
+
+class EventCustomActionsChanged : Event()
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventCustomCalculationFinished.java b/app/src/main/java/info/nightscout/androidaps/events/EventCustomCalculationFinished.java
deleted file mode 100644
index e52761dc58..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/events/EventCustomCalculationFinished.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package info.nightscout.androidaps.events;
-
-/**
- * Created by mike on 13.02.2018.
- */
-
-public class EventCustomCalculationFinished extends Event {
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventCustomCalculationFinished.kt b/app/src/main/java/info/nightscout/androidaps/events/EventCustomCalculationFinished.kt
new file mode 100644
index 0000000000..f6092b395d
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventCustomCalculationFinished.kt
@@ -0,0 +1,3 @@
+package info.nightscout.androidaps.events
+
+class EventCustomCalculationFinished : Event()
\ No newline at end of file
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventExtendedBolusChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventExtendedBolusChange.java
deleted file mode 100644
index 8881b0ecc1..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/events/EventExtendedBolusChange.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package info.nightscout.androidaps.events;
-
-/**
- * Created by mike on 15.05.2017.
- */
-
-public class EventExtendedBolusChange extends Event {
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventExtendedBolusChange.kt b/app/src/main/java/info/nightscout/androidaps/events/EventExtendedBolusChange.kt
new file mode 100644
index 0000000000..4ed0ca5ffe
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventExtendedBolusChange.kt
@@ -0,0 +1,3 @@
+package info.nightscout.androidaps.events
+
+class EventExtendedBolusChange : EventLoop()
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventFeatureRunning.java b/app/src/main/java/info/nightscout/androidaps/events/EventFeatureRunning.java
deleted file mode 100644
index 0d07cd6c61..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/events/EventFeatureRunning.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package info.nightscout.androidaps.events;
-
-/**
- * Created by jamorham on 07/02/2018.
- *
- * Event to indicate that an app feature is being used, for example bolus wizard being opened
- *
- * The purpose this has been created for is to enable opportunistic connection to the pump
- * so that it is already connected before the user wishes to enact a pump function
- *
- */
-
-public class EventFeatureRunning extends Event {
-
- private Feature feature = Feature.UNKNOWN;
-
- public EventFeatureRunning() {
- }
-
- public EventFeatureRunning(Feature feature) {
- this.feature = feature;
- }
-
- public Feature getFeature() {
- return feature;
- }
-
- public enum Feature {
- UNKNOWN,
- MAIN,
- WIZARD,
-
- JUST_ADD_MORE_HERE
- }
-
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventFoodDatabaseChanged.java b/app/src/main/java/info/nightscout/androidaps/events/EventFoodDatabaseChanged.java
deleted file mode 100644
index 48e6be3a14..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/events/EventFoodDatabaseChanged.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package info.nightscout.androidaps.events;
-
-/**
- * Created by mike on 20.09.2017.
- */
-
-public class EventFoodDatabaseChanged extends Event {
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventFoodDatabaseChanged.kt b/app/src/main/java/info/nightscout/androidaps/events/EventFoodDatabaseChanged.kt
new file mode 100644
index 0000000000..83402c3cb6
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventFoodDatabaseChanged.kt
@@ -0,0 +1,3 @@
+package info.nightscout.androidaps.events
+
+class EventFoodDatabaseChanged : Event()
\ No newline at end of file
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventInitializationChanged.java b/app/src/main/java/info/nightscout/androidaps/events/EventInitializationChanged.java
deleted file mode 100644
index f2bef1d3d0..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/events/EventInitializationChanged.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package info.nightscout.androidaps.events;
-
-/**
- * Created by mike on 13.12.2016.
- */
-
-public class EventInitializationChanged extends Event {
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventInitializationChanged.kt b/app/src/main/java/info/nightscout/androidaps/events/EventInitializationChanged.kt
new file mode 100644
index 0000000000..33ab0062c5
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventInitializationChanged.kt
@@ -0,0 +1,3 @@
+package info.nightscout.androidaps.events
+
+class EventInitializationChanged : Event()
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventLocationChange.kt b/app/src/main/java/info/nightscout/androidaps/events/EventLocationChange.kt
new file mode 100644
index 0000000000..fee6c9f800
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventLocationChange.kt
@@ -0,0 +1,5 @@
+package info.nightscout.androidaps.events
+
+import android.location.Location
+
+class EventLocationChange(var location: Location) : Event()
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventLoop.java b/app/src/main/java/info/nightscout/androidaps/events/EventLoop.java
deleted file mode 100644
index d694d52537..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/events/EventLoop.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package info.nightscout.androidaps.events;
-
-/** Supeclass for all events concerned with input or output into or from the LoopPlugin. */
-public abstract class EventLoop extends Event {
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventLoop.kt b/app/src/main/java/info/nightscout/androidaps/events/EventLoop.kt
new file mode 100644
index 0000000000..dd28e2323b
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventLoop.kt
@@ -0,0 +1,4 @@
+package info.nightscout.androidaps.events
+
+/** Supeclass for all events concerned with input or output into or from the LoopPlugin. */
+abstract class EventLoop : Event()
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventNetworkChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventNetworkChange.java
deleted file mode 100644
index 546d6f8624..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/events/EventNetworkChange.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package info.nightscout.androidaps.events;
-
-
-import info.nightscout.androidaps.utils.StringUtils;
-
-public class EventNetworkChange extends Event {
-
- public boolean mobileConnected = false;
- public boolean wifiConnected = false;
-
- public String ssid = "";
- public boolean roaming = false;
-
- public String getSsid() {
- return StringUtils.removeSurroundingQuotes(ssid);
- }
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventNetworkChange.kt b/app/src/main/java/info/nightscout/androidaps/events/EventNetworkChange.kt
new file mode 100644
index 0000000000..62c8bdd13e
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventNetworkChange.kt
@@ -0,0 +1,16 @@
+package info.nightscout.androidaps.events
+
+import info.nightscout.androidaps.utils.StringUtils
+
+class EventNetworkChange : Event() {
+
+ var mobileConnected = false
+ var wifiConnected = false
+
+ var ssid = ""
+ var roaming = false
+
+ fun connectedSsid(): String {
+ return StringUtils.removeSurroundingQuotes(ssid)
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventNewBG.java b/app/src/main/java/info/nightscout/androidaps/events/EventNewBG.java
deleted file mode 100644
index dc4d434e0a..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/events/EventNewBG.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package info.nightscout.androidaps.events;
-
-import android.support.annotation.Nullable;
-
-import info.nightscout.androidaps.db.BgReading;
-
-/**
- * Created by mike on 05.06.2016.
- */
-public class EventNewBG extends EventLoop {
- @Nullable
- public final BgReading bgReading;
-
- public EventNewBG(BgReading bgReading) {
- this.bgReading = bgReading;
- }
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventNewBG.kt b/app/src/main/java/info/nightscout/androidaps/events/EventNewBG.kt
new file mode 100644
index 0000000000..08c05407c9
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventNewBG.kt
@@ -0,0 +1,5 @@
+package info.nightscout.androidaps.events
+
+import info.nightscout.androidaps.db.BgReading
+
+class EventNewBG(val bgReading: BgReading?) : EventLoop()
\ No newline at end of file
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventNewBasalProfile.java b/app/src/main/java/info/nightscout/androidaps/events/EventNewBasalProfile.java
deleted file mode 100644
index f26a310b6b..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/events/EventNewBasalProfile.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package info.nightscout.androidaps.events;
-
-/**
- * Created by mike on 04.06.2016.
- */
-public class EventNewBasalProfile extends Event {
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventNewBasalProfile.kt b/app/src/main/java/info/nightscout/androidaps/events/EventNewBasalProfile.kt
new file mode 100644
index 0000000000..2ffa5a9724
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventNewBasalProfile.kt
@@ -0,0 +1,3 @@
+package info.nightscout.androidaps.events
+
+class EventNewBasalProfile : Event()
\ No newline at end of file
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventNsFood.java b/app/src/main/java/info/nightscout/androidaps/events/EventNsFood.java
deleted file mode 100644
index 90b6f5681b..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/events/EventNsFood.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package info.nightscout.androidaps.events;
-
-import android.os.Bundle;
-
-/**
- * Event which is published with data fetched from NightScout specific for the
- * Food-class.
- *
- * Payload is the from NS retrieved JSON-String which should be handled by all
- * subscriber.
- */
-
-public class EventNsFood extends Event {
-
- public static final int ADD = 0;
- public static final int UPDATE = 1;
- public static final int REMOVE = 2;
-
- private final int mode;
-
- private final Bundle payload;
-
- public EventNsFood(int mode, Bundle payload) {
- this.mode = mode;
- this.payload = payload;
- }
-
- public int getMode() {
- return mode;
- }
-
- public Bundle getPayload() {
- return payload;
- }
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventNsFood.kt b/app/src/main/java/info/nightscout/androidaps/events/EventNsFood.kt
new file mode 100644
index 0000000000..2f34e76c85
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventNsFood.kt
@@ -0,0 +1,19 @@
+package info.nightscout.androidaps.events
+
+import android.os.Bundle
+
+/**
+ * Event which is published with data fetched from NightScout specific for the
+ * Food-class.
+ *
+ * Payload is the from NS retrieved JSON-String which should be handled by all
+ * subscriber.
+ */
+
+class EventNsFood(val mode: Int, val payload: Bundle) : Event() {
+ companion object {
+ val ADD = 0
+ val UPDATE = 1
+ val REMOVE = 2
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventNsTreatment.java b/app/src/main/java/info/nightscout/androidaps/events/EventNsTreatment.java
deleted file mode 100644
index 2c5ba6c9c0..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/events/EventNsTreatment.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package info.nightscout.androidaps.events;
-
-import org.json.JSONObject;
-
-
-/**
- * Event which is published with data fetched from NightScout specific for the
- * Treatment-class.
- *
- * Payload is the from NS retrieved JSON-String which should be handled by all
- * subscriber.
- */
-
-public class EventNsTreatment extends Event {
-
- public static final int ADD = 0;
- public static final int UPDATE = 1;
- public static final int REMOVE = 2;
-
- private final int mode;
-
- private final JSONObject payload;
-
- public EventNsTreatment(int mode, JSONObject payload) {
- this.mode = mode;
- this.payload = payload;
- }
-
- public int getMode() {
- return mode;
- }
-
- public JSONObject getPayload() {
- return payload;
- }
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventNsTreatment.kt b/app/src/main/java/info/nightscout/androidaps/events/EventNsTreatment.kt
new file mode 100644
index 0000000000..149894c221
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventNsTreatment.kt
@@ -0,0 +1,21 @@
+package info.nightscout.androidaps.events
+
+import org.json.JSONObject
+
+
+/**
+ * Event which is published with data fetched from NightScout specific for the
+ * Treatment-class.
+ *
+ *
+ * Payload is the from NS retrieved JSON-String which should be handled by all
+ * subscriber.
+ */
+
+class EventNsTreatment(val mode: Int, val payload: JSONObject) : Event() {
+ companion object {
+ val ADD = 0
+ val UPDATE = 1
+ val REMOVE = 2
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventPreferenceChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventPreferenceChange.java
deleted file mode 100644
index f23d4e802a..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/events/EventPreferenceChange.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package info.nightscout.androidaps.events;
-
-import info.nightscout.androidaps.MainApp;
-
-/**
- * Created by mike on 19.06.2016.
- */
-public class EventPreferenceChange extends Event {
- public String changedKey;
- public EventPreferenceChange(String key) {
- changedKey = key;
- }
-
- public EventPreferenceChange(int resourceID) {
- changedKey = MainApp.gs(resourceID);
- }
-
- public boolean isChanged(int id) {
- return changedKey.equals(MainApp.gs(id));
- }
-
- public boolean isChanged(String id) {
- return changedKey.equals(id);
- }
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventPreferenceChange.kt b/app/src/main/java/info/nightscout/androidaps/events/EventPreferenceChange.kt
new file mode 100644
index 0000000000..d224d75df1
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventPreferenceChange.kt
@@ -0,0 +1,19 @@
+package info.nightscout.androidaps.events
+
+import info.nightscout.androidaps.MainApp
+
+class EventPreferenceChange : Event {
+ private var changedKey: String? = null
+
+ constructor(key: String) {
+ changedKey = key
+ }
+
+ constructor(resourceID: Int) {
+ changedKey = MainApp.gs(resourceID)
+ }
+
+ fun isChanged(id: Int): Boolean {
+ return changedKey == MainApp.gs(id)
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventProfileNeedsUpdate.java b/app/src/main/java/info/nightscout/androidaps/events/EventProfileNeedsUpdate.java
deleted file mode 100644
index 9e3f3b08c7..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/events/EventProfileNeedsUpdate.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package info.nightscout.androidaps.events;
-
-/**
- * Created by mike on 02.06.2017.
- */
-
-public class EventProfileNeedsUpdate extends Event {
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventProfileNeedsUpdate.kt b/app/src/main/java/info/nightscout/androidaps/events/EventProfileNeedsUpdate.kt
new file mode 100644
index 0000000000..2baf1db945
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventProfileNeedsUpdate.kt
@@ -0,0 +1,3 @@
+package info.nightscout.androidaps.events
+
+class EventProfileNeedsUpdate : Event()
\ No newline at end of file
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventProfileStoreChanged.java b/app/src/main/java/info/nightscout/androidaps/events/EventProfileStoreChanged.java
deleted file mode 100644
index 0b2d933c12..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/events/EventProfileStoreChanged.java
+++ /dev/null
@@ -1,4 +0,0 @@
-package info.nightscout.androidaps.events;
-
-public class EventProfileStoreChanged extends Event {
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventProfileStoreChanged.kt b/app/src/main/java/info/nightscout/androidaps/events/EventProfileStoreChanged.kt
new file mode 100644
index 0000000000..0e839ca2d3
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventProfileStoreChanged.kt
@@ -0,0 +1,3 @@
+package info.nightscout.androidaps.events
+
+class EventProfileStoreChanged : Event()
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventPumpStatusChanged.java b/app/src/main/java/info/nightscout/androidaps/events/EventPumpStatusChanged.java
deleted file mode 100644
index 6729a4e703..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/events/EventPumpStatusChanged.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package info.nightscout.androidaps.events;
-
-import info.nightscout.androidaps.MainApp;
-import info.nightscout.androidaps.R;
-
-/**
- * Created by mike on 19.02.2017.
- */
-
-public class EventPumpStatusChanged extends Event {
- public static final int CONNECTING = 0;
- public static final int CONNECTED = 1;
- public static final int HANDSHAKING = 2;
- public static final int PERFORMING = 3;
- public static final int DISCONNECTING = 4;
- public static final int DISCONNECTED = 5;
-
- public int sStatus = DISCONNECTED;
- public int sSecondsElapsed = 0;
- public String sPerfomingAction = "";
-
- public static String error = "";
-
- public EventPumpStatusChanged(int status) {
- sStatus = status;
- sSecondsElapsed = 0;
- error = "";
- }
-
- public EventPumpStatusChanged(int status, int secondsElapsed) {
- sStatus = status;
- sSecondsElapsed = secondsElapsed;
- error = "";
- }
-
- public EventPumpStatusChanged(int status, String error) {
- sStatus = status;
- sSecondsElapsed = 0;
- this.error = error;
- }
-
- public EventPumpStatusChanged(String action) {
- sStatus = PERFORMING;
- sSecondsElapsed = 0;
- sPerfomingAction = action;
- }
-
- public String textStatus() {
- if (sStatus == CONNECTING)
- return String.format(MainApp.gs(R.string.danar_history_connectingfor), sSecondsElapsed);
- else if (sStatus == HANDSHAKING)
- return MainApp.gs(R.string.handshaking);
- else if (sStatus == CONNECTED)
- return MainApp.gs(R.string.connected);
- else if (sStatus == PERFORMING)
- return sPerfomingAction;
- else if (sStatus == DISCONNECTING)
- return MainApp.gs(R.string.disconnecting);
- else if (sStatus == DISCONNECTED)
- return "";
- return "";
- }
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventPumpStatusChanged.kt b/app/src/main/java/info/nightscout/androidaps/events/EventPumpStatusChanged.kt
new file mode 100644
index 0000000000..3d25bc1ca5
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventPumpStatusChanged.kt
@@ -0,0 +1,62 @@
+package info.nightscout.androidaps.events
+
+import info.nightscout.androidaps.MainApp
+import info.nightscout.androidaps.R
+
+class EventPumpStatusChanged : EventStatus {
+
+ enum class Status {
+ CONNECTING,
+ CONNECTED,
+ HANDSHAKING,
+ PERFORMING,
+ DISCONNECTING,
+ DISCONNECTED
+ }
+
+ var sStatus: Status = Status.DISCONNECTED
+ var sSecondsElapsed = 0
+ var sPerfomingAction = ""
+ var error = ""
+
+ constructor(status: Status) {
+ sStatus = status
+ sSecondsElapsed = 0
+ error = ""
+ }
+
+ constructor(status: Status, secondsElapsed: Int) {
+ sStatus = status
+ sSecondsElapsed = secondsElapsed
+ error = ""
+ }
+
+ constructor(status: Status, error: String) {
+ sStatus = status
+ sSecondsElapsed = 0
+ this.error = error
+ }
+
+ constructor(action: String) {
+ sStatus = Status.PERFORMING
+ sSecondsElapsed = 0
+ sPerfomingAction = action
+ }
+
+ // status for startup wizard
+ override fun getStatus(): String {
+ if (sStatus == Status.CONNECTING)
+ return String.format(MainApp.gs(R.string.danar_history_connectingfor), sSecondsElapsed)
+ else if (sStatus == Status.HANDSHAKING)
+ return MainApp.gs(R.string.handshaking)
+ else if (sStatus == Status.CONNECTED)
+ return MainApp.gs(R.string.connected)
+ else if (sStatus == Status.PERFORMING)
+ return sPerfomingAction
+ else if (sStatus == Status.DISCONNECTING)
+ return MainApp.gs(R.string.disconnecting)
+ else if (sStatus == Status.DISCONNECTED)
+ return ""
+ return ""
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventRebuildTabs.kt b/app/src/main/java/info/nightscout/androidaps/events/EventRebuildTabs.kt
new file mode 100644
index 0000000000..aa0db3467a
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventRebuildTabs.kt
@@ -0,0 +1,3 @@
+package info.nightscout.androidaps.events
+
+class EventRebuildTabs @JvmOverloads constructor(var recreate: Boolean = false) : Event()
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventRefreshGui.java b/app/src/main/java/info/nightscout/androidaps/events/EventRefreshGui.java
deleted file mode 100644
index 390ad8ea4f..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/events/EventRefreshGui.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package info.nightscout.androidaps.events;
-
-/**
- * Created by mike on 13.06.2016.
- */
-public class EventRefreshGui extends Event {
- public boolean recreate = false;
- public EventRefreshGui(boolean recreate) {
- this.recreate = recreate;
- }
- public EventRefreshGui(){
- this(false);
- }
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventRefreshOverview.java b/app/src/main/java/info/nightscout/androidaps/events/EventRefreshOverview.java
deleted file mode 100644
index 2ba78fa9ec..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/events/EventRefreshOverview.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package info.nightscout.androidaps.events;
-
-/**
- * Created by mike on 16.06.2017.
- */
-
-public class EventRefreshOverview extends Event {
- public String from;
-
- public EventRefreshOverview(String from) {
- this.from = from;
- }
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventRefreshOverview.kt b/app/src/main/java/info/nightscout/androidaps/events/EventRefreshOverview.kt
new file mode 100644
index 0000000000..533a25dd40
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventRefreshOverview.kt
@@ -0,0 +1,3 @@
+package info.nightscout.androidaps.events
+
+class EventRefreshOverview(var from: String) : Event()
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventReloadProfileSwitchData.java b/app/src/main/java/info/nightscout/androidaps/events/EventReloadProfileSwitchData.java
deleted file mode 100644
index 212e8856d9..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/events/EventReloadProfileSwitchData.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package info.nightscout.androidaps.events;
-
-/**
- * Created by mike on 12.06.2017.
- */
-
-public class EventReloadProfileSwitchData extends Event {
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventReloadProfileSwitchData.kt b/app/src/main/java/info/nightscout/androidaps/events/EventReloadProfileSwitchData.kt
new file mode 100644
index 0000000000..6f6d848b5e
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventReloadProfileSwitchData.kt
@@ -0,0 +1,3 @@
+package info.nightscout.androidaps.events
+
+class EventReloadProfileSwitchData : Event()
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventReloadTempBasalData.java b/app/src/main/java/info/nightscout/androidaps/events/EventReloadTempBasalData.java
deleted file mode 100644
index 80125cbb4a..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/events/EventReloadTempBasalData.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package info.nightscout.androidaps.events;
-
-/**
- * Created by mike on 29.05.2017.
- */
-
-public class EventReloadTempBasalData extends Event {
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventReloadTempBasalData.kt b/app/src/main/java/info/nightscout/androidaps/events/EventReloadTempBasalData.kt
new file mode 100644
index 0000000000..fa8f720896
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventReloadTempBasalData.kt
@@ -0,0 +1,3 @@
+package info.nightscout.androidaps.events
+
+class EventReloadTempBasalData : Event()
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventReloadTreatmentData.java b/app/src/main/java/info/nightscout/androidaps/events/EventReloadTreatmentData.java
deleted file mode 100644
index 0ba9b95ad7..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/events/EventReloadTreatmentData.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package info.nightscout.androidaps.events;
-
-/**
- * Created by mike on 29.05.2017.
- */
-
-public class EventReloadTreatmentData extends Event {
- public Object next;
-
- public EventReloadTreatmentData(Object next) {
- this.next = next;
- }
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventReloadTreatmentData.kt b/app/src/main/java/info/nightscout/androidaps/events/EventReloadTreatmentData.kt
new file mode 100644
index 0000000000..1f8b2938b9
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventReloadTreatmentData.kt
@@ -0,0 +1,3 @@
+package info.nightscout.androidaps.events
+
+class EventReloadTreatmentData(var next: Event) : Event()
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventStatus.kt b/app/src/main/java/info/nightscout/androidaps/events/EventStatus.kt
new file mode 100644
index 0000000000..193c3b1fdb
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventStatus.kt
@@ -0,0 +1,6 @@
+package info.nightscout.androidaps.events
+
+// pass string to startup wizard
+abstract class EventStatus :Event() {
+ abstract fun getStatus() : String
+}
\ No newline at end of file
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventTempBasalChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventTempBasalChange.java
deleted file mode 100644
index 73660bb00e..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/events/EventTempBasalChange.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package info.nightscout.androidaps.events;
-
-/**
- * Created by mike on 05.06.2016.
- */
-public class EventTempBasalChange extends EventLoop {
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventTempBasalChange.kt b/app/src/main/java/info/nightscout/androidaps/events/EventTempBasalChange.kt
new file mode 100644
index 0000000000..3f3ecf732e
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventTempBasalChange.kt
@@ -0,0 +1,3 @@
+package info.nightscout.androidaps.events
+
+class EventTempBasalChange : EventLoop()
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventTempTargetChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventTempTargetChange.java
deleted file mode 100644
index 4e3bf5c5f8..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/events/EventTempTargetChange.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package info.nightscout.androidaps.events;
-
-/**
- * Created by mike on 13.01.2017.
- */
-
-public class EventTempTargetChange extends Event {
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventTempTargetChange.kt b/app/src/main/java/info/nightscout/androidaps/events/EventTempTargetChange.kt
new file mode 100644
index 0000000000..c108d6589c
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventTempTargetChange.kt
@@ -0,0 +1,3 @@
+package info.nightscout.androidaps.events
+
+class EventTempTargetChange : Event()
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventTreatmentChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventTreatmentChange.java
deleted file mode 100644
index 990f28a388..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/events/EventTreatmentChange.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package info.nightscout.androidaps.events;
-
-import android.support.annotation.Nullable;
-
-import info.nightscout.androidaps.plugins.treatments.Treatment;
-
-/**
- * Created by mike on 04.06.2016.
- */
-public class EventTreatmentChange extends EventLoop {
- @Nullable
- public final Treatment treatment;
-
- public EventTreatmentChange(Treatment treatment) {
- this.treatment = treatment;
- }
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventTreatmentChange.kt b/app/src/main/java/info/nightscout/androidaps/events/EventTreatmentChange.kt
new file mode 100644
index 0000000000..9cbc9d1563
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventTreatmentChange.kt
@@ -0,0 +1,5 @@
+package info.nightscout.androidaps.events
+
+import info.nightscout.androidaps.plugins.treatments.Treatment
+
+class EventTreatmentChange(val treatment: Treatment?) : EventLoop()
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventUpdateGui.java b/app/src/main/java/info/nightscout/androidaps/events/EventUpdateGui.java
deleted file mode 100644
index 3471d2e851..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/events/EventUpdateGui.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package info.nightscout.androidaps.events;
-
-/** Base class for events to update the UI, mostly a specific tab. */
-public abstract class EventUpdateGui extends Event {
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventUpdateGui.kt b/app/src/main/java/info/nightscout/androidaps/events/EventUpdateGui.kt
new file mode 100644
index 0000000000..cc21e784b9
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventUpdateGui.kt
@@ -0,0 +1,4 @@
+package info.nightscout.androidaps.events
+
+/** Base class for events to update the UI, mostly a specific tab. */
+abstract class EventUpdateGui : Event()
diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/APSInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/APSInterface.java
index e2f3460701..7d32e37ff0 100644
--- a/app/src/main/java/info/nightscout/androidaps/interfaces/APSInterface.java
+++ b/app/src/main/java/info/nightscout/androidaps/interfaces/APSInterface.java
@@ -6,8 +6,9 @@ import info.nightscout.androidaps.plugins.aps.loop.APSResult;
* Created by mike on 10.06.2016.
*/
public interface APSInterface {
- public APSResult getLastAPSResult();
- public long getLastAPSRun();
+ APSResult getLastAPSResult();
- public void invoke(String initiator, boolean tempBasalFallback);
+ long getLastAPSRun();
+
+ void invoke(String initiator, boolean tempBasalFallback);
}
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 f1c79dd5cb..14b2d549af 100644
--- a/app/src/main/java/info/nightscout/androidaps/interfaces/ConstraintsInterface.java
+++ b/app/src/main/java/info/nightscout/androidaps/interfaces/ConstraintsInterface.java
@@ -61,6 +61,6 @@ public interface ConstraintsInterface {
default Constraint applyMaxIOBConstraints(Constraint maxIob) {
return maxIob;
- };
+ }
}
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 01be296539..f7c8e9ada4 100644
--- a/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java
+++ b/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java
@@ -1,16 +1,23 @@
package info.nightscout.androidaps.interfaces;
import android.os.SystemClock;
-import android.support.v4.app.FragmentActivity;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.FragmentActivity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.events.EventConfigBuilderChange;
+import info.nightscout.androidaps.events.EventRebuildTabs;
import info.nightscout.androidaps.logging.L;
-import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderFragment;
+import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
+import info.nightscout.androidaps.plugins.configBuilder.EventConfigBuilderUpdateGui;
import info.nightscout.androidaps.queue.CommandQueue;
+import info.nightscout.androidaps.utils.SP;
/**
* Created by mike on 09.06.2016.
@@ -38,17 +45,46 @@ public abstract class PluginBase {
// 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 void switchAllowed(boolean newState, FragmentActivity activity, PluginType type) {
+ performPluginSwitch(newState, type);
}
-// public PluginType getType() {
-// return mainType;
-// }
+ protected void confirmPumpPluginActivation(boolean newState, FragmentActivity activity, PluginType type) {
+ if (type == PluginType.PUMP) {
+ boolean allowHardwarePump = SP.getBoolean("allow_hardware_pump", false);
+ if (allowHardwarePump || activity == null) {
+ performPluginSwitch(newState, type);
+ } else {
+ AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+ builder.setMessage(R.string.allow_hardware_pump_text)
+ .setPositiveButton(R.string.yes, (dialog, id) -> {
+ performPluginSwitch(newState, type);
+ SP.putBoolean("allow_hardware_pump", true);
+ if (L.isEnabled(L.PUMP))
+ log.debug("First time HW pump allowed!");
+ })
+ .setNegativeButton(R.string.cancel, (dialog, id) -> {
+ RxBus.INSTANCE.send(new EventConfigBuilderUpdateGui());
+ if (L.isEnabled(L.PUMP))
+ log.debug("User does not allow switching to HW pump!");
+ });
+ builder.create().show();
+ }
+ } else {
+ performPluginSwitch(newState, type);
+ }
+ }
-// public String getFragmentClass() {
-// return fragmentClass;
-// }
+ private void performPluginSwitch(boolean enabled, PluginType type) {
+ setPluginEnabled(type, enabled);
+ setFragmentVisible(type, enabled);
+ ConfigBuilderPlugin.getPlugin().processOnEnabledCategoryChanged(this, getType());
+ ConfigBuilderPlugin.getPlugin().storeSettings("CheckedCheckboxEnabled");
+ RxBus.INSTANCE.send(new EventRebuildTabs());
+ RxBus.INSTANCE.send(new EventConfigBuilderChange());
+ RxBus.INSTANCE.send(new EventConfigBuilderUpdateGui());
+ ConfigBuilderPlugin.getPlugin().logPluginStatus();
+ }
public String getName() {
if (pluginDescription.pluginName == -1)
@@ -80,10 +116,6 @@ public abstract class PluginBase {
return pluginDescription.preferencesId;
}
- public int getAdvancedPreferencesId() {
- return pluginDescription.advancedPreferencesId;
- }
-
public boolean isEnabled(PluginType type) {
if (pluginDescription.alwaysEnabled && type == pluginDescription.mainType)
return true;
@@ -143,7 +175,7 @@ public abstract class PluginBase {
}
public boolean isFragmentVisible() {
- if (pluginDescription.alwayVisible)
+ if (pluginDescription.alwaysVisible)
return true;
if (pluginDescription.neverVisible)
return false;
diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/PluginDescription.java b/app/src/main/java/info/nightscout/androidaps/interfaces/PluginDescription.java
index 1634fc672d..5882c5870c 100644
--- a/app/src/main/java/info/nightscout/androidaps/interfaces/PluginDescription.java
+++ b/app/src/main/java/info/nightscout/androidaps/interfaces/PluginDescription.java
@@ -3,7 +3,7 @@ package info.nightscout.androidaps.interfaces;
public class PluginDescription {
PluginType mainType = PluginType.GENERAL;
String fragmentClass = null;
- public boolean alwayVisible = false;
+ public boolean alwaysVisible = false;
public boolean neverVisible = false;
public boolean alwaysEnabled = false;
boolean showInList = true;
@@ -11,7 +11,6 @@ public class PluginDescription {
int shortName = -1;
int description = -1;
int preferencesId = -1;
- int advancedPreferencesId = -1;
public boolean enableByDefault = false;
public boolean visibleByDefault = false;
@@ -30,8 +29,8 @@ public class PluginDescription {
return this;
}
- public PluginDescription alwayVisible(boolean alwayVisible) {
- this.alwayVisible = alwayVisible;
+ public PluginDescription alwaysVisible(boolean alwayVisible) {
+ this.alwaysVisible = alwayVisible;
return this;
}
@@ -60,11 +59,6 @@ public class PluginDescription {
return this;
}
- public PluginDescription advancedPreferencesId(int advancedPreferencesId) {
- this.advancedPreferencesId = advancedPreferencesId;
- return this;
- }
-
public PluginDescription enableByDefault(boolean enableByDefault) {
this.enableByDefault = enableByDefault;
return this;
diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/ProfileInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/ProfileInterface.java
index e3b368fe86..482278e437 100644
--- a/app/src/main/java/info/nightscout/androidaps/interfaces/ProfileInterface.java
+++ b/app/src/main/java/info/nightscout/androidaps/interfaces/ProfileInterface.java
@@ -1,6 +1,6 @@
package info.nightscout.androidaps.interfaces;
-import android.support.annotation.Nullable;
+import androidx.annotation.Nullable;
import info.nightscout.androidaps.data.ProfileStore;
diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java
index 3690312cf8..025f10076d 100644
--- a/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java
+++ b/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java
@@ -7,8 +7,10 @@ import java.util.List;
import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
+import info.nightscout.androidaps.plugins.common.ManufacturerType;
import info.nightscout.androidaps.plugins.general.actions.defs.CustomAction;
import info.nightscout.androidaps.plugins.general.actions.defs.CustomActionType;
+import info.nightscout.androidaps.plugins.pump.common.defs.PumpType;
/**
* Created by mike on 04.06.2016.
@@ -16,21 +18,30 @@ import info.nightscout.androidaps.plugins.general.actions.defs.CustomActionType;
public interface PumpInterface {
boolean isInitialized(); // true if pump status has been read and is ready to accept commands
+
boolean isSuspended(); // true if suspended (not delivering insulin)
+
boolean isBusy(); // if true pump is not ready to accept commands right now
+
boolean isConnected(); // true if BT connection is established
+
boolean isConnecting(); // true if BT connection is in progress
+
boolean isHandshakeInProgress(); // true if BT is connected but initial handshake is still in progress
+
void finishHandshaking(); // set initial handshake completed
void connect(String reason);
+
void disconnect(String reason);
+
void stopConnecting();
void getPumpStatus();
// Upload to pump new basal profile
PumpEnactResult setNewBasalProfile(Profile profile);
+
boolean isThisProfileSet(Profile profile);
long lastDataTime();
@@ -42,18 +53,29 @@ public interface PumpInterface {
int getBatteryLevel(); // in percent as integer
PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo);
+
void stopBolusDelivering();
+
PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile, boolean enforceNew);
+
PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, boolean enforceNew);
+
PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes);
+
//some pumps might set a very short temp close to 100% as cancelling a temp can be noisy
//when the cancel request is requested by the user (forced), the pump should always do a real cancel
PumpEnactResult cancelTempBasal(boolean enforceNew);
+
PumpEnactResult cancelExtendedBolus();
// Status to be passed to NS
JSONObject getJSONStatus(Profile profile, String profileName);
- String deviceID();
+
+ ManufacturerType manufacturer();
+
+ PumpType model();
+
+ String serialNumber();
// Pump capabilities
PumpDescription getPumpDescription();
@@ -65,10 +87,16 @@ public interface PumpInterface {
PumpEnactResult loadTDDs();
- public boolean canHandleDST();
+ boolean canHandleDST();
List getCustomActions();
void executeCustomAction(CustomActionType customActionType);
+ /**
+ * This method will be called when time or Timezone changes, and pump driver can then do a specific action (for
+ * example update clock on pump).
+ */
+ void timeDateOrTimeZoneChanged();
+
}
diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/TreatmentsInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/TreatmentsInterface.java
index 0ef71dac2a..43661b117a 100644
--- a/app/src/main/java/info/nightscout/androidaps/interfaces/TreatmentsInterface.java
+++ b/app/src/main/java/info/nightscout/androidaps/interfaces/TreatmentsInterface.java
@@ -5,6 +5,7 @@ import java.util.List;
import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.MealData;
+import info.nightscout.androidaps.data.NonOverlappingIntervals;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.ProfileSwitch;
@@ -25,12 +26,13 @@ public interface TreatmentsInterface {
IobTotal getLastCalculationTreatments();
IobTotal getCalculationToTimeTreatments(long time);
IobTotal getLastCalculationTempBasals();
- IobTotal getCalculationToTimeTempBasals(long time, Profile profile);
+ IobTotal getCalculationToTimeTempBasals(long time);
MealData getMealData();
List getTreatmentsFromHistory();
List getTreatments5MinBackFromHistory(long time);
+ List getTreatmentsFromHistoryAfterTimestamp(long timestamp);
long getLastBolusTime();
// real basals (not faked by extended bolus)
@@ -42,7 +44,7 @@ public interface TreatmentsInterface {
// basal that can be faked by extended boluses
boolean isTempBasalInProgress();
TemporaryBasal getTempBasalFromHistory(long time);
- Intervals getTemporaryBasalsFromHistory();
+ NonOverlappingIntervals getTemporaryBasalsFromHistory();
boolean isInHistoryExtendedBoluslInProgress();
ExtendedBolus getExtendedBolusFromHistory(long time);
@@ -63,4 +65,4 @@ public interface TreatmentsInterface {
long oldestDataAvailable();
-}
+}
\ No newline at end of file
diff --git a/app/src/main/java/info/nightscout/androidaps/logging/L.java b/app/src/main/java/info/nightscout/androidaps/logging/L.java
index f685bbd424..25b6750844 100644
--- a/app/src/main/java/info/nightscout/androidaps/logging/L.java
+++ b/app/src/main/java/info/nightscout/androidaps/logging/L.java
@@ -77,6 +77,7 @@ public class L {
public static final String CORE = "CORE";
public static final String AUTOSENS = "AUTOSENS";
+ public static final String AUTOMATION = "AUTOMATION";
public static final String EVENTS = "EVENTS";
public static final String GLUCOSE = "GLUCOSE";
public static final String BGSOURCE = "BGSOURCE";
@@ -87,6 +88,7 @@ public class L {
public static final String DATAFOOD = "DATAFOOD";
public static final String DATATREATMENTS = "DATATREATMENTS";
public static final String NSCLIENT = "NSCLIENT";
+ public static final String TIDEPOOL = "TIDEPOOL";
public static final String CONSTRAINTS = "CONSTRAINTS";
public static final String PUMP = "PUMP";
public static final String PUMPQUEUE = "PUMPQUEUE";
@@ -96,11 +98,13 @@ public class L {
public static final String PROFILE = "PROFILE";
public static final String CONFIGBUILDER = "CONFIGBUILDER";
public static final String UI = "UI";
+ public static final String LOCATION = "LOCATION";
public static final String SMS = "SMS";
private static void initialize() {
logElements = new ArrayList<>();
logElements.add(new LogElement(APS, true));
+ logElements.add(new LogElement(AUTOMATION, true));
logElements.add(new LogElement(AUTOSENS, false));
logElements.add(new LogElement(BGSOURCE, true));
logElements.add(new LogElement(GLUCOSE, false));
@@ -112,8 +116,10 @@ public class L {
logElements.add(new LogElement(DATASERVICE, true));
logElements.add(new LogElement(DATATREATMENTS, true));
logElements.add(new LogElement(EVENTS, false, true));
+ logElements.add(new LogElement(LOCATION, true));
logElements.add(new LogElement(NOTIFICATION, true));
logElements.add(new LogElement(NSCLIENT, true));
+ logElements.add(new LogElement(TIDEPOOL, true));
logElements.add(new LogElement(OVERVIEW, true));
logElements.add(new LogElement(PROFILE, true));
logElements.add(new LogElement(PUMP, true));
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopFragment.java
deleted file mode 100644
index 951631eb0c..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopFragment.java
+++ /dev/null
@@ -1,145 +0,0 @@
-package info.nightscout.androidaps.plugins.aps.loop;
-
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.text.Html;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.TextView;
-
-import com.squareup.otto.Subscribe;
-
-import butterknife.BindView;
-import butterknife.ButterKnife;
-import butterknife.OnClick;
-import info.nightscout.androidaps.MainApp;
-import info.nightscout.androidaps.R;
-import info.nightscout.androidaps.interfaces.Constraint;
-import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopSetLastRunGui;
-import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopUpdateGui;
-import info.nightscout.androidaps.plugins.common.SubscriberFragment;
-import info.nightscout.androidaps.utils.FabricPrivacy;
-
-public class LoopFragment extends SubscriberFragment {
- @BindView(R.id.loop_run)
- Button runNowButton;
- @BindView(R.id.loop_lastrun)
- TextView lastRunView;
- @BindView(R.id.loop_lastenact)
- TextView lastEnactView;
- @BindView(R.id.loop_source)
- TextView sourceView;
- @BindView(R.id.loop_request)
- TextView requestView;
- @BindView(R.id.loop_constraintsprocessed)
- TextView constraintsProcessedView;
- @BindView(R.id.loop_constraints)
- TextView constraintsView;
- @BindView(R.id.loop_tbrsetbypump)
- TextView tbrSetByPumpView;
- @BindView(R.id.loop_smbsetbypump)
- TextView smbSetByPumpView;
-
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- try {
- View view = inflater.inflate(R.layout.loop_fragment, container, false);
- unbinder = ButterKnife.bind(this, view);
- return view;
- } catch (Exception e) {
- FabricPrivacy.logException(e);
- }
- return null;
- }
-
- @OnClick(R.id.loop_run)
- void onRunClick() {
- lastRunView.setText(MainApp.gs(R.string.executing));
- new Thread(() -> LoopPlugin.getPlugin().invoke("Loop button", true)).start();
- }
-
- @Subscribe
- public void onStatusEvent(final EventLoopUpdateGui ev) {
- updateGUI();
- }
-
- @Subscribe
- public void onStatusEvent(final EventLoopSetLastRunGui ev) {
- clearGUI();
- final Activity activity = getActivity();
- if (activity != null)
- activity.runOnUiThread(() -> {
- synchronized (LoopFragment.this) {
- if (lastRunView != null) lastRunView.setText(ev.text);
- }
- });
- }
-
-
- @Override
- protected void updateGUI() {
- Activity activity = getActivity();
- if (activity != null)
- activity.runOnUiThread(() -> {
- 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();
- }
- constraintsView.setText(constraints);
- }
- }
- });
- }
-
- void clearGUI() {
- Activity activity = getActivity();
- if (activity != null)
- activity.runOnUiThread(() -> {
- 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/aps/loop/LoopFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopFragment.kt
new file mode 100644
index 0000000000..b7549fcfed
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopFragment.kt
@@ -0,0 +1,109 @@
+package info.nightscout.androidaps.plugins.aps.loop
+
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import info.nightscout.androidaps.MainApp
+import info.nightscout.androidaps.R
+import info.nightscout.androidaps.interfaces.Constraint
+import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopSetLastRunGui
+import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopUpdateGui
+import info.nightscout.androidaps.plugins.bus.RxBus
+import info.nightscout.androidaps.utils.*
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.disposables.CompositeDisposable
+import kotlinx.android.synthetic.main.loop_fragment.*
+
+class LoopFragment : Fragment() {
+
+ private var disposable: CompositeDisposable = CompositeDisposable()
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?): View? {
+ return inflater.inflate(R.layout.loop_fragment, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ loop_run.setOnClickListener {
+ loop_lastrun.text = MainApp.gs(R.string.executing)
+ Thread { LoopPlugin.getPlugin().invoke("Loop button", true) }.start()
+ }
+ }
+
+ @Synchronized
+ override fun onResume() {
+ super.onResume()
+ disposable += RxBus
+ .toObservable(EventLoopUpdateGui::class.java)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe({
+ updateGUI()
+ }, {
+ FabricPrivacy.logException(it)
+ })
+
+ disposable += RxBus
+ .toObservable(EventLoopSetLastRunGui::class.java)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe({
+ clearGUI()
+ loop_lastrun.text = it.text
+ }, {
+ FabricPrivacy.logException(it)
+ })
+
+ updateGUI()
+ SP.putBoolean(R.string.key_objectiveuseloop, true)
+ }
+
+ @Synchronized
+ override fun onPause() {
+ super.onPause()
+ disposable.clear()
+ }
+
+ @Synchronized
+ fun updateGUI() {
+ if (loop_request == null) return
+ LoopPlugin.lastRun?.let {
+ loop_request.text = it.request?.toSpanned() ?: ""
+ loop_constraintsprocessed.text = it.constraintsProcessed?.toSpanned() ?: ""
+ loop_source.text = it.source ?: ""
+ loop_lastrun.text = it.lastAPSRun?.let { lastRun -> DateUtil.dateAndTimeString(lastRun.time) }
+ ?: ""
+ loop_lastenact.text = it.lastAPSRun?.let { lastEnact -> DateUtil.dateAndTimeString(lastEnact.time) }
+ ?: ""
+ loop_tbrsetbypump.text = it.tbrSetByPump?.let { tbrSetByPump -> HtmlHelper.fromHtml(tbrSetByPump.toHtml()) }
+ ?: ""
+ loop_smbsetbypump.text = it.smbSetByPump?.let { smbSetByPump -> HtmlHelper.fromHtml(smbSetByPump.toHtml()) }
+ ?: ""
+
+ val constraints =
+ it.constraintsProcessed?.let { constraintsProcessed ->
+ val allConstraints = Constraint(0.0)
+ constraintsProcessed.rateConstraint?.let { rateConstraint -> allConstraints.copyReasons(rateConstraint) }
+ constraintsProcessed.smbConstraint?.let { smbConstraint -> allConstraints.copyReasons(smbConstraint) }
+ allConstraints.mostLimitedReasons
+ } ?: ""
+ loop_constraints.text = constraints
+ }
+ }
+
+ @Synchronized
+ private fun clearGUI() {
+ if (loop_request == null) return
+ loop_request.text = ""
+ loop_constraints.text = ""
+ loop_constraintsprocessed.text = ""
+ loop_source.text = ""
+ loop_lastrun.text = ""
+ loop_lastenact.text = ""
+ loop_tbrsetbypump.text = ""
+ loop_smbsetbypump.text = ""
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java
index 92378a1d6b..f339bd3771 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java
@@ -10,10 +10,9 @@ import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.SystemClock;
-import android.support.annotation.NonNull;
-import android.support.v4.app.NotificationCompat;
-import com.squareup.otto.Subscribe;
+import androidx.annotation.NonNull;
+import androidx.core.app.NotificationCompat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -47,10 +46,11 @@ import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopSetLastRunGui;
import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopUpdateGui;
import info.nightscout.androidaps.plugins.aps.loop.events.EventNewOpenLoopNotification;
+import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
-import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin;
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
+import info.nightscout.androidaps.plugins.general.overview.dialogs.ErrorHelperActivity;
import info.nightscout.androidaps.plugins.general.wear.ActionStringHandler;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished;
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin;
@@ -61,12 +61,15 @@ import info.nightscout.androidaps.utils.FabricPrivacy;
import info.nightscout.androidaps.utils.SP;
import info.nightscout.androidaps.utils.T;
import info.nightscout.androidaps.utils.ToastUtils;
+import io.reactivex.disposables.CompositeDisposable;
+import io.reactivex.schedulers.Schedulers;
/**
* Created by mike on 05.08.2016.
*/
public class LoopPlugin extends PluginBase {
private static Logger log = LoggerFactory.getLogger(L.APS);
+ private CompositeDisposable disposable = new CompositeDisposable();
private static final String CHANNEL_ID = "AndroidAPS-Openloop";
@@ -115,9 +118,39 @@ public class LoopPlugin extends PluginBase {
@Override
protected void onStart() {
- MainApp.bus().register(this);
createNotificationChannel();
super.onStart();
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventTempTargetChange.class)
+ .observeOn(Schedulers.io())
+ .subscribe(event -> {
+ invoke("EventTempTargetChange", true);
+ }, FabricPrivacy::logException)
+ );
+ /**
+ * This method is triggered once autosens calculation has completed, so the LoopPlugin
+ * has current data to work with. However, autosens calculation can be triggered by multiple
+ * sources and currently only a new BG should trigger a loop run. Hence we return early if
+ * the event causing the calculation is not EventNewBg.
+ *
+ */
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventAutosensCalculationFinished.class)
+ .observeOn(Schedulers.io())
+ .subscribe(event -> {
+ // Autosens calculation not triggered by a new BG
+ if (!(event.getCause() instanceof EventNewBG)) return;
+
+ BgReading bgReading = DatabaseHelper.actualBg();
+ // BG outdated
+ if (bgReading == null) return;
+ // already looped with that value
+ if (bgReading.date <= lastBgTriggeredRun) return;
+
+ lastBgTriggeredRun = bgReading.date;
+ invoke("AutosenseCalculation for " + bgReading, true);
+ }, FabricPrivacy::logException)
+ );
}
private void createNotificationChannel() {
@@ -134,8 +167,8 @@ public class LoopPlugin extends PluginBase {
@Override
protected void onStop() {
+ disposable.clear();
super.onStop();
- MainApp.bus().unregister(this);
}
@Override
@@ -144,43 +177,10 @@ public class LoopPlugin extends PluginBase {
return pump == null || pump.getPumpDescription().isTempBasalCapable;
}
- /**
- * This method is triggered once autosens calculation has completed, so the LoopPlugin
- * has current data to work with. However, autosens calculation can be triggered by multiple
- * sources and currently only a new BG should trigger a loop run. Hence we return early if
- * the event causing the calculation is not EventNewBg.
- *
- */
- @Subscribe
- public void onStatusEvent(final EventAutosensCalculationFinished ev) {
- if (!(ev.cause instanceof EventNewBG)) {
- // Autosens calculation not triggered by a new BG
- return;
- }
- BgReading bgReading = DatabaseHelper.actualBg();
- if (bgReading == null) {
- // BG outdated
- return;
- }
- if (bgReading.date <= lastBgTriggeredRun) {
- // already looped with that value
- return;
- }
-
- lastBgTriggeredRun = bgReading.date;
- invoke("AutosenseCalculation for " + bgReading, true);
- }
-
public long suspendedTo() {
return loopSuspendedTill;
}
- @Subscribe
- public void onStatusEvent(final EventTempTargetChange ev) {
- new Thread(() -> invoke("EventTempTargetChange", true)).start();
- }
-
-
public void suspendTo(long endTime) {
loopSuspendedTill = endTime;
isSuperBolus = false;
@@ -278,7 +278,7 @@ public class LoopPlugin extends PluginBase {
String message = MainApp.gs(R.string.loopdisabled) + "\n" + loopEnabled.getReasons();
if (L.isEnabled(L.APS))
log.debug(message);
- MainApp.bus().post(new EventLoopSetLastRunGui(message));
+ RxBus.INSTANCE.send(new EventLoopSetLastRunGui(message));
return;
}
final PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
@@ -289,10 +289,10 @@ public class LoopPlugin extends PluginBase {
Profile profile = ProfileFunctions.getInstance().getProfile();
- if (!ProfileFunctions.getInstance().isProfileValid("Loop")) {
+ if (profile == null || !ProfileFunctions.getInstance().isProfileValid("Loop")) {
if (L.isEnabled(L.APS))
log.debug(MainApp.gs(R.string.noprofileselected));
- MainApp.bus().post(new EventLoopSetLastRunGui(MainApp.gs(R.string.noprofileselected)));
+ RxBus.INSTANCE.send(new EventLoopSetLastRunGui(MainApp.gs(R.string.noprofileselected)));
return;
}
@@ -307,7 +307,7 @@ public class LoopPlugin extends PluginBase {
// Check if we have any result
if (result == null) {
- MainApp.bus().post(new EventLoopSetLastRunGui(MainApp.gs(R.string.noapsselected)));
+ RxBus.INSTANCE.send(new EventLoopSetLastRunGui(MainApp.gs(R.string.noapsselected)));
return;
}
@@ -349,14 +349,14 @@ public class LoopPlugin extends PluginBase {
if (isSuspended()) {
if (L.isEnabled(L.APS))
log.debug(MainApp.gs(R.string.loopsuspended));
- MainApp.bus().post(new EventLoopSetLastRunGui(MainApp.gs(R.string.loopsuspended)));
+ RxBus.INSTANCE.send(new EventLoopSetLastRunGui(MainApp.gs(R.string.loopsuspended)));
return;
}
if (pump.isSuspended()) {
if (L.isEnabled(L.APS))
log.debug(MainApp.gs(R.string.pumpsuspended));
- MainApp.bus().post(new EventLoopSetLastRunGui(MainApp.gs(R.string.pumpsuspended)));
+ RxBus.INSTANCE.send(new EventLoopSetLastRunGui(MainApp.gs(R.string.pumpsuspended)));
return;
}
@@ -372,7 +372,7 @@ public class LoopPlugin extends PluginBase {
lastRun.tbrSetByPump = waiting;
if (resultAfterConstraints.bolusRequested)
lastRun.smbSetByPump = waiting;
- MainApp.bus().post(new EventLoopUpdateGui());
+ RxBus.INSTANCE.send(new EventLoopUpdateGui());
FabricPrivacy.getInstance().logCustom("APSRequest");
applyTBRRequest(resultAfterConstraints, profile, new Callback() {
@Override
@@ -393,11 +393,11 @@ public class LoopPlugin extends PluginBase {
LoopPlugin.getPlugin().invoke("tempBasalFallback", allowNotification, true);
}).start();
}
- MainApp.bus().post(new EventLoopUpdateGui());
+ RxBus.INSTANCE.send(new EventLoopUpdateGui());
}
});
}
- MainApp.bus().post(new EventLoopUpdateGui());
+ RxBus.INSTANCE.send(new EventLoopUpdateGui());
}
});
} else {
@@ -414,7 +414,7 @@ public class LoopPlugin extends PluginBase {
.setAutoCancel(true)
.setPriority(Notification.PRIORITY_HIGH)
.setCategory(Notification.CATEGORY_ALARM)
- .setVisibility(Notification.VISIBILITY_PUBLIC);
+ .setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
if (SP.getBoolean("wearcontrol", false)) {
builder.setLocalOnly(true);
}
@@ -438,7 +438,7 @@ public class LoopPlugin extends PluginBase {
(NotificationManager) MainApp.instance().getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
mNotificationManager.notify(Constants.notificationID, builder.build());
- MainApp.bus().post(new EventNewOpenLoopNotification());
+ RxBus.INSTANCE.send(new EventNewOpenLoopNotification());
// Send to Wear
ActionStringHandler.handleInitiate("changeRequest");
@@ -451,7 +451,7 @@ public class LoopPlugin extends PluginBase {
}
}
- MainApp.bus().post(new EventLoopUpdateGui());
+ RxBus.INSTANCE.send(new EventLoopUpdateGui());
} finally {
if (L.isEnabled(L.APS))
log.debug("invoke end");
@@ -469,13 +469,9 @@ public class LoopPlugin extends PluginBase {
lastRun.lastEnact = new Date();
lastRun.lastOpenModeAccept = new Date();
NSUpload.uploadDeviceStatus();
- ObjectivesPlugin objectivesPlugin = MainApp.getSpecificPlugin(ObjectivesPlugin.class);
- if (objectivesPlugin != null) {
- ObjectivesPlugin.getPlugin().manualEnacts++;
- ObjectivesPlugin.getPlugin().saveProgress();
- }
+ SP.incInt(R.string.key_ObjectivesmanualEnacts);
}
- MainApp.bus().post(new EventAcceptOpenLoopChange());
+ RxBus.INSTANCE.send(new EventAcceptOpenLoopChange());
}
});
FabricPrivacy.getInstance().logCustom("AcceptTemp");
@@ -644,20 +640,48 @@ public class LoopPlugin extends PluginBase {
TreatmentsInterface activeTreatments = TreatmentsPlugin.getPlugin();
LoopPlugin.getPlugin().disconnectTo(System.currentTimeMillis() + durationInMinutes * 60 * 1000L);
- ConfigBuilderPlugin.getPlugin().getCommandQueue().tempBasalPercent(0, durationInMinutes, true, profile, new Callback() {
- @Override
- public void run() {
- if (!result.success) {
- ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.tempbasaldeliveryerror));
+
+ if (pump.getPumpDescription().tempBasalStyle == PumpDescription.ABSOLUTE) {
+ ConfigBuilderPlugin.getPlugin().getCommandQueue().tempBasalAbsolute(0, durationInMinutes, true, profile, new Callback() {
+ @Override
+ public void run() {
+ if (!result.success) {
+ Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
+ i.putExtra("soundid", R.raw.boluserror);
+ i.putExtra("status", result.comment);
+ i.putExtra("title", MainApp.gs(R.string.tempbasaldeliveryerror));
+ i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ MainApp.instance().startActivity(i);
+ }
}
- }
- });
+ });
+ } else {
+ ConfigBuilderPlugin.getPlugin().getCommandQueue().tempBasalPercent(0, durationInMinutes, true, profile, new Callback() {
+ @Override
+ public void run() {
+ if (!result.success) {
+ Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
+ i.putExtra("soundid", R.raw.boluserror);
+ i.putExtra("status", result.comment);
+ i.putExtra("title", MainApp.gs(R.string.tempbasaldeliveryerror));
+ i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ MainApp.instance().startActivity(i);
+ }
+ }
+ });
+ }
+
if (pump.getPumpDescription().isExtendedBolusCapable && activeTreatments.isInHistoryExtendedBoluslInProgress()) {
ConfigBuilderPlugin.getPlugin().getCommandQueue().cancelExtended(new Callback() {
@Override
public void run() {
if (!result.success) {
- ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.extendedbolusdeliveryerror));
+ Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
+ i.putExtra("soundid", R.raw.boluserror);
+ i.putExtra("status", result.comment);
+ i.putExtra("title", MainApp.gs(R.string.extendedbolusdeliveryerror));
+ i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ MainApp.instance().startActivity(i);
}
}
});
@@ -671,7 +695,12 @@ public class LoopPlugin extends PluginBase {
@Override
public void run() {
if (!result.success) {
- ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.tempbasaldeliveryerror));
+ Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
+ i.putExtra("soundid", R.raw.boluserror);
+ i.putExtra("status", result.comment);
+ i.putExtra("title", MainApp.gs(R.string.tempbasaldeliveryerror));
+ i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ MainApp.instance().startActivity(i);
}
}
});
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/events/EventLoopSetLastRunGui.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/events/EventLoopSetLastRunGui.java
deleted file mode 100644
index 0d2a45f528..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/events/EventLoopSetLastRunGui.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package info.nightscout.androidaps.plugins.aps.loop.events;
-
-import info.nightscout.androidaps.events.EventUpdateGui;
-
-/**
- * Created by mike on 05.08.2016.
- */
-public class EventLoopSetLastRunGui extends EventUpdateGui {
- public String text = null;
-
- public EventLoopSetLastRunGui(String text) {
- this.text = text;
- }
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/events/EventLoopSetLastRunGui.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/events/EventLoopSetLastRunGui.kt
new file mode 100644
index 0000000000..19c7e92c5c
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/events/EventLoopSetLastRunGui.kt
@@ -0,0 +1,8 @@
+package info.nightscout.androidaps.plugins.aps.loop.events
+
+import info.nightscout.androidaps.events.EventUpdateGui
+
+/**
+ * Created by mike on 05.08.2016.
+ */
+class EventLoopSetLastRunGui(val text: String) : EventUpdateGui()
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/events/EventLoopUpdateGui.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/events/EventLoopUpdateGui.java
deleted file mode 100644
index f746dfb0a0..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/events/EventLoopUpdateGui.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package info.nightscout.androidaps.plugins.aps.loop.events;
-
-import info.nightscout.androidaps.events.EventUpdateGui;
-
-/**
- * Created by mike on 05.08.2016.
- */
-public class EventLoopUpdateGui extends EventUpdateGui {
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/events/EventLoopUpdateGui.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/events/EventLoopUpdateGui.kt
new file mode 100644
index 0000000000..89507d85f8
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/events/EventLoopUpdateGui.kt
@@ -0,0 +1,8 @@
+package info.nightscout.androidaps.plugins.aps.loop.events
+
+import info.nightscout.androidaps.events.EventUpdateGui
+
+/**
+ * Created by mike on 05.08.2016.
+ */
+class EventLoopUpdateGui : EventUpdateGui()
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/events/EventNewOpenLoopNotification.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/events/EventNewOpenLoopNotification.java
deleted file mode 100644
index 6a0a4dc0cf..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/events/EventNewOpenLoopNotification.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package info.nightscout.androidaps.plugins.aps.loop.events;
-
-import info.nightscout.androidaps.events.Event;
-
-/**
- * Created by mike on 07.08.2016.
- */
-public class EventNewOpenLoopNotification extends Event {
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/events/EventNewOpenLoopNotification.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/events/EventNewOpenLoopNotification.kt
new file mode 100644
index 0000000000..2933318dd6
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/events/EventNewOpenLoopNotification.kt
@@ -0,0 +1,5 @@
+package info.nightscout.androidaps.plugins.aps.loop.events
+
+import info.nightscout.androidaps.events.Event
+
+class EventNewOpenLoopNotification : Event()
\ No newline at end of file
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalAdapterAMAJS.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalAdapterAMAJS.java
index 5b5c8cb63d..703dc4255b 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalAdapterAMAJS.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalAdapterAMAJS.java
@@ -16,6 +16,9 @@ import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
+import java.nio.charset.StandardCharsets;
+
+import javax.annotation.Nullable;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
@@ -59,6 +62,7 @@ public class DetermineBasalAdapterAMAJS {
mScriptReader = scriptReader;
}
+ @Nullable
public DetermineBasalResultAMA invoke() {
if (L.isEnabled(L.APS)) {
@@ -277,7 +281,7 @@ public class DetermineBasalAdapterAMAJS {
private String readFile(String filename) throws IOException {
byte[] bytes = mScriptReader.readFile(filename);
- String string = new String(bytes, "UTF-8");
+ String string = new String(bytes, StandardCharsets.UTF_8);
if (string.startsWith("#!/usr/bin/env node")) {
string = string.substring(20);
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAFragment.java
deleted file mode 100644
index 0aadf52cbd..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAFragment.java
+++ /dev/null
@@ -1,134 +0,0 @@
-package info.nightscout.androidaps.plugins.aps.openAPSAMA;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.TextView;
-
-import com.squareup.otto.Subscribe;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import info.nightscout.androidaps.MainApp;
-import info.nightscout.androidaps.R;
-import info.nightscout.androidaps.logging.L;
-import info.nightscout.androidaps.plugins.aps.openAPSMA.events.EventOpenAPSUpdateGui;
-import info.nightscout.androidaps.plugins.aps.openAPSMA.events.EventOpenAPSUpdateResultGui;
-import info.nightscout.androidaps.plugins.common.SubscriberFragment;
-import info.nightscout.androidaps.utils.DateUtil;
-import info.nightscout.androidaps.utils.JSONFormatter;
-
-public class OpenAPSAMAFragment extends SubscriberFragment implements View.OnClickListener {
- private static Logger log = LoggerFactory.getLogger(L.APS);
-
- Button run;
- TextView lastRunView;
- TextView glucoseStatusView;
- TextView currentTempView;
- TextView iobDataView;
- TextView profileView;
- TextView mealDataView;
- TextView autosensDataView;
- TextView resultView;
- TextView scriptdebugView;
- TextView requestView;
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- View view = inflater.inflate(R.layout.openapsama_fragment, container, false);
-
- run = (Button) view.findViewById(R.id.openapsma_run);
- run.setOnClickListener(this);
- lastRunView = (TextView) view.findViewById(R.id.openapsma_lastrun);
- glucoseStatusView = (TextView) view.findViewById(R.id.openapsma_glucosestatus);
- currentTempView = (TextView) view.findViewById(R.id.openapsma_currenttemp);
- iobDataView = (TextView) view.findViewById(R.id.openapsma_iobdata);
- profileView = (TextView) view.findViewById(R.id.openapsma_profile);
- mealDataView = (TextView) view.findViewById(R.id.openapsma_mealdata);
- autosensDataView = (TextView) view.findViewById(R.id.openapsma_autosensdata);
- scriptdebugView = (TextView) view.findViewById(R.id.openapsma_scriptdebugdata);
- resultView = (TextView) view.findViewById(R.id.openapsma_result);
- requestView = (TextView) view.findViewById(R.id.openapsma_request);
-
- updateGUI();
- return view;
- }
-
- @Override
- public void onClick(View view) {
- switch (view.getId()) {
- case R.id.openapsma_run:
- OpenAPSAMAPlugin.getPlugin().invoke("OpenAPSAMA button", false);
- break;
- }
-
- }
-
- @Subscribe
- public void onStatusEvent(final EventOpenAPSUpdateGui ev) {
- updateGUI();
- }
-
- @Subscribe
- public void onStatusEvent(final EventOpenAPSUpdateResultGui ev) {
- updateResultGUI(ev.text);
- }
-
- @Override
- protected void updateGUI() {
- Activity activity = getActivity();
- if (activity != null)
- activity.runOnUiThread(() -> {
- DetermineBasalResultAMA lastAPSResult = OpenAPSAMAPlugin.getPlugin().lastAPSResult;
- if (lastAPSResult != null) {
- resultView.setText(JSONFormatter.format(lastAPSResult.json));
- requestView.setText(lastAPSResult.toSpanned());
- }
- DetermineBasalAdapterAMAJS determineBasalAdapterAMAJS = OpenAPSAMAPlugin.getPlugin().lastDetermineBasalAdapterAMAJS;
- if (determineBasalAdapterAMAJS != null) {
- glucoseStatusView.setText(JSONFormatter.format(determineBasalAdapterAMAJS.getGlucoseStatusParam()));
- currentTempView.setText(JSONFormatter.format(determineBasalAdapterAMAJS.getCurrentTempParam()));
- try {
- JSONArray iobArray = new JSONArray(determineBasalAdapterAMAJS.getIobDataParam());
- iobDataView.setText(String.format(MainApp.gs(R.string.array_of_elements), iobArray.length()) + "\n" + JSONFormatter.format(iobArray.getString(0)));
- } catch (JSONException e) {
- log.error("Unhandled exception", e);
- iobDataView.setText("JSONException");
- }
- profileView.setText(JSONFormatter.format(determineBasalAdapterAMAJS.getProfileParam()));
- mealDataView.setText(JSONFormatter.format(determineBasalAdapterAMAJS.getMealDataParam()));
- scriptdebugView.setText(determineBasalAdapterAMAJS.getScriptDebug());
- }
- if (OpenAPSAMAPlugin.getPlugin().lastAPSRun != 0) {
- lastRunView.setText(DateUtil.dateAndTimeFullString(OpenAPSAMAPlugin.getPlugin().lastAPSRun));
- }
- if (OpenAPSAMAPlugin.getPlugin().lastAutosensResult != null) {
- autosensDataView.setText(JSONFormatter.format(OpenAPSAMAPlugin.getPlugin().lastAutosensResult.json()));
- }
- });
- }
-
- void updateResultGUI(final String text) {
- Activity activity = getActivity();
- if (activity != null)
- activity.runOnUiThread(() -> {
- resultView.setText(text);
- glucoseStatusView.setText("");
- currentTempView.setText("");
- iobDataView.setText("");
- profileView.setText("");
- mealDataView.setText("");
- autosensDataView.setText("");
- scriptdebugView.setText("");
- requestView.setText("");
- lastRunView.setText("");
- });
- }
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAFragment.kt
new file mode 100644
index 0000000000..94747a4597
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAFragment.kt
@@ -0,0 +1,115 @@
+package info.nightscout.androidaps.plugins.aps.openAPSAMA
+
+import android.os.Bundle
+import android.text.TextUtils
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import info.nightscout.androidaps.MainApp
+import info.nightscout.androidaps.R
+import info.nightscout.androidaps.logging.L
+import info.nightscout.androidaps.plugins.aps.openAPSMA.events.EventOpenAPSUpdateGui
+import info.nightscout.androidaps.plugins.aps.openAPSMA.events.EventOpenAPSUpdateResultGui
+import info.nightscout.androidaps.plugins.bus.RxBus
+import info.nightscout.androidaps.utils.DateUtil
+import info.nightscout.androidaps.utils.FabricPrivacy
+import info.nightscout.androidaps.utils.JSONFormatter
+import info.nightscout.androidaps.utils.plusAssign
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.disposables.CompositeDisposable
+import kotlinx.android.synthetic.main.openapsama_fragment.*
+import org.json.JSONArray
+import org.json.JSONException
+import org.slf4j.LoggerFactory
+
+class OpenAPSAMAFragment : Fragment() {
+ private val log = LoggerFactory.getLogger(L.APS)
+ private var disposable: CompositeDisposable = CompositeDisposable()
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?): View? {
+ return inflater.inflate(R.layout.openapsama_fragment, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ openapsma_run.setOnClickListener {
+ OpenAPSAMAPlugin.getPlugin().invoke("OpenAPSAMA button", false)
+ }
+ }
+
+ @Synchronized
+ override fun onResume() {
+ super.onResume()
+
+ disposable += RxBus
+ .toObservable(EventOpenAPSUpdateGui::class.java)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe({
+ updateGUI()
+ }, {
+ FabricPrivacy.logException(it)
+ })
+ disposable += RxBus
+ .toObservable(EventOpenAPSUpdateResultGui::class.java)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe({
+ updateResultGUI(it.text)
+ }, {
+ FabricPrivacy.logException(it)
+ })
+
+ updateGUI()
+ }
+
+ @Synchronized
+ override fun onPause() {
+ super.onPause()
+ disposable.clear()
+ }
+
+ @Synchronized
+ private fun updateGUI() {
+ if (openapsma_result == null) return
+ OpenAPSAMAPlugin.getPlugin().lastAPSResult?.let { lastAPSResult ->
+ openapsma_result.text = JSONFormatter.format(lastAPSResult.json)
+ openapsma_request.text = lastAPSResult.toSpanned()
+ }
+ OpenAPSAMAPlugin.getPlugin().lastDetermineBasalAdapterAMAJS?.let { determineBasalAdapterAMAJS ->
+ openapsma_glucosestatus.text = JSONFormatter.format(determineBasalAdapterAMAJS.glucoseStatusParam)
+ openapsma_currenttemp.text = JSONFormatter.format(determineBasalAdapterAMAJS.currentTempParam)
+ try {
+ val iobArray = JSONArray(determineBasalAdapterAMAJS.iobDataParam)
+ openapsma_iobdata.text = TextUtils.concat(String.format(MainApp.gs(R.string.array_of_elements), iobArray.length()) + "\n", JSONFormatter.format(iobArray.getString(0)))
+ } catch (e: JSONException) {
+ log.error("Unhandled exception", e)
+ openapsma_iobdata.text = "JSONException see log for details"
+ }
+
+ openapsma_profile.text = JSONFormatter.format(determineBasalAdapterAMAJS.profileParam)
+ openapsma_mealdata.text = JSONFormatter.format(determineBasalAdapterAMAJS.mealDataParam)
+ openapsma_scriptdebugdata.text = determineBasalAdapterAMAJS.scriptDebug
+ }
+ if (OpenAPSAMAPlugin.getPlugin().lastAPSRun != 0L) {
+ openapsma_lastrun.text = DateUtil.dateAndTimeFullString(OpenAPSAMAPlugin.getPlugin().lastAPSRun)
+ }
+ OpenAPSAMAPlugin.getPlugin().lastAutosensResult?.let {
+ openapsma_autosensdata.text = JSONFormatter.format(it.json())
+ }
+ }
+
+ private fun updateResultGUI(text: String) {
+ openapsma_result.text = text
+ openapsma_glucosestatus.text = ""
+ openapsma_currenttemp.text = ""
+ openapsma_iobdata.text = ""
+ openapsma_profile.text = ""
+ openapsma_mealdata.text = ""
+ openapsma_autosensdata.text = ""
+ openapsma_scriptdebugdata.text = ""
+ openapsma_request.text = ""
+ openapsma_lastrun.text = ""
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAPlugin.java
index 1f7deebea4..ef31ad599e 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAPlugin.java
@@ -6,7 +6,6 @@ import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
-import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus;
import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.MealData;
import info.nightscout.androidaps.data.Profile;
@@ -17,17 +16,20 @@ import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.logging.L;
-import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
-import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
-import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensData;
-import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult;
-import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.aps.loop.APSResult;
import info.nightscout.androidaps.plugins.aps.loop.ScriptReader;
import info.nightscout.androidaps.plugins.aps.openAPSMA.events.EventOpenAPSUpdateGui;
import info.nightscout.androidaps.plugins.aps.openAPSMA.events.EventOpenAPSUpdateResultGui;
+import info.nightscout.androidaps.plugins.bus.RxBus;
+import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
+import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
+import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensData;
+import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult;
+import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus;
+import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
import info.nightscout.androidaps.utils.DateUtil;
+import info.nightscout.androidaps.utils.FabricPrivacy;
import info.nightscout.androidaps.utils.HardLimits;
import info.nightscout.androidaps.utils.Profiler;
import info.nightscout.androidaps.utils.Round;
@@ -99,21 +101,21 @@ public class OpenAPSAMAPlugin extends PluginBase implements APSInterface {
PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
if (profile == null) {
- MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.noprofileselected)));
+ RxBus.INSTANCE.send(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.noprofileselected)));
if (L.isEnabled(L.APS))
log.debug(MainApp.gs(R.string.noprofileselected));
return;
}
if (!isEnabled(PluginType.APS)) {
- MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.openapsma_disabled)));
+ RxBus.INSTANCE.send(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.openapsma_disabled)));
if (L.isEnabled(L.APS))
log.debug(MainApp.gs(R.string.openapsma_disabled));
return;
}
if (glucoseStatus == null) {
- MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.openapsma_noglucosedata)));
+ RxBus.INSTANCE.send(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.openapsma_noglucosedata)));
if (L.isEnabled(L.APS))
log.debug(MainApp.gs(R.string.openapsma_noglucosedata));
return;
@@ -171,7 +173,7 @@ public class OpenAPSAMAPlugin extends PluginBase implements APSInterface {
if (MainApp.getConstraintChecker().isAutosensModeEnabled().value()) {
AutosensData autosensData = IobCobCalculatorPlugin.getPlugin().getLastAutosensDataSynchronized("OpenAPSPlugin");
if (autosensData == null) {
- MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.openaps_noasdata)));
+ RxBus.INSTANCE.send(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.openaps_noasdata)));
return;
}
lastAutosensResult = autosensData.autosensResult;
@@ -192,7 +194,8 @@ public class OpenAPSAMAPlugin extends PluginBase implements APSInterface {
isTempTarget
);
} catch (JSONException e) {
- log.error("Unable to set data: " + e.toString());
+ FabricPrivacy.logException(e);
+ return;
}
@@ -200,23 +203,31 @@ public class OpenAPSAMAPlugin extends PluginBase implements APSInterface {
if (L.isEnabled(L.APS))
Profiler.log(log, "AMA calculation", start);
// Fix bug determine basal
- if (determineBasalResultAMA.rate == 0d && determineBasalResultAMA.duration == 0 && !TreatmentsPlugin.getPlugin().isTempBasalInProgress())
- determineBasalResultAMA.tempBasalRequested = false;
+ if (determineBasalResultAMA == null) {
+ if (L.isEnabled(L.APS))
+ log.error("SMB calculation returned null");
+ lastDetermineBasalAdapterAMAJS = null;
+ lastAPSResult = null;
+ lastAPSRun = 0;
+ } else {
+ if (determineBasalResultAMA.rate == 0d && determineBasalResultAMA.duration == 0 && !TreatmentsPlugin.getPlugin().isTempBasalInProgress())
+ determineBasalResultAMA.tempBasalRequested = false;
- determineBasalResultAMA.iob = iobArray[0];
+ determineBasalResultAMA.iob = iobArray[0];
- long now = System.currentTimeMillis();
+ long now = System.currentTimeMillis();
- try {
- determineBasalResultAMA.json.put("timestamp", DateUtil.toISOString(now));
- } catch (JSONException e) {
- log.error("Unhandled exception", e);
+ try {
+ determineBasalResultAMA.json.put("timestamp", DateUtil.toISOString(now));
+ } catch (JSONException e) {
+ log.error("Unhandled exception", e);
+ }
+
+ lastDetermineBasalAdapterAMAJS = determineBasalAdapterAMAJS;
+ lastAPSResult = determineBasalResultAMA;
+ lastAPSRun = now;
}
-
- lastDetermineBasalAdapterAMAJS = determineBasalAdapterAMAJS;
- lastAPSResult = determineBasalResultAMA;
- lastAPSRun = now;
- MainApp.bus().post(new EventOpenAPSUpdateGui());
+ RxBus.INSTANCE.send(new EventOpenAPSUpdateGui());
//deviceStatus.suggested = determineBasalResultAMA.json;
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/DetermineBasalAdapterMAJS.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/DetermineBasalAdapterMAJS.java
index ae1f390ded..1ded34b7cb 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/DetermineBasalAdapterMAJS.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/DetermineBasalAdapterMAJS.java
@@ -14,6 +14,9 @@ import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
+import java.nio.charset.StandardCharsets;
+
+import javax.annotation.Nullable;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.R;
@@ -47,6 +50,7 @@ public class DetermineBasalAdapterMAJS {
mScriptReader = scriptReader;
}
+ @Nullable
public DetermineBasalResultMA invoke() {
DetermineBasalResultMA determineBasalResultMA = null;
@@ -207,7 +211,7 @@ public class DetermineBasalAdapterMAJS {
private String readFile(String filename) throws IOException {
byte[] bytes = mScriptReader.readFile(filename);
- String string = new String(bytes, "UTF-8");
+ String string = new String(bytes, StandardCharsets.UTF_8);
if (string.startsWith("#!/usr/bin/env node")) {
string = string.substring(20);
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/LoggerCallback.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/LoggerCallback.java
index 30ce388f5d..a2596d9174 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/LoggerCallback.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/LoggerCallback.java
@@ -36,16 +36,14 @@ public class LoggerCallback extends ScriptableObject {
public void jsFunction_log(Object obj1) {
if (L.isEnabled(L.APS))
- log.debug(obj1.toString());
+ log.debug(obj1.toString().trim());
logBuffer.append(obj1.toString());
- logBuffer.append(' ');
}
public void jsFunction_error(Object obj1) {
if (L.isEnabled(L.APS))
- log.error(obj1.toString());
+ log.error(obj1.toString().trim());
errorBuffer.append(obj1.toString());
- errorBuffer.append(' ');
}
@@ -60,4 +58,4 @@ public class LoggerCallback extends ScriptableObject {
}
return ret;
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/OpenAPSMAFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/OpenAPSMAFragment.java
deleted file mode 100644
index 5d632a44fc..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/OpenAPSMAFragment.java
+++ /dev/null
@@ -1,116 +0,0 @@
-package info.nightscout.androidaps.plugins.aps.openAPSMA;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.TextView;
-
-import com.squareup.otto.Subscribe;
-
-import info.nightscout.androidaps.R;
-import info.nightscout.androidaps.plugins.aps.openAPSMA.events.EventOpenAPSUpdateGui;
-import info.nightscout.androidaps.plugins.aps.openAPSMA.events.EventOpenAPSUpdateResultGui;
-import info.nightscout.androidaps.plugins.common.SubscriberFragment;
-import info.nightscout.androidaps.utils.DateUtil;
-import info.nightscout.androidaps.utils.FabricPrivacy;
-import info.nightscout.androidaps.utils.JSONFormatter;
-
-public class OpenAPSMAFragment extends SubscriberFragment implements View.OnClickListener {
- Button run;
- TextView lastRunView;
- TextView glucoseStatusView;
- TextView currentTempView;
- TextView iobDataView;
- TextView profileView;
- TextView mealDataView;
- TextView resultView;
- TextView requestView;
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- try {
- View view = inflater.inflate(R.layout.openapsma_fragment, container, false);
-
- run = (Button) view.findViewById(R.id.openapsma_run);
- run.setOnClickListener(this);
- lastRunView = (TextView) view.findViewById(R.id.openapsma_lastrun);
- glucoseStatusView = (TextView) view.findViewById(R.id.openapsma_glucosestatus);
- currentTempView = (TextView) view.findViewById(R.id.openapsma_currenttemp);
- iobDataView = (TextView) view.findViewById(R.id.openapsma_iobdata);
- profileView = (TextView) view.findViewById(R.id.openapsma_profile);
- mealDataView = (TextView) view.findViewById(R.id.openapsma_mealdata);
- resultView = (TextView) view.findViewById(R.id.openapsma_result);
- requestView = (TextView) view.findViewById(R.id.openapsma_request);
-
- updateGUI();
- return view;
- } catch (Exception e) {
- FabricPrivacy.logException(e);
- }
-
- return null;
- }
-
- @Override
- public void onClick(View view) {
- switch (view.getId()) {
- case R.id.openapsma_run:
- OpenAPSMAPlugin.getPlugin().invoke("OpenAPSMA button", false);
- break;
- }
-
- }
-
- @Subscribe
- public void onStatusEvent(final EventOpenAPSUpdateGui ev) {
- updateGUI();
- }
-
- @Subscribe
- public void onStatusEvent(final EventOpenAPSUpdateResultGui ev) {
- updateResultGUI(ev.text);
- }
-
- @Override
- protected void updateGUI() {
- Activity activity = getActivity();
- if (activity != null)
- activity.runOnUiThread(() -> {
- DetermineBasalResultMA lastAPSResult = OpenAPSMAPlugin.getPlugin().lastAPSResult;
- if (lastAPSResult != null) {
- resultView.setText(JSONFormatter.format(lastAPSResult.json));
- requestView.setText(lastAPSResult.toSpanned());
- }
- DetermineBasalAdapterMAJS determineBasalAdapterMAJS = OpenAPSMAPlugin.getPlugin().lastDetermineBasalAdapterMAJS;
- if (determineBasalAdapterMAJS != null) {
- glucoseStatusView.setText(JSONFormatter.format(determineBasalAdapterMAJS.getGlucoseStatusParam()));
- currentTempView.setText(JSONFormatter.format(determineBasalAdapterMAJS.getCurrentTempParam()));
- iobDataView.setText(JSONFormatter.format(determineBasalAdapterMAJS.getIobDataParam()));
- profileView.setText(JSONFormatter.format(determineBasalAdapterMAJS.getProfileParam()));
- mealDataView.setText(JSONFormatter.format(determineBasalAdapterMAJS.getMealDataParam()));
- }
- if (OpenAPSMAPlugin.getPlugin().lastAPSRun != 0) {
- lastRunView.setText(DateUtil.dateAndTimeFullString(OpenAPSMAPlugin.getPlugin().lastAPSRun));
- }
- });
- }
-
- private void updateResultGUI(final String text) {
- Activity activity = getActivity();
- if (activity != null)
- activity.runOnUiThread(() -> {
- resultView.setText(text);
- glucoseStatusView.setText("");
- currentTempView.setText("");
- iobDataView.setText("");
- profileView.setText("");
- mealDataView.setText("");
- requestView.setText("");
- lastRunView.setText("");
- });
- }
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/OpenAPSMAFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/OpenAPSMAFragment.kt
new file mode 100644
index 0000000000..1b72f57365
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/OpenAPSMAFragment.kt
@@ -0,0 +1,100 @@
+package info.nightscout.androidaps.plugins.aps.openAPSMA
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import info.nightscout.androidaps.R
+import info.nightscout.androidaps.logging.L
+import info.nightscout.androidaps.plugins.aps.openAPSMA.events.EventOpenAPSUpdateGui
+import info.nightscout.androidaps.plugins.aps.openAPSMA.events.EventOpenAPSUpdateResultGui
+import info.nightscout.androidaps.plugins.bus.RxBus
+import info.nightscout.androidaps.utils.DateUtil
+import info.nightscout.androidaps.utils.FabricPrivacy
+import info.nightscout.androidaps.utils.JSONFormatter
+import info.nightscout.androidaps.utils.plusAssign
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.disposables.CompositeDisposable
+import kotlinx.android.synthetic.main.openapsama_fragment.*
+import org.slf4j.LoggerFactory
+
+class OpenAPSMAFragment : Fragment() {
+ private val log = LoggerFactory.getLogger(L.APS)
+ private var disposable: CompositeDisposable = CompositeDisposable()
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?): View? {
+ return inflater.inflate(R.layout.openapsma_fragment, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ openapsma_run.setOnClickListener {
+ OpenAPSMAPlugin.getPlugin().invoke("OpenAPSMA button", false)
+ }
+
+ }
+
+ @Synchronized
+ override fun onResume() {
+ super.onResume()
+
+ disposable += RxBus
+ .toObservable(EventOpenAPSUpdateGui::class.java)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe({
+ updateGUI()
+ }, {
+ FabricPrivacy.logException(it)
+ })
+ disposable += RxBus
+ .toObservable(EventOpenAPSUpdateResultGui::class.java)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe({
+ updateResultGUI(it.text)
+ }, {
+ FabricPrivacy.logException(it)
+ })
+ updateGUI()
+ }
+
+ @Synchronized
+ override fun onPause() {
+ super.onPause()
+ disposable.clear()
+ }
+
+ @Synchronized
+ private fun updateGUI() {
+ if (openapsma_result == null) return
+ OpenAPSMAPlugin.getPlugin().lastAPSResult?.let { lastAPSResult ->
+ openapsma_result.text = JSONFormatter.format(lastAPSResult.json)
+ openapsma_request.text = lastAPSResult.toSpanned()
+ }
+ OpenAPSMAPlugin.getPlugin().lastDetermineBasalAdapterMAJS?.let { determineBasalAdapterMAJS ->
+ openapsma_glucosestatus.text = JSONFormatter.format(determineBasalAdapterMAJS.glucoseStatusParam)
+ openapsma_currenttemp.text = JSONFormatter.format(determineBasalAdapterMAJS.currentTempParam)
+ openapsma_iobdata.text = JSONFormatter.format(determineBasalAdapterMAJS.iobDataParam)
+ openapsma_profile.text = JSONFormatter.format(determineBasalAdapterMAJS.profileParam)
+ openapsma_mealdata.text = JSONFormatter.format(determineBasalAdapterMAJS.mealDataParam)
+ }
+ if (OpenAPSMAPlugin.getPlugin().lastAPSRun != 0L) {
+ openapsma_lastrun.text = DateUtil.dateAndTimeString(OpenAPSMAPlugin.getPlugin().lastAPSRun)
+ }
+ }
+
+ @Synchronized
+ private fun updateResultGUI(text: String) {
+ if (openapsma_result == null) return
+ openapsma_result.text = text
+ openapsma_glucosestatus.text = ""
+ openapsma_currenttemp.text = ""
+ openapsma_iobdata.text = ""
+ openapsma_profile.text = ""
+ openapsma_mealdata.text = ""
+ openapsma_request.text = ""
+ openapsma_lastrun.text = ""
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/OpenAPSMAPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/OpenAPSMAPlugin.java
index 2dd78bdb82..899c0151d8 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/OpenAPSMAPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/OpenAPSMAPlugin.java
@@ -6,7 +6,6 @@ import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
-import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus;
import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.MealData;
import info.nightscout.androidaps.data.Profile;
@@ -17,14 +16,17 @@ import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.logging.L;
-import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
-import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
import info.nightscout.androidaps.plugins.aps.loop.APSResult;
import info.nightscout.androidaps.plugins.aps.loop.ScriptReader;
import info.nightscout.androidaps.plugins.aps.openAPSMA.events.EventOpenAPSUpdateGui;
import info.nightscout.androidaps.plugins.aps.openAPSMA.events.EventOpenAPSUpdateResultGui;
+import info.nightscout.androidaps.plugins.bus.RxBus;
+import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
+import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
+import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus;
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
import info.nightscout.androidaps.utils.DateUtil;
+import info.nightscout.androidaps.utils.FabricPrivacy;
import info.nightscout.androidaps.utils.HardLimits;
import info.nightscout.androidaps.utils.Profiler;
import info.nightscout.androidaps.utils.Round;
@@ -98,21 +100,21 @@ public class OpenAPSMAPlugin extends PluginBase implements APSInterface {
PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
if (profile == null) {
- MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.noprofileselected)));
+ RxBus.INSTANCE.send(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.noprofileselected)));
if (L.isEnabled(L.APS))
log.debug(MainApp.gs(R.string.noprofileselected));
return;
}
if (!isEnabled(PluginType.APS)) {
- MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.openapsma_disabled)));
+ RxBus.INSTANCE.send(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.openapsma_disabled)));
if (L.isEnabled(L.APS))
log.debug(MainApp.gs(R.string.openapsma_disabled));
return;
}
if (glucoseStatus == null) {
- MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.openapsma_noglucosedata)));
+ RxBus.INSTANCE.send(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.openapsma_noglucosedata)));
if (L.isEnabled(L.APS))
log.debug(MainApp.gs(R.string.openapsma_noglucosedata));
return;
@@ -169,7 +171,8 @@ public class OpenAPSMAPlugin extends PluginBase implements APSInterface {
try {
determineBasalAdapterMAJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, ConfigBuilderPlugin.getPlugin().getActivePump().getBaseBasalRate(), iobTotal, glucoseStatus, mealData);
} catch (JSONException e) {
- log.error("Unhandled exception", e);
+ FabricPrivacy.logException(e);
+ return;
}
if (L.isEnabled(L.APS))
Profiler.log(log, "MA calculation", start);
@@ -178,22 +181,30 @@ public class OpenAPSMAPlugin extends PluginBase implements APSInterface {
long now = System.currentTimeMillis();
DetermineBasalResultMA determineBasalResultMA = determineBasalAdapterMAJS.invoke();
- // Fix bug determinef basal
- if (determineBasalResultMA.rate == 0d && determineBasalResultMA.duration == 0 && !TreatmentsPlugin.getPlugin().isTempBasalInProgress())
- determineBasalResultMA.tempBasalRequested = false;
+ if (determineBasalResultMA == null) {
+ if (L.isEnabled(L.APS))
+ log.error("MA calculation returned null");
+ lastDetermineBasalAdapterMAJS = null;
+ lastAPSResult = null;
+ lastAPSRun = 0;
+ } else {
+ // Fix bug determinef basal
+ if (determineBasalResultMA.rate == 0d && determineBasalResultMA.duration == 0 && !TreatmentsPlugin.getPlugin().isTempBasalInProgress())
+ determineBasalResultMA.tempBasalRequested = false;
- determineBasalResultMA.iob = iobTotal;
+ determineBasalResultMA.iob = iobTotal;
- try {
- determineBasalResultMA.json.put("timestamp", DateUtil.toISOString(now));
- } catch (JSONException e) {
- log.error("Unhandled exception", e);
+ try {
+ determineBasalResultMA.json.put("timestamp", DateUtil.toISOString(now));
+ } catch (JSONException e) {
+ log.error("Unhandled exception", e);
+ }
+
+ lastDetermineBasalAdapterMAJS = determineBasalAdapterMAJS;
+ lastAPSResult = determineBasalResultMA;
+ lastAPSRun = now;
}
-
- lastDetermineBasalAdapterMAJS = determineBasalAdapterMAJS;
- lastAPSResult = determineBasalResultMA;
- lastAPSRun = now;
- MainApp.bus().post(new EventOpenAPSUpdateGui());
+ RxBus.INSTANCE.send(new EventOpenAPSUpdateGui());
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/events/EventOpenAPSUpdateGui.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/events/EventOpenAPSUpdateGui.java
deleted file mode 100644
index de4292025d..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/events/EventOpenAPSUpdateGui.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package info.nightscout.androidaps.plugins.aps.openAPSMA.events;
-
-import info.nightscout.androidaps.events.EventUpdateGui;
-
-/**
- * Created by mike on 05.08.2016.
- */
-public class EventOpenAPSUpdateGui extends EventUpdateGui {
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/events/EventOpenAPSUpdateGui.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/events/EventOpenAPSUpdateGui.kt
new file mode 100644
index 0000000000..2b642c6880
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/events/EventOpenAPSUpdateGui.kt
@@ -0,0 +1,5 @@
+package info.nightscout.androidaps.plugins.aps.openAPSMA.events
+
+import info.nightscout.androidaps.events.EventUpdateGui
+
+class EventOpenAPSUpdateGui : EventUpdateGui()
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/events/EventOpenAPSUpdateResultGui.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/events/EventOpenAPSUpdateResultGui.java
deleted file mode 100644
index fb5ea7e78f..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/events/EventOpenAPSUpdateResultGui.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package info.nightscout.androidaps.plugins.aps.openAPSMA.events;
-
-import info.nightscout.androidaps.events.EventUpdateGui;
-
-/**
- * Created by mike on 05.08.2016.
- */
-public class EventOpenAPSUpdateResultGui extends EventUpdateGui {
- public String text;
-
- public EventOpenAPSUpdateResultGui(String text) {
- this.text = text;
- }
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/events/EventOpenAPSUpdateResultGui.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/events/EventOpenAPSUpdateResultGui.kt
new file mode 100644
index 0000000000..4ba02b8755
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/events/EventOpenAPSUpdateResultGui.kt
@@ -0,0 +1,5 @@
+package info.nightscout.androidaps.plugins.aps.openAPSMA.events
+
+import info.nightscout.androidaps.events.EventUpdateGui
+
+class EventOpenAPSUpdateResultGui(val text: String) : EventUpdateGui()
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.java
index bfb75503c1..b7b6d82e5e 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.java
@@ -16,6 +16,9 @@ import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
+import java.nio.charset.StandardCharsets;
+
+import javax.annotation.Nullable;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
@@ -68,6 +71,7 @@ public class DetermineBasalAdapterSMBJS {
}
+ @Nullable
public DetermineBasalResultSMB invoke() {
@@ -340,7 +344,7 @@ public class DetermineBasalAdapterSMBJS {
private String readFile(String filename) throws IOException {
byte[] bytes = mScriptReader.readFile(filename);
- String string = new String(bytes, "UTF-8");
+ String string = new String(bytes, StandardCharsets.UTF_8);
if (string.startsWith("#!/usr/bin/env node")) {
string = string.substring(20);
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBFragment.java
deleted file mode 100644
index 18828e840e..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBFragment.java
+++ /dev/null
@@ -1,157 +0,0 @@
-package info.nightscout.androidaps.plugins.aps.openAPSSMB;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.TextView;
-
-import com.squareup.otto.Subscribe;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import butterknife.BindView;
-import butterknife.ButterKnife;
-import butterknife.OnClick;
-import info.nightscout.androidaps.MainApp;
-import info.nightscout.androidaps.R;
-import info.nightscout.androidaps.logging.L;
-import info.nightscout.androidaps.plugins.aps.openAPSMA.events.EventOpenAPSUpdateGui;
-import info.nightscout.androidaps.plugins.aps.openAPSMA.events.EventOpenAPSUpdateResultGui;
-import info.nightscout.androidaps.plugins.common.SubscriberFragment;
-import info.nightscout.androidaps.utils.DateUtil;
-import info.nightscout.androidaps.utils.JSONFormatter;
-
-public class OpenAPSSMBFragment extends SubscriberFragment {
- private static Logger log = LoggerFactory.getLogger(L.APS);
-
- @BindView(R.id.openapsma_run)
- Button run;
- @BindView(R.id.openapsma_lastrun)
- TextView lastRunView;
- @BindView(R.id.openapsma_constraints)
- TextView constraintsView;
- @BindView(R.id.openapsma_glucosestatus)
- TextView glucoseStatusView;
- @BindView(R.id.openapsma_currenttemp)
- TextView currentTempView;
- @BindView(R.id.openapsma_iobdata)
- TextView iobDataView;
- @BindView(R.id.openapsma_profile)
- TextView profileView;
- @BindView(R.id.openapsma_mealdata)
- TextView mealDataView;
- @BindView(R.id.openapsma_autosensdata)
- TextView autosensDataView;
- @BindView(R.id.openapsma_result)
- TextView resultView;
- @BindView(R.id.openapsma_scriptdebugdata)
- TextView scriptdebugView;
- @BindView(R.id.openapsma_request)
- TextView requestView;
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- View view = inflater.inflate(R.layout.openapsama_fragment, container, false);
-
- unbinder = ButterKnife.bind(this, view);
- return view;
- }
-
- @OnClick(R.id.openapsma_run)
- public void onRunClick() {
- OpenAPSSMBPlugin.getPlugin().invoke("OpenAPSSMB button", false);
- }
-
- @Subscribe
- public void onStatusEvent(final EventOpenAPSUpdateGui ev) {
- updateGUI();
- }
-
- @Subscribe
- public void onStatusEvent(final EventOpenAPSUpdateResultGui ev) {
- updateResultGUI(ev.text);
- }
-
- @Override
- protected void updateGUI() {
- Activity activity = getActivity();
- if (activity != null)
- activity.runOnUiThread(() -> {
- 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 != 0) {
- lastRunView.setText(DateUtil.dateAndTimeFullString(plugin.lastAPSRun));
- }
- if (plugin.lastAutosensResult != null) {
- autosensDataView.setText(JSONFormatter.format(plugin.lastAutosensResult.json()).toString().trim());
- }
- }
- });
- }
-
- void updateResultGUI(final String text) {
- Activity activity = getActivity();
- if (activity != null)
- activity.runOnUiThread(() -> {
- 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/aps/openAPSSMB/OpenAPSSMBFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBFragment.kt
new file mode 100644
index 0000000000..06ad0d01fd
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBFragment.kt
@@ -0,0 +1,122 @@
+package info.nightscout.androidaps.plugins.aps.openAPSSMB
+
+import android.annotation.SuppressLint
+import android.os.Bundle
+import android.text.TextUtils
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import info.nightscout.androidaps.MainApp
+import info.nightscout.androidaps.R
+import info.nightscout.androidaps.logging.L
+import info.nightscout.androidaps.plugins.aps.openAPSMA.events.EventOpenAPSUpdateGui
+import info.nightscout.androidaps.plugins.aps.openAPSMA.events.EventOpenAPSUpdateResultGui
+import info.nightscout.androidaps.plugins.bus.RxBus
+import info.nightscout.androidaps.utils.DateUtil
+import info.nightscout.androidaps.utils.FabricPrivacy
+import info.nightscout.androidaps.utils.JSONFormatter
+import info.nightscout.androidaps.utils.plusAssign
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.disposables.CompositeDisposable
+import kotlinx.android.synthetic.main.openapsama_fragment.*
+import org.json.JSONArray
+import org.json.JSONException
+import org.slf4j.LoggerFactory
+
+class OpenAPSSMBFragment : Fragment() {
+ private val log = LoggerFactory.getLogger(L.APS)
+ private var disposable: CompositeDisposable = CompositeDisposable()
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?): View? {
+ return inflater.inflate(R.layout.openapsama_fragment, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ openapsma_run.setOnClickListener {
+ OpenAPSSMBPlugin.getPlugin().invoke("OpenAPSSMB button", false)
+ }
+ }
+
+ @Synchronized
+ override fun onResume() {
+ super.onResume()
+ disposable += RxBus
+ .toObservable(EventOpenAPSUpdateGui::class.java)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe({
+ updateGUI()
+ }, {
+ FabricPrivacy.logException(it)
+ })
+ disposable += RxBus
+ .toObservable(EventOpenAPSUpdateResultGui::class.java)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe({
+ updateResultGUI(it.text)
+ }, {
+ FabricPrivacy.logException(it)
+ })
+
+ updateGUI()
+ }
+
+ @Synchronized
+ override fun onPause() {
+ super.onPause()
+ disposable.clear()
+ }
+
+ @Synchronized
+ fun updateGUI() {
+ if (openapsma_result == null) return
+ val plugin = OpenAPSSMBPlugin.getPlugin()
+ plugin.lastAPSResult?.let { lastAPSResult ->
+ openapsma_result.text = JSONFormatter.format(lastAPSResult.json)
+ openapsma_request.text = lastAPSResult.toSpanned()
+ }
+ plugin.lastDetermineBasalAdapterSMBJS?.let { determineBasalAdapterSMBJS ->
+ openapsma_glucosestatus.text = JSONFormatter.format(determineBasalAdapterSMBJS.glucoseStatusParam)
+ openapsma_currenttemp.text = JSONFormatter.format(determineBasalAdapterSMBJS.currentTempParam)
+ try {
+ val iobArray = JSONArray(determineBasalAdapterSMBJS.iobDataParam)
+ openapsma_iobdata.text = TextUtils.concat(String.format(MainApp.gs(R.string.array_of_elements), iobArray.length()) + "\n", JSONFormatter.format(iobArray.getString(0)))
+ } catch (e: JSONException) {
+ log.error("Unhandled exception", e)
+ @SuppressLint("SetTextl18n")
+ openapsma_iobdata.text = "JSONException see log for details"
+ }
+
+ openapsma_profile.text = JSONFormatter.format(determineBasalAdapterSMBJS.profileParam)
+ openapsma_mealdata.text = JSONFormatter.format(determineBasalAdapterSMBJS.mealDataParam)
+ openapsma_scriptdebugdata.text = determineBasalAdapterSMBJS.scriptDebug
+ plugin.lastAPSResult?.inputConstraints?.let {
+ openapsma_constraints.text = it.reasons
+ }
+ }
+ if (plugin.lastAPSRun != 0L) {
+ openapsma_lastrun.text = DateUtil.dateAndTimeFullString(plugin.lastAPSRun)
+ }
+ plugin.lastAutosensResult?.let {
+ openapsma_autosensdata.text = JSONFormatter.format(it.json())
+ }
+ }
+
+ @Synchronized
+ private fun updateResultGUI(text: String) {
+ if (openapsma_result == null) return
+ openapsma_result.text = text
+ openapsma_glucosestatus.text = ""
+ openapsma_currenttemp.text = ""
+ openapsma_iobdata.text = ""
+ openapsma_profile.text = ""
+ openapsma_mealdata.text = ""
+ openapsma_autosensdata.text = ""
+ openapsma_scriptdebugdata.text = ""
+ openapsma_request.text = ""
+ openapsma_lastrun.text = ""
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.java
index 728e3145d6..d410eba291 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.java
@@ -6,7 +6,6 @@ import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
-import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus;
import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.MealData;
import info.nightscout.androidaps.data.Profile;
@@ -19,18 +18,21 @@ import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.logging.L;
-import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
-import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
-import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensData;
-import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult;
-import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.aps.loop.APSResult;
import info.nightscout.androidaps.plugins.aps.loop.ScriptReader;
-import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
import info.nightscout.androidaps.plugins.aps.openAPSMA.events.EventOpenAPSUpdateGui;
import info.nightscout.androidaps.plugins.aps.openAPSMA.events.EventOpenAPSUpdateResultGui;
+import info.nightscout.androidaps.plugins.bus.RxBus;
+import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
+import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
+import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
+import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensData;
+import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult;
+import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus;
+import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
import info.nightscout.androidaps.utils.DateUtil;
+import info.nightscout.androidaps.utils.FabricPrivacy;
import info.nightscout.androidaps.utils.HardLimits;
import info.nightscout.androidaps.utils.Profiler;
import info.nightscout.androidaps.utils.Round;
@@ -103,21 +105,21 @@ public class OpenAPSSMBPlugin extends PluginBase implements APSInterface, Constr
PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
if (profile == null) {
- MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.noprofileselected)));
+ RxBus.INSTANCE.send(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.noprofileselected)));
if (L.isEnabled(L.APS))
log.debug(MainApp.gs(R.string.noprofileselected));
return;
}
if (!isEnabled(PluginType.APS)) {
- MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.openapsma_disabled)));
+ RxBus.INSTANCE.send(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.openapsma_disabled)));
if (L.isEnabled(L.APS))
log.debug(MainApp.gs(R.string.openapsma_disabled));
return;
}
if (glucoseStatus == null) {
- MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.openapsma_noglucosedata)));
+ RxBus.INSTANCE.send(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.openapsma_noglucosedata)));
if (L.isEnabled(L.APS))
log.debug(MainApp.gs(R.string.openapsma_noglucosedata));
return;
@@ -139,11 +141,7 @@ public class OpenAPSSMBPlugin extends PluginBase implements APSInterface, Constr
long start = System.currentTimeMillis();
long startPart = System.currentTimeMillis();
- IobTotal[] iobArray = IobCobCalculatorPlugin.getPlugin().calculateIobArrayForSMB(profile);
- if (L.isEnabled(L.APS))
- Profiler.log(log, "calculateIobArrayInDia()", startPart);
- startPart = System.currentTimeMillis();
MealData mealData = TreatmentsPlugin.getPlugin().getMealData();
if (L.isEnabled(L.APS))
Profiler.log(log, "getMealData()", startPart);
@@ -181,7 +179,7 @@ public class OpenAPSSMBPlugin extends PluginBase implements APSInterface, Constr
if (MainApp.getConstraintChecker().isAutosensModeEnabled().value()) {
AutosensData autosensData = IobCobCalculatorPlugin.getPlugin().getLastAutosensDataSynchronized("OpenAPSPlugin");
if (autosensData == null) {
- MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.openaps_noasdata)));
+ RxBus.INSTANCE.send(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.openaps_noasdata)));
return;
}
lastAutosensResult = autosensData.autosensResult;
@@ -190,6 +188,11 @@ public class OpenAPSSMBPlugin extends PluginBase implements APSInterface, Constr
lastAutosensResult.sensResult = "autosens disabled";
}
+ IobTotal[] iobArray = IobCobCalculatorPlugin.getPlugin().calculateIobArrayForSMB(lastAutosensResult, SMBDefaults.exercise_mode, SMBDefaults.half_basal_exercise_target, isTempTarget);
+ if (L.isEnabled(L.APS))
+ Profiler.log(log, "calculateIobArrayInDia()", startPart);
+
+ startPart = System.currentTimeMillis();
Constraint smbAllowed = new Constraint<>(!tempBasalFallback);
MainApp.getConstraintChecker().isSMBModeEnabled(smbAllowed);
inputConstraints.copyReasons(smbAllowed);
@@ -217,7 +220,7 @@ public class OpenAPSSMBPlugin extends PluginBase implements APSInterface, Constr
advancedFiltering.value()
);
} catch (JSONException e) {
- log.error(e.getMessage());
+ FabricPrivacy.logException(e);
return;
}
@@ -226,25 +229,33 @@ public class OpenAPSSMBPlugin extends PluginBase implements APSInterface, Constr
DetermineBasalResultSMB determineBasalResultSMB = determineBasalAdapterSMBJS.invoke();
if (L.isEnabled(L.APS))
Profiler.log(log, "SMB calculation", start);
- // TODO still needed with oref1?
- // Fix bug determine basal
- if (determineBasalResultSMB.rate == 0d && determineBasalResultSMB.duration == 0 && !TreatmentsPlugin.getPlugin().isTempBasalInProgress())
- determineBasalResultSMB.tempBasalRequested = false;
+ if (determineBasalResultSMB == null) {
+ if (L.isEnabled(L.APS))
+ log.error("SMB calculation returned null");
+ lastDetermineBasalAdapterSMBJS = null;
+ lastAPSResult = null;
+ lastAPSRun = 0;
+ } else {
+ // TODO still needed with oref1?
+ // Fix bug determine basal
+ if (determineBasalResultSMB.rate == 0d && determineBasalResultSMB.duration == 0 && !TreatmentsPlugin.getPlugin().isTempBasalInProgress())
+ determineBasalResultSMB.tempBasalRequested = false;
- determineBasalResultSMB.iob = iobArray[0];
+ determineBasalResultSMB.iob = iobArray[0];
- try {
- determineBasalResultSMB.json.put("timestamp", DateUtil.toISOString(now));
- } catch (JSONException e) {
- log.error("Unhandled exception", e);
+ try {
+ determineBasalResultSMB.json.put("timestamp", DateUtil.toISOString(now));
+ } catch (JSONException e) {
+ log.error("Unhandled exception", e);
+ }
+
+ determineBasalResultSMB.inputConstraints = inputConstraints;
+
+ lastDetermineBasalAdapterSMBJS = determineBasalAdapterSMBJS;
+ lastAPSResult = determineBasalResultSMB;
+ lastAPSRun = now;
}
-
- determineBasalResultSMB.inputConstraints = inputConstraints;
-
- lastDetermineBasalAdapterSMBJS = determineBasalAdapterSMBJS;
- lastAPSResult = determineBasalResultSMB;
- lastAPSRun = now;
- MainApp.bus().post(new EventOpenAPSUpdateGui());
+ RxBus.INSTANCE.send(new EventOpenAPSUpdateGui());
//deviceStatus.suggested = determineBasalResultAMA.json;
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/bus/RxBus.kt b/app/src/main/java/info/nightscout/androidaps/plugins/bus/RxBus.kt
new file mode 100644
index 0000000000..1774df1471
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/bus/RxBus.kt
@@ -0,0 +1,23 @@
+package info.nightscout.androidaps.plugins.bus
+
+import info.nightscout.androidaps.events.Event
+import io.reactivex.Observable
+import io.reactivex.schedulers.Schedulers
+import io.reactivex.subjects.PublishSubject
+
+// Use object so we have a singleton instance
+object RxBus {
+
+ private val publisher = PublishSubject.create()
+
+ fun send(event: Event) {
+ publisher.onNext(event)
+ }
+
+ // Listen should return an Observable and not the publisher
+ // Using ofType we filter only events that match that class type
+ fun toObservable(eventType: Class): Observable =
+ publisher
+ .subscribeOn(Schedulers.io())
+ .ofType(eventType)
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/common/ManufacturerType.java b/app/src/main/java/info/nightscout/androidaps/plugins/common/ManufacturerType.java
new file mode 100644
index 0000000000..0f61dd3320
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/common/ManufacturerType.java
@@ -0,0 +1,27 @@
+package info.nightscout.androidaps.plugins.common;
+
+public enum ManufacturerType {
+
+ AndroidAPS("AndroidAPS"),
+ Medtronic("Medtronic"),
+ Sooil("SOOIL"),
+
+ Tandem("Tandem"),
+ Insulet("Insulet"),
+ Animas("Animas"), Cellnovo("Cellnovo"), Roche("Roche");
+
+
+
+ private String description;
+
+ ManufacturerType(String description) {
+
+ this.description = description;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/common/SubscriberFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/common/SubscriberFragment.java
deleted file mode 100644
index 3ac877b42d..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/common/SubscriberFragment.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package info.nightscout.androidaps.plugins.common;
-
-import android.support.v4.app.Fragment;
-
-import butterknife.Unbinder;
-import info.nightscout.androidaps.MainApp;
-
-abstract public class SubscriberFragment extends Fragment {
- protected Unbinder unbinder;
-
- @Override
- public void onPause() {
- super.onPause();
- MainApp.bus().unregister(this);
- }
-
- @Override
- public void onResume() {
- super.onResume();
- MainApp.bus().register(this);
- updateGUI();
- }
-
- @Override public synchronized void onDestroyView() {
- super.onDestroyView();
- if (unbinder != null)
- unbinder.unbind();
- }
-
-
- protected abstract void updateGUI();
-}
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
deleted file mode 100644
index 47b5d49357..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ConfigBuilderFragment.java
+++ /dev/null
@@ -1,283 +0,0 @@
-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;
-import android.widget.Button;
-import android.widget.CheckBox;
-import android.widget.ImageButton;
-import android.widget.LinearLayout;
-import android.widget.RadioButton;
-import android.widget.ScrollView;
-import android.widget.TextView;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import butterknife.BindView;
-import butterknife.ButterKnife;
-import butterknife.OnClick;
-import butterknife.Unbinder;
-import info.nightscout.androidaps.MainApp;
-import info.nightscout.androidaps.R;
-import info.nightscout.androidaps.activities.PreferencesActivity;
-import info.nightscout.androidaps.events.EventConfigBuilderChange;
-import info.nightscout.androidaps.events.EventRefreshGui;
-import info.nightscout.androidaps.interfaces.APSInterface;
-import info.nightscout.androidaps.interfaces.BgSourceInterface;
-import info.nightscout.androidaps.interfaces.ConstraintsInterface;
-import info.nightscout.androidaps.interfaces.InsulinInterface;
-import info.nightscout.androidaps.interfaces.PluginBase;
-import info.nightscout.androidaps.interfaces.PluginType;
-import info.nightscout.androidaps.interfaces.ProfileInterface;
-import info.nightscout.androidaps.interfaces.PumpInterface;
-import info.nightscout.androidaps.interfaces.SensitivityInterface;
-import info.nightscout.androidaps.plugins.common.SubscriberFragment;
-import info.nightscout.androidaps.plugins.insulin.InsulinOrefRapidActingPlugin;
-import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin;
-import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin;
-import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref0Plugin;
-import info.nightscout.androidaps.utils.FabricPrivacy;
-import info.nightscout.androidaps.utils.PasswordProtection;
-
-
-public class ConfigBuilderFragment extends SubscriberFragment {
-
- private List pluginViewHolders = new ArrayList<>();
-
- @BindView(R.id.categories)
- LinearLayout categories;
-
- @BindView(R.id.main_layout)
- ScrollView mainLayout;
- @BindView(R.id.unlock)
- Button unlock;
-
- @Override
- public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- try {
- View view = inflater.inflate(R.layout.configbuilder_fragment, container, false);
- unbinder = ButterKnife.bind(this, view);
-
- if (PasswordProtection.isLocked("settings_password"))
- mainLayout.setVisibility(View.GONE);
- else unlock.setVisibility(View.GONE);
-
- createViews();
-
- return view;
- } catch (Exception e) {
- FabricPrivacy.logException(e);
- }
-
- return null;
- }
-
- @OnClick(R.id.unlock)
- void onClickUnlock() {
- PasswordProtection.QueryPassword(getContext(), R.string.settings_password, "settings_password", () -> {
- mainLayout.setVisibility(View.VISIBLE);
- unlock.setVisibility(View.GONE);
- }, null);
- }
-
- @Override
- public void onDestroyView() {
- super.onDestroyView();
- for (PluginViewHolder pluginViewHolder : pluginViewHolders) pluginViewHolder.unbind();
- pluginViewHolders.clear();
- }
-
- @Override
- protected void updateGUI() {
- for (PluginViewHolder pluginViewHolder : pluginViewHolders) pluginViewHolder.update();
- }
-
- private void createViews() {
- 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(@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) {
- PluginViewHolder pluginViewHolder = new PluginViewHolder(pluginType, plugin);
- pluginContainer.addView(pluginViewHolder.getBaseView());
- pluginViewHolders.add(pluginViewHolder);
- }
- categories.addView(parent);
- }
-
- private boolean areMultipleSelectionsAllowed(PluginType type) {
- return type == PluginType.GENERAL || type == PluginType.CONSTRAINTS ||type == PluginType.LOOP;
- }
-
- public static void processOnEnabledCategoryChanged(PluginBase changedPlugin, PluginType type) {
- ArrayList pluginsInCategory = null;
- switch (type) {
- // Multiple selection allowed
- case GENERAL:
- case CONSTRAINTS:
- case LOOP:
- break;
- // Single selection allowed
- case INSULIN:
- pluginsInCategory = MainApp.getSpecificPluginsListByInterface(InsulinInterface.class);
- break;
- case SENSITIVITY:
- pluginsInCategory = MainApp.getSpecificPluginsListByInterface(SensitivityInterface.class);
- break;
- case APS:
- pluginsInCategory = MainApp.getSpecificPluginsListByInterface(APSInterface.class);
- break;
- case PROFILE:
- pluginsInCategory = MainApp.getSpecificPluginsListByInterface(ProfileInterface.class);
- break;
- case BGSOURCE:
- pluginsInCategory = MainApp.getSpecificPluginsListByInterface(BgSourceInterface.class);
- break;
- case TREATMENT:
- case PUMP:
- pluginsInCategory = MainApp.getSpecificPluginsListByInterface(PumpInterface.class);
- break;
- }
- if (pluginsInCategory != null) {
- boolean newSelection = changedPlugin.isEnabled(type);
- if (newSelection) { // new plugin selected -> disable others
- for (PluginBase p : pluginsInCategory) {
- if (p.getName().equals(changedPlugin.getName())) {
- // this is new selected
- } else {
- p.setPluginEnabled(type, false);
- p.setFragmentVisible(type, false);
- }
- }
- } else { // enable first plugin in list
- if (type == PluginType.PUMP)
- VirtualPumpPlugin.getPlugin().setPluginEnabled(type, true);
- else if (type == PluginType.INSULIN)
- InsulinOrefRapidActingPlugin.getPlugin().setPluginEnabled(type, true);
- else if (type == PluginType.SENSITIVITY)
- SensitivityOref0Plugin.getPlugin().setPluginEnabled(type, true);
- else if (type == PluginType.PROFILE)
- NSProfilePlugin.getPlugin().setPluginEnabled(type, true);
- else
- pluginsInCategory.get(0).setPluginEnabled(type, true);
- }
- }
- }
-
- public class PluginViewHolder {
-
- private Unbinder unbinder;
- private PluginType pluginType;
- private PluginBase plugin;
-
- LinearLayout baseView;
- @BindView(R.id.plugin_enabled_exclusive)
- RadioButton enabledExclusive;
- @BindView(R.id.plugin_enabled_inclusive)
- CheckBox enabledInclusive;
- @BindView(R.id.plugin_name)
- TextView pluginName;
- @BindView(R.id.plugin_description)
- TextView pluginDescription;
- @BindView(R.id.plugin_preferences)
- ImageButton pluginPreferences;
- @BindView(R.id.plugin_visibility)
- CheckBox pluginVisibility;
-
- 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);
- update();
- }
-
- public LinearLayout getBaseView() {
- return baseView;
- }
-
- public void update() {
- 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());
- if (plugin.getDescription() == null) pluginDescription.setVisibility(View.GONE);
- else {
- pluginDescription.setVisibility(View.VISIBLE);
- pluginDescription.setText(plugin.getDescription());
- }
- 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(pluginType));
- pluginVisibility.setChecked(plugin.isFragmentVisible());
- }
-
- @OnClick(R.id.plugin_visibility)
- void onVisibilityChanged() {
- plugin.setFragmentVisible(pluginType, pluginVisibility.isChecked());
- ConfigBuilderPlugin.getPlugin().storeSettings("CheckedCheckboxVisible");
- MainApp.bus().post(new EventRefreshGui());
- ConfigBuilderPlugin.getPlugin().logPluginStatus();
- }
-
- @OnClick({R.id.plugin_enabled_exclusive, R.id.plugin_enabled_inclusive})
- void onEnabledChanged() {
- plugin.switchAllowed(new PluginSwitcher(), getActivity());
- }
-
- @OnClick(R.id.plugin_preferences)
- void onPluginPreferencesClicked() {
- PasswordProtection.QueryPassword(getContext(), R.string.settings_password, "settings_password", () -> {
- Intent i = new Intent(getContext(), PreferencesActivity.class);
- i.putExtra("id", plugin.getPreferencesId());
- startActivity(i);
- }, null);
- }
-
- public void unbind() {
- 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();
- }
-
- public void cancel(){
- updateGUI();
- }
- }
- }
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ConfigBuilderFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ConfigBuilderFragment.kt
new file mode 100644
index 0000000000..059bec1444
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ConfigBuilderFragment.kt
@@ -0,0 +1,98 @@
+package info.nightscout.androidaps.plugins.configBuilder
+
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.LinearLayout
+import android.widget.TextView
+import androidx.annotation.StringRes
+import androidx.fragment.app.Fragment
+import info.nightscout.androidaps.MainApp
+import info.nightscout.androidaps.R
+import info.nightscout.androidaps.interfaces.*
+import info.nightscout.androidaps.plugins.bus.RxBus
+import info.nightscout.androidaps.utils.FabricPrivacy
+import info.nightscout.androidaps.utils.PasswordProtection
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.disposables.CompositeDisposable
+import kotlinx.android.synthetic.main.configbuilder_fragment.*
+import java.util.*
+
+class ConfigBuilderFragment : Fragment() {
+
+ private var disposable: CompositeDisposable = CompositeDisposable()
+ private val pluginViewHolders = ArrayList()
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?): View? {
+ return inflater.inflate(R.layout.configbuilder_fragment, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ if (PasswordProtection.isLocked("settings_password"))
+ configbuilder_main_layout.visibility = View.GONE
+ else
+ unlock.visibility = View.GONE
+
+ unlock.setOnClickListener {
+ PasswordProtection.QueryPassword(context, R.string.settings_password, "settings_password", {
+ configbuilder_main_layout.visibility = View.VISIBLE
+ unlock.visibility = View.GONE
+ }, null)
+ }
+ }
+
+ @Synchronized
+ override fun onResume() {
+ super.onResume()
+ disposable.add(RxBus
+ .toObservable(EventConfigBuilderUpdateGui::class.java)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe({
+ for (pluginViewHolder in pluginViewHolders) pluginViewHolder.update()
+ }, {
+ FabricPrivacy.logException(it)
+ }))
+ updateGUI()
+ }
+
+ @Synchronized
+ override fun onPause() {
+ super.onPause()
+ disposable.clear()
+ }
+
+ @Synchronized
+ private fun updateGUI() {
+ configbuilder_categories.removeAllViews()
+ createViewsForPlugins(R.string.configbuilder_profile, R.string.configbuilder_profile_description, PluginType.PROFILE, MainApp.getSpecificPluginsVisibleInListByInterface(ProfileInterface::class.java, PluginType.PROFILE))
+ createViewsForPlugins(R.string.configbuilder_insulin, R.string.configbuilder_insulin_description, PluginType.INSULIN, MainApp.getSpecificPluginsVisibleInListByInterface(InsulinInterface::class.java, PluginType.INSULIN))
+ createViewsForPlugins(R.string.configbuilder_bgsource, R.string.configbuilder_bgsource_description, PluginType.BGSOURCE, MainApp.getSpecificPluginsVisibleInListByInterface(BgSourceInterface::class.java, 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.java, 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.java, 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 fun createViewsForPlugins(@StringRes title: Int, @StringRes description: Int, pluginType: PluginType, plugins: List) {
+ if (plugins.size == 0) return
+ val parent = layoutInflater.inflate(R.layout.configbuilder_single_category, null) as LinearLayout
+ (parent.findViewById(R.id.category_title) as TextView).text = MainApp.gs(title)
+ (parent.findViewById(R.id.category_description) as TextView).text = MainApp.gs(description)
+ val pluginContainer = parent.findViewById(R.id.category_plugins)
+ for (plugin in plugins) {
+ val pluginViewHolder = PluginViewHolder(this, pluginType, plugin)
+ pluginContainer.addView(pluginViewHolder.baseView)
+ pluginViewHolders.add(pluginViewHolder)
+ }
+ configbuilder_categories.addView(parent)
+ }
+
+}
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 3c3531da86..f43513fbf5 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
@@ -1,6 +1,6 @@
package info.nightscout.androidaps.plugins.configBuilder;
-import android.support.annotation.Nullable;
+import androidx.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -20,7 +20,9 @@ import info.nightscout.androidaps.interfaces.ProfileInterface;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.interfaces.SensitivityInterface;
import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.insulin.InsulinOrefRapidActingPlugin;
+import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin;
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin;
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref0Plugin;
import info.nightscout.androidaps.queue.CommandQueue;
@@ -57,7 +59,7 @@ public class ConfigBuilderPlugin extends PluginBase {
.fragmentClass(ConfigBuilderFragment.class.getName())
.showInList(true)
.alwaysEnabled(true)
- .alwayVisible(false)
+ .alwaysVisible(false)
.pluginName(R.string.configbuilder)
.shortName(R.string.configbuilder_shortname)
.description(R.string.description_config_builder)
@@ -66,14 +68,12 @@ public class ConfigBuilderPlugin extends PluginBase {
@Override
protected void onStart() {
- MainApp.bus().register(this);
super.onStart();
}
@Override
protected void onStop() {
super.onStop();
- MainApp.bus().unregister(this);
}
@@ -82,7 +82,7 @@ public class ConfigBuilderPlugin extends PluginBase {
upgradeSettings();
loadSettings();
setAlwaysEnabledPluginsEnabled();
- MainApp.bus().post(new EventAppInitialized());
+ RxBus.INSTANCE.send(new EventAppInitialized());
}
private void setAlwaysEnabledPluginsEnabled() {
@@ -102,7 +102,7 @@ public class ConfigBuilderPlugin extends PluginBase {
for (PluginBase p : pluginList) {
PluginType type = p.getType();
- if (p.pluginDescription.alwaysEnabled && p.pluginDescription.alwayVisible)
+ if (p.pluginDescription.alwaysEnabled && p.pluginDescription.alwaysVisible)
continue;
if (p.pluginDescription.alwaysEnabled && p.pluginDescription.neverVisible)
continue;
@@ -232,31 +232,37 @@ public class ConfigBuilderPlugin extends PluginBase {
return commandQueue;
}
+ @Nullable
public BgSourceInterface getActiveBgSource() {
return activeBgSource;
}
+ @Nullable
public ProfileInterface getActiveProfileInterface() {
return activeProfile;
}
+ @Nullable
public InsulinInterface getActiveInsulin() {
return activeInsulin;
}
+ @Nullable
public APSInterface getActiveAPS() {
return activeAPS;
}
+ @Nullable
public PumpInterface getActivePump() {
return activePump;
}
+ @Nullable
public SensitivityInterface getActiveSensitivity() {
return activeSensitivity;
}
- void logPluginStatus() {
+ public void logPluginStatus() {
if (L.isEnabled(L.CONFIGBUILDER))
for (PluginBase p : pluginList) {
log.debug(p.getName() + ":" +
@@ -399,4 +405,58 @@ public class ConfigBuilderPlugin extends PluginBase {
return found;
}
+ public void processOnEnabledCategoryChanged(PluginBase changedPlugin, PluginType type) {
+ ArrayList pluginsInCategory = null;
+ switch (type) {
+ // Multiple selection allowed
+ case GENERAL:
+ case CONSTRAINTS:
+ case LOOP:
+ break;
+ // Single selection allowed
+ case INSULIN:
+ pluginsInCategory = MainApp.getSpecificPluginsListByInterface(InsulinInterface.class);
+ break;
+ case SENSITIVITY:
+ pluginsInCategory = MainApp.getSpecificPluginsListByInterface(SensitivityInterface.class);
+ break;
+ case APS:
+ pluginsInCategory = MainApp.getSpecificPluginsListByInterface(APSInterface.class);
+ break;
+ case PROFILE:
+ pluginsInCategory = MainApp.getSpecificPluginsListByInterface(ProfileInterface.class);
+ break;
+ case BGSOURCE:
+ pluginsInCategory = MainApp.getSpecificPluginsListByInterface(BgSourceInterface.class);
+ break;
+ case TREATMENT:
+ case PUMP:
+ pluginsInCategory = MainApp.getSpecificPluginsListByInterface(PumpInterface.class);
+ break;
+ }
+ if (pluginsInCategory != null) {
+ boolean newSelection = changedPlugin.isEnabled(type);
+ if (newSelection) { // new plugin selected -> disable others
+ for (PluginBase p : pluginsInCategory) {
+ if (p.getName().equals(changedPlugin.getName())) {
+ // this is new selected
+ } else {
+ p.setPluginEnabled(type, false);
+ p.setFragmentVisible(type, false);
+ }
+ }
+ } else { // enable first plugin in list
+ if (type == PluginType.PUMP)
+ VirtualPumpPlugin.getPlugin().setPluginEnabled(type, true);
+ else if (type == PluginType.INSULIN)
+ InsulinOrefRapidActingPlugin.getPlugin().setPluginEnabled(type, true);
+ else if (type == PluginType.SENSITIVITY)
+ SensitivityOref0Plugin.getPlugin().setPluginEnabled(type, true);
+ else if (type == PluginType.PROFILE)
+ NSProfilePlugin.getPlugin().setPluginEnabled(type, true);
+ else
+ pluginsInCategory.get(0).setPluginEnabled(type, true);
+ }
+ }
+ }
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/DetailedBolusInfoStorage.java b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/DetailedBolusInfoStorage.java
deleted file mode 100644
index b19948fc5e..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/DetailedBolusInfoStorage.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package info.nightscout.androidaps.plugins.configBuilder;
-
-import android.support.annotation.Nullable;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import info.nightscout.androidaps.data.DetailedBolusInfo;
-import info.nightscout.androidaps.logging.L;
-
-/**
- * Created by mike on 08.08.2017.
- */
-
-public class DetailedBolusInfoStorage {
- private static Logger log = LoggerFactory.getLogger(L.PUMP);
- private static List store = new ArrayList<>();
-
- public static synchronized void add(DetailedBolusInfo detailedBolusInfo) {
- log.debug("Stored bolus info: " + detailedBolusInfo);
- store.add(detailedBolusInfo);
- }
-
- @Nullable
- public static synchronized DetailedBolusInfo findDetailedBolusInfo(long bolustime) {
- DetailedBolusInfo found = null;
- for (int i = 0; i < store.size(); i++) {
- long infoTime = store.get(i).date;
- if (L.isEnabled(L.PUMP))
- log.debug("Existing bolus info: " + store.get(i));
- if (bolustime > infoTime - 60 * 1000 && bolustime < infoTime + 60 * 1000) {
- found = store.get(i);
- if (L.isEnabled(L.PUMP))
- log.debug("Using & removing bolus info: " + store.get(i));
- store.remove(i);
- break;
- }
- }
- return found;
- }
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/EventConfigBuilderUpdateGui.kt b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/EventConfigBuilderUpdateGui.kt
new file mode 100644
index 0000000000..e57fd79983
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/EventConfigBuilderUpdateGui.kt
@@ -0,0 +1,6 @@
+package info.nightscout.androidaps.plugins.configBuilder
+
+import info.nightscout.androidaps.events.EventUpdateGui
+
+class EventConfigBuilderUpdateGui : EventUpdateGui() {
+}
\ No newline at end of file
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/PluginViewHolder.kt b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/PluginViewHolder.kt
new file mode 100644
index 0000000000..86e0f39437
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/PluginViewHolder.kt
@@ -0,0 +1,82 @@
+package info.nightscout.androidaps.plugins.configBuilder
+
+import android.content.Intent
+import android.view.View
+import android.widget.*
+import info.nightscout.androidaps.R
+import info.nightscout.androidaps.activities.PreferencesActivity
+import info.nightscout.androidaps.events.EventRebuildTabs
+import info.nightscout.androidaps.interfaces.PluginBase
+import info.nightscout.androidaps.interfaces.PluginType
+import info.nightscout.androidaps.plugins.bus.RxBus
+import info.nightscout.androidaps.utils.PasswordProtection
+
+class PluginViewHolder internal constructor(private val fragment: ConfigBuilderFragment,
+ private val pluginType: PluginType,
+ private val plugin: PluginBase) {
+
+ val baseView: LinearLayout = fragment.layoutInflater.inflate(R.layout.configbuilder_single_plugin, null) as LinearLayout
+ private val enabledExclusive: RadioButton
+ private val enabledInclusive: CheckBox
+ private val pluginName: TextView
+ private val pluginDescription: TextView
+ private val pluginPreferences: ImageButton
+ private val pluginVisibility: CheckBox
+
+ init {
+ enabledExclusive = baseView.findViewById(R.id.plugin_enabled_exclusive)
+ enabledInclusive = baseView.findViewById(R.id.plugin_enabled_inclusive)
+ pluginName = baseView.findViewById(R.id.plugin_name)
+ pluginDescription = baseView.findViewById(R.id.plugin_description)
+ pluginPreferences = baseView.findViewById(R.id.plugin_preferences)
+ pluginVisibility = baseView.findViewById(R.id.plugin_visibility)
+
+ pluginVisibility.setOnClickListener {
+ plugin.setFragmentVisible(pluginType, pluginVisibility.isChecked)
+ ConfigBuilderPlugin.getPlugin().storeSettings("CheckedCheckboxVisible")
+ RxBus.send(EventRebuildTabs())
+ ConfigBuilderPlugin.getPlugin().logPluginStatus()
+ }
+
+ enabledExclusive.setOnClickListener {
+ plugin.switchAllowed(if (enabledExclusive.visibility == View.VISIBLE) enabledExclusive.isChecked else enabledInclusive.isChecked, fragment.activity, pluginType)
+ }
+ enabledInclusive.setOnClickListener {
+ plugin.switchAllowed(if (enabledExclusive.visibility == View.VISIBLE) enabledExclusive.isChecked else enabledInclusive.isChecked, fragment.activity, pluginType)
+ }
+
+ pluginPreferences.setOnClickListener {
+ PasswordProtection.QueryPassword(fragment.context, R.string.settings_password, "settings_password", {
+ val i = Intent(fragment.context, PreferencesActivity::class.java)
+ i.putExtra("id", plugin.preferencesId)
+ fragment.startActivity(i)
+ }, null)
+ }
+ update()
+ }
+
+ fun update() {
+ enabledExclusive.visibility = if (areMultipleSelectionsAllowed(pluginType)) View.GONE else View.VISIBLE
+ enabledInclusive.visibility = if (areMultipleSelectionsAllowed(pluginType)) View.VISIBLE else View.GONE
+ enabledExclusive.isChecked = plugin.isEnabled(pluginType)
+ enabledInclusive.isChecked = plugin.isEnabled(pluginType)
+ enabledInclusive.isEnabled = !plugin.pluginDescription.alwaysEnabled
+ enabledExclusive.isEnabled = !plugin.pluginDescription.alwaysEnabled
+ pluginName.text = plugin.name
+ if (plugin.description == null)
+ pluginDescription.visibility = View.GONE
+ else {
+ pluginDescription.visibility = View.VISIBLE
+ pluginDescription.text = plugin.description
+ }
+ pluginPreferences.visibility = if (plugin.preferencesId == -1 || !plugin.isEnabled(pluginType)) View.INVISIBLE else View.VISIBLE
+ pluginVisibility.visibility = if (plugin.hasFragment()) View.VISIBLE else View.INVISIBLE
+ pluginVisibility.isEnabled = !(plugin.pluginDescription.neverVisible || plugin.pluginDescription.alwaysVisible) && plugin.isEnabled(pluginType)
+ pluginVisibility.isChecked = plugin.isFragmentVisible
+ }
+
+ private fun areMultipleSelectionsAllowed(type: PluginType): Boolean {
+ return type == PluginType.GENERAL || type == PluginType.CONSTRAINTS || type == PluginType.LOOP
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ProfileFunctions.java b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ProfileFunctions.java
index 0360ba4a68..025d8dac1e 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ProfileFunctions.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ProfileFunctions.java
@@ -2,10 +2,10 @@ package info.nightscout.androidaps.plugins.configBuilder;
import android.content.Intent;
import android.os.Bundle;
-import android.support.annotation.Nullable;
+
+import androidx.annotation.Nullable;
import com.google.firebase.analytics.FirebaseAnalytics;
-import com.squareup.otto.Subscribe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -23,13 +23,18 @@ import info.nightscout.androidaps.events.EventProfileNeedsUpdate;
import info.nightscout.androidaps.interfaces.ProfileInterface;
import info.nightscout.androidaps.interfaces.TreatmentsInterface;
import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.general.overview.dialogs.ErrorHelperActivity;
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
import info.nightscout.androidaps.queue.Callback;
import info.nightscout.androidaps.utils.FabricPrivacy;
+import info.nightscout.androidaps.utils.SP;
+import io.reactivex.disposables.CompositeDisposable;
+import io.reactivex.schedulers.Schedulers;
public class ProfileFunctions {
private static Logger log = LoggerFactory.getLogger(L.PROFILE);
+ private CompositeDisposable disposable = new CompositeDisposable();
private static ProfileFunctions profileFunctions = null;
@@ -43,29 +48,30 @@ public class ProfileFunctions {
ProfileFunctions.getInstance(); // register to bus at start
}
- ProfileFunctions() {
- MainApp.bus().register(this);
- }
-
- @Subscribe
- public void onProfileSwitch(EventProfileNeedsUpdate ignored) {
- if (L.isEnabled(L.PROFILE))
- log.debug("onProfileSwitch");
- ConfigBuilderPlugin.getPlugin().getCommandQueue().setProfile(getProfile(), new Callback() {
- @Override
- public void run() {
- if (!result.success) {
- Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
- i.putExtra("soundid", R.raw.boluserror);
- i.putExtra("status", result.comment);
- i.putExtra("title", MainApp.gs(R.string.failedupdatebasalprofile));
- i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- MainApp.instance().startActivity(i);
- }
- if (result.enacted)
- MainApp.bus().post(new EventNewBasalProfile());
- }
- });
+ private ProfileFunctions() {
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventProfileNeedsUpdate.class)
+ .observeOn(Schedulers.io())
+ .subscribe(event -> {
+ if (L.isEnabled(L.PROFILE))
+ log.debug("onProfileSwitch");
+ ConfigBuilderPlugin.getPlugin().getCommandQueue().setProfile(getProfile(), new Callback() {
+ @Override
+ public void run() {
+ if (!result.success) {
+ Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
+ i.putExtra("soundid", R.raw.boluserror);
+ i.putExtra("status", result.comment);
+ i.putExtra("title", MainApp.gs(R.string.failedupdatebasalprofile));
+ i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ MainApp.instance().startActivity(i);
+ }
+ if (result.enacted)
+ RxBus.INSTANCE.send(new EventNewBasalProfile());
+ }
+ });
+ }, FabricPrivacy::logException)
+ );
}
public String getProfileName() {
@@ -101,7 +107,8 @@ public class ProfileFunctions {
}
public boolean isProfileValid(String from) {
- return getProfile() != null && getProfile().isValid(from);
+ Profile profile = getProfile();
+ return profile != null && profile.isValid(from);
}
@Nullable
@@ -159,6 +166,8 @@ public class ProfileFunctions {
public static void doProfileSwitch(final ProfileStore profileStore, final String profileName, final int duration, final int percentage, final int timeshift) {
ProfileSwitch profileSwitch = prepareProfileSwitch(profileStore, profileName, duration, percentage, timeshift, System.currentTimeMillis());
TreatmentsPlugin.getPlugin().addToHistoryProfileSwitch(profileSwitch);
+ if (percentage == 90 && duration == 10)
+ SP.putBoolean(R.string.key_objectiveuseprofileswitch, true);
}
public static void doProfileSwitch(final int duration, final int percentage, final int timeshift) {
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/dstHelper/DstHelperPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/dstHelper/DstHelperPlugin.java
index ec3ef44881..e026d6589d 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/dstHelper/DstHelperPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/dstHelper/DstHelperPlugin.java
@@ -15,6 +15,7 @@ import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
+import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification;
@@ -89,6 +90,6 @@ public class DstHelperPlugin extends PluginBase implements ConstraintsInterface
private void warnUser(int id, String warningText) {
Notification notification = new Notification(id, warningText, Notification.LOW);
- MainApp.bus().post(new EventNewNotification(notification));
+ RxBus.INSTANCE.send(new EventNewNotification(notification));
}
}
\ No newline at end of file
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesFragment.java
deleted file mode 100644
index b943571089..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesFragment.java
+++ /dev/null
@@ -1,229 +0,0 @@
-package info.nightscout.androidaps.plugins.constraints.objectives;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.support.annotation.NonNull;
-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.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.CheckBox;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import java.util.Date;
-
-import info.nightscout.androidaps.MainApp;
-import info.nightscout.androidaps.R;
-import info.nightscout.androidaps.plugins.common.SubscriberFragment;
-import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective;
-import info.nightscout.androidaps.utils.FabricPrivacy;
-
-public class ObjectivesFragment extends SubscriberFragment {
- RecyclerView recyclerView;
- CheckBox enableFake;
- TextView reset;
- ObjectivesAdapter objectivesAdapter = new ObjectivesAdapter();
- Handler handler = new Handler(Looper.getMainLooper());
-
- private Runnable objectiveUpdater = new Runnable() {
- @Override
- public void run() {
- handler.postDelayed(this, 60 * 1000);
- updateGUI();
- }
- };
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- try {
- View view = inflater.inflate(R.layout.objectives_fragment, container, false);
-
- 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.getPlugin().saveProgress();
- recyclerView.getAdapter().notifyDataSetChanged();
- scrollToCurrentObjective();
- });
- scrollToCurrentObjective();
- startUpdateTimer();
- return view;
- } catch (Exception e) {
- FabricPrivacy.logException(e);
- }
-
- return null;
- }
-
- @Override
- public synchronized void onDestroyView() {
- super.onDestroyView();
- handler.removeCallbacks(objectiveUpdater);
- }
-
- private void startUpdateTimer() {
- handler.removeCallbacks(objectiveUpdater);
- for (Objective objective : ObjectivesPlugin.getPlugin().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.getPlugin().getObjectives().size(); i++) {
- Objective objective = ObjectivesPlugin.getPlugin().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.getPlugin().getObjectives().get(position);
- holder.title.setText(MainApp.gs(R.string.nth_objective, position + 1));
- holder.revert.setVisibility(View.INVISIBLE);
- 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.getPlugin().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);
- if(objective.isRevertable()) {
- holder.revert.setVisibility(View.VISIBLE);
- }
- 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();
- });
- holder.revert.setOnClickListener((view) -> {
- objective.setAccomplishedOn(null);
- objective.setStartedOn(null);
- if (position > 0) {
- Objective prevObj = ObjectivesPlugin.getPlugin().getObjectives().get(position - 1);
- prevObj.setAccomplishedOn(null);
- }
- notifyDataSetChanged();
- scrollToCurrentObjective();
- });
- }
-
-
-
- @Override
- public int getItemCount() {
- return ObjectivesPlugin.getPlugin().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 Button revert;
-
- 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);
- revert = itemView.findViewById(R.id.objective_back);
- }
- }
- }
-
- @Override
- public void updateGUI() {
- Activity activity = getActivity();
- if (activity != null)
- activity.runOnUiThread(() -> {
- objectivesAdapter.notifyDataSetChanged();
- });
- }
-
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesFragment.kt
new file mode 100644
index 0000000000..70242d3433
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesFragment.kt
@@ -0,0 +1,324 @@
+package info.nightscout.androidaps.plugins.constraints.objectives
+
+import android.graphics.Color
+import android.os.Bundle
+import android.os.Handler
+import android.os.Looper
+import android.view.Gravity
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Button
+import android.widget.EditText
+import android.widget.LinearLayout
+import android.widget.TextView
+import androidx.fragment.app.Fragment
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.LinearSmoothScroller
+import androidx.recyclerview.widget.RecyclerView
+import info.nightscout.androidaps.MainApp
+import info.nightscout.androidaps.R
+import info.nightscout.androidaps.logging.L
+import info.nightscout.androidaps.plugins.bus.RxBus
+import info.nightscout.androidaps.plugins.constraints.objectives.activities.ObjectivesExamDialog
+import info.nightscout.androidaps.plugins.constraints.objectives.events.EventObjectivesUpdateGui
+import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective.ExamTask
+import info.nightscout.androidaps.receivers.NetworkChangeReceiver
+import info.nightscout.androidaps.utils.*
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.disposables.CompositeDisposable
+import kotlinx.android.synthetic.main.objectives_fragment.*
+import org.slf4j.LoggerFactory
+
+class ObjectivesFragment : Fragment() {
+ private val log = LoggerFactory.getLogger(L.CONSTRAINTS)
+ private val objectivesAdapter = ObjectivesAdapter()
+ private val handler = Handler(Looper.getMainLooper())
+
+ private var disposable: CompositeDisposable = CompositeDisposable()
+
+ private val objectiveUpdater = object : Runnable {
+ override fun run() {
+ handler.postDelayed(this, (60 * 1000).toLong())
+ updateGUI()
+ }
+ }
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?): View? {
+ return inflater.inflate(R.layout.objectives_fragment, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ objectives_recyclerview.layoutManager = LinearLayoutManager(view.context)
+ objectives_recyclerview.adapter = objectivesAdapter
+ objectives_fake.setOnClickListener { updateGUI() }
+ objectives_reset.setOnClickListener {
+ ObjectivesPlugin.reset()
+ objectives_recyclerview.adapter?.notifyDataSetChanged()
+ scrollToCurrentObjective()
+ }
+ scrollToCurrentObjective()
+ startUpdateTimer()
+ }
+
+ @Synchronized
+ override fun onResume() {
+ super.onResume()
+ disposable.add(RxBus
+ .toObservable(EventObjectivesUpdateGui::class.java)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe({
+ objectives_recyclerview.adapter?.notifyDataSetChanged()
+ }, {
+ FabricPrivacy.logException(it)
+ })
+ )
+ }
+
+ @Synchronized
+ override fun onPause() {
+ super.onPause()
+ disposable.clear()
+ }
+
+ @Synchronized
+ override fun onDestroyView() {
+ super.onDestroyView()
+ handler.removeCallbacks(objectiveUpdater)
+ }
+
+ private fun startUpdateTimer() {
+ handler.removeCallbacks(objectiveUpdater)
+ for (objective in ObjectivesPlugin.objectives) {
+ if (objective.isStarted && !objective.isAccomplished) {
+ val timeTillNextMinute = (System.currentTimeMillis() - objective.startedOn) % (60 * 1000)
+ handler.postDelayed(objectiveUpdater, timeTillNextMinute)
+ break
+ }
+ }
+ }
+
+ private fun scrollToCurrentObjective() {
+ for (i in 0 until ObjectivesPlugin.objectives.size) {
+ val objective = ObjectivesPlugin.objectives[i]
+ if (!objective.isStarted || !objective.isAccomplished) {
+ val smoothScroller = object : LinearSmoothScroller(context!!) {
+ override fun getVerticalSnapPreference(): Int {
+ return SNAP_TO_START
+ }
+
+ override fun calculateTimeForScrolling(dx: Int): Int {
+ return super.calculateTimeForScrolling(dx) * 4
+ }
+ }
+ smoothScroller.targetPosition = i
+ objectives_recyclerview.layoutManager?.startSmoothScroll(smoothScroller)
+ break
+ }
+ }
+ }
+
+ private inner class ObjectivesAdapter : RecyclerView.Adapter() {
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ return ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.objectives_item, parent, false))
+ }
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ val objective = ObjectivesPlugin.objectives[position]
+ holder.title.text = MainApp.gs(R.string.nth_objective, position + 1)
+ holder.revert.visibility = View.GONE
+ if (objective.objective != 0) {
+ holder.objective.visibility = View.VISIBLE
+ holder.objective.text = MainApp.gs(objective.objective)
+ } else
+ holder.objective.visibility = View.GONE
+ if (objective.gate != 0) {
+ holder.gate.visibility = View.VISIBLE
+ holder.gate.text = MainApp.gs(objective.gate)
+ } else
+ holder.gate.visibility = View.GONE
+ if (!objective.isStarted) {
+ holder.gate.setTextColor(-0x1)
+ holder.verify.visibility = View.GONE
+ holder.progress.visibility = View.GONE
+ holder.accomplished.visibility = View.GONE
+ if (position == 0 || ObjectivesPlugin.objectives[position - 1].isAccomplished)
+ holder.start.visibility = View.VISIBLE
+ else
+ holder.start.visibility = View.GONE
+ } else if (objective.isAccomplished) {
+ holder.gate.setTextColor(-0xb350b0)
+ holder.verify.visibility = View.GONE
+ holder.progress.visibility = View.GONE
+ holder.start.visibility = View.GONE
+ holder.accomplished.visibility = View.VISIBLE
+ } else if (objective.isStarted) {
+ holder.gate.setTextColor(-0x1)
+ holder.verify.visibility = View.VISIBLE
+ holder.verify.isEnabled = objective.isCompleted || objectives_fake.isChecked
+ holder.start.visibility = View.GONE
+ holder.accomplished.visibility = View.GONE
+ if (objective.isRevertable) {
+ holder.revert.visibility = View.VISIBLE
+ }
+ holder.progress.visibility = View.VISIBLE
+ holder.progress.removeAllViews()
+ for (task in objective.tasks) {
+ if (task.shouldBeIgnored()) continue
+ // name
+ val name = TextView(holder.progress.context)
+ name.text = MainApp.gs(task.task) + ":"
+ name.setTextColor(-0x1)
+ holder.progress.addView(name, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
+ // hint
+ task.hints.forEach { h ->
+ if (!task.isCompleted)
+ holder.progress.addView(h.generate(context))
+ }
+ // state
+ val state = TextView(holder.progress.context)
+ state.setTextColor(-0x1)
+ val basicHTML = "%2\$s "
+ val formattedHTML = String.format(basicHTML, if (task.isCompleted) "#4CAF50" else "#FF9800", task.progress)
+ state.text = HtmlHelper.fromHtml(formattedHTML)
+ state.gravity = Gravity.END
+ holder.progress.addView(state, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
+ if (task is ExamTask) {
+ state.setOnClickListener {
+ val dialog = ObjectivesExamDialog()
+ val bundle = Bundle()
+ val taskPosition = objective.tasks.indexOf(task)
+ bundle.putInt("currentTask", taskPosition)
+ dialog.arguments = bundle
+ ObjectivesExamDialog.objective = objective
+ fragmentManager?.let { dialog.show(it, "ObjectivesFragment") }
+ }
+ }
+ // horizontal line
+ val separator = View(holder.progress.context)
+ separator.setBackgroundColor(Color.DKGRAY)
+ holder.progress.addView(separator, LinearLayout.LayoutParams.MATCH_PARENT, 2)
+ }
+ }
+ holder.accomplished.text = MainApp.gs(R.string.accomplished, DateUtil.dateAndTimeString(objective.accomplishedOn))
+ holder.accomplished.setTextColor(-0x3e3e3f)
+ holder.verify.setOnClickListener {
+ holder.verify.visibility = View.INVISIBLE
+ NetworkChangeReceiver.fetch()
+ if (objectives_fake.isChecked) {
+ objective.accomplishedOn = DateUtil.now()
+ scrollToCurrentObjective()
+ startUpdateTimer()
+ RxBus.send(EventObjectivesUpdateGui())
+ } else
+ SntpClient.ntpTime(object : SntpClient.Callback() {
+ override fun run() {
+ activity?.runOnUiThread {
+ holder.verify.visibility = View.VISIBLE
+ log.debug("NTP time: $time System time: ${DateUtil.now()}")
+ if (!networkConnected) {
+ ToastUtils.showToastInUiThread(context, R.string.notconnected)
+ } else if (success) {
+ if (objective.isCompleted(time)) {
+ objective.accomplishedOn = time
+ scrollToCurrentObjective()
+ startUpdateTimer()
+ RxBus.send(EventObjectivesUpdateGui())
+ } else {
+ ToastUtils.showToastInUiThread(context, R.string.requirementnotmet)
+ }
+ } else {
+ ToastUtils.showToastInUiThread(context, R.string.failedretrievetime)
+ }
+ }
+ }
+ }, NetworkChangeReceiver.isConnected())
+ }
+ holder.start.setOnClickListener {
+ holder.start.visibility = View.INVISIBLE
+ NetworkChangeReceiver.fetch()
+ if (objectives_fake.isChecked) {
+ objective.startedOn = DateUtil.now()
+ scrollToCurrentObjective()
+ startUpdateTimer()
+ RxBus.send(EventObjectivesUpdateGui())
+ } else
+ SntpClient.ntpTime(object : SntpClient.Callback() {
+ override fun run() {
+ activity?.runOnUiThread {
+ holder.start.visibility = View.VISIBLE
+ log.debug("NTP time: $time System time: ${DateUtil.now()}")
+ if (!networkConnected) {
+ ToastUtils.showToastInUiThread(context, R.string.notconnected)
+ } else if (success) {
+ objective.startedOn = time
+ scrollToCurrentObjective()
+ startUpdateTimer()
+ RxBus.send(EventObjectivesUpdateGui())
+ } else {
+ ToastUtils.showToastInUiThread(context, R.string.failedretrievetime)
+ }
+ }
+ }
+ }, NetworkChangeReceiver.isConnected())
+ }
+ holder.revert.setOnClickListener {
+ objective.accomplishedOn = 0
+ objective.startedOn = 0
+ if (position > 0) {
+ val prevObj = ObjectivesPlugin.objectives[position - 1]
+ prevObj.accomplishedOn = 0
+ }
+ scrollToCurrentObjective()
+ RxBus.send(EventObjectivesUpdateGui())
+ }
+ if (objective.hasSpecialInput && !objective.isAccomplished && objective.isStarted) {
+ // generate random request code if none exists
+ val request = SP.getString(R.string.key_objectives_request_code, String.format("%1$05d", (Math.random() * 99999).toInt()))
+ SP.putString(R.string.key_objectives_request_code, request)
+ holder.requestCode.text = MainApp.gs(R.string.requestcode, request)
+ holder.requestCode.visibility = View.VISIBLE
+ holder.enterButton.visibility = View.VISIBLE
+ holder.input.visibility = View.VISIBLE
+ holder.inputHint.visibility = View.VISIBLE
+ holder.enterButton.setOnClickListener {
+ val input = holder.input.text.toString()
+ objective.specialAction(activity, input)
+ RxBus.send(EventObjectivesUpdateGui())
+ }
+ } else {
+ holder.enterButton.visibility = View.GONE
+ holder.input.visibility = View.GONE
+ holder.inputHint.visibility = View.GONE
+ holder.requestCode.visibility = View.GONE
+ }
+ }
+
+
+ override fun getItemCount(): Int {
+ return ObjectivesPlugin.objectives.size
+ }
+
+ inner class ViewHolder internal constructor(itemView: View) : RecyclerView.ViewHolder(itemView) {
+ val title: TextView = itemView.findViewById(R.id.objective_title)
+ val objective: TextView = itemView.findViewById(R.id.objective_objective)
+ val gate: TextView = itemView.findViewById(R.id.objective_gate)
+ val accomplished: TextView = itemView.findViewById(R.id.objective_accomplished)
+ val progress: LinearLayout = itemView.findViewById(R.id.objective_progress)
+ val verify: Button = itemView.findViewById(R.id.objective_verify)
+ val start: Button = itemView.findViewById(R.id.objective_start)
+ val revert: Button = itemView.findViewById(R.id.objective_back)
+ val inputHint: TextView = itemView.findViewById(R.id.objective_inputhint)
+ val input: EditText = itemView.findViewById(R.id.objective_input)
+ val enterButton: Button = itemView.findViewById(R.id.objective_enterbutton)
+ val requestCode: TextView = itemView.findViewById(R.id.objective_requestcode)
+ }
+ }
+
+ fun updateGUI() {
+ activity?.runOnUiThread { objectivesAdapter.notifyDataSetChanged() }
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesPlugin.java
deleted file mode 100644
index 1d18cd14b4..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesPlugin.java
+++ /dev/null
@@ -1,164 +0,0 @@
-package info.nightscout.androidaps.plugins.constraints.objectives;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import info.nightscout.androidaps.Config;
-import info.nightscout.androidaps.MainApp;
-import info.nightscout.androidaps.R;
-import info.nightscout.androidaps.interfaces.Constraint;
-import info.nightscout.androidaps.interfaces.ConstraintsInterface;
-import info.nightscout.androidaps.interfaces.PluginBase;
-import info.nightscout.androidaps.interfaces.PluginDescription;
-import info.nightscout.androidaps.interfaces.PluginType;
-import info.nightscout.androidaps.interfaces.PumpInterface;
-import info.nightscout.androidaps.logging.L;
-import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
-import info.nightscout.androidaps.plugins.constraints.objectives.events.EventObjectivesSaved;
-import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective;
-import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective1;
-import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective2;
-import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective3;
-import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective4;
-import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective5;
-import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective6;
-import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective7;
-import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective8;
-import info.nightscout.androidaps.utils.SP;
-
-/**
- * Created by mike on 05.08.2016.
- */
-public class ObjectivesPlugin extends PluginBase implements ConstraintsInterface {
- private static Logger log = LoggerFactory.getLogger(L.CONSTRAINTS);
-
- private static ObjectivesPlugin objectivesPlugin;
-
- public List objectives = new ArrayList<>();
- public boolean bgIsAvailableInNS = false;
- public boolean pumpStatusIsAvailableInNS = false;
- public Integer manualEnacts = 0;
-
- public static ObjectivesPlugin getPlugin() {
- if (objectivesPlugin == null) {
- objectivesPlugin = new ObjectivesPlugin();
- }
- return objectivesPlugin;
- }
-
- private ObjectivesPlugin() {
- super(new PluginDescription()
- .mainType(PluginType.CONSTRAINTS)
- .fragmentClass(ObjectivesFragment.class.getName())
- .alwaysEnabled(!Config.NSCLIENT)
- .showInList(!Config.NSCLIENT)
- .pluginName(R.string.objectives)
- .shortName(R.string.objectives_shortname)
- .description(R.string.description_objectives)
- );
- setupObjectives();
- loadProgress();
- }
-
- @Override
- public boolean specialEnableCondition() {
- PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
- return pump == null || pump.getPumpDescription().isTempBasalCapable;
- }
-
- 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());
- }
-
- public void reset() {
- for (Objective objective : objectives) {
- objective.setStartedOn(null);
- objective.setAccomplishedOn(null);
- }
- bgIsAvailableInNS = false;
- pumpStatusIsAvailableInNS = false;
- manualEnacts = 0;
- saveProgress();
- }
-
- public void saveProgress() {
- SP.putBoolean("Objectives" + "bgIsAvailableInNS", bgIsAvailableInNS);
- SP.putBoolean("Objectives" + "pumpStatusIsAvailableInNS", pumpStatusIsAvailableInNS);
- SP.putString("Objectives" + "manualEnacts", Integer.toString(manualEnacts));
- if (L.isEnabled(L.CONSTRAINTS))
- log.debug("Objectives stored");
- MainApp.bus().post(new EventObjectivesSaved());
- }
-
- private void loadProgress() {
- bgIsAvailableInNS = SP.getBoolean("Objectives" + "bgIsAvailableInNS", false);
- pumpStatusIsAvailableInNS = SP.getBoolean("Objectives" + "pumpStatusIsAvailableInNS", false);
- try {
- manualEnacts = SP.getInt("Objectives" + "manualEnacts", 0);
- } catch (Exception e) {
- log.error("Unhandled exception", e);
- }
- if (L.isEnabled(L.CONSTRAINTS))
- log.debug("Objectives loaded");
- }
-
- public List getObjectives() {
- return objectives;
- }
-
- /**
- * Constraints interface
- **/
- @Override
- public Constraint isLoopInvocationAllowed(Constraint value) {
- if (!objectives.get(0).isStarted())
- value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 1), this);
- return value;
- }
-
- @Override
- public Constraint isClosedLoopAllowed(Constraint value) {
- if (!objectives.get(3).isStarted())
- value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 4), this);
- return value;
- }
-
- @Override
- public Constraint isAutosensModeEnabled(Constraint value) {
- if (!objectives.get(5).isStarted())
- value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 6), this);
- return value;
- }
-
- @Override
- public Constraint isAMAModeEnabled(Constraint value) {
- if (!objectives.get(6).isStarted())
- value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 7), this);
- return value;
- }
-
- @Override
- public Constraint isSMBModeEnabled(Constraint value) {
- if (!objectives.get(7).isStarted())
- value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 8), this);
- return value;
- }
-
- @Override
- public Constraint applyMaxIOBConstraints(Constraint maxIob) {
- 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/constraints/objectives/ObjectivesPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesPlugin.kt
new file mode 100644
index 0000000000..ca3e1d3126
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesPlugin.kt
@@ -0,0 +1,170 @@
+package info.nightscout.androidaps.plugins.constraints.objectives
+
+import android.app.Activity
+import com.google.common.base.Charsets
+import com.google.common.hash.Hashing
+import info.nightscout.androidaps.BuildConfig
+import info.nightscout.androidaps.Config
+import info.nightscout.androidaps.MainApp
+import info.nightscout.androidaps.R
+import info.nightscout.androidaps.interfaces.*
+import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
+import info.nightscout.androidaps.plugins.constraints.objectives.objectives.*
+import info.nightscout.androidaps.utils.DateUtil
+import info.nightscout.androidaps.utils.OKDialog
+import info.nightscout.androidaps.utils.SP
+import java.util.*
+
+/**
+ * Created by mike on 05.08.2016.
+ */
+object ObjectivesPlugin : PluginBase(PluginDescription()
+ .mainType(PluginType.CONSTRAINTS)
+ .fragmentClass(ObjectivesFragment::class.qualifiedName)
+ .alwaysEnabled(Config.APS)
+ .showInList(Config.APS)
+ .pluginName(R.string.objectives)
+ .shortName(R.string.objectives_shortname)
+ .description(R.string.description_objectives)), ConstraintsInterface {
+
+ var objectives: MutableList = ArrayList()
+
+ val FIRST_OBJECTIVE = 0
+ val USAGE_OBJECTIVE = 1
+ val EXAM_OBJECTIVE = 2
+ val OPENLOOP_OBJECTIVE = 3
+ val MAXBASAL_OBJECTIVE = 4
+ val MAXIOB_ZERO_CL_OBJECTIVE = 5
+ val MAXIOB_OBJECTIVE = 6
+ val AUTOSENS_OBJECTIVE = 7
+ val AMA_OBJECTIVE = 8
+ val SMB_OBJECTIVE = 9
+
+ init {
+ convertSP()
+ setupObjectives()
+ }
+
+ override fun specialEnableCondition(): Boolean {
+ val pump = ConfigBuilderPlugin.getPlugin().activePump
+ return pump == null || pump.pumpDescription.isTempBasalCapable
+ }
+
+ // convert 2.3 SP version
+ private fun convertSP() {
+ doConvertSP(0, "config")
+ doConvertSP(1, "openloop")
+ doConvertSP(2, "maxbasal")
+ doConvertSP(3, "maxiobzero")
+ doConvertSP(4, "maxiob")
+ doConvertSP(5, "autosens")
+ doConvertSP(6, "ama")
+ doConvertSP(7, "smb")
+ }
+
+ private fun doConvertSP(number: Int, name: String) {
+ if (!SP.contains("Objectives_" + name + "_started")) {
+ SP.putLong("Objectives_" + name + "_started", SP.getLong("Objectives" + number + "started", 0L))
+ SP.putLong("Objectives_" + name + "_accomplished", SP.getLong("Objectives" + number + "accomplished", 0L))
+ }
+ // TODO: we can remove Objectives1accomplished sometimes later
+ }
+
+ private fun setupObjectives() {
+ objectives.clear()
+ objectives.add(Objective0())
+ objectives.add(Objective1())
+ objectives.add(Objective2())
+ objectives.add(Objective3())
+ objectives.add(Objective4())
+ objectives.add(Objective5())
+ objectives.add(Objective6())
+ objectives.add(Objective7())
+ objectives.add(Objective8())
+ objectives.add(Objective9())
+ }
+
+ fun reset() {
+ for (objective in objectives) {
+ objective.startedOn = 0
+ objective.accomplishedOn = 0
+ }
+ SP.putBoolean(R.string.key_ObjectivesbgIsAvailableInNS, false)
+ SP.putBoolean(R.string.key_ObjectivespumpStatusIsAvailableInNS, false)
+ SP.putInt(R.string.key_ObjectivesmanualEnacts, 0)
+ SP.putBoolean(R.string.key_objectiveuseprofileswitch, false)
+ SP.putBoolean(R.string.key_objectiveusedisconnect, false)
+ SP.putBoolean(R.string.key_objectiveusereconnect, false)
+ SP.putBoolean(R.string.key_objectiveusetemptarget, false)
+ SP.putBoolean(R.string.key_objectiveuseactions, false)
+ SP.putBoolean(R.string.key_objectiveuseloop, false)
+ SP.putBoolean(R.string.key_objectiveusescale, false)
+ }
+
+ fun completeObjectives(activity: Activity, request: String) {
+ val requestCode = SP.getString(R.string.key_objectives_request_code, "")
+ var url = SP.getString(R.string.key_nsclientinternal_url, "").toLowerCase()
+ if (!url.endsWith("\"")) url = "$url/"
+ val hashNS = Hashing.sha1().hashString(url + BuildConfig.APPLICATION_ID + "/" + requestCode, Charsets.UTF_8).toString()
+ if (request.equals(hashNS.substring(0, 10), ignoreCase = true)) {
+ SP.putLong("Objectives_" + "openloop" + "_started", DateUtil.now())
+ SP.putLong("Objectives_" + "openloop" + "_accomplished", DateUtil.now())
+ SP.putLong("Objectives_" + "maxbasal" + "_started", DateUtil.now())
+ SP.putLong("Objectives_" + "maxbasal" + "_accomplished", DateUtil.now())
+ SP.putLong("Objectives_" + "maxiobzero" + "_started", DateUtil.now())
+ SP.putLong("Objectives_" + "maxiobzero" + "_accomplished", DateUtil.now())
+ SP.putLong("Objectives_" + "maxiob" + "_started", DateUtil.now())
+ SP.putLong("Objectives_" + "maxiob" + "_accomplished", DateUtil.now())
+ SP.putLong("Objectives_" + "autosens" + "_started", DateUtil.now())
+ SP.putLong("Objectives_" + "autosens" + "_accomplished", DateUtil.now())
+ SP.putLong("Objectives_" + "ama" + "_started", DateUtil.now())
+ SP.putLong("Objectives_" + "ama" + "_accomplished", DateUtil.now())
+ SP.putLong("Objectives_" + "smb" + "_started", DateUtil.now())
+ SP.putLong("Objectives_" + "smb" + "_accomplished", DateUtil.now())
+ setupObjectives()
+ OKDialog.show(activity, "", MainApp.gs(R.string.codeaccepted), null)
+ } else {
+ OKDialog.show(activity, "", MainApp.gs(R.string.codeinvalid), null)
+ }
+ }
+
+ /**
+ * Constraints interface
+ */
+ override fun isLoopInvocationAllowed(value: Constraint): Constraint {
+ if (!objectives[FIRST_OBJECTIVE].isStarted)
+ value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), FIRST_OBJECTIVE + 1), this)
+ return value
+ }
+
+ override fun isClosedLoopAllowed(value: Constraint): Constraint {
+ if (!objectives[MAXIOB_ZERO_CL_OBJECTIVE].isStarted)
+ value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), MAXIOB_ZERO_CL_OBJECTIVE + 1), this)
+ return value
+ }
+
+ override fun isAutosensModeEnabled(value: Constraint): Constraint {
+ if (!objectives[AUTOSENS_OBJECTIVE].isStarted)
+ value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), AUTOSENS_OBJECTIVE + 1), this)
+ return value
+ }
+
+ override fun isAMAModeEnabled(value: Constraint): Constraint {
+ if (!objectives[AMA_OBJECTIVE].isStarted)
+ value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), AMA_OBJECTIVE + 1), this)
+ return value
+ }
+
+ override fun isSMBModeEnabled(value: Constraint): Constraint {
+ if (!objectives[SMB_OBJECTIVE].isStarted)
+ value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), SMB_OBJECTIVE + 1), this)
+ return value
+ }
+
+ override fun applyMaxIOBConstraints(maxIob: Constraint): Constraint {
+ if (objectives[MAXIOB_ZERO_CL_OBJECTIVE].isStarted && !objectives[MAXIOB_ZERO_CL_OBJECTIVE].isAccomplished)
+ maxIob.set(0.0, String.format(MainApp.gs(R.string.objectivenotfinished), MAXIOB_ZERO_CL_OBJECTIVE + 1), this)
+ return maxIob
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/activities/ObjectivesExamDialog.kt b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/activities/ObjectivesExamDialog.kt
new file mode 100644
index 0000000000..1428652be5
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/activities/ObjectivesExamDialog.kt
@@ -0,0 +1,130 @@
+package info.nightscout.androidaps.plugins.constraints.objectives.activities
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.DialogFragment
+import info.nightscout.androidaps.MainApp
+import info.nightscout.androidaps.R
+import info.nightscout.androidaps.plugins.bus.RxBus
+import info.nightscout.androidaps.plugins.constraints.objectives.events.EventObjectivesUpdateGui
+import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective
+import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective.*
+import info.nightscout.androidaps.utils.DateUtil
+import info.nightscout.androidaps.utils.OKDialog
+import info.nightscout.androidaps.utils.T
+import info.nightscout.androidaps.utils.ToastUtils
+import kotlinx.android.synthetic.main.objectives_exam_fragment.*
+
+class ObjectivesExamDialog : DialogFragment() {
+ companion object {
+ var objective: Objective? = null
+ }
+
+ var currentTask = 0
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?): View? {
+ // load data from bundle
+ (savedInstanceState ?: arguments)?.let { bundle ->
+ currentTask = bundle.getInt("currentTask", 0)
+ }
+
+ return inflater.inflate(R.layout.objectives_exam_fragment, container, false)
+ }
+
+ override fun onStart() {
+ super.onStart()
+ dialog?.setCanceledOnTouchOutside(false)
+ dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ }
+
+ override fun onResume() {
+ super.onResume()
+ updateGui()
+ }
+
+ override fun onSaveInstanceState(bundle: Bundle) {
+ super.onSaveInstanceState(bundle)
+ bundle.putInt("currentTask", currentTask)
+ }
+
+ fun updateGui() {
+ objective?.let { objective ->
+ val task: ExamTask = objective.tasks[currentTask] as ExamTask
+ objectives_exam_name.setText(task.task)
+ objectives_exam_question.setText(task.question)
+ // Options
+ objectives_exam_options.removeAllViews()
+ task.options.forEach {
+ val cb = it.generate(context)
+ if (task.answered) {
+ cb.isEnabled = false
+ if (it.isCorrect)
+ cb.isChecked = true
+ }
+ objectives_exam_options.addView(cb)
+ }
+ // Hints
+ objectives_exam_hints.removeAllViews()
+ for (h in task.hints) {
+ objectives_exam_hints.addView(h.generate(context))
+ }
+ // Disabled to
+ objectives_exam_disabledto.text = MainApp.gs(R.string.answerdisabledto, DateUtil.timeString(task.disabledTo))
+ objectives_exam_disabledto.visibility = if (task.isEnabledAnswer) View.GONE else View.VISIBLE
+ // Buttons
+ objectives_exam_verify.isEnabled = !task.answered && task.isEnabledAnswer
+ objectives_exam_verify.setOnClickListener {
+ var result = true
+ for (o in task.options) {
+ val option: Option = o as Option;
+ result = result && option.evaluate()
+ }
+ task.setAnswered(result);
+ if (!result) {
+ task.disabledTo = DateUtil.now() + T.hours(1).msecs()
+ ToastUtils.showToastInUiThread(context, R.string.wronganswer)
+ } else task.disabledTo = 0
+ updateGui()
+ RxBus.send(EventObjectivesUpdateGui())
+ }
+ close.setOnClickListener { dismiss() }
+ objectives_exam_reset.setOnClickListener {
+ task.answered = false
+ //task.disabledTo = 0
+ updateGui()
+ RxBus.send(EventObjectivesUpdateGui())
+ }
+ objectives_back_button.isEnabled = currentTask != 0
+ objectives_back_button.setOnClickListener {
+ currentTask--
+ updateGui()
+ }
+ objectives_next_button.isEnabled = currentTask != objective.tasks.size - 1
+ objectives_next_button.setOnClickListener {
+ currentTask++
+ updateGui()
+ }
+
+ objectives_next_unanswered_button.isEnabled = !objective.isCompleted
+ objectives_next_unanswered_button.setOnClickListener {
+ for (i in (currentTask + 1)..(objective.tasks.size - 1)) {
+ if (!objective.tasks[i].isCompleted) {
+ currentTask = i
+ updateGui()
+ return@setOnClickListener
+ }
+ }
+ for (i in 0..currentTask) {
+ if (!objective.tasks[i].isCompleted) {
+ currentTask = i
+ updateGui()
+ return@setOnClickListener
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/events/EventObjectivesSaved.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/events/EventObjectivesSaved.java
deleted file mode 100644
index d4dbb0251d..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/events/EventObjectivesSaved.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package info.nightscout.androidaps.plugins.constraints.objectives.events;
-
-import info.nightscout.androidaps.events.Event;
-
-public class EventObjectivesSaved extends Event {
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/events/EventObjectivesUpdateGui.kt b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/events/EventObjectivesUpdateGui.kt
new file mode 100644
index 0000000000..fd59db7d9f
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/events/EventObjectivesUpdateGui.kt
@@ -0,0 +1,5 @@
+package info.nightscout.androidaps.plugins.constraints.objectives.events
+
+import info.nightscout.androidaps.events.EventUpdateGui
+
+class EventObjectivesUpdateGui : EventUpdateGui()
\ No newline at end of file
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective.java
index 83abe15688..c882a921f5 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective.java
@@ -1,35 +1,46 @@
package info.nightscout.androidaps.plugins.constraints.objectives.objectives;
-import android.support.annotation.StringRes;
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Color;
+import android.text.util.Linkify;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.TextView;
+
+import androidx.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.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.SP;
import info.nightscout.androidaps.utils.T;
public abstract class Objective {
- private int number;
+ private String spName;
@StringRes
private int objective;
@StringRes
private int gate;
- private Date startedOn;
- private Date accomplishedOn;
- private List tasks = new ArrayList<>();
+ private long startedOn;
+ private long accomplishedOn;
+ List tasks = new ArrayList<>();
+ public boolean hasSpecialInput = false;
- public Objective(int number, @StringRes int objective, @StringRes int gate) {
- this.number = number;
+ public Objective(String spName, @StringRes int objective, @StringRes int gate) {
+ this.spName = spName;
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;
+ startedOn = SP.getLong("Objectives_" + spName + "_started", 0L);
+ accomplishedOn = SP.getLong("Objectives_" + spName + "_accomplished", 0L);
+ if ((accomplishedOn - DateUtil.now()) > T.hours(3).msecs() || (startedOn - DateUtil.now()) > T.hours(3).msecs()) { // more than 3 hours in the future
+ startedOn = 0;
+ accomplishedOn = 0;
+ }
setupTasks(tasks);
for (Task task : tasks) task.objective = this;
}
@@ -42,19 +53,27 @@ public abstract class Objective {
return true;
}
+ public boolean isCompleted(long trueTime) {
+ for (Task task : tasks) {
+ if (!task.shouldBeIgnored() && !task.isCompleted(trueTime))
+ return false;
+ }
+ return true;
+ }
+
public boolean isRevertable() {
return false;
}
public boolean isAccomplished() {
- return accomplishedOn != null;
+ return accomplishedOn != 0 && accomplishedOn < DateUtil.now();
}
public boolean isStarted() {
- return startedOn != null;
+ return startedOn != 0;
}
- public Date getStartedOn() {
+ public long getStartedOn() {
return startedOn;
}
@@ -66,14 +85,18 @@ public abstract class Objective {
return gate;
}
- public void setStartedOn(Date startedOn) {
+ public void setStartedOn(long startedOn) {
this.startedOn = startedOn;
- SP.putLong("Objectives" + number + "started", startedOn == null ? 0 : startedOn.getTime());
+ SP.putLong("Objectives_" + spName + "_started", startedOn);
}
- public void setAccomplishedOn(Date accomplishedOn) {
+ public void setAccomplishedOn(long accomplishedOn) {
this.accomplishedOn = accomplishedOn;
- SP.putLong("Objectives" + number + "accomplished", accomplishedOn == null ? 0 : accomplishedOn.getTime());
+ SP.putLong("Objectives_" + spName + "_accomplished", accomplishedOn);
+ }
+
+ public long getAccomplishedOn() {
+ return accomplishedOn;
}
protected void setupTasks(List tasks) {
@@ -84,16 +107,19 @@ public abstract class Objective {
return tasks;
}
+ public void specialAction(Activity activity, String input) {}
+
public abstract class Task {
@StringRes
private int task;
private Objective objective;
+ ArrayList hints = new ArrayList<>();
public Task(@StringRes int task) {
this.task = task;
}
- public int getTask() {
+ public @StringRes int getTask() {
return task;
}
@@ -102,11 +128,21 @@ public abstract class Objective {
}
public abstract boolean isCompleted();
+ public boolean isCompleted(long trueTime) { return isCompleted(); };
public String getProgress() {
return MainApp.gs(isCompleted() ? R.string.completed_well_done : R.string.not_completed_yet);
}
+ Task hint(Hint hint) {
+ hints.add(hint);
+ return this;
+ }
+
+ public ArrayList getHints() {
+ return hints;
+ }
+
public boolean shouldBeIgnored() {
return false;
}
@@ -116,19 +152,24 @@ public abstract class Objective {
private long minimumDuration;
- public MinimumDurationTask(long minimumDuration) {
+ MinimumDurationTask(long minimumDuration) {
super(R.string.time_elapsed);
this.minimumDuration = minimumDuration;
}
@Override
public boolean isCompleted() {
- return getObjective().isStarted() && System.currentTimeMillis() - getObjective().getStartedOn().getTime() >= minimumDuration;
+ return getObjective().isStarted() && System.currentTimeMillis() - getObjective().getStartedOn() >= minimumDuration;
+ }
+
+ @Override
+ public boolean isCompleted(long trueTime) {
+ return getObjective().isStarted() && trueTime - getObjective().getStartedOn() >= minimumDuration;
}
@Override
public String getProgress() {
- return getDurationText(System.currentTimeMillis() - getObjective().getStartedOn().getTime())
+ return getDurationText(System.currentTimeMillis() - getObjective().getStartedOn())
+ " / " + getDurationText(minimumDuration);
}
@@ -142,4 +183,107 @@ public abstract class Objective {
}
}
+ public class ExamTask extends Task {
+ @StringRes
+ int question;
+ ArrayList options = new ArrayList<>();
+ private String spIdentifier;
+ private boolean answered;
+ private long disabledTo;
+
+ ExamTask(@StringRes int task, @StringRes int question, String spIdentifier) {
+ super(task);
+ this.question = question;
+ this.spIdentifier = spIdentifier;
+ answered = SP.getBoolean("ExamTask_" + spIdentifier, false);
+ disabledTo = SP.getLong("DisabledTo_" + spIdentifier, 0L);
+ }
+
+ public void setDisabledTo(long newState) {
+ disabledTo = newState;
+ SP.putLong("DisabledTo_" + spIdentifier, disabledTo);
+ }
+
+ public long getDisabledTo() {
+ return disabledTo;
+ }
+
+ public boolean isEnabledAnswer() {
+ return disabledTo < DateUtil.now();
+ }
+
+ public void setAnswered(boolean newState) {
+ answered = newState;
+ SP.putBoolean("ExamTask_" + spIdentifier, answered);
+ }
+
+ public boolean getAnswered() {
+ return answered;
+ }
+
+ ExamTask option(Option option) {
+ options.add(option);
+ return this;
+ }
+
+ public @StringRes int getQuestion() {
+ return question;
+ }
+
+ public List getOptions() {
+ return options;
+ }
+
+ @Override
+ public boolean isCompleted() {
+ return answered;
+ }
+ }
+
+ public class Option {
+ @StringRes int option;
+ boolean isCorrect;
+
+ CheckBox cb; // TODO: change it, this will block releasing memeory
+
+ Option(@StringRes int option, boolean isCorrect) {
+ this.option = option;
+ this.isCorrect = isCorrect;
+ }
+
+ public boolean isCorrect() {
+ return isCorrect;
+ }
+
+ public CheckBox generate(Context context) {
+ cb = new CheckBox(context);
+ cb.setText(option);
+ return cb;
+ }
+
+ public boolean evaluate() {
+ boolean selection = cb.isChecked();
+ if (selection && isCorrect) return true;
+ if (!selection && !isCorrect) return true;
+ return false;
+ }
+ }
+
+ public class Hint {
+ @StringRes int hint;
+
+ Hint(@StringRes int hint) {
+ this.hint = hint;
+ }
+
+ public TextView generate(Context context) {
+ TextView textView = new TextView(context);
+ textView.setText(hint);
+ textView.setAutoLinkMask(Linkify.WEB_URLS);
+ textView.setLinksClickable(true);
+ textView.setLinkTextColor(Color.YELLOW);
+ Linkify.addLinks(textView, Linkify.WEB_URLS);
+ return textView;
+ }
+ }
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective0.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective0.java
new file mode 100644
index 0000000000..f6f0267a23
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective0.java
@@ -0,0 +1,84 @@
+package info.nightscout.androidaps.plugins.constraints.objectives.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.constraints.objectives.ObjectivesPlugin;
+import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
+import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin;
+import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin;
+import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
+import info.nightscout.androidaps.utils.DateUtil;
+import info.nightscout.androidaps.utils.SP;
+
+public class Objective0 extends Objective {
+
+ public Objective0() {
+ super("config", 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 SP.getBoolean(R.string.key_ObjectivesbgIsAvailableInNS, false);
+ }
+ });
+ 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 SP.getBoolean(R.string.key_ObjectivespumpStatusIsAvailableInNS, false);
+ }
+ });
+ 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.getPlugin().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/constraints/objectives/objectives/Objective1.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective1.java
index 65a716abab..1687b56987 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective1.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective1.java
@@ -3,82 +3,60 @@ package info.nightscout.androidaps.plugins.constraints.objectives.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.constraints.objectives.ObjectivesPlugin;
-import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
-import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin;
-import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin;
-import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
-import info.nightscout.androidaps.utils.DateUtil;
+import info.nightscout.androidaps.plugins.general.actions.ActionsPlugin;
import info.nightscout.androidaps.utils.SP;
public class Objective1 extends Objective {
+
public Objective1() {
- super(0, R.string.objectives_0_objective, R.string.objectives_0_gate);
+ super("usage", R.string.objectives_usage_objective, R.string.objectives_usage_gate);
}
@Override
protected void setupTasks(List tasks) {
- tasks.add(new Task(R.string.objectives_bgavailableinns) {
+ tasks.add(new Task(R.string.objectives_useprofileswitch) {
@Override
public boolean isCompleted() {
- return ObjectivesPlugin.getPlugin().bgIsAvailableInNS;
+ return SP.getBoolean(R.string.key_objectiveuseprofileswitch, false);
}
});
- tasks.add(new Task(R.string.nsclienthaswritepermission) {
+ tasks.add(new Task(R.string.objectives_usedisconnectpump) {
@Override
public boolean isCompleted() {
- return NSClientPlugin.getPlugin().hasWritePermission();
+ return SP.getBoolean(R.string.key_objectiveusedisconnect, false);
}
- });
- tasks.add(new Task(R.string.virtualpump_uploadstatus_title) {
+ }.hint(new Hint(R.string.disconnectpump_hint)));
+ tasks.add(new Task(R.string.objectives_usereconnectpump) {
@Override
public boolean isCompleted() {
- return SP.getBoolean("virtualpump_uploadstatus", false);
+ return SP.getBoolean(R.string.key_objectiveusereconnect, false);
}
-
- @Override
- public boolean shouldBeIgnored() {
- return !VirtualPumpPlugin.getPlugin().isEnabled(PluginType.PUMP);
- }
- });
- tasks.add(new Task(R.string.objectives_pumpstatusavailableinns) {
+ }.hint(new Hint(R.string.disconnectpump_hint)));
+ tasks.add(new Task(R.string.objectives_usetemptarget) {
@Override
public boolean isCompleted() {
- return ObjectivesPlugin.getPlugin().pumpStatusIsAvailableInNS;
+ return SP.getBoolean(R.string.key_objectiveusetemptarget, false);
}
- });
- tasks.add(new Task(R.string.hasbgdata) {
+ }.hint(new Hint(R.string.usetemptarget_hint)));
+ tasks.add(new Task(R.string.objectives_useactions) {
@Override
public boolean isCompleted() {
- return DatabaseHelper.lastBg() != null;
+ return SP.getBoolean(R.string.key_objectiveuseactions, false) && ActionsPlugin.INSTANCE.isEnabled(PluginType.GENERAL) && ActionsPlugin.INSTANCE.isFragmentVisible();
}
- });
- tasks.add(new Task(R.string.loopenabled) {
+ }.hint(new Hint(R.string.useaction_hint)));
+ tasks.add(new Task(R.string.objectives_useloop) {
@Override
public boolean isCompleted() {
- return LoopPlugin.getPlugin().isEnabled(PluginType.LOOP);
+ return SP.getBoolean(R.string.key_objectiveuseloop, false);
}
- });
- tasks.add(new Task(R.string.apsselected) {
+ }.hint(new Hint(R.string.useaction_hint)));
+ tasks.add(new Task(R.string.objectives_usescale) {
@Override
public boolean isCompleted() {
- APSInterface usedAPS = ConfigBuilderPlugin.getPlugin().getActiveAPS();
- if (usedAPS != null && ((PluginBase) usedAPS).isEnabled(PluginType.APS))
- return true;
- return false;
+ return SP.getBoolean(R.string.key_objectiveusescale, false);
}
- });
- tasks.add(new Task(R.string.activate_profile) {
- @Override
- public boolean isCompleted() {
- return TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(DateUtil.now()) != null;
- }
- });
+ }.hint(new Hint(R.string.usescale_hint)));
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective2.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective2.java
index 6f97bfdd95..017ad33a8c 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective2.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective2.java
@@ -1,36 +1,211 @@
package info.nightscout.androidaps.plugins.constraints.objectives.objectives;
+import java.util.Collections;
import java.util.List;
-import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
-import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin;
-import info.nightscout.androidaps.utils.T;
public class Objective2 extends Objective {
- public final int MANUAL_ENACTS_NEEDED = 20;
public Objective2() {
- super(1, R.string.objectives_1_objective, R.string.objectives_1_gate);
+ super("exam", R.string.objectives_exam_objective, R.string.objectives_exam_gate);
+ for (Task task : tasks) {
+ if (!task.isCompleted()) setAccomplishedOn(0);
+ }
}
@Override
protected void setupTasks(List tasks) {
- tasks.add(new MinimumDurationTask(T.days(7).msecs()));
- tasks.add(new Task(R.string.objectives_manualenacts) {
- @Override
- public boolean isCompleted() {
- return ObjectivesPlugin.getPlugin().manualEnacts >= MANUAL_ENACTS_NEEDED;
- }
+ tasks.add(new ExamTask(R.string.dia_label, R.string.dia_whatmeansdia,"dia")
+ .option(new Option(R.string.dia_minimumis3h, false))
+ .option(new Option(R.string.dia_minimumis5h, true))
+ .option(new Option(R.string.dia_meaningisequaltodiapump, false))
+ .option(new Option(R.string.dia_valuemustbedetermined, true))
+ .hint(new Hint(R.string.dia_hint1))
+ );
+ tasks.add(new ExamTask(R.string.hypott_label, R.string.hypott_whenhypott,"hypott")
+ .option(new Option(R.string.hypott_goinglow, false))
+ .option(new Option(R.string.hypott_preventoversmb, true))
+ .hint(new Hint(R.string.hypott_hint1))
+ );
+ tasks.add(new ExamTask(R.string.offlineprofile_label, R.string.offlineprofile_whatprofile,"offlineprofile")
+ .option(new Option(R.string.localprofile, true))
+ .option(new Option(R.string.nsprofile, false))
+ .option(new Option(R.string.offlineprofile_nsprofile, true))
+ .hint(new Hint(R.string.offlineprofile_hint1))
+ );
+ tasks.add(new ExamTask(R.string.pumpdisconnect_label, R.string.pumpdisconnect_label,"pumpdisconnect")
+ .option(new Option(R.string.pumpdisconnect_letknow, true))
+ .option(new Option(R.string.pumpdisconnect_suspend, false))
+ .option(new Option(R.string.pumpdisconnect_dontchnage, false))
+ .hint(new Hint(R.string.pumpdisconnect_hint1))
+ );
+ tasks.add(new ExamTask(R.string.objectives_label, R.string.objectives_howtosave,"objectives")
+ .option(new Option(R.string.objectives_exportsettings, true))
+ .option(new Option(R.string.objectives_storeelsewhere, true))
+ .option(new Option(R.string.objectives_doexportonstart, false))
+ .option(new Option(R.string.objectives_doexportafterchange, true))
+ .option(new Option(R.string.objectives_doexportafterobjective, true))
+ .option(new Option(R.string.objectives_doexportafterfirtssettings, true))
+ .hint(new Hint(R.string.objectives_hint1))
+ .hint(new Hint(R.string.objectives_hint2))
+ );
+ tasks.add(new ExamTask(R.string.noisycgm_label, R.string.noisycgm_whattodo,"noisycgm")
+ .option(new Option(R.string.nothing, false))
+ .option(new Option(R.string.disconnectpumpfor1h, false))
+ .option(new Option(R.string.noisycgm_pause, true))
+ .option(new Option(R.string.noisycgm_replacesensor, true))
+ .option(new Option(R.string.noisycgm_turnoffphone, false))
+ .option(new Option(R.string.noisycgm_checksmoothing, true))
+ .hint(new Hint(R.string.noisycgm_hint1))
+ );
+ tasks.add(new ExamTask(R.string.exercise_label, R.string.exercise_whattodo,"exercise")
+ .option(new Option(R.string.nothing, false))
+ .option(new Option(R.string.exercise_setactivitytt, true))
+ .option(new Option(R.string.exercise_switchprofilebelow100, true))
+ .option(new Option(R.string.exercise_switchprofileabove100, false))
+ .option(new Option(R.string.exercise_stoploop, false))
+ .option(new Option(R.string.exercise_doitbeforestart, true))
+ .option(new Option(R.string.exercise_afterstart, true))
+ .hint(new Hint(R.string.exercise_hint1))
+ );
+ tasks.add(new ExamTask(R.string.suspendloop_label, R.string.suspendloop_doigetinsulin,"suspendloop")
+ .option(new Option(R.string.suspendloop_yes, true))
+ .option(new Option(R.string.suspendloop_no, false))
+ );
+ tasks.add(new ExamTask(R.string.basaltest_label, R.string.basaltest_when,"basaltest")
+ .option(new Option(R.string.basaltest_beforeloop, true))
+ .option(new Option(R.string.basaltest_havingregularhypo, true))
+ .option(new Option(R.string.basaltest_havingregularhyper, true))
+ .hint(new Hint(R.string.basaltest_hint1))
+ );
+ tasks.add(new ExamTask(R.string.basalhelp_label, R.string.basalhelp_where,"basalhelp")
+ .option(new Option(R.string.basalhelp_diabetesteam, true))
+ .option(new Option(R.string.basalhelp_google, false))
+ .option(new Option(R.string.basalhelp_facebook, false))
+ .hint(new Hint(R.string.basalhelp_hint1))
+ );
+ tasks.add(new ExamTask(R.string.prerequisites_label, R.string.prerequisites_what, "prerequisites")
+ .option(new Option(R.string.prerequisites_determinedcorrectprofile, true))
+ .option(new Option(R.string.prerequisites_computer, true))
+ .option(new Option(R.string.prerequisites_phone, true))
+ .option(new Option(R.string.prerequisites_car, false))
+ .option(new Option(R.string.prerequisites_nightscout, true))
+ .option(new Option(R.string.prerequisites_tidepoolaccount, false))
+ .option(new Option(R.string.prerequisites_googleaccount, false))
+ .option(new Option(R.string.prerequisites_githubaccount, false))
+ .option(new Option(R.string.prerequisites_beanandroiddeveloper, false))
+ .option(new Option(R.string.prerequisites_own670g, false))
+ .option(new Option(R.string.prerequisites_smartwatch, false))
+ .option(new Option(R.string.prerequisites_supportedcgm, true))
+ .hint(new Hint(R.string.prerequisites_hint1))
+ );
+ tasks.add(new ExamTask(R.string.update_label, R.string.whatistrue,"update")
+ .option(new Option(R.string.update_git, true))
+ .option(new Option(R.string.update_asap, true))
+ .option(new Option(R.string.update_keys, true))
+ .option(new Option(R.string.update_neverupdate, false))
+ .option(new Option(R.string.update_askfriend, false))
+ .hint(new Hint(R.string.update_hint1))
+ );
+ tasks.add(new ExamTask(R.string.troubleshooting_label, R.string.troubleshooting_wheretoask,"troubleshooting")
+ .option(new Option(R.string.troubleshooting_fb, true))
+ .option(new Option(R.string.troubleshooting_wiki, true))
+ .option(new Option(R.string.troubleshooting_gitter, true))
+ .option(new Option(R.string.troubleshooting_googlesupport, false))
+ .option(new Option(R.string.troubleshooting_yourendo, false))
+ .hint(new Hint(R.string.troubleshooting_hint1))
+ .hint(new Hint(R.string.troubleshooting_hint2))
+ .hint(new Hint(R.string.troubleshooting_hint3))
+ );
+ tasks.add(new ExamTask(R.string.insulin_label, R.string.insulin_ultrarapid,"insulin")
+ .option(new Option(R.string.insulin_fiasp, true))
+ .option(new Option(R.string.insulin_novorapid, false))
+ .option(new Option(R.string.insulin_humalog, false))
+ .option(new Option(R.string.insulin_actrapid, false))
+ .hint(new Hint(R.string.insulin_hint1))
+ );
+ tasks.add(new ExamTask(R.string.sensitivity_label, R.string.sensitivity_which,"sensitivity")
+ .option(new Option(R.string.sensitivityweightedaverage, true))
+ .option(new Option(R.string.sensitivityoref0, false))
+ .option(new Option(R.string.sensitivityoref1, false))
+ .option(new Option(R.string.sensitivityaaps, true))
+ .hint(new Hint(R.string.sensitivity_hint1))
+ );
+ tasks.add(new ExamTask(R.string.sensitivity_label, R.string.sensitivityuam_which,"sensitivityuam")
+ .option(new Option(R.string.sensitivityweightedaverage, false))
+ .option(new Option(R.string.sensitivityoref0, false))
+ .option(new Option(R.string.sensitivityoref1, true))
+ .option(new Option(R.string.sensitivityaaps, false))
+ .hint(new Hint(R.string.sensitivity_hint1))
+ );
+ tasks.add(new ExamTask(R.string.wrongcarbs_label, R.string.wrongcarbs_whattodo,"wrongcarbs")
+ .option(new Option(R.string.wrongcarbs_addfakeinsulin, false))
+ .option(new Option(R.string.wrongcarbs_treatmentstab, true))
+ );
+ tasks.add(new ExamTask(R.string.extendedcarbs_label, R.string.extendedcarbs_handling,"extendedcarbs")
+ .option(new Option(R.string.extendedcarbs_useextendedcarbs, true))
+ .option(new Option(R.string.extendedcarbs_add, false))
+ .option(new Option(R.string.extendedcarbs_useextendedbolus, false))
+ .hint(new Hint(R.string.extendedcarbs_hint1))
+ );
+ tasks.add(new ExamTask(R.string.nsclient_label, R.string.nsclient_howcanyou,"nsclient")
+ .option(new Option(R.string.nsclient_nightscout, true))
+ .option(new Option(R.string.nsclientinternal, true))
+ .option(new Option(R.string.nsclient_dexcomfollow, true))
+ .option(new Option(R.string.nsclient_dexcomfollowxdrip, false))
+ .option(new Option(R.string.nsclient_xdripfollower, true))
+ .option(new Option(R.string.nsclient_looponiphone, false))
+ .option(new Option(R.string.nsclient_spikeiphone, true))
+ .hint(new Hint(R.string.nsclient_hint1))
+ );
+ tasks.add(new ExamTask(R.string.isf_label, R.string.whatistrue,"isf")
+ .option(new Option(R.string.isf_increasingvalue, true))
+ .option(new Option(R.string.isf_decreasingvalue, false))
+ .option(new Option(R.string.isf_noeffect, false))
+ .option(new Option(R.string.isf_preferences, false))
+ .option(new Option(R.string.isf_profile, false))
+ .hint(new Hint(R.string.isf_hint1))
+ .hint(new Hint(R.string.isf_hint2))
+ );
+ tasks.add(new ExamTask(R.string.ic_label, R.string.whatistrue,"ic")
+ .option(new Option(R.string.ic_increasingvalue, true))
+ .option(new Option(R.string.ic_decreasingvalue, false))
+ .option(new Option(R.string.ic_noeffect, false))
+ .option(new Option(R.string.ic_different, false))
+ .option(new Option(R.string.ic_meaning, false))
+ .hint(new Hint(R.string.ic_hint1))
+ );
+ tasks.add(new ExamTask(R.string.profileswitch_label, R.string.profileswitch_pctwillchange,"profileswitch")
+ .option(new Option(R.string.profileswitch_basalhigher, false))
+ .option(new Option(R.string.profileswitch_basallower, true))
+ .option(new Option(R.string.profileswitch_ichigher, true))
+ .option(new Option(R.string.profileswitch_iclower, false))
+ .option(new Option(R.string.profileswitch_isfhigher, true))
+ .option(new Option(R.string.profileswitch_isflower, false))
+ .option(new Option(R.string.profileswitch_overall, true))
+ .option(new Option(R.string.profileswitch_targethigher, false))
+ .option(new Option(R.string.profileswitch_targetlower, false))
+ .option(new Option(R.string.profileswitch_targetbottom, false))
+ .hint(new Hint(R.string.profileswitch_hint1))
+ );
- @Override
- public String getProgress() {
- if (ObjectivesPlugin.getPlugin().manualEnacts >= MANUAL_ENACTS_NEEDED)
- return MainApp.gs(R.string.completed_well_done);
- else
- return ObjectivesPlugin.getPlugin().manualEnacts + " / " + MANUAL_ENACTS_NEEDED;
- }
- });
+ tasks.add(new ExamTask(R.string.profileswitch_label, R.string.profileswitchtime_iwant,"profileswitchtime")
+ .option(new Option(R.string.profileswitchtime_1, false))
+ .option(new Option(R.string.profileswitchtime__1, true))
+ .option(new Option(R.string.profileswitchtime_60, false))
+ .option(new Option(R.string.profileswitchtime__60, false))
+ .hint(new Hint(R.string.profileswitchtime_hint1))
+ );
+
+ tasks.add(new ExamTask(R.string.other_medication_label, R.string.other_medication_text,"otherMedicationWarning")
+ .option(new Option(R.string.yes, true))
+ .option(new Option(R.string.no, false))
+ );
+
+ for (Task task : tasks)
+ Collections.shuffle(((ExamTask)task).options);
}
+
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective3.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective3.java
index 4924d9434c..c9ac7d8935 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective3.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective3.java
@@ -1,10 +1,45 @@
package info.nightscout.androidaps.plugins.constraints.objectives.objectives;
+import android.app.Activity;
+
+import java.util.List;
+
+import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin;
+import info.nightscout.androidaps.utils.SP;
+import info.nightscout.androidaps.utils.T;
public class Objective3 extends Objective {
+ public final int MANUAL_ENACTS_NEEDED = 20;
+
public Objective3() {
- super(2, R.string.objectives_2_objective, R.string.objectives_2_gate);
+ super("openloop", R.string.objectives_openloop_objective, R.string.objectives_openloop_gate);
+ hasSpecialInput = true;
+ }
+
+ @Override
+ protected void setupTasks(List tasks) {
+ tasks.add(new MinimumDurationTask(T.days(7).msecs()));
+ tasks.add(new Task(R.string.objectives_manualenacts) {
+ @Override
+ public boolean isCompleted() {
+ return SP.getInt(R.string.key_ObjectivesmanualEnacts, 0) >= MANUAL_ENACTS_NEEDED;
+ }
+
+ @Override
+ public String getProgress() {
+ if (SP.getInt(R.string.key_ObjectivesmanualEnacts, 0) >= MANUAL_ENACTS_NEEDED)
+ return MainApp.gs(R.string.completed_well_done);
+ else
+ return SP.getInt(R.string.key_ObjectivesmanualEnacts, 0) + " / " + MANUAL_ENACTS_NEEDED;
+ }
+ });
+ }
+
+ @Override
+ public void specialAction(Activity activity, String input) {
+ ObjectivesPlugin.INSTANCE.completeObjectives(activity, input);
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective4.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective4.java
index 1bbb4ef7c2..bb46d3c338 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective4.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective4.java
@@ -1,33 +1,10 @@
package info.nightscout.androidaps.plugins.constraints.objectives.objectives;
-import java.util.List;
-
import info.nightscout.androidaps.R;
-import info.nightscout.androidaps.interfaces.Constraint;
-import info.nightscout.androidaps.plugins.constraints.safety.SafetyPlugin;
-import info.nightscout.androidaps.utils.T;
public class Objective4 extends Objective {
public Objective4() {
- super(3, R.string.objectives_3_objective, R.string.objectives_3_gate);
- }
-
- @Override
- protected void setupTasks(List tasks) {
- tasks.add(new MinimumDurationTask(T.days(5).msecs()));
- tasks.add(new Task(R.string.closedmodeenabled) {
- @Override
- public boolean isCompleted() {
- Constraint closedLoopEnabled = new Constraint<>(true);
- SafetyPlugin.getPlugin().isClosedLoopAllowed(closedLoopEnabled);
- return closedLoopEnabled.value();
- }
- });
- }
-
- @Override
- public boolean isRevertable() {
- return true;
+ super("maxbasal", R.string.objectives_maxbasal_objective, R.string.objectives_maxbasal_gate);
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective5.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective5.java
index b04062655a..2407594069 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective5.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective5.java
@@ -2,25 +2,32 @@ package info.nightscout.androidaps.plugins.constraints.objectives.objectives;
import java.util.List;
-import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.interfaces.Constraint;
+import info.nightscout.androidaps.plugins.constraints.safety.SafetyPlugin;
import info.nightscout.androidaps.utils.T;
public class Objective5 extends Objective {
public Objective5() {
- super(4, R.string.objectives_4_objective, R.string.objectives_4_gate);
+ super("maxiobzero", R.string.objectives_maxiobzero_objective, R.string.objectives_maxiobzero_gate);
}
@Override
protected void setupTasks(List tasks) {
- tasks.add(new MinimumDurationTask(T.days(1).msecs()));
- tasks.add(new Task(R.string.maxiobset) {
+ tasks.add(new MinimumDurationTask(T.days(5).msecs()));
+ tasks.add(new Task(R.string.closedmodeenabled) {
@Override
public boolean isCompleted() {
- double maxIOB = MainApp.getConstraintChecker().getMaxIOBAllowed().value();
- return maxIOB > 0;
+ Constraint closedLoopEnabled = new Constraint<>(true);
+ SafetyPlugin.getPlugin().isClosedLoopAllowed(closedLoopEnabled);
+ return closedLoopEnabled.value();
}
});
}
+
+ @Override
+ public boolean isRevertable() {
+ return true;
+ }
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective6.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective6.java
index 284dfa3ab0..1b224bd40c 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective6.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective6.java
@@ -2,17 +2,25 @@ package info.nightscout.androidaps.plugins.constraints.objectives.objectives;
import java.util.List;
+import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.utils.T;
public class Objective6 extends Objective {
public Objective6() {
- super(5, R.string.objectives_5_objective, R.string.objectives_5_gate);
+ super("maxiob", R.string.objectives_maxiob_objective, R.string.objectives_maxiob_gate);
}
@Override
protected void setupTasks(List tasks) {
- tasks.add(new MinimumDurationTask(T.days(7).msecs()));
+ tasks.add(new MinimumDurationTask(T.days(1).msecs()));
+ 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/constraints/objectives/objectives/Objective7.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective7.java
index f90411ecfb..497eb0a180 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective7.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective7.java
@@ -3,16 +3,17 @@ package info.nightscout.androidaps.plugins.constraints.objectives.objectives;
import java.util.List;
import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin;
import info.nightscout.androidaps.utils.T;
public class Objective7 extends Objective {
public Objective7() {
- super(6, R.string.objectives_6_objective, 0);
+ super("autosens", R.string.objectives_autosens_objective, R.string.objectives_autosens_gate);
}
@Override
protected void setupTasks(List tasks) {
- tasks.add(new MinimumDurationTask(T.days(28).msecs()));
+ tasks.add(new MinimumDurationTask(T.days(7).msecs()));
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective8.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective8.java
index 7148f5e5ad..3f943041b6 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective8.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective8.java
@@ -3,12 +3,13 @@ package info.nightscout.androidaps.plugins.constraints.objectives.objectives;
import java.util.List;
import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin;
import info.nightscout.androidaps.utils.T;
public class Objective8 extends Objective {
public Objective8() {
- super(7, R.string.objectives_7_objective, R.string.objectives_7_gate);
+ super("ama", R.string.objectives_ama_objective, 0);
}
@Override
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective9.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective9.java
new file mode 100644
index 0000000000..106c25cb79
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective9.java
@@ -0,0 +1,18 @@
+package info.nightscout.androidaps.plugins.constraints.objectives.objectives;
+
+import java.util.List;
+
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.utils.T;
+
+public class Objective9 extends Objective {
+
+ public Objective9() {
+ super("smb", R.string.objectives_smb_objective, R.string.objectives_smb_gate);
+ }
+
+ @Override
+ protected void setupTasks(List tasks) {
+ tasks.add(new MinimumDurationTask(T.days(28).msecs()));
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPlugin.java
index 65dc119c6a..4d66f36194 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPlugin.java
@@ -13,10 +13,11 @@ 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.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAPlugin;
import info.nightscout.androidaps.plugins.aps.openAPSMA.OpenAPSMAPlugin;
import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin;
+import info.nightscout.androidaps.plugins.bus.RxBus;
+import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification;
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin;
@@ -68,7 +69,7 @@ public class SafetyPlugin extends PluginBase implements ConstraintsInterface {
if (!MainApp.isEngineeringModeOrRelease()) {
if (value.value()) {
Notification n = new Notification(Notification.TOAST_ALARM, MainApp.gs(R.string.closed_loop_disabled_on_dev_branch), Notification.NORMAL);
- MainApp.bus().post(new EventNewNotification(n));
+ RxBus.INSTANCE.send(new EventNewNotification(n));
}
value.set(false, MainApp.gs(R.string.closed_loop_disabled_on_dev_branch), this);
}
@@ -125,6 +126,10 @@ public class SafetyPlugin extends PluginBase implements ConstraintsInterface {
if (Config.APS) {
double maxBasal = SP.getDouble(R.string.key_openapsma_max_basal, 1d);
+ if (maxBasal < profile.getMaxDailyBasal()) {
+ maxBasal = profile.getMaxDailyBasal();
+ absoluteRate.addReason(MainApp.gs(R.string.increasingmaxbasal), this);
+ }
absoluteRate.setIfSmaller(maxBasal, String.format(MainApp.gs(R.string.limitingbasalratio), maxBasal, MainApp.gs(R.string.maxvalueinpreferences)), this);
// Check percentRate but absolute rate too, because we know real current basal in pump
@@ -196,7 +201,7 @@ public class SafetyPlugin extends PluginBase implements ConstraintsInterface {
PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
if (pump != null) {
- double rounded = Round.roundTo(insulin.value(), pump.getPumpDescription().pumpType.determineCorrectBolusSize(insulin.value()));
+ double rounded = pump.getPumpDescription().pumpType.determineCorrectBolusSize(insulin.value());
insulin.setIfDifferent(rounded, MainApp.gs(R.string.pumplimit), this);
}
return insulin;
@@ -213,7 +218,7 @@ public class SafetyPlugin extends PluginBase implements ConstraintsInterface {
PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
if (pump != null) {
- double rounded = Round.roundTo(insulin.value(), pump.getPumpDescription().pumpType.determineCorrectExtendedBolusSize(insulin.value()));
+ double rounded = pump.getPumpDescription().pumpType.determineCorrectExtendedBolusSize(insulin.value());
insulin.setIfDifferent(rounded, MainApp.gs(R.string.pumplimit), this);
}
return insulin;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/signatureVerifier/SignatureVerifierPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/signatureVerifier/SignatureVerifierPlugin.java
new file mode 100644
index 0000000000..89dbb56ca5
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/signatureVerifier/SignatureVerifierPlugin.java
@@ -0,0 +1,241 @@
+package info.nightscout.androidaps.plugins.constraints.signatureVerifier;
+
+import android.content.pm.PackageManager;
+import android.content.pm.Signature;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.spongycastle.util.encoders.Hex;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.interfaces.Constraint;
+import info.nightscout.androidaps.interfaces.ConstraintsInterface;
+import info.nightscout.androidaps.interfaces.PluginBase;
+import info.nightscout.androidaps.interfaces.PluginDescription;
+import info.nightscout.androidaps.interfaces.PluginType;
+import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.bus.RxBus;
+import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification;
+import info.nightscout.androidaps.plugins.general.overview.notifications.Notification;
+import info.nightscout.androidaps.utils.SP;
+
+/**
+ * AndroidAPS is meant to be build by the user.
+ * In case someone decides to leak a ready-to-use APK nonetheless, we can still disable it.
+ * Self-compiled APKs with privately held certificates cannot and will not be disabled.
+ */
+public class SignatureVerifierPlugin extends PluginBase implements ConstraintsInterface {
+
+ private static final String REVOKED_CERTS_URL = "https://raw.githubusercontent.com/MilosKozak/AndroidAPS/master/app/src/main/assets/revoked_certs.txt";
+ private static final long UPDATE_INTERVAL = TimeUnit.DAYS.toMillis(1);
+
+ private static SignatureVerifierPlugin plugin = new SignatureVerifierPlugin();
+
+ private Logger log = LoggerFactory.getLogger(L.CORE);
+ private final Object $lock = new Object[0];
+ private File revokedCertsFile;
+ private List revokedCerts;
+
+ public static SignatureVerifierPlugin getPlugin() {
+ return plugin;
+ }
+
+ private SignatureVerifierPlugin() {
+ super(new PluginDescription()
+ .mainType(PluginType.CONSTRAINTS)
+ .neverVisible(true)
+ .alwaysEnabled(true)
+ .showInList(false)
+ .pluginName(R.string.signature_verifier));
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ revokedCertsFile = new File(MainApp.instance().getFilesDir(), "revoked_certs.txt");
+ new Thread(() -> {
+ loadLocalRevokedCerts();
+ if (shouldDownloadCerts()) {
+ try {
+ downloadAndSaveRevokedCerts();
+ } catch (IOException e) {
+ log.error("Could not download revoked certs", e);
+ }
+ }
+ if (hasIllegalSignature()) showNotification();
+ }).start();
+ }
+
+ @Override
+ public Constraint isLoopInvocationAllowed(Constraint value) {
+ if (hasIllegalSignature()) {
+ showNotification();
+ value.set(false);
+ }
+ if (shouldDownloadCerts()) {
+ new Thread(() -> {
+ try {
+ downloadAndSaveRevokedCerts();
+ } catch (IOException e) {
+ log.error("Could not download revoked certs", e);
+ }
+ }).start();
+ }
+ return value;
+ }
+
+ private void showNotification() {
+ Notification notification = new Notification(Notification.INVALID_VERSION, MainApp.gs(R.string.running_invalid_version), Notification.URGENT);
+ RxBus.INSTANCE.send(new EventNewNotification(notification));
+ }
+
+ private boolean hasIllegalSignature() {
+ try {
+ synchronized ($lock) {
+ if (revokedCerts == null) return false;
+ Signature[] signatures = MainApp.instance().getPackageManager().getPackageInfo(MainApp.instance().getPackageName(), PackageManager.GET_SIGNATURES).signatures;
+ if (signatures != null) {
+ for (Signature signature : signatures) {
+ MessageDigest digest = MessageDigest.getInstance("SHA256");
+ byte[] fingerprint = digest.digest(signature.toByteArray());
+ for (byte[] cert : revokedCerts) {
+ if (Arrays.equals(cert, fingerprint)) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ } catch (PackageManager.NameNotFoundException | NoSuchAlgorithmException e) {
+ log.error("Error in SignatureVerifierPlugin", e);
+ }
+ return false;
+ }
+
+ public List shortHashes() {
+ List hashes = new ArrayList<>();
+ try {
+ Signature[] signatures = MainApp.instance().getPackageManager().getPackageInfo(MainApp.instance().getPackageName(), PackageManager.GET_SIGNATURES).signatures;
+ if (signatures != null) {
+ for (Signature signature : signatures) {
+ MessageDigest digest = MessageDigest.getInstance("SHA256");
+ byte[] fingerprint = digest.digest(signature.toByteArray());
+ String hash = Hex.toHexString(fingerprint);
+ log.debug("Found signature: " + hash);
+ log.debug("Found signature (short): " + singleCharMap(fingerprint));
+ hashes.add(singleCharMap(fingerprint));
+ }
+ }
+ } catch (PackageManager.NameNotFoundException | NoSuchAlgorithmException e) {
+ log.error("Error in SignatureVerifierPlugin", e);
+ }
+ return hashes;
+ }
+
+ String map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!\"§$%&/()=?,.-;:_<>|°^`´\\@€*'#+~{}[]¿¡áéíóúàèìòùöäü`ÁÉÍÓÚÀÈÌÒÙÖÄÜßÆÇÊËÎÏԌ۟æçêëîïôœûÿĆČĐŠŽćđšžñΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ\u03A2ΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρςστυφχψωϨϩϪϫϬϭϮϯϰϱϲϳϴϵ϶ϷϸϹϺϻϼϽϾϿЀЁЂЃЄЅІЇЈЉЊЋЌЍЎЏАБВГДЕЖЗ";
+
+ private String singleCharMap(byte[] array) {
+ StringBuilder sb = new StringBuilder();
+ for (byte b : array) {
+ sb.append(map.charAt(b & 0xFF));
+ }
+ return sb.toString();
+ }
+
+ private String singleCharUnMap(String shortHash) {
+ byte[] array = new byte[shortHash.length()];
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < array.length; i++) {
+ sb.append(String.format("%02x",(int) map.charAt(map.indexOf(shortHash.charAt(i)))));
+ }
+ return sb.toString();
+ }
+
+ private boolean shouldDownloadCerts() {
+ return System.currentTimeMillis() - SP.getLong(R.string.key_last_revoked_certs_check, 0L) >= UPDATE_INTERVAL;
+ }
+
+ private void downloadAndSaveRevokedCerts() throws IOException {
+ String download = downloadRevokedCerts();
+ saveRevokedCerts(download);
+ SP.putLong(R.string.key_last_revoked_certs_check, System.currentTimeMillis());
+ synchronized ($lock) {
+ revokedCerts = parseRevokedCertsFile(download);
+ }
+ }
+
+ private void loadLocalRevokedCerts() {
+ try {
+ String revokedCerts = readCachedDownloadedRevokedCerts();
+ if (revokedCerts == null) revokedCerts = readRevokedCertsInAssets();
+ synchronized ($lock) {
+ this.revokedCerts = parseRevokedCertsFile(revokedCerts);
+ }
+ } catch (IOException e) {
+ log.error("Error in SignatureVerifierPlugin", e);
+ }
+ }
+
+ private void saveRevokedCerts(String revokedCerts) throws IOException {
+ OutputStream outputStream = new FileOutputStream(revokedCertsFile);
+ outputStream.write(revokedCerts.getBytes(StandardCharsets.UTF_8));
+ outputStream.close();
+ }
+
+ private String downloadRevokedCerts() throws IOException {
+ URLConnection connection = new URL(REVOKED_CERTS_URL).openConnection();
+ return readInputStream(connection.getInputStream());
+ }
+
+ private String readInputStream(InputStream inputStream) throws IOException {
+ try {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ byte[] buffer = new byte[1024];
+ int read;
+ while ((read = inputStream.read(buffer)) != -1) {
+ baos.write(buffer, 0, read);
+ }
+ baos.flush();
+ return new String(baos.toByteArray(), StandardCharsets.UTF_8);
+ } finally {
+ inputStream.close();
+ }
+ }
+
+ private String readRevokedCertsInAssets() throws IOException {
+ InputStream inputStream = MainApp.instance().getAssets().open("revoked_certs.txt");
+ return readInputStream(inputStream);
+ }
+
+ private String readCachedDownloadedRevokedCerts() throws IOException {
+ if (!revokedCertsFile.exists()) return null;
+ return readInputStream(new FileInputStream(revokedCertsFile));
+ }
+
+ private List parseRevokedCertsFile(String file) {
+ List revokedCerts = new ArrayList<>();
+ for (String line : file.split("\n")) {
+ if (line.startsWith("#")) continue;
+ revokedCerts.add(Hex.decode(line.replace(" ", "").replace(":", "")));
+ }
+ return revokedCerts;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/storage/StorageConstraintPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/storage/StorageConstraintPlugin.java
index 197fd5c17a..f40b7728e5 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/storage/StorageConstraintPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/storage/StorageConstraintPlugin.java
@@ -17,6 +17,7 @@ import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification;
@@ -56,9 +57,9 @@ public class StorageConstraintPlugin extends PluginBase implements ConstraintsIn
if (diskfree < Constants.MINIMUM_FREE_SPACE) {
value.set(false, MainApp.gs(R.string.diskfull, Constants.MINIMUM_FREE_SPACE), this);
Notification notification = new Notification(Notification.DISKFULL, MainApp.gs(R.string.diskfull, Constants.MINIMUM_FREE_SPACE), Notification.NORMAL);
- MainApp.bus().post(new EventNewNotification(notification));
+ RxBus.INSTANCE.send(new EventNewNotification(notification));
} else {
- MainApp.bus().post(new EventDismissNotification(Notification.DISKFULL));
+ RxBus.INSTANCE.send(new EventDismissNotification(Notification.DISKFULL));
}
return value;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/versionChecker/VersionCheckerPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/versionChecker/VersionCheckerPlugin.kt
similarity index 93%
rename from app/src/main/java/info/nightscout/androidaps/plugins/general/versionChecker/VersionCheckerPlugin.kt
rename to app/src/main/java/info/nightscout/androidaps/plugins/constraints/versionChecker/VersionCheckerPlugin.kt
index c0335ea64a..ee267c689e 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/versionChecker/VersionCheckerPlugin.kt
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/versionChecker/VersionCheckerPlugin.kt
@@ -1,8 +1,9 @@
-package info.nightscout.androidaps.plugins.general.versionChecker
+package info.nightscout.androidaps.plugins.constraints.versionChecker
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R
import info.nightscout.androidaps.interfaces.*
+import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
import info.nightscout.androidaps.utils.SP
@@ -46,7 +47,7 @@ object VersionCheckerPlugin : PluginBase(PluginDescription()
//notify
val message = MainApp.gs(R.string.new_version_warning, Math.round((now - SP.getLong(R.string.key_last_time_this_version_detected, now)) / TimeUnit.DAYS.toMillis(1).toDouble()))
val notification = Notification(Notification.OLDVERSION, message, Notification.NORMAL)
- MainApp.bus().post(EventNewNotification(notification))
+ RxBus.send(EventNewNotification(notification))
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/versionChecker/VersionCheckerUtils.kt b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/versionChecker/VersionCheckerUtils.kt
similarity index 73%
rename from app/src/main/java/info/nightscout/androidaps/plugins/general/versionChecker/VersionCheckerUtils.kt
rename to app/src/main/java/info/nightscout/androidaps/plugins/constraints/versionChecker/VersionCheckerUtils.kt
index 8791030abb..4b19e33540 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/versionChecker/VersionCheckerUtils.kt
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/versionChecker/VersionCheckerUtils.kt
@@ -1,4 +1,4 @@
-package info.nightscout.androidaps.plugins.general.versionChecker
+package info.nightscout.androidaps.plugins.constraints.versionChecker
import android.content.Context
import android.net.ConnectivityManager
@@ -6,32 +6,25 @@ import info.nightscout.androidaps.BuildConfig
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R
import info.nightscout.androidaps.logging.L
+import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
import info.nightscout.androidaps.utils.SP
-import org.apache.http.HttpResponse
-import org.apache.http.client.methods.HttpGet
-import org.apache.http.impl.client.DefaultHttpClient
import org.slf4j.LoggerFactory
import java.io.IOException
-import java.io.InputStream
+import java.net.URL
import java.util.concurrent.TimeUnit
+
// check network connection
fun isConnected(): Boolean {
val connMgr = MainApp.instance().applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
return connMgr.activeNetworkInfo?.isConnected ?: false
}
-// convert inputstream to String
-@Throws(IOException::class)
-inline fun InputStream.findVersion(): String? {
+fun findVersion(file :String?): String? {
val regex = "(.*)version(.*)\"(((\\d+)\\.)+(\\d+))\"(.*)".toRegex()
- return bufferedReader()
- .readLines()
- .filter { regex.matches(it) }
- .mapNotNull { regex.matchEntire(it)?.groupValues?.getOrNull(3) }
- .firstOrNull()
+ return file?.lines()?.filter { regex.matches(it) }?.mapNotNull { regex.matchEntire(it)?.groupValues?.getOrNull(3) }?.firstOrNull()
}
private val log = LoggerFactory.getLogger(L.CORE)
@@ -39,24 +32,21 @@ private val log = LoggerFactory.getLogger(L.CORE)
fun triggerCheckVersion() {
- if(!SP.contains(R.string.key_last_time_this_version_detected)) {
+ if (!SP.contains(R.string.key_last_time_this_version_detected)) {
// On a new installation, set it as 30 days old in order to warn that there is a new version.
SP.putLong(R.string.key_last_time_this_version_detected, System.currentTimeMillis() - TimeUnit.DAYS.toMillis(30))
}
// If we are good, only check once every day.
- if(System.currentTimeMillis() > SP.getLong(R.string.key_last_time_this_version_detected, 0) + CHECK_EVERY){
+ if (System.currentTimeMillis() > SP.getLong(R.string.key_last_time_this_version_detected, 0) + CHECK_EVERY) {
checkVersion()
}
}
-@Suppress("DEPRECATION")
private fun checkVersion() = if (isConnected()) {
Thread {
try {
- val request = HttpGet("https://raw.githubusercontent.com/MilosKozak/AndroidAPS/master/app/build.gradle")
- val response: HttpResponse = DefaultHttpClient().execute(request)
- val version: String? = response.entity.content?.findVersion()
+ val version: String? = findVersion(URL("https://raw.githubusercontent.com/MilosKozak/AndroidAPS/master/app/build.gradle").readText())
compareWithCurrentVersion(version, BuildConfig.VERSION_NAME)
} catch (e: IOException) {
log.debug("Github master version check error: $e")
@@ -90,10 +80,10 @@ fun onVersionNotDetectable() {
fun onNewVersionDetected(currentVersion: String, newVersion: String?) {
val now = System.currentTimeMillis()
- if(now > SP.getLong(R.string.key_last_versionchecker_warning, 0) + WARN_EVERY) {
+ if (now > SP.getLong(R.string.key_last_versionchecker_warning, 0) + WARN_EVERY) {
log.debug("Version ${currentVersion} outdated. Found $newVersion")
val notification = Notification(Notification.NEWVERSIONDETECTED, String.format(MainApp.gs(R.string.versionavailable), newVersion.toString()), Notification.LOW)
- MainApp.bus().post(EventNewNotification(notification))
+ RxBus.send(EventNewNotification(notification))
SP.putLong(R.string.key_last_versionchecker_warning, now)
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.java
deleted file mode 100644
index ff99978fed..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.java
+++ /dev/null
@@ -1,338 +0,0 @@
-package info.nightscout.androidaps.plugins.general.actions;
-
-
-import android.app.Activity;
-import android.content.Intent;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentManager;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.LinearLayout;
-
-import com.squareup.otto.Subscribe;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import info.nightscout.androidaps.Config;
-import info.nightscout.androidaps.MainApp;
-import info.nightscout.androidaps.R;
-import info.nightscout.androidaps.activities.HistoryBrowseActivity;
-import info.nightscout.androidaps.activities.TDDStatsActivity;
-import info.nightscout.androidaps.db.ExtendedBolus;
-import info.nightscout.androidaps.db.TemporaryBasal;
-import info.nightscout.androidaps.events.EventExtendedBolusChange;
-import info.nightscout.androidaps.events.EventInitializationChanged;
-import info.nightscout.androidaps.events.EventRefreshOverview;
-import info.nightscout.androidaps.events.EventTempBasalChange;
-import info.nightscout.androidaps.interfaces.PumpInterface;
-import info.nightscout.androidaps.plugins.common.SubscriberFragment;
-import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
-import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
-import info.nightscout.androidaps.plugins.general.actions.defs.CustomAction;
-import info.nightscout.androidaps.plugins.general.actions.dialogs.FillDialog;
-import info.nightscout.androidaps.plugins.general.actions.dialogs.NewExtendedBolusDialog;
-import info.nightscout.androidaps.plugins.general.actions.dialogs.NewTempBasalDialog;
-import info.nightscout.androidaps.plugins.general.careportal.CareportalFragment;
-import info.nightscout.androidaps.plugins.general.careportal.Dialogs.NewNSTreatmentDialog;
-import info.nightscout.androidaps.plugins.general.careportal.OptionsToShow;
-import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
-import info.nightscout.androidaps.utils.FabricPrivacy;
-import info.nightscout.androidaps.utils.SingleClickButton;
-
-
-/**
- * A simple {@link Fragment} subclass.
- */
-public class ActionsFragment extends SubscriberFragment implements View.OnClickListener {
-
- static ActionsPlugin actionsPlugin = new ActionsPlugin();
-
- static public ActionsPlugin getPlugin() {
- return actionsPlugin;
- }
-
- View actionsFragmentView;
- SingleClickButton profileSwitch;
- SingleClickButton tempTarget;
- SingleClickButton extendedBolus;
- SingleClickButton extendedBolusCancel;
- SingleClickButton tempBasal;
- SingleClickButton tempBasalCancel;
- SingleClickButton fill;
- SingleClickButton tddStats;
- SingleClickButton history;
-
- private Map pumpCustomActions = new HashMap<>();
- private List pumpCustomButtons = new ArrayList<>();
-
- public ActionsFragment() {
- super();
- }
-
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- try {
- View view = inflater.inflate(R.layout.actions_fragment, container, false);
-
- profileSwitch = (SingleClickButton) view.findViewById(R.id.actions_profileswitch);
- tempTarget = (SingleClickButton) view.findViewById(R.id.actions_temptarget);
- extendedBolus = (SingleClickButton) view.findViewById(R.id.actions_extendedbolus);
- extendedBolusCancel = (SingleClickButton) view.findViewById(R.id.actions_extendedbolus_cancel);
- tempBasal = (SingleClickButton) view.findViewById(R.id.actions_settempbasal);
- tempBasalCancel = (SingleClickButton) view.findViewById(R.id.actions_canceltempbasal);
- fill = (SingleClickButton) view.findViewById(R.id.actions_fill);
- tddStats = view.findViewById(R.id.actions_tddstats);
- history = view.findViewById(R.id.actions_historybrowser);
-
- profileSwitch.setOnClickListener(this);
- tempTarget.setOnClickListener(this);
- extendedBolus.setOnClickListener(this);
- extendedBolusCancel.setOnClickListener(this);
- tempBasal.setOnClickListener(this);
- tempBasalCancel.setOnClickListener(this);
- fill.setOnClickListener(this);
- history.setOnClickListener(this);
- tddStats.setOnClickListener(this);
-
- actionsFragmentView = view;
-
- updateGUI();
- return view;
- } catch (Exception e) {
- FabricPrivacy.logException(e);
- }
-
- return null;
- }
-
- @Subscribe
- public void onStatusEvent(final EventInitializationChanged ev) {
- updateGUI();
- }
-
- @Subscribe
- public void onStatusEvent(final EventRefreshOverview ev) {
- updateGUI();
- }
-
- @Subscribe
- public void onStatusEvent(final EventExtendedBolusChange ev) {
- updateGUI();
- }
-
- @Subscribe
- public void onStatusEvent(final EventTempBasalChange ev) {
- updateGUI();
- }
-
- @Override
- protected void updateGUI() {
- Activity activity = getActivity();
- if (activity != null)
- activity.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- if (ConfigBuilderPlugin.getPlugin().getActiveProfileInterface() != null && ConfigBuilderPlugin.getPlugin().getActiveProfileInterface().getProfile() != null) {
- profileSwitch.setVisibility(View.VISIBLE);
- } else {
- profileSwitch.setVisibility(View.GONE);
- }
-
- if (ProfileFunctions.getInstance().getProfile() == null) {
- tempTarget.setVisibility(View.GONE);
- extendedBolus.setVisibility(View.GONE);
- extendedBolusCancel.setVisibility(View.GONE);
- tempBasal.setVisibility(View.GONE);
- tempBasalCancel.setVisibility(View.GONE);
- fill.setVisibility(View.GONE);
- return;
- }
-
- final PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
- final boolean basalprofileEnabled = MainApp.isEngineeringModeOrRelease()
- && pump.getPumpDescription().isSetBasalProfileCapable;
-
- if (!basalprofileEnabled || !pump.isInitialized() || pump.isSuspended())
- profileSwitch.setVisibility(View.GONE);
- else
- profileSwitch.setVisibility(View.VISIBLE);
-
- if (!pump.getPumpDescription().isExtendedBolusCapable || !pump.isInitialized() || pump.isSuspended() || pump.isFakingTempsByExtendedBoluses()) {
- extendedBolus.setVisibility(View.GONE);
- extendedBolusCancel.setVisibility(View.GONE);
- } else {
- ExtendedBolus activeExtendedBolus = TreatmentsPlugin.getPlugin().getExtendedBolusFromHistory(System.currentTimeMillis());
- if (activeExtendedBolus != null) {
- extendedBolus.setVisibility(View.GONE);
- extendedBolusCancel.setVisibility(View.VISIBLE);
- extendedBolusCancel.setText(MainApp.gs(R.string.cancel) + " " + activeExtendedBolus.toString());
- } else {
- extendedBolus.setVisibility(View.VISIBLE);
- extendedBolusCancel.setVisibility(View.GONE);
- }
- }
-
-
- if (!pump.getPumpDescription().isTempBasalCapable || !pump.isInitialized() || pump.isSuspended()) {
- tempBasal.setVisibility(View.GONE);
- tempBasalCancel.setVisibility(View.GONE);
- } else {
- final TemporaryBasal activeTemp = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(System.currentTimeMillis());
- if (activeTemp != null) {
- tempBasal.setVisibility(View.GONE);
- tempBasalCancel.setVisibility(View.VISIBLE);
- tempBasalCancel.setText(MainApp.gs(R.string.cancel) + " " + activeTemp.toStringShort());
- } else {
- tempBasal.setVisibility(View.VISIBLE);
- tempBasalCancel.setVisibility(View.GONE);
- }
- }
-
- if (!pump.getPumpDescription().isRefillingCapable || !pump.isInitialized() || pump.isSuspended())
- fill.setVisibility(View.GONE);
- else
- fill.setVisibility(View.VISIBLE);
-
- if (!Config.APS)
- tempTarget.setVisibility(View.GONE);
- else
- tempTarget.setVisibility(View.VISIBLE);
-
- if (!pump.getPumpDescription().supportsTDDs)
- tddStats.setVisibility(View.GONE);
- else
- tddStats.setVisibility(View.VISIBLE);
-
- checkPumpCustomActions();
-
- }
- });
- }
-
-
- View.OnClickListener pumpCustomActionsListener = v -> {
-
- SingleClickButton btn = (SingleClickButton) v;
-
- CustomAction customAction = this.pumpCustomActions.get(btn.getText().toString());
-
- ConfigBuilderPlugin.getPlugin().getActivePump().executeCustomAction(customAction.getCustomActionType());
-
- };
-
-
- private void checkPumpCustomActions() {
-
- PumpInterface activePump = ConfigBuilderPlugin.getPlugin().getActivePump();
-
- removePumpCustomActions();
-
- if (activePump == null) {
- return;
- }
-
- List customActions = activePump.getCustomActions();
-
- if (customActions != null && customActions.size() > 0) {
-
- LinearLayout ll = actionsFragmentView.findViewById(R.id.action_buttons_layout);
-
- for (CustomAction customAction : customActions) {
-
- SingleClickButton btn = new SingleClickButton(getContext(), null, android.R.attr.buttonStyle);
- btn.setText(MainApp.gs(customAction.getName()));
-
- LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
- LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT, 0.5f);
- layoutParams.setMargins(20, 8, 20, 8); // 10,3,10,3
-
- btn.setLayoutParams(layoutParams);
- btn.setOnClickListener(pumpCustomActionsListener);
-
- Drawable top = getResources().getDrawable(customAction.getIconResourceId());
- btn.setCompoundDrawablesWithIntrinsicBounds(null, top, null, null);
-
- ll.addView(btn);
-
- this.pumpCustomActions.put(MainApp.gs(customAction.getName()), customAction);
- this.pumpCustomButtons.add(btn);
-
- }
- }
-
- }
-
-
- private void removePumpCustomActions() {
-
- if (pumpCustomActions.size() == 0)
- return;
-
- LinearLayout ll = actionsFragmentView.findViewById(R.id.action_buttons_layout);
-
- for (SingleClickButton customButton : pumpCustomButtons) {
- ll.removeView(customButton);
- }
-
- pumpCustomButtons.clear();
- pumpCustomActions.clear();
- }
-
-
- @Override
- public void onClick(View view) {
- FragmentManager manager = getFragmentManager();
- switch (view.getId()) {
- case R.id.actions_profileswitch:
- NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog();
- final OptionsToShow profileswitch = CareportalFragment.PROFILESWITCH;
- profileswitch.executeProfileSwitch = true;
- newDialog.setOptions(profileswitch, R.string.careportal_profileswitch);
- newDialog.show(manager, "NewNSTreatmentDialog");
- break;
- case R.id.actions_temptarget:
- NewNSTreatmentDialog newTTDialog = new NewNSTreatmentDialog();
- final OptionsToShow temptarget = CareportalFragment.TEMPTARGET;
- temptarget.executeTempTarget = true;
- newTTDialog.setOptions(temptarget, R.string.careportal_temporarytarget);
- newTTDialog.show(manager, "NewNSTreatmentDialog");
- break;
- case R.id.actions_extendedbolus:
- NewExtendedBolusDialog newExtendedDialog = new NewExtendedBolusDialog();
- newExtendedDialog.show(manager, "NewExtendedDialog");
- break;
- case R.id.actions_extendedbolus_cancel:
- if (TreatmentsPlugin.getPlugin().isInHistoryExtendedBoluslInProgress()) {
- ConfigBuilderPlugin.getPlugin().getCommandQueue().cancelExtended(null);
- }
- break;
- case R.id.actions_canceltempbasal:
- if (TreatmentsPlugin.getPlugin().isTempBasalInProgress()) {
- ConfigBuilderPlugin.getPlugin().getCommandQueue().cancelTempBasal(true, null);
- }
- break;
- case R.id.actions_settempbasal:
- NewTempBasalDialog newTempDialog = new NewTempBasalDialog();
- newTempDialog.show(manager, "NewTempDialog");
- break;
- case R.id.actions_fill:
- FillDialog fillDialog = new FillDialog();
- fillDialog.show(manager, "FillDialog");
- break;
- case R.id.actions_historybrowser:
- startActivity(new Intent(getContext(), HistoryBrowseActivity.class));
- break;
- case R.id.actions_tddstats:
- startActivity(new Intent(getContext(), TDDStatsActivity.class));
- break;
- }
- }
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.kt
new file mode 100644
index 0000000000..dfc06e6156
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.kt
@@ -0,0 +1,242 @@
+package info.nightscout.androidaps.plugins.general.actions
+
+
+import android.content.Intent
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.LinearLayout
+import androidx.fragment.app.Fragment
+import info.nightscout.androidaps.Config
+import info.nightscout.androidaps.MainApp
+import info.nightscout.androidaps.R
+import info.nightscout.androidaps.activities.HistoryBrowseActivity
+import info.nightscout.androidaps.activities.TDDStatsActivity
+import info.nightscout.androidaps.events.*
+import info.nightscout.androidaps.plugins.bus.RxBus
+import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
+import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions
+import info.nightscout.androidaps.plugins.general.actions.defs.CustomAction
+import info.nightscout.androidaps.plugins.general.actions.dialogs.FillDialog
+import info.nightscout.androidaps.plugins.general.actions.dialogs.NewExtendedBolusDialog
+import info.nightscout.androidaps.plugins.general.actions.dialogs.NewTempBasalDialog
+import info.nightscout.androidaps.plugins.general.careportal.CareportalFragment
+import info.nightscout.androidaps.plugins.general.careportal.Dialogs.NewNSTreatmentDialog
+import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
+import info.nightscout.androidaps.queue.Callback
+import info.nightscout.androidaps.utils.*
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.disposables.CompositeDisposable
+import kotlinx.android.synthetic.main.actions_fragment.*
+import java.util.*
+
+class ActionsFragment : Fragment() {
+
+ private var disposable: CompositeDisposable = CompositeDisposable()
+
+ private val pumpCustomActions = HashMap()
+ private val pumpCustomButtons = ArrayList()
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?): View? {
+ return inflater.inflate(R.layout.actions_fragment, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ actions_profileswitch.setOnClickListener {
+ val newDialog = NewNSTreatmentDialog()
+ val profileSwitch = CareportalFragment.PROFILESWITCH
+ profileSwitch.executeProfileSwitch = true
+ newDialog.setOptions(profileSwitch, R.string.careportal_profileswitch)
+ fragmentManager?.let { newDialog.show(it, "NewNSTreatmentDialog") }
+ }
+ actions_temptarget.setOnClickListener {
+ val newTTDialog = NewNSTreatmentDialog()
+ val temptarget = CareportalFragment.TEMPTARGET
+ temptarget.executeTempTarget = true
+ newTTDialog.setOptions(temptarget, R.string.careportal_temporarytarget)
+ fragmentManager?.let { newTTDialog.show(it, "NewNSTreatmentDialog") }
+ }
+ actions_extendedbolus.setOnClickListener {
+ fragmentManager?.let { NewExtendedBolusDialog().show(it, "NewExtendedDialog") }
+ }
+ actions_extendedbolus_cancel.setOnClickListener {
+ if (TreatmentsPlugin.getPlugin().isInHistoryExtendedBoluslInProgress) {
+ ConfigBuilderPlugin.getPlugin().commandQueue.cancelExtended(object : Callback() {
+ override fun run() {
+ if (!result.success)
+ ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.extendedbolusdeliveryerror))
+ }
+ })
+ }
+ }
+ actions_settempbasal.setOnClickListener { fragmentManager?.let { NewTempBasalDialog().show(it, "NewTempDialog") } }
+ actions_canceltempbasal.setOnClickListener {
+ if (TreatmentsPlugin.getPlugin().isTempBasalInProgress) {
+ ConfigBuilderPlugin.getPlugin().commandQueue.cancelTempBasal(true, object : Callback() {
+ override fun run() {
+ if (!result.success)
+ ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.tempbasaldeliveryerror))
+ }
+ })
+ }
+ }
+ actions_fill.setOnClickListener { fragmentManager?.let { FillDialog().show(it, "FillDialog") } }
+ actions_historybrowser.setOnClickListener { startActivity(Intent(context, HistoryBrowseActivity::class.java)) }
+ actions_tddstats.setOnClickListener { startActivity(Intent(context, TDDStatsActivity::class.java)) }
+
+ SP.putBoolean(R.string.key_objectiveuseactions, true)
+ }
+
+ @Synchronized
+ override fun onResume() {
+ super.onResume()
+ disposable += RxBus
+ .toObservable(EventInitializationChanged::class.java)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe({
+ updateGui()
+ }, {
+ FabricPrivacy.logException(it)
+ })
+ disposable += RxBus
+ .toObservable(EventRefreshOverview::class.java)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe({
+ updateGui()
+ }, {
+ FabricPrivacy.logException(it)
+ })
+ disposable += RxBus
+ .toObservable(EventExtendedBolusChange::class.java)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe({
+ updateGui()
+ }, {
+ FabricPrivacy.logException(it)
+ })
+ disposable += RxBus
+ .toObservable(EventTempBasalChange::class.java)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe({
+ updateGui()
+ }, {
+ FabricPrivacy.logException(it)
+ })
+ disposable += RxBus
+ .toObservable(EventCustomActionsChanged::class.java)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe({
+ updateGui()
+ }, {
+ FabricPrivacy.logException(it)
+ })
+ updateGui()
+ }
+
+ @Synchronized
+ override fun onPause() {
+ super.onPause()
+ disposable.clear()
+ }
+
+ @Synchronized
+ fun updateGui() {
+ actions_profileswitch?.visibility =
+ if (ConfigBuilderPlugin.getPlugin().activeProfileInterface?.profile != null) View.VISIBLE
+ else View.GONE
+
+ if (ProfileFunctions.getInstance().profile == null) {
+ actions_temptarget?.visibility = View.GONE
+ actions_extendedbolus?.visibility = View.GONE
+ actions_extendedbolus_cancel?.visibility = View.GONE
+ actions_settempbasal?.visibility = View.GONE
+ actions_canceltempbasal?.visibility = View.GONE
+ actions_fill?.visibility = View.GONE
+ return
+ }
+
+ val pump = ConfigBuilderPlugin.getPlugin().activePump ?: return
+ val basalProfileEnabled = MainApp.isEngineeringModeOrRelease() && pump.pumpDescription.isSetBasalProfileCapable
+
+ actions_profileswitch?.visibility = if (!basalProfileEnabled || !pump.isInitialized || pump.isSuspended) View.GONE else View.VISIBLE
+
+ if (!pump.pumpDescription.isExtendedBolusCapable || !pump.isInitialized || pump.isSuspended || pump.isFakingTempsByExtendedBoluses || Config.APS) {
+ actions_extendedbolus?.visibility = View.GONE
+ actions_extendedbolus_cancel?.visibility = View.GONE
+ } else {
+ val activeExtendedBolus = TreatmentsPlugin.getPlugin().getExtendedBolusFromHistory(System.currentTimeMillis())
+ if (activeExtendedBolus != null) {
+ actions_extendedbolus?.visibility = View.GONE
+ actions_extendedbolus_cancel?.visibility = View.VISIBLE
+ actions_extendedbolus_cancel?.text = MainApp.gs(R.string.cancel) + " " + activeExtendedBolus.toString()
+ } else {
+ actions_extendedbolus?.visibility = View.VISIBLE
+ actions_extendedbolus_cancel?.visibility = View.GONE
+ }
+ }
+
+ if (!pump.pumpDescription.isTempBasalCapable || !pump.isInitialized || pump.isSuspended) {
+ actions_settempbasal?.visibility = View.GONE
+ actions_canceltempbasal?.visibility = View.GONE
+ } else {
+ val activeTemp = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(System.currentTimeMillis())
+ if (activeTemp != null) {
+ actions_settempbasal?.visibility = View.GONE
+ actions_canceltempbasal?.visibility = View.VISIBLE
+ actions_canceltempbasal?.text = MainApp.gs(R.string.cancel) + " " + activeTemp.toStringShort()
+ } else {
+ actions_settempbasal?.visibility = View.VISIBLE
+ actions_canceltempbasal?.visibility = View.GONE
+ }
+ }
+
+ actions_fill?.visibility =
+ if (!pump.pumpDescription.isRefillingCapable || !pump.isInitialized || pump.isSuspended) View.GONE
+ else View.VISIBLE
+
+ actions_temptarget?.visibility = if (!Config.APS) View.GONE else View.VISIBLE
+ actions_tddstats?.visibility = if (!pump.pumpDescription.supportsTDDs) View.GONE else View.VISIBLE
+ checkPumpCustomActions()
+ }
+
+ private fun checkPumpCustomActions() {
+ val activePump = ConfigBuilderPlugin.getPlugin().activePump ?: return
+ val customActions = activePump.customActions ?: return
+ removePumpCustomActions()
+
+ for (customAction in customActions) {
+ if (!customAction.isEnabled) continue
+
+ val btn = SingleClickButton(context, null, android.R.attr.buttonStyle)
+ btn.text = MainApp.gs(customAction.name)
+
+ val layoutParams = LinearLayout.LayoutParams(
+ LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT, 0.5f)
+ layoutParams.setMargins(20, 8, 20, 8) // 10,3,10,3
+
+ btn.layoutParams = layoutParams
+ btn.setOnClickListener { v ->
+ val b = v as SingleClickButton
+ val action = this.pumpCustomActions[b.text.toString()]
+ ConfigBuilderPlugin.getPlugin().activePump!!.executeCustomAction(action!!.customActionType)
+ }
+
+ val top = resources.getDrawable(customAction.iconResourceId)
+ btn.setCompoundDrawablesWithIntrinsicBounds(null, top, null, null)
+
+ action_buttons_layout?.addView(btn)
+
+ this.pumpCustomActions[MainApp.gs(customAction.name)] = customAction
+ this.pumpCustomButtons.add(btn)
+ }
+ }
+
+ private fun removePumpCustomActions() {
+ for (customButton in pumpCustomButtons) action_buttons_layout?.removeView(customButton)
+ pumpCustomButtons.clear()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsPlugin.java
deleted file mode 100644
index 5d47206e5c..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsPlugin.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package info.nightscout.androidaps.plugins.general.actions;
-
-import info.nightscout.androidaps.R;
-import info.nightscout.androidaps.interfaces.PluginBase;
-import info.nightscout.androidaps.interfaces.PluginDescription;
-import info.nightscout.androidaps.interfaces.PluginType;
-
-/**
- * Created by mike on 05.11.2016.
- */
-
-public class ActionsPlugin extends PluginBase {
-
- public ActionsPlugin() {
- super(new PluginDescription()
- .mainType(PluginType.GENERAL)
- .fragmentClass(ActionsFragment.class.getName())
- .pluginName(R.string.actions)
- .shortName(R.string.actions_shortname)
- .description(R.string.description_actions)
- );
- }
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsPlugin.kt
new file mode 100644
index 0000000000..04afb826a2
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsPlugin.kt
@@ -0,0 +1,13 @@
+package info.nightscout.androidaps.plugins.general.actions
+
+import info.nightscout.androidaps.R
+import info.nightscout.androidaps.interfaces.PluginBase
+import info.nightscout.androidaps.interfaces.PluginDescription
+import info.nightscout.androidaps.interfaces.PluginType
+
+object ActionsPlugin : PluginBase(PluginDescription()
+ .mainType(PluginType.GENERAL)
+ .fragmentClass(ActionsFragment::class.qualifiedName)
+ .pluginName(R.string.actions)
+ .shortName(R.string.actions_shortname)
+ .description(R.string.description_actions))
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/defs/CustomAction.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/defs/CustomAction.java
index e5e119baad..5e5f707928 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/defs/CustomAction.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/defs/CustomAction.java
@@ -12,31 +12,36 @@ public class CustomAction {
private String iconName;
private CustomActionType customActionType;
private int iconResourceId;
+ private boolean enabled = true;
public CustomAction(int nameResourceId, CustomActionType actionType) {
- this.name = nameResourceId;
- this.customActionType = actionType;
- this.iconResourceId = R.drawable.icon_actions_profileswitch;
+ this(nameResourceId, actionType, R.drawable.icon_actions_profileswitch, true);
}
+
public CustomAction(int nameResourceId, CustomActionType actionType, int iconResourceId) {
+ this(nameResourceId, actionType, iconResourceId, true);
+ }
+
+ public CustomAction(int nameResourceId, CustomActionType actionType, boolean enabled) {
+ this(nameResourceId, actionType, R.drawable.icon_actions_profileswitch, enabled);
+ }
+
+ public CustomAction(int nameResourceId, CustomActionType actionType, int iconResourceId, boolean enabled) {
this.name = nameResourceId;
this.customActionType = actionType;
this.iconResourceId = iconResourceId;
+ this.enabled = enabled;
}
public int getName() {
-
return name;
}
-
-
public CustomActionType getCustomActionType() {
-
return customActionType;
}
@@ -44,4 +49,15 @@ public class CustomAction {
public int getIconResourceId() {
return iconResourceId;
}
+
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/dialogs/FillDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/dialogs/FillDialog.java
index 94d548a444..77e4f85ea0 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/dialogs/FillDialog.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/dialogs/FillDialog.java
@@ -3,8 +3,8 @@ package info.nightscout.androidaps.plugins.general.actions.dialogs;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
-import android.support.v4.app.DialogFragment;
-import android.support.v7.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
+import androidx.appcompat.app.AlertDialog;
import android.text.Editable;
import android.text.Html;
import android.text.TextWatcher;
@@ -103,7 +103,7 @@ public class FillDialog extends DialogFragment implements OnClickListener {
Double maxInsulin = MainApp.getConstraintChecker().getMaxBolusAllowed().value();
double bolusstep = ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().bolusStep;
editInsulin = view.findViewById(R.id.fill_insulinamount);
- editInsulin.setParams(0d, 0d, maxInsulin, bolusstep, DecimalFormatter.pumpSupportedBolusFormat(), false, textWatcher);
+ editInsulin.setParams(0d, 0d, maxInsulin, bolusstep, DecimalFormatter.pumpSupportedBolusFormat(), false, view.findViewById(R.id.ok), textWatcher);
Button preset1Button = view.findViewById(R.id.fill_preset_button1);
@@ -184,7 +184,7 @@ public class FillDialog extends DialogFragment implements OnClickListener {
confirmMessage.add("");
confirmMessage.add(MainApp.gs(R.string.bolus) + ": " + "" + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints) + "U" + " ");
if (Math.abs(insulinAfterConstraints - insulin) > 0.01d)
- confirmMessage.add("" + MainApp.gs(R.string.bolusconstraintapplied) + " ");
+ confirmMessage.add(MainApp.gs(R.string.bolusconstraintappliedwarning, MainApp.gc(R.color.warning), insulin, insulinAfterConstraints));
}
if (pumpSiteChangeCheckbox.isChecked())
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/dialogs/NewExtendedBolusDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/dialogs/NewExtendedBolusDialog.java
index 579e9e2f06..99e877efcc 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/dialogs/NewExtendedBolusDialog.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/dialogs/NewExtendedBolusDialog.java
@@ -4,8 +4,8 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
-import android.support.v4.app.DialogFragment;
-import android.support.v7.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
+import androidx.appcompat.app.AlertDialog;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -42,12 +42,12 @@ public class NewExtendedBolusDialog extends DialogFragment implements View.OnCli
Double maxInsulin = MainApp.getConstraintChecker().getMaxExtendedBolusAllowed().value();
editInsulin = (NumberPicker) view.findViewById(R.id.overview_newextendedbolus_insulin);
- editInsulin.setParams(0d, 0d, maxInsulin, 0.1d, new DecimalFormat("0.00"), false);
+ editInsulin.setParams(0d, 0d, maxInsulin, 0.1d, new DecimalFormat("0.00"), false, view.findViewById(R.id.ok));
double extendedDurationStep = ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().extendedBolusDurationStep;
double extendedMaxDuration = ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().extendedBolusMaxDuration;
editDuration = (NumberPicker) view.findViewById(R.id.overview_newextendedbolus_duration);
- editDuration.setParams(extendedDurationStep, extendedDurationStep, extendedMaxDuration, extendedDurationStep, new DecimalFormat("0"), false);
+ editDuration.setParams(extendedDurationStep, extendedDurationStep, extendedMaxDuration, extendedDurationStep, new DecimalFormat("0"), false, view.findViewById(R.id.ok));
view.findViewById(R.id.ok).setOnClickListener(this);
view.findViewById(R.id.cancel).setOnClickListener(this);
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/dialogs/NewTempBasalDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/dialogs/NewTempBasalDialog.java
index 80969b51b0..cad2e22f85 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/dialogs/NewTempBasalDialog.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/dialogs/NewTempBasalDialog.java
@@ -3,8 +3,8 @@ package info.nightscout.androidaps.plugins.general.actions.dialogs;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
-import android.support.v4.app.DialogFragment;
-import android.support.v7.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
+import androidx.appcompat.app.AlertDialog;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -66,17 +66,17 @@ public class NewTempBasalDialog extends DialogFragment implements View.OnClickLi
basalPercent = (NumberPicker) view.findViewById(R.id.overview_newtempbasal_basalpercentinput);
double maxTempPercent = pumpDescription.maxTempPercent;
double tempPercentStep = pumpDescription.tempPercentStep;
- basalPercent.setParams(100d, 0d, maxTempPercent, tempPercentStep, new DecimalFormat("0"), true);
+ basalPercent.setParams(100d, 0d, maxTempPercent, tempPercentStep, new DecimalFormat("0"), true, view.findViewById(R.id.ok));
Profile profile = ProfileFunctions.getInstance().getProfile();
Double currentBasal = profile != null ? profile.getBasal() : 0d;
basalAbsolute = (NumberPicker) view.findViewById(R.id.overview_newtempbasal_basalabsoluteinput);
- basalAbsolute.setParams(currentBasal, 0d, pumpDescription.maxTempAbsolute, pumpDescription.tempAbsoluteStep, new DecimalFormat("0.00"), true);
+ basalAbsolute.setParams(currentBasal, 0d, pumpDescription.maxTempAbsolute, pumpDescription.tempAbsoluteStep, new DecimalFormat("0.00"), true, view.findViewById(R.id.ok));
double tempDurationStep = pumpDescription.tempDurationStep;
double tempMaxDuration = pumpDescription.tempMaxDuration;
duration = (NumberPicker) view.findViewById(R.id.overview_newtempbasal_duration);
- duration.setParams(tempDurationStep, tempDurationStep, tempMaxDuration, tempDurationStep, new DecimalFormat("0"), false);
+ duration.setParams(tempDurationStep, tempDurationStep, tempMaxDuration, tempDurationStep, new DecimalFormat("0"), false, view.findViewById(R.id.ok));
if ((pumpDescription.tempBasalStyle & PumpDescription.PERCENT) == PumpDescription.PERCENT && (pumpDescription.tempBasalStyle & PumpDescription.ABSOLUTE) == PumpDescription.ABSOLUTE) {
// Both allowed
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/AutomationEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/AutomationEvent.java
new file mode 100644
index 0000000000..6eb3be382b
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/AutomationEvent.java
@@ -0,0 +1,98 @@
+package info.nightscout.androidaps.plugins.general.automation;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import info.nightscout.androidaps.plugins.general.automation.actions.Action;
+import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger;
+import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector;
+
+public class AutomationEvent {
+
+ private Trigger trigger = new TriggerConnector();
+ private List actions = new ArrayList<>();
+ private String title;
+ private boolean enabled = true;
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public void setTrigger(Trigger trigger) {
+ this.trigger = trigger;
+ }
+
+ public Trigger getTrigger() {
+ return trigger;
+ }
+
+ public List getActions() {
+ return actions;
+ }
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public void setEnabled(boolean newState) {
+ enabled = newState;
+ }
+
+ public TriggerConnector getPreconditions() {
+ TriggerConnector trigger = new TriggerConnector(TriggerConnector.Type.AND);
+ for (Action action : actions) {
+ if (action.precondition != null)
+ trigger.add(action.precondition);
+ }
+ return trigger;
+ }
+
+ public void addAction(Action action) {
+ actions.add(action);
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public String toJSON() {
+ JSONObject o = new JSONObject();
+ try {
+ // title
+ o.put("title", title);
+ o.put("enabled", enabled);
+ // trigger
+ o.put("trigger", trigger.toJSON());
+ // actions
+ JSONArray array = new JSONArray();
+ for (Action a : actions) {
+ array.put(a.toJSON());
+ }
+ o.put("actions", array);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return o.toString();
+ }
+
+ public AutomationEvent fromJSON(String data) {
+ try {
+ JSONObject d = new JSONObject(data);
+ title = d.optString("title", "");
+ enabled = d.optBoolean("enabled", true);
+ trigger = Trigger.instantiate(d.getString("trigger"));
+ JSONArray array = d.getJSONArray("actions");
+ actions.clear();
+ for (int i = 0; i < array.length(); i++) {
+ actions.add(Action.instantiate(new JSONObject(array.getString(i))));
+ }
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return this;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/AutomationFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/AutomationFragment.kt
new file mode 100644
index 0000000000..d1135c21ed
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/AutomationFragment.kt
@@ -0,0 +1,84 @@
+package info.nightscout.androidaps.plugins.general.automation
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import androidx.recyclerview.widget.LinearLayoutManager
+import info.nightscout.androidaps.R
+import info.nightscout.androidaps.plugins.bus.RxBus
+import info.nightscout.androidaps.plugins.general.automation.dialogs.EditEventDialog
+import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationDataChanged
+import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationUpdateGui
+import info.nightscout.androidaps.utils.FabricPrivacy
+import info.nightscout.androidaps.utils.plusAssign
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.disposables.CompositeDisposable
+import kotlinx.android.synthetic.main.automation_fragment.*
+
+class AutomationFragment : Fragment() {
+
+ private var disposable: CompositeDisposable = CompositeDisposable()
+ private var eventListAdapter: EventListAdapter? = null
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ return inflater.inflate(R.layout.automation_fragment, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ eventListAdapter = EventListAdapter(AutomationPlugin.automationEvents, fragmentManager, activity)
+ automation_eventListView.layoutManager = LinearLayoutManager(context)
+ automation_eventListView.adapter = eventListAdapter
+
+ automation_fabAddEvent.setOnClickListener {
+ val dialog = EditEventDialog()
+ val args = Bundle()
+ args.putString("event", AutomationEvent().toJSON())
+ args.putInt("position", -1) // New event
+ dialog.arguments = args
+ fragmentManager?.let { dialog.show(it, "EditEventDialog") }
+ }
+
+ }
+
+ @Synchronized
+ override fun onResume() {
+ super.onResume()
+ disposable += RxBus
+ .toObservable(EventAutomationUpdateGui::class.java)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe({
+ updateGui()
+ }, {
+ FabricPrivacy.logException(it)
+ })
+ disposable += RxBus
+ .toObservable(EventAutomationDataChanged::class.java)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe({
+ eventListAdapter?.notifyDataSetChanged()
+ }, {
+ FabricPrivacy.logException(it)
+ })
+ updateGui()
+ }
+
+ @Synchronized
+ override fun onPause() {
+ super.onPause()
+ disposable.clear()
+ }
+
+ @Synchronized
+ private fun updateGui() {
+ eventListAdapter?.notifyDataSetChanged()
+ val sb = StringBuilder()
+ for (l in AutomationPlugin.executionLog.reversed())
+ sb.append(l).append("\n")
+ automation_logView?.text = sb.toString()
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/AutomationPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/AutomationPlugin.kt
new file mode 100644
index 0000000000..8b78ae6458
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/AutomationPlugin.kt
@@ -0,0 +1,235 @@
+package info.nightscout.androidaps.plugins.general.automation
+
+import android.content.Intent
+import android.os.Build
+import android.os.Handler
+import info.nightscout.androidaps.MainApp
+import info.nightscout.androidaps.R
+import info.nightscout.androidaps.events.EventChargingState
+import info.nightscout.androidaps.events.EventLocationChange
+import info.nightscout.androidaps.events.EventNetworkChange
+import info.nightscout.androidaps.events.EventPreferenceChange
+import info.nightscout.androidaps.interfaces.PluginBase
+import info.nightscout.androidaps.interfaces.PluginDescription
+import info.nightscout.androidaps.interfaces.PluginType
+import info.nightscout.androidaps.logging.L
+import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
+import info.nightscout.androidaps.plugins.bus.RxBus
+import info.nightscout.androidaps.plugins.general.automation.actions.*
+import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationDataChanged
+import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationUpdateGui
+import info.nightscout.androidaps.plugins.general.automation.triggers.*
+import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished
+import info.nightscout.androidaps.queue.Callback
+import info.nightscout.androidaps.services.LocationService
+import info.nightscout.androidaps.utils.*
+import io.reactivex.disposables.CompositeDisposable
+import io.reactivex.schedulers.Schedulers
+import org.json.JSONArray
+import org.json.JSONException
+import org.json.JSONObject
+import org.slf4j.LoggerFactory
+import java.util.*
+
+object AutomationPlugin : PluginBase(PluginDescription()
+ .mainType(PluginType.GENERAL)
+ .fragmentClass(AutomationFragment::class.qualifiedName)
+ .pluginName(R.string.automation)
+ .shortName(R.string.automation_short)
+ .preferencesId(R.xml.pref_automation)
+ .description(R.string.automation_description)) {
+
+ private val log = LoggerFactory.getLogger(L.AUTOMATION)
+ private var disposable: CompositeDisposable = CompositeDisposable()
+
+ private const val key_AUTOMATION_EVENTS = "AUTOMATION_EVENTS"
+
+ val automationEvents = ArrayList()
+ var executionLog: MutableList = ArrayList()
+
+ private val loopHandler = Handler()
+ private lateinit var refreshLoop: Runnable
+
+ init {
+ refreshLoop = Runnable {
+ processActions()
+ loopHandler.postDelayed(refreshLoop, T.mins(1).msecs())
+ }
+ }
+
+ override fun onStart() {
+ val context = MainApp.instance().applicationContext
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
+ context.startForegroundService(Intent(context, LocationService::class.java))
+ else
+ context.startService(Intent(context, LocationService::class.java))
+
+ super.onStart()
+ loadFromSP()
+ loopHandler.postDelayed(refreshLoop, T.mins(1).msecs())
+
+ disposable += RxBus
+ .toObservable(EventPreferenceChange::class.java)
+ .observeOn(Schedulers.io())
+ .subscribe({ e ->
+ if (e.isChanged(R.string.key_location)) {
+ context.stopService(Intent(context, LocationService::class.java))
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
+ context.startForegroundService(Intent(context, LocationService::class.java))
+ else
+ context.startService(Intent(context, LocationService::class.java))
+ }
+ }, {
+ FabricPrivacy.logException(it)
+ })
+ disposable += RxBus
+ .toObservable(EventAutomationDataChanged::class.java)
+ .observeOn(Schedulers.io())
+ .subscribe({ storeToSP() }, {
+ FabricPrivacy.logException(it)
+ })
+ disposable += RxBus
+ .toObservable(EventLocationChange::class.java)
+ .observeOn(Schedulers.io())
+ .subscribe({ e ->
+ e?.let {
+ log.debug("Grabbed location: $it.location.latitude $it.location.longitude Provider: $it.location.provider")
+ processActions()
+ }
+ }, {
+ FabricPrivacy.logException(it)
+ })
+ disposable += RxBus
+ .toObservable(EventChargingState::class.java)
+ .observeOn(Schedulers.io())
+ .subscribe({ processActions() }, {
+ FabricPrivacy.logException(it)
+ })
+ disposable += RxBus
+ .toObservable(EventNetworkChange::class.java)
+ .observeOn(Schedulers.io())
+ .subscribe({ processActions() }, {
+ FabricPrivacy.logException(it)
+ })
+ disposable += RxBus
+ .toObservable(EventAutosensCalculationFinished::class.java)
+ .observeOn(Schedulers.io())
+ .subscribe({ processActions() }, {
+ FabricPrivacy.logException(it)
+ })
+ }
+
+ override fun onStop() {
+ disposable.clear()
+ loopHandler.removeCallbacks(refreshLoop)
+ val context = MainApp.instance().applicationContext
+ context.stopService(Intent(context, LocationService::class.java))
+ super.onStop()
+ }
+
+ private fun storeToSP() {
+ val array = JSONArray()
+ try {
+ for (event in automationEvents) {
+ array.put(JSONObject(event.toJSON()))
+ }
+ } catch (e: JSONException) {
+ e.printStackTrace()
+ }
+
+ SP.putString(key_AUTOMATION_EVENTS, array.toString())
+ }
+
+ private fun loadFromSP() {
+ automationEvents.clear()
+ val data = SP.getString(key_AUTOMATION_EVENTS, "")
+ if (data != "") {
+ try {
+ val array = JSONArray(data)
+ for (i in 0 until array.length()) {
+ val o = array.getJSONObject(i)
+ val event = AutomationEvent().fromJSON(o.toString())
+ automationEvents.add(event)
+ }
+ } catch (e: JSONException) {
+ e.printStackTrace()
+ }
+ }
+ }
+
+ @Synchronized
+ private fun processActions() {
+ if (!isEnabled(PluginType.GENERAL))
+ return
+ if (LoopPlugin.getPlugin().isSuspended) {
+ if (L.isEnabled(L.AUTOMATION))
+ log.debug("Loop deactivated")
+ return
+ }
+
+ if (L.isEnabled(L.AUTOMATION))
+ log.debug("processActions")
+ for (event in automationEvents) {
+ if (event.isEnabled && event.trigger.shouldRun() && event.preconditions.shouldRun()) {
+ val actions = event.actions
+ for (action in actions) {
+ action.doAction(object : Callback() {
+ override fun run() {
+ val sb = StringBuilder()
+ sb.append(DateUtil.timeString(DateUtil.now()))
+ sb.append(" ")
+ sb.append(if (result.success) "☺" else "X")
+ sb.append(" ")
+ sb.append(event.title)
+ sb.append(": ")
+ sb.append(action.shortDescription())
+ sb.append(": ")
+ sb.append(result.comment)
+ executionLog.add(sb.toString())
+ if (L.isEnabled(L.AUTOMATION))
+ log.debug("Executed: $sb")
+ RxBus.send(EventAutomationUpdateGui())
+ }
+ })
+ }
+ event.trigger.executed(DateUtil.now())
+ }
+ }
+ storeToSP() // save last run time
+ }
+
+ fun getActionDummyObjects(): List {
+ return listOf(
+ //ActionLoopDisable(),
+ //ActionLoopEnable(),
+ //ActionLoopResume(),
+ //ActionLoopSuspend(),
+ ActionStartTempTarget(),
+ ActionStopTempTarget(),
+ ActionNotification(),
+ ActionProfileSwitchPercent(),
+ ActionProfileSwitch(),
+ ActionSendSMS()
+ )
+ }
+
+ fun getTriggerDummyObjects(): List {
+ return listOf(
+ TriggerTime(),
+ TriggerRecurringTime(),
+ TriggerTimeRange(),
+ TriggerBg(),
+ TriggerDelta(),
+ TriggerIob(),
+ TriggerCOB(),
+ TriggerProfilePercent(),
+ TriggerTempTarget(),
+ TriggerWifiSsid(),
+ TriggerLocation(),
+ TriggerAutosensValue(),
+ TriggerBolusAgo(),
+ TriggerPumpLastConnection()
+ )
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/EventListAdapter.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/EventListAdapter.java
new file mode 100644
index 0000000000..08079a9110
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/EventListAdapter.java
@@ -0,0 +1,138 @@
+package info.nightscout.androidaps.plugins.general.automation;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.CheckBox;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import androidx.annotation.DrawableRes;
+import androidx.annotation.NonNull;
+import androidx.fragment.app.FragmentManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import java.util.HashSet;
+import java.util.List;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.plugins.bus.RxBus;
+import info.nightscout.androidaps.plugins.general.automation.actions.Action;
+import info.nightscout.androidaps.plugins.general.automation.dialogs.EditEventDialog;
+import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationDataChanged;
+import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector;
+import info.nightscout.androidaps.utils.OKDialog;
+
+class EventListAdapter extends RecyclerView.Adapter {
+ private final List eventList;
+ private final FragmentManager fragmentManager;
+ private final Activity activity;
+
+ EventListAdapter(List events, FragmentManager fragmentManager, Activity activity) {
+ this.eventList = events;
+ this.fragmentManager = fragmentManager;
+ this.activity = activity;
+ }
+
+ @NonNull
+ @Override
+ public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.automation_event_item, parent, false);
+ return new ViewHolder(v, parent.getContext());
+ }
+
+ private void addImage(@DrawableRes int res, Context context, LinearLayout layout) {
+ ImageView iv = new ImageView(context);
+ iv.setImageResource(res);
+ iv.setLayoutParams(new LinearLayout.LayoutParams(MainApp.dpToPx(24), MainApp.dpToPx(24)));
+ layout.addView(iv);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
+ final AutomationEvent event = eventList.get(position);
+ holder.eventTitle.setText(event.getTitle());
+ holder.enabled.setChecked(event.isEnabled());
+ holder.iconLayout.removeAllViews();
+
+ // trigger icons
+ HashSet triggerIcons = new HashSet<>();
+ TriggerConnector.fillIconSet((TriggerConnector) event.getTrigger(), triggerIcons);
+ for (int res : triggerIcons) {
+ addImage(res, holder.context, holder.iconLayout);
+ }
+
+ // arrow icon
+ ImageView iv = new ImageView(holder.context);
+ iv.setImageResource(R.drawable.ic_arrow_forward_white_24dp);
+ iv.setLayoutParams(new LinearLayout.LayoutParams(MainApp.dpToPx(24), MainApp.dpToPx(24)));
+ iv.setPadding(MainApp.dpToPx(4), 0, MainApp.dpToPx(4), 0);
+ holder.iconLayout.addView(iv);
+
+ // action icons
+ HashSet actionIcons = new HashSet<>();
+ for (Action action : event.getActions()) {
+ if (action.icon().isPresent())
+ actionIcons.add(action.icon().get());
+ }
+ for (int res : actionIcons) {
+ addImage(res, holder.context, holder.iconLayout);
+ }
+
+ // enabled event
+ holder.enabled.setOnClickListener(v -> {
+ event.setEnabled((holder.enabled.isChecked()));
+ RxBus.INSTANCE.send(new EventAutomationDataChanged());
+ });
+
+ // remove event
+ holder.iconTrash.setOnClickListener(v ->
+ OKDialog.showConfirmation(activity, MainApp.gs(R.string.removerecord) + " " + event.getTitle(), () -> {
+ eventList.remove(event);
+ RxBus.INSTANCE.send(new EventAutomationDataChanged());
+ })
+ );
+
+ // edit event
+ holder.rootLayout.setOnClickListener(v -> {
+ //EditEventDialog dialog = EditEventDialog.Companion.newInstance(event, false);
+ EditEventDialog dialog = new EditEventDialog();
+ Bundle args = new Bundle();
+ args.putString("event", event.toJSON());
+ args.putInt("position", position);
+ dialog.setArguments(args);
+ if (fragmentManager != null)
+ dialog.show(fragmentManager, "EditEventDialog");
+ });
+ }
+
+ @Override
+ public int getItemCount() {
+ return eventList.size();
+ }
+
+ static class ViewHolder extends RecyclerView.ViewHolder {
+ final RelativeLayout rootLayout;
+ final LinearLayout iconLayout;
+ final TextView eventTitle;
+ final Context context;
+ final ImageView iconTrash;
+ final CheckBox enabled;
+
+ ViewHolder(View view, Context context) {
+ super(view);
+ this.context = context;
+ eventTitle = view.findViewById(R.id.viewEventTitle);
+ rootLayout = view.findViewById(R.id.rootLayout);
+ iconLayout = view.findViewById(R.id.iconLayout);
+ iconTrash = view.findViewById(R.id.iconTrash);
+ enabled = view.findViewById(R.id.automation_enabled);
+ }
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/Action.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/Action.java
new file mode 100644
index 0000000000..796f023f1d
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/Action.java
@@ -0,0 +1,104 @@
+package info.nightscout.androidaps.plugins.general.automation.actions;
+
+import android.widget.LinearLayout;
+
+import com.google.common.base.Optional;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import javax.annotation.Nullable;
+
+import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger;
+import info.nightscout.androidaps.queue.Callback;
+
+/*
+ Action ideas:
+
+ * cancel temp target
+ * change preference setting
+ * enable/disable plugin
+ * create notification
+ * create ugly alarm
+ * create profile switch
+ * set/cancel tbr
+ * set/cancel extended bolus
+ * run bolus wizard
+
+ Trigger ideas:
+
+ * location (close to)
+ * connected to specific wifi
+ * internet available/not available
+ * nsclient connected/disconnected
+ * iob
+ * cob
+ * autosens value
+ * delta, short delta, long delta
+ * last bolus ago
+ * is tbr running
+ * bolus wizard result
+ * loop is enabled, disabled, suspended, running
+
+*/
+
+
+public abstract class Action {
+
+ public Trigger precondition = null;
+
+ public abstract int friendlyName();
+
+ public abstract String shortDescription();
+
+ public abstract void doAction(Callback callback);
+
+ public void generateDialog(LinearLayout root) {
+ }
+
+ public boolean hasDialog() {
+ return false;
+ }
+
+ public String toJSON() {
+ JSONObject o = new JSONObject();
+ try {
+ o.put("type", this.getClass().getName());
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return o.toString();
+ }
+
+ public abstract Optional icon();
+
+ public Action fromJSON(String data) {
+ return this;
+ }
+
+ @Nullable
+ public static Action instantiate(JSONObject object) {
+ try {
+ String type = object.getString("type");
+ JSONObject data = object.optJSONObject("data");
+ Class clazz = Class.forName(type);
+ return ((Action) clazz.newInstance()).fromJSON(data != null ? data.toString() : "");
+ } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | JSONException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ public void apply(Action a) {
+ try {
+ JSONObject object = new JSONObject(a.toJSON());
+ String type = object.getString("type");
+ JSONObject data = object.getJSONObject("data");
+ if (type.equals(getClass().getName())) {
+ fromJSON(data.toString());
+ }
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionLoopDisable.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionLoopDisable.java
new file mode 100644
index 0000000000..cf8326a0f2
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionLoopDisable.java
@@ -0,0 +1,49 @@
+package info.nightscout.androidaps.plugins.general.automation.actions;
+
+import com.google.common.base.Optional;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.data.PumpEnactResult;
+import info.nightscout.androidaps.events.EventRefreshOverview;
+import info.nightscout.androidaps.interfaces.PluginType;
+import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
+import info.nightscout.androidaps.plugins.bus.RxBus;
+import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
+import info.nightscout.androidaps.queue.Callback;
+
+public class ActionLoopDisable extends Action {
+ @Override
+ public int friendlyName() {
+ return R.string.disableloop;
+ }
+
+ @Override
+ public String shortDescription() {
+ return MainApp.gs(R.string.disableloop);
+ }
+
+ @Override
+ public void doAction(Callback callback) {
+ if (LoopPlugin.getPlugin().isEnabled(PluginType.LOOP)) {
+ LoopPlugin.getPlugin().setPluginEnabled(PluginType.LOOP, false);
+ ConfigBuilderPlugin.getPlugin().storeSettings("ActionLoopDisable");
+ ConfigBuilderPlugin.getPlugin().getCommandQueue().cancelTempBasal(true, new Callback() {
+ @Override
+ public void run() {
+ RxBus.INSTANCE.send(new EventRefreshOverview("ActionLoopDisable"));
+ if (callback != null)
+ callback.result(result).run();
+ }
+ });
+ } else {
+ if (callback != null)
+ callback.result(new PumpEnactResult().success(true).comment(R.string.alreadydisabled)).run();
+ }
+ }
+
+ @Override
+ public Optional icon() {
+ return Optional.of(R.drawable.ic_stop_24dp);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionLoopEnable.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionLoopEnable.java
new file mode 100644
index 0000000000..f33bec8e3f
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionLoopEnable.java
@@ -0,0 +1,44 @@
+package info.nightscout.androidaps.plugins.general.automation.actions;
+
+import com.google.common.base.Optional;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.data.PumpEnactResult;
+import info.nightscout.androidaps.events.EventRefreshOverview;
+import info.nightscout.androidaps.interfaces.PluginType;
+import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
+import info.nightscout.androidaps.plugins.bus.RxBus;
+import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
+import info.nightscout.androidaps.queue.Callback;
+
+public class ActionLoopEnable extends Action {
+ @Override
+ public int friendlyName() {
+ return R.string.enableloop;
+ }
+
+ @Override
+ public String shortDescription() {
+ return MainApp.gs(R.string.enableloop);
+ }
+
+ @Override
+ public void doAction(Callback callback) {
+ if (!LoopPlugin.getPlugin().isEnabled(PluginType.LOOP)) {
+ LoopPlugin.getPlugin().setPluginEnabled(PluginType.LOOP, true);
+ ConfigBuilderPlugin.getPlugin().storeSettings("ActionLoopEnable");
+ RxBus.INSTANCE.send(new EventRefreshOverview("ActionLoopEnable"));
+ if (callback != null)
+ callback.result(new PumpEnactResult().success(true).comment(R.string.ok)).run();
+ } else {
+ if (callback != null)
+ callback.result(new PumpEnactResult().success(true).comment(R.string.alreadyenabled)).run();
+ }
+ }
+
+ @Override
+ public Optional icon() {
+ return Optional.of(R.drawable.ic_play_circle_outline_24dp);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionLoopResume.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionLoopResume.java
new file mode 100644
index 0000000000..38e5dee33a
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionLoopResume.java
@@ -0,0 +1,45 @@
+package info.nightscout.androidaps.plugins.general.automation.actions;
+
+import com.google.common.base.Optional;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.data.PumpEnactResult;
+import info.nightscout.androidaps.events.EventRefreshOverview;
+import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
+import info.nightscout.androidaps.plugins.bus.RxBus;
+import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
+import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
+import info.nightscout.androidaps.queue.Callback;
+
+public class ActionLoopResume extends Action {
+ @Override
+ public int friendlyName() {
+ return R.string.resumeloop;
+ }
+
+ @Override
+ public String shortDescription() {
+ return MainApp.gs(R.string.resumeloop);
+ }
+
+ @Override
+ public void doAction(Callback callback) {
+ if (LoopPlugin.getPlugin().isSuspended()) {
+ LoopPlugin.getPlugin().suspendTo(0);
+ ConfigBuilderPlugin.getPlugin().storeSettings("ActionLoopResume");
+ NSUpload.uploadOpenAPSOffline(0);
+ RxBus.INSTANCE.send(new EventRefreshOverview("ActionLoopResume"));
+ if (callback != null)
+ callback.result(new PumpEnactResult().success(true).comment(R.string.ok)).run();
+ } else {
+ if (callback != null)
+ callback.result(new PumpEnactResult().success(true).comment(R.string.notsuspended)).run();
+ }
+ }
+
+ @Override
+ public Optional icon() {
+ return Optional.of(R.drawable.ic_replay_24dp);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionLoopSuspend.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionLoopSuspend.java
new file mode 100644
index 0000000000..bd221d8f81
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionLoopSuspend.java
@@ -0,0 +1,91 @@
+package info.nightscout.androidaps.plugins.general.automation.actions;
+
+import android.widget.LinearLayout;
+
+import com.google.common.base.Optional;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.data.PumpEnactResult;
+import info.nightscout.androidaps.events.EventRefreshOverview;
+import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
+import info.nightscout.androidaps.plugins.bus.RxBus;
+import info.nightscout.androidaps.plugins.general.automation.elements.InputDuration;
+import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement;
+import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
+import info.nightscout.androidaps.queue.Callback;
+import info.nightscout.androidaps.utils.JsonHelper;
+
+public class ActionLoopSuspend extends Action {
+ public InputDuration minutes = new InputDuration(0, InputDuration.TimeUnit.MINUTES);
+
+ @Override
+ public int friendlyName() {
+ return R.string.suspendloop;
+ }
+
+ @Override
+ public String shortDescription() {
+ return MainApp.gs(R.string.suspendloopforXmin, minutes.getMinutes());
+ }
+
+ @Override
+ public void doAction(Callback callback) {
+ if (!LoopPlugin.getPlugin().isSuspended()) {
+ LoopPlugin.getPlugin().suspendLoop(minutes.getMinutes());
+ RxBus.INSTANCE.send(new EventRefreshOverview("ActionLoopSuspend"));
+ if (callback != null)
+ callback.result(new PumpEnactResult().success(true).comment(R.string.ok)).run();
+ } else {
+ if (callback != null)
+ callback.result(new PumpEnactResult().success(true).comment(R.string.alreadysuspended)).run();
+ }
+ }
+
+ @Override
+ public Optional icon() {
+ return Optional.of(R.drawable.ic_pause_circle_outline_24dp);
+ }
+
+ @Override
+ public String toJSON() {
+ JSONObject o = new JSONObject();
+ JSONObject data = new JSONObject();
+ try {
+ data.put("minutes", minutes.getMinutes());
+ o.put("type", this.getClass().getName());
+ o.put("data", data);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return o.toString();
+ }
+
+ @Override
+ public Action fromJSON(String data) {
+ try {
+ JSONObject o = new JSONObject(data);
+ minutes.setMinutes(JsonHelper.safeGetInt(o, "minutes"));
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return this;
+ }
+
+ @Override
+ public boolean hasDialog() {
+ return true;
+ }
+
+ @Override
+ public void generateDialog(LinearLayout root) {
+
+ new LayoutBuilder()
+ .add(new LabelWithElement(MainApp.gs(R.string.careportal_newnstreatment_duration_min_label), "", minutes))
+ .build(root);
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionNotification.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionNotification.java
new file mode 100644
index 0000000000..1f7ad543c2
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionNotification.java
@@ -0,0 +1,91 @@
+package info.nightscout.androidaps.plugins.general.automation.actions;
+
+import android.widget.LinearLayout;
+
+import com.google.common.base.Optional;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.data.PumpEnactResult;
+import info.nightscout.androidaps.events.EventRefreshOverview;
+import info.nightscout.androidaps.plugins.bus.RxBus;
+import info.nightscout.androidaps.plugins.general.automation.elements.InputString;
+import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement;
+import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
+import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
+import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification;
+import info.nightscout.androidaps.plugins.general.overview.notifications.Notification;
+import info.nightscout.androidaps.queue.Callback;
+import info.nightscout.androidaps.utils.JsonHelper;
+
+public class ActionNotification extends Action {
+ public InputString text = new InputString();
+
+ @Override
+ public int friendlyName() {
+ return R.string.notification;
+ }
+
+ @Override
+ public String shortDescription() {
+ return MainApp.gs(R.string.notification_message, text.getValue());
+ }
+
+ @Override
+ public void doAction(Callback callback) {
+ Notification notification = new Notification(Notification.USERMESSAGE, text.getValue(), Notification.URGENT);
+ RxBus.INSTANCE.send(new EventNewNotification(notification));
+ NSUpload.uploadError(text.getValue());
+ RxBus.INSTANCE.send(new EventRefreshOverview("ActionNotification"));
+ if (callback != null)
+ callback.result(new PumpEnactResult().success(true).comment(R.string.ok)).run();
+
+ }
+
+ @Override
+ public Optional icon() {
+ return Optional.of(R.drawable.ic_notifications);
+ }
+
+ @Override
+ public String toJSON() {
+ JSONObject o = new JSONObject();
+ JSONObject data = new JSONObject();
+ try {
+ data.put("text", text.getValue());
+ o.put("type", this.getClass().getName());
+ o.put("data", data);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return o.toString();
+ }
+
+ @Override
+ public Action fromJSON(String data) {
+ try {
+ JSONObject o = new JSONObject(data);
+ text.setValue(JsonHelper.safeGetString(o, "text"));
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return this;
+ }
+
+ @Override
+ public boolean hasDialog() {
+ return true;
+ }
+
+ @Override
+ public void generateDialog(LinearLayout root) {
+
+ new LayoutBuilder()
+ .add(new LabelWithElement(MainApp.gs(R.string.message_short), "", text))
+ .build(root);
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionProfileSwitch.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionProfileSwitch.java
new file mode 100644
index 0000000000..50fbb786db
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionProfileSwitch.java
@@ -0,0 +1,118 @@
+package info.nightscout.androidaps.plugins.general.automation.actions;
+
+import android.widget.LinearLayout;
+
+import com.google.common.base.Optional;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.data.ProfileStore;
+import info.nightscout.androidaps.data.PumpEnactResult;
+import info.nightscout.androidaps.interfaces.ProfileInterface;
+import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
+import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
+import info.nightscout.androidaps.plugins.general.automation.elements.InputProfileName;
+import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement;
+import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
+import info.nightscout.androidaps.queue.Callback;
+import info.nightscout.androidaps.utils.JsonHelper;
+
+public class ActionProfileSwitch extends Action {
+ private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
+ public InputProfileName inputProfileName = new InputProfileName(ProfileFunctions.getInstance().getProfileName());
+ String profileName = "";
+
+ public ActionProfileSwitch() {
+ // Prevent action if active profile is already active
+ // but we don't have a trigger IS_NOT_EQUAL
+ // so check is in the doRun()
+ }
+
+ @Override
+ public int friendlyName() {
+ return R.string.profilename;
+ }
+
+ @Override
+ public String shortDescription() {
+ String returned = MainApp.gs(R.string.changengetoprofilename, inputProfileName.getValue());
+ return returned;
+ }
+
+ @Override
+ public void doAction(Callback callback) {
+
+ String activeProfileName = ProfileFunctions.getInstance().getProfileName();
+ //Check for uninitialized profileName
+ if ( profileName.equals("")){ profileName = activeProfileName; }
+
+ if (profileName.equals(activeProfileName)) {
+ // Profile is already switched
+ return;
+ }
+ ProfileInterface activeProfile = ConfigBuilderPlugin.getPlugin().getActiveProfileInterface();
+ if (activeProfile == null) return;
+ ProfileStore profileStore = activeProfile.getProfile();
+ if (profileStore == null) return;
+ if(profileStore.getSpecificProfile(profileName) == null) {
+ if (L.isEnabled(L.AUTOMATION))
+ log.error("Selected profile does not exist! - "+ profileName);
+ return;
+ }
+
+ ProfileFunctions.doProfileSwitch(profileStore, profileName, 0, 100, 0);
+ if (callback != null)
+ callback.result(new PumpEnactResult().success(true).comment(R.string.ok)).run();
+ }
+
+ @Override
+ public void generateDialog(LinearLayout root) {
+ new LayoutBuilder()
+ .add(new LabelWithElement(MainApp.gs(R.string.profilename), "", inputProfileName))
+ .build(root);
+ }
+
+ @Override
+ public boolean hasDialog() {
+ return true;
+ }
+
+ @Override
+ public String toJSON() {
+ JSONObject o = new JSONObject();
+ try {
+ o.put("type", ActionProfileSwitch.class.getName());
+ JSONObject data = new JSONObject();
+ data.put("profileToSwitchTo", inputProfileName.getValue());
+ o.put("data", data);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return o.toString();
+ }
+
+ @Override
+ public Action fromJSON(String data) {
+
+ try {
+ JSONObject d = new JSONObject(data);
+ profileName = JsonHelper.safeGetString(d, "profileToSwitchTo");
+ inputProfileName.setValue(profileName);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return this;
+ }
+
+ @Override
+ public Optional icon() {
+ return Optional.of(R.drawable.icon_actions_profileswitch);
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionProfileSwitchPercent.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionProfileSwitchPercent.java
new file mode 100644
index 0000000000..20b6abb081
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionProfileSwitchPercent.java
@@ -0,0 +1,95 @@
+package info.nightscout.androidaps.plugins.general.automation.actions;
+
+import android.widget.LinearLayout;
+
+import com.google.common.base.Optional;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.data.PumpEnactResult;
+import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
+import info.nightscout.androidaps.plugins.general.automation.elements.Comparator;
+import info.nightscout.androidaps.plugins.general.automation.elements.InputDuration;
+import info.nightscout.androidaps.plugins.general.automation.elements.InputPercent;
+import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement;
+import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
+import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerProfilePercent;
+import info.nightscout.androidaps.queue.Callback;
+import info.nightscout.androidaps.utils.JsonHelper;
+
+public class ActionProfileSwitchPercent extends Action {
+ InputPercent pct = new InputPercent();
+ InputDuration duration = new InputDuration(0, InputDuration.TimeUnit.MINUTES);
+
+ public ActionProfileSwitchPercent() {
+ precondition = new TriggerProfilePercent().comparator(Comparator.Compare.IS_EQUAL).setValue(100);
+ }
+
+ @Override
+ public int friendlyName() {
+ return R.string.profilepercentage;
+ }
+
+ @Override
+ public String shortDescription() {
+ if (duration.getMinutes() == 0)
+ return MainApp.gs(R.string.startprofileforever, (int) pct.getValue());
+ else
+ return MainApp.gs(R.string.startprofile, (int) pct.getValue(), duration.getMinutes());
+ }
+
+ @Override
+ public void doAction(Callback callback) {
+ ProfileFunctions.doProfileSwitch((int) duration.getValue(), (int) pct.getValue(), 0);
+ if (callback != null)
+ callback.result(new PumpEnactResult().success(true).comment(R.string.ok)).run();
+ }
+
+ @Override
+ public void generateDialog(LinearLayout root) {
+ new LayoutBuilder()
+ .add(new LabelWithElement(MainApp.gs(R.string.percent_u), "", pct))
+ .add(new LabelWithElement(MainApp.gs(R.string.careportal_newnstreatment_duration_min_label), "", duration))
+ .build(root);
+ }
+
+ @Override
+ public boolean hasDialog() {
+ return true;
+ }
+
+ @Override
+ public String toJSON() {
+ JSONObject o = new JSONObject();
+ try {
+ o.put("type", ActionProfileSwitchPercent.class.getName());
+ JSONObject data = new JSONObject();
+ data.put("percentage", pct.getValue());
+ data.put("durationInMinutes", duration.getMinutes());
+ o.put("data", data);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return o.toString();
+ }
+
+ @Override
+ public Action fromJSON(String data) {
+ try {
+ JSONObject d = new JSONObject(data);
+ pct.setValue(JsonHelper.safeGetInt(d, "percentage"));
+ duration.setMinutes(JsonHelper.safeGetInt(d, "durationInMinutes"));
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return this;
+ }
+
+ @Override
+ public Optional icon() {
+ return Optional.of(R.drawable.icon_actions_profileswitch);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionSendSMS.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionSendSMS.java
new file mode 100644
index 0000000000..f8afafca75
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionSendSMS.java
@@ -0,0 +1,88 @@
+package info.nightscout.androidaps.plugins.general.automation.actions;
+
+import android.widget.LinearLayout;
+
+import com.google.common.base.Optional;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.data.PumpEnactResult;
+import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.general.automation.elements.InputString;
+import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement;
+import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
+import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin;
+import info.nightscout.androidaps.queue.Callback;
+import info.nightscout.androidaps.utils.JsonHelper;
+
+public class ActionSendSMS extends Action {
+
+ public InputString text = new InputString();
+
+ @Override
+ public int friendlyName() {
+ return R.string.sendsmsactiondescription;
+ }
+
+ @Override
+ public String shortDescription() {
+ return MainApp.gs(R.string.sendsmsactionlabel, text.getValue());
+ }
+
+ @Override
+ public void doAction(Callback callback) {
+ boolean result = SmsCommunicatorPlugin.getPlugin().sendNotificationToAllNumbers(text.getValue());
+ if (callback != null)
+ callback.result(new PumpEnactResult().success(result).comment(result ? R.string.ok : R.string.danar_error)).run();
+
+ }
+
+ @Override
+ public Optional icon() {
+ return Optional.of(R.drawable.ic_notifications);
+ }
+
+ @Override
+ public String toJSON() {
+ JSONObject o = new JSONObject();
+ JSONObject data = new JSONObject();
+ try {
+ data.put("text", text.getValue());
+ o.put("type", this.getClass().getName());
+ o.put("data", data);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return o.toString();
+ }
+
+ @Override
+ public Action fromJSON(String data) {
+ try {
+ JSONObject o = new JSONObject(data);
+ text.setValue(JsonHelper.safeGetString(o, "text"));
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return this;
+ }
+
+ @Override
+ public boolean hasDialog() {
+ return true;
+ }
+
+ @Override
+ public void generateDialog(LinearLayout root) {
+
+ new LayoutBuilder()
+ .add(new LabelWithElement(MainApp.gs(R.string.sendsmsactiontext), "", text))
+ .build(root);
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionStartTempTarget.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionStartTempTarget.java
new file mode 100644
index 0000000000..659bb508eb
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionStartTempTarget.java
@@ -0,0 +1,119 @@
+package info.nightscout.androidaps.plugins.general.automation.actions;
+
+import android.widget.LinearLayout;
+
+import com.google.common.base.Optional;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+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.data.PumpEnactResult;
+import info.nightscout.androidaps.db.Source;
+import info.nightscout.androidaps.db.TempTarget;
+import info.nightscout.androidaps.plugins.general.automation.elements.ComparatorExists;
+import info.nightscout.androidaps.plugins.general.automation.elements.InputDuration;
+import info.nightscout.androidaps.plugins.general.automation.elements.InputTempTarget;
+import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement;
+import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
+import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerTempTarget;
+import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
+import info.nightscout.androidaps.queue.Callback;
+import info.nightscout.androidaps.utils.DateUtil;
+import info.nightscout.androidaps.utils.JsonHelper;
+
+public class ActionStartTempTarget extends Action {
+ String reason = "";
+ InputTempTarget value = new InputTempTarget();
+ InputDuration duration = new InputDuration(0, InputDuration.TimeUnit.MINUTES);
+ private TempTarget tempTarget;
+
+ public ActionStartTempTarget() {
+ precondition = new TriggerTempTarget().comparator(ComparatorExists.Compare.NOT_EXISTS);
+ }
+
+ @Override
+ public int friendlyName() {
+ return R.string.starttemptarget;
+ }
+
+ @Override
+ public String shortDescription() {
+ tempTarget = new TempTarget()
+ .date(DateUtil.now())
+ .duration(duration.getMinutes())
+ .reason(reason)
+ .source(Source.USER)
+ .low(Profile.toMgdl(value.getValue(), value.getUnits()))
+ .high(Profile.toMgdl(value.getValue(), value.getUnits()));
+ return MainApp.gs(R.string.starttemptarget) + ": " + (tempTarget == null ? "null" : tempTarget.friendlyDescription(value.getUnits()));
+ }
+
+ @Override
+ public void doAction(Callback callback) {
+ tempTarget = new TempTarget()
+ .date(DateUtil.now())
+ .duration(duration.getMinutes())
+ .reason(reason)
+ .source(Source.USER)
+ .low(Profile.toMgdl(value.getValue(), value.getUnits()))
+ .high(Profile.toMgdl(value.getValue(), value.getUnits()));
+ TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget);
+ if (callback != null)
+ callback.result(new PumpEnactResult().success(true).comment(R.string.ok)).run();
+ }
+
+ @Override
+ public void generateDialog(LinearLayout root) {
+ int unitResId = value.getUnits().equals(Constants.MGDL) ? R.string.mgdl : R.string.mmol;
+
+ new LayoutBuilder()
+ .add(new LabelWithElement(MainApp.gs(R.string.careportal_temporarytarget) + " [" + MainApp.gs(unitResId) + "]", "", value))
+ .add(new LabelWithElement(MainApp.gs(R.string.careportal_newnstreatment_duration_min_label), "", duration))
+ .build(root);
+ }
+
+ @Override
+ public boolean hasDialog() {
+ return true;
+ }
+
+ @Override
+ public String toJSON() {
+ JSONObject o = new JSONObject();
+ try {
+ o.put("type", ActionStartTempTarget.class.getName());
+ JSONObject data = new JSONObject();
+ data.put("reason", reason);
+ data.put("value", value.getValue());
+ data.put("units", value.getUnits());
+ data.put("durationInMinutes", duration.getMinutes());
+ o.put("data", data);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return o.toString();
+ }
+
+ @Override
+ public Action fromJSON(String data) {
+ try {
+ JSONObject d = new JSONObject(data);
+ reason = JsonHelper.safeGetString(d, "reason");
+ value.setUnits(JsonHelper.safeGetString(d, "units"));
+ value.setValue(JsonHelper.safeGetDouble(d, "value"));
+ duration.setMinutes(JsonHelper.safeGetInt(d, "durationInMinutes"));
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return this;
+ }
+
+ @Override
+ public Optional icon() {
+ return Optional.of(R.drawable.icon_cp_cgm_target);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionStopTempTarget.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionStopTempTarget.java
new file mode 100644
index 0000000000..de251c499e
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionStopTempTarget.java
@@ -0,0 +1,77 @@
+package info.nightscout.androidaps.plugins.general.automation.actions;
+
+import com.google.common.base.Optional;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.data.PumpEnactResult;
+import info.nightscout.androidaps.db.Source;
+import info.nightscout.androidaps.db.TempTarget;
+import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
+import info.nightscout.androidaps.queue.Callback;
+import info.nightscout.androidaps.utils.DateUtil;
+import info.nightscout.androidaps.utils.JsonHelper;
+
+public class ActionStopTempTarget extends Action {
+ String reason = "";
+ private TempTarget tempTarget;
+
+ public ActionStopTempTarget() {
+ }
+
+ @Override
+ public int friendlyName() {
+ return R.string.stoptemptarget;
+ }
+
+ @Override
+ public String shortDescription() {
+ return MainApp.gs(R.string.stoptemptarget);
+ }
+
+ @Override
+ public void doAction(Callback callback) {
+ tempTarget = new TempTarget().date(DateUtil.now()).duration(0).reason(reason).source(Source.USER).low(0).high(0);
+ TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget);
+ if (callback != null)
+ callback.result(new PumpEnactResult().success(true).comment(R.string.ok)).run();
+ }
+
+ @Override
+ public boolean hasDialog() {
+ return false;
+ }
+
+ @Override
+ public String toJSON() {
+ JSONObject o = new JSONObject();
+ try {
+ o.put("type", ActionStopTempTarget.class.getName());
+ JSONObject data = new JSONObject();
+ data.put("reason", reason);
+ o.put("data", data);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return o.toString();
+ }
+
+ @Override
+ public Action fromJSON(String data) {
+ try {
+ JSONObject d = new JSONObject(data);
+ reason = JsonHelper.safeGetString(d, "reason");
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return this;
+ }
+
+ @Override
+ public Optional icon() {
+ return Optional.of(R.drawable.ic_stop_24dp);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/dialogs/ActionListAdapter.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/dialogs/ActionListAdapter.kt
new file mode 100644
index 0000000000..8c9efedd20
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/dialogs/ActionListAdapter.kt
@@ -0,0 +1,54 @@
+package info.nightscout.androidaps.plugins.general.automation.dialogs
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.LinearLayout
+import android.widget.TextView
+import androidx.fragment.app.FragmentManager
+import androidx.recyclerview.widget.RecyclerView
+import info.nightscout.androidaps.R
+import info.nightscout.androidaps.plugins.bus.RxBus
+import info.nightscout.androidaps.plugins.general.automation.actions.Action
+import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationUpdateGui
+
+class ActionListAdapter(private val fragmentManager: FragmentManager, private val actionList: MutableList) : RecyclerView.Adapter() {
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ val v = LayoutInflater.from(parent.context).inflate(R.layout.automation_action_item, parent, false)
+ return ViewHolder(v)
+ }
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ val action = actionList[position]
+ holder.bind(action, fragmentManager, this, position, actionList)
+ }
+
+ override fun getItemCount(): Int {
+ return actionList.size
+ }
+
+ class ViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
+
+ fun bind(action: Action, fragmentManager: FragmentManager, recyclerView: RecyclerView.Adapter, position : Int, actionList: MutableList) {
+ view.findViewById(R.id.automation_layoutText).setOnClickListener {
+ if (action.hasDialog()) {
+ val args = Bundle()
+ args.putInt("actionPosition", position)
+ args.putString("action", action.toJSON())
+ val dialog = EditActionDialog()
+ dialog.arguments = args
+ dialog.show(fragmentManager, "EditActionDialog")
+ }
+ }
+ view.findViewById(R.id.automation_iconTrash).setOnClickListener {
+ actionList.remove(action)
+ recyclerView.notifyDataSetChanged()
+ RxBus.send(EventAutomationUpdateGui())
+ }
+ view.findViewById(R.id.automation_viewActionTitle).text = action.shortDescription()
+ }
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/dialogs/ChooseActionDialog.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/dialogs/ChooseActionDialog.kt
new file mode 100644
index 0000000000..2096d5a541
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/dialogs/ChooseActionDialog.kt
@@ -0,0 +1,90 @@
+package info.nightscout.androidaps.plugins.general.automation.dialogs
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.RadioButton
+import androidx.fragment.app.DialogFragment
+import info.nightscout.androidaps.R
+import info.nightscout.androidaps.plugins.bus.RxBus
+import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin
+import info.nightscout.androidaps.plugins.general.automation.actions.Action
+import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationAddAction
+import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationUpdateGui
+import kotlinx.android.synthetic.main.automation_dialog_choose_action.*
+import kotlinx.android.synthetic.main.okcancel.*
+
+class ChooseActionDialog : DialogFragment() {
+
+ var checkedIndex = -1
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?): View? {
+ // restore checked radio button
+ savedInstanceState?.let { bundle ->
+ checkedIndex = bundle.getInt("checkedIndex")
+ }
+
+ dialog?.setCanceledOnTouchOutside(false)
+ return inflater.inflate(R.layout.automation_dialog_choose_action, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ for (a in AutomationPlugin.getActionDummyObjects()) {
+ val radioButton = RadioButton(context)
+ radioButton.setText(a.friendlyName())
+ radioButton.tag = a.javaClass
+ automation_radioGroup.addView(radioButton)
+ }
+
+ if (checkedIndex != -1)
+ (automation_radioGroup.getChildAt(checkedIndex) as RadioButton).isChecked = true
+
+ // OK button
+ ok.setOnClickListener {
+ dismiss()
+ instantiateAction()?.let {
+ RxBus.send(EventAutomationAddAction(it))
+ RxBus.send(EventAutomationUpdateGui())
+ }
+ }
+
+ // Cancel button
+ cancel.setOnClickListener { dismiss() }
+ }
+
+ override fun onStart() {
+ super.onStart()
+ dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
+ }
+
+ override fun onSaveInstanceState(bundle: Bundle) {
+ bundle.putInt("checkedIndex", determineCheckedIndex())
+ }
+
+ private fun instantiateAction(): Action? {
+ return getActionClass()?.let {
+ it.newInstance() as Action
+ }
+ }
+
+ private fun getActionClass(): Class<*>? {
+ val radioButtonID = automation_radioGroup.checkedRadioButtonId
+ val radioButton = automation_radioGroup.findViewById(radioButtonID)
+ return radioButton?.let {
+ it.tag as Class<*>
+ }
+ }
+
+ private fun determineCheckedIndex(): Int {
+ for (i in 0 until automation_radioGroup.childCount) {
+ if ((automation_radioGroup.getChildAt(i) as RadioButton).isChecked)
+ return i
+ }
+ return -1
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/dialogs/ChooseTriggerDialog.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/dialogs/ChooseTriggerDialog.kt
new file mode 100644
index 0000000000..b2317fc6a2
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/dialogs/ChooseTriggerDialog.kt
@@ -0,0 +1,96 @@
+package info.nightscout.androidaps.plugins.general.automation.dialogs
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.RadioButton
+import androidx.fragment.app.DialogFragment
+import info.nightscout.androidaps.R
+import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin
+import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger
+import kotlinx.android.synthetic.main.automation_dialog_choose_trigger.*
+import kotlinx.android.synthetic.main.okcancel.*
+
+class ChooseTriggerDialog : DialogFragment() {
+
+ private var checkedIndex = -1
+
+ private var clickListener: OnClickListener? = null
+
+ interface OnClickListener {
+ fun onClick(newTriggerObject: Trigger)
+ }
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?): View? {
+ // restore checked radio button
+ savedInstanceState?.let { bundle ->
+ checkedIndex = bundle.getInt("checkedIndex")
+ }
+
+ dialog?.setCanceledOnTouchOutside(false)
+ return inflater.inflate(R.layout.automation_dialog_choose_trigger, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ for (t in AutomationPlugin.getTriggerDummyObjects()) {
+ val radioButton = RadioButton(context)
+ radioButton.setText(t.friendlyName())
+ radioButton.tag = t.javaClass
+ automation_chooseTriggerRadioGroup.addView(radioButton)
+ }
+
+ if (checkedIndex != -1)
+ (automation_chooseTriggerRadioGroup.getChildAt(checkedIndex) as RadioButton).isChecked = true
+
+ // OK button
+ ok.setOnClickListener {
+ dismiss()
+ instantiateTrigger()?.let {
+ clickListener?.onClick(it)
+ }
+ }
+
+ // Cancel button
+ cancel.setOnClickListener { dismiss() }
+ }
+
+ override fun onStart() {
+ super.onStart()
+ dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
+ }
+
+ fun setOnClickListener(clickListener: OnClickListener) {
+ this.clickListener = clickListener
+ }
+
+ override fun onSaveInstanceState(bundle: Bundle) {
+ bundle.putInt("checkedIndex", determineCheckedIndex())
+ }
+
+ private fun instantiateTrigger(): Trigger? {
+ return getTriggerClass()?.let {
+ it.newInstance() as Trigger
+ }
+ }
+
+ private fun getTriggerClass(): Class<*>? {
+ val radioButtonID = automation_chooseTriggerRadioGroup.checkedRadioButtonId
+ val radioButton = automation_chooseTriggerRadioGroup.findViewById(radioButtonID)
+ return radioButton?.let {
+ it.tag as Class<*>
+ }
+ }
+
+ private fun determineCheckedIndex(): Int {
+ for (i in 0 until automation_chooseTriggerRadioGroup.childCount) {
+ if ((automation_chooseTriggerRadioGroup.getChildAt(i) as RadioButton).isChecked)
+ return i
+ }
+ return -1
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/dialogs/EditActionDialog.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/dialogs/EditActionDialog.kt
new file mode 100644
index 0000000000..2c49f81bba
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/dialogs/EditActionDialog.kt
@@ -0,0 +1,65 @@
+package info.nightscout.androidaps.plugins.general.automation.dialogs
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.DialogFragment
+import info.nightscout.androidaps.R
+import info.nightscout.androidaps.plugins.bus.RxBus
+import info.nightscout.androidaps.plugins.general.automation.actions.Action
+import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationUpdateAction
+import kotlinx.android.synthetic.main.automation_dialog_action.*
+import kotlinx.android.synthetic.main.okcancel.*
+import org.json.JSONObject
+
+class EditActionDialog : DialogFragment() {
+ private var action: Action? = null
+ private var actionPosition: Int = -1
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?): View? {
+ // load data from bundle
+ (savedInstanceState ?: arguments)?.let { bundle ->
+ actionPosition = bundle.getInt("actionPosition", -1)
+ bundle.getString("action")?.let { action = Action.instantiate(JSONObject(it)) }
+ }
+
+ dialog?.setCanceledOnTouchOutside(false)
+ return inflater.inflate(R.layout.automation_dialog_action, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ action?.let {
+ automation_actionTitle.setText(it.friendlyName())
+ automation_editActionLayout.removeAllViews()
+ it.generateDialog(automation_editActionLayout)
+ }
+
+ // OK button
+ ok.setOnClickListener {
+ dismiss()
+ action?.let {
+ RxBus.send(EventAutomationUpdateAction(it, actionPosition))
+ }
+ }
+
+ // Cancel button
+ cancel.setOnClickListener { dismiss() }
+ }
+
+ override fun onStart() {
+ super.onStart()
+ dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
+ }
+
+ override fun onSaveInstanceState(bundle: Bundle) {
+ super.onSaveInstanceState(bundle)
+ action?.let {
+ bundle.putInt("actionPosition", actionPosition)
+ bundle.putString("action", it.toJSON())
+ }
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/dialogs/EditEventDialog.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/dialogs/EditEventDialog.kt
new file mode 100644
index 0000000000..85aab0f538
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/dialogs/EditEventDialog.kt
@@ -0,0 +1,168 @@
+package info.nightscout.androidaps.plugins.general.automation.dialogs
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.DialogFragment
+import androidx.recyclerview.widget.LinearLayoutManager
+import info.nightscout.androidaps.R
+import info.nightscout.androidaps.plugins.bus.RxBus
+import info.nightscout.androidaps.plugins.general.automation.AutomationEvent
+import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin
+import info.nightscout.androidaps.plugins.general.automation.events.*
+import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector
+import info.nightscout.androidaps.utils.FabricPrivacy
+import info.nightscout.androidaps.utils.ToastUtils
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.disposables.CompositeDisposable
+import kotlinx.android.synthetic.main.automation_dialog_event.*
+import kotlinx.android.synthetic.main.okcancel.*
+
+class EditEventDialog : DialogFragment() {
+
+ private var actionListAdapter: ActionListAdapter? = null
+ private var event: AutomationEvent = AutomationEvent()
+ private var position: Int = -1
+
+ private var disposable: CompositeDisposable = CompositeDisposable()
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?): View? {
+ // load data from bundle
+ (savedInstanceState ?: arguments)?.let { bundle ->
+ position = bundle.getInt("position", -1)
+ bundle.getString("event")?.let { event = AutomationEvent().fromJSON(it) }
+ }
+
+ dialog?.setCanceledOnTouchOutside(false)
+ return inflater.inflate(R.layout.automation_dialog_event, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ automation_inputEventTitle.setText(event.title)
+ automation_triggerDescription.text = event.trigger.friendlyDescription()
+
+ automation_editTrigger.setOnClickListener {
+ val args = Bundle()
+ args.putString("trigger", event.trigger.toJSON())
+ val dialog = EditTriggerDialog()
+ dialog.arguments = args
+ fragmentManager?.let { dialog.show(it, "EditTriggerDialog") }
+ }
+
+ // setup action list view
+ fragmentManager?.let { actionListAdapter = ActionListAdapter(it, event.actions) }
+ automation_actionListView.layoutManager = LinearLayoutManager(context)
+ automation_actionListView.adapter = actionListAdapter
+
+ automation_addAction.setOnClickListener { fragmentManager?.let { ChooseActionDialog().show(it, "ChooseActionDialog") } }
+
+ // OK button
+ ok.setOnClickListener {
+ // check for title
+ val title = automation_inputEventTitle.text.toString()
+ if (title.isEmpty()) {
+ ToastUtils.showToastInUiThread(context, R.string.automation_missing_task_name)
+ return@setOnClickListener
+ }
+ event.title = title
+ // check for at least one trigger
+ val con = event.trigger as TriggerConnector
+ if (con.size() == 0) {
+ ToastUtils.showToastInUiThread(context, R.string.automation_missing_trigger)
+ return@setOnClickListener
+ }
+ // check for at least one action
+ if (event.actions.isEmpty()) {
+ ToastUtils.showToastInUiThread(context, R.string.automation_missing_action)
+ return@setOnClickListener
+ }
+ // store
+ if (position == -1)
+ AutomationPlugin.automationEvents.add(event)
+ else
+ AutomationPlugin.automationEvents[position] = event
+
+ dismiss()
+ RxBus.send(EventAutomationDataChanged())
+ }
+
+ // Cancel button
+ cancel.setOnClickListener { dismiss() }
+
+ showPreconditions()
+
+ disposable.add(RxBus
+ .toObservable(EventAutomationUpdateGui::class.java)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe({
+ actionListAdapter?.notifyDataSetChanged()
+ showPreconditions()
+ }, {
+ FabricPrivacy.logException(it)
+ })
+ )
+ disposable.add(RxBus
+ .toObservable(EventAutomationAddAction::class.java)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe({
+ event.addAction(it.action)
+ actionListAdapter?.notifyDataSetChanged()
+ }, {
+ FabricPrivacy.logException(it)
+ })
+ )
+ disposable.add(RxBus
+ .toObservable(EventAutomationUpdateTrigger::class.java)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe({
+ event.trigger = it.trigger
+ automation_triggerDescription.text = event.trigger.friendlyDescription()
+ }, {
+ FabricPrivacy.logException(it)
+ })
+ )
+ disposable.add(RxBus
+ .toObservable(EventAutomationUpdateAction::class.java)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe({
+ event.actions[it.position] = it.action
+ actionListAdapter?.notifyDataSetChanged()
+ }, {
+ FabricPrivacy.logException(it)
+ })
+ )
+ }
+
+ override fun onStart() {
+ super.onStart()
+ dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
+ }
+
+ override fun onDestroyView() {
+ super.onDestroyView()
+ disposable.clear()
+ }
+
+ override fun onSaveInstanceState(bundle: Bundle) {
+ super.onSaveInstanceState(bundle)
+ bundle.putString("event", event.toJSON())
+ bundle.putInt("position", position)
+ }
+
+ private fun showPreconditions() {
+ val forcedTriggers = event.preconditions
+ if (forcedTriggers.size() > 0) {
+ automation_forcedTriggerDescription.visibility = View.VISIBLE
+ automation_forcedTriggerDescriptionLabel.visibility = View.VISIBLE
+ automation_forcedTriggerDescription.text = forcedTriggers.friendlyDescription()
+ } else {
+ automation_forcedTriggerDescription.visibility = View.GONE
+ automation_forcedTriggerDescriptionLabel.visibility = View.GONE
+ }
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/dialogs/EditTriggerDialog.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/dialogs/EditTriggerDialog.kt
new file mode 100644
index 0000000000..eda9c6177f
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/dialogs/EditTriggerDialog.kt
@@ -0,0 +1,55 @@
+package info.nightscout.androidaps.plugins.general.automation.dialogs
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.DialogFragment
+import info.nightscout.androidaps.R
+import info.nightscout.androidaps.plugins.bus.RxBus
+import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationUpdateTrigger
+import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger
+import kotlinx.android.synthetic.main.automation_dialog_edit_trigger.*
+import kotlinx.android.synthetic.main.okcancel.*
+
+class EditTriggerDialog : DialogFragment() {
+
+ private var trigger: Trigger? = null
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?): View? {
+ // load data from bundle
+ (savedInstanceState ?: arguments)?.let { bundle ->
+ bundle.getString("trigger")?.let { trigger = Trigger.instantiate(it) }
+ }
+
+ dialog?.setCanceledOnTouchOutside(false)
+ return inflater.inflate(R.layout.automation_dialog_edit_trigger, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ // display root trigger
+ trigger?.generateDialog(automation_layoutTrigger, fragmentManager)
+
+ // OK button
+ ok.setOnClickListener {
+ dismiss()
+ trigger?.let { trigger -> RxBus.send(EventAutomationUpdateTrigger(trigger)) }
+ }
+
+ // Cancel button
+ cancel.setOnClickListener { dismiss() }
+ }
+
+ override fun onStart() {
+ super.onStart()
+ dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
+ }
+
+ override fun onSaveInstanceState(bundle: Bundle) {
+ super.onSaveInstanceState(bundle)
+ trigger?.let { bundle.putString("trigger", it.toJSON()) }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/dialogs/TriggerListAdapter.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/dialogs/TriggerListAdapter.java
new file mode 100644
index 0000000000..98d225d84e
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/dialogs/TriggerListAdapter.java
@@ -0,0 +1,186 @@
+package info.nightscout.androidaps.plugins.general.automation.dialogs;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.Spinner;
+
+import androidx.fragment.app.FragmentManager;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger;
+import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector;
+
+public class TriggerListAdapter {
+ private final LinearLayout mRootLayout;
+ private final FragmentManager mFragmentManager;
+ private final Context mContext;
+ private final TriggerConnector mRootConnector;
+
+ public TriggerListAdapter(FragmentManager fragmentManager, Context context, LinearLayout rootLayout, TriggerConnector rootTrigger) {
+ mRootLayout = rootLayout;
+ mFragmentManager = fragmentManager;
+ mContext = context;
+ mRootConnector = rootTrigger;
+ build(fragmentManager);
+ }
+
+ public Context getContext() {
+ return mContext;
+ }
+
+ private FragmentManager getFM() {
+ return mFragmentManager;
+ }
+
+ private void destroy() {
+ mRootLayout.removeAllViews();
+ }
+
+ private void build(FragmentManager fragmentManager) {
+ for (int i = 0; i < mRootConnector.size(); ++i) {
+ final Trigger trigger = mRootConnector.get(i);
+
+ // spinner
+ if (i > 0) {
+ createSpinner(trigger);
+ }
+
+ // trigger layout
+ trigger.generateDialog(mRootLayout, fragmentManager);
+
+ // buttons
+ createButtons(fragmentManager, trigger);
+ }
+
+ if (mRootConnector.size() == 0) {
+ Button buttonAdd = new Button(mContext);
+ buttonAdd.setText(MainApp.gs(R.string.addnew));
+ buttonAdd.setOnClickListener(v -> {
+ ChooseTriggerDialog dialog = new ChooseTriggerDialog();
+ dialog.setOnClickListener(newTriggerObject -> {
+ mRootConnector.add(newTriggerObject);
+ rebuild(fragmentManager);
+ });
+ dialog.show(fragmentManager, "ChooseTriggerDialog");
+ });
+ mRootLayout.addView(buttonAdd);
+ }
+ }
+
+ private Spinner createSpinner() {
+ Spinner spinner = new Spinner(mContext);
+ ArrayAdapter spinnerArrayAdapter = new ArrayAdapter<>(mContext, android.R.layout.simple_spinner_item, TriggerConnector.Type.labels());
+ spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ spinner.setAdapter(spinnerArrayAdapter);
+ return spinner;
+ }
+
+ private void createSpinner(Trigger trigger) {
+ final TriggerConnector connector = trigger.getConnector();
+ final int initialPosition = connector.getConnectorType().ordinal();
+ Spinner spinner = createSpinner();
+ spinner.setSelection(initialPosition);
+ spinner.setBackgroundColor(MainApp.gc(R.color.black_overlay));
+ LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
+ LinearLayout.LayoutParams.MATCH_PARENT,
+ LinearLayout.LayoutParams.WRAP_CONTENT
+ );
+ params.setMargins(0, MainApp.dpToPx(8), 0, MainApp.dpToPx(8));
+ spinner.setLayoutParams(params);
+ spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView> parent, View view, int position, long id) {
+ if (position != initialPosition) {
+ // connector type changed
+ changeConnector(getFM(), trigger, connector, TriggerConnector.Type.values()[position]);
+ }
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView> parent) {
+ }
+ });
+ mRootLayout.addView(spinner);
+ }
+
+ private void createButtons(FragmentManager fragmentManager, Trigger trigger) {
+ // do not create buttons for TriggerConnector
+ if (trigger instanceof TriggerConnector) {
+ return;
+ }
+
+ // Button Layout
+ LinearLayout buttonLayout = new LinearLayout(mContext);
+ buttonLayout.setOrientation(LinearLayout.HORIZONTAL);
+ buttonLayout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
+ mRootLayout.addView(buttonLayout);
+
+ // Button [-]
+ Button buttonRemove = new Button(mContext);
+ buttonRemove.setText(MainApp.gs(R.string.delete_short));
+ buttonRemove.setOnClickListener(v -> {
+ final TriggerConnector connector = trigger.getConnector();
+ connector.remove(trigger);
+ connector.simplify().rebuildView(getFM());
+ });
+ buttonLayout.addView(buttonRemove);
+
+ // Button [+]
+ Button buttonAdd = new Button(mContext);
+ buttonAdd.setText(MainApp.gs(R.string.add_short));
+ buttonAdd.setOnClickListener(v -> {
+ ChooseTriggerDialog dialog = new ChooseTriggerDialog();
+ dialog.show(fragmentManager, "ChooseTriggerDialog");
+ dialog.setOnClickListener(newTriggerObject -> {
+ TriggerConnector connector = trigger.getConnector();
+ connector.add(connector.pos(trigger) + 1, newTriggerObject);
+ connector.simplify().rebuildView(getFM());
+ });
+ });
+ buttonLayout.addView(buttonAdd);
+
+ // Button [*]
+ Button buttonCopy = new Button(mContext);
+ buttonCopy.setText(MainApp.gs(R.string.copy_short));
+ buttonCopy.setOnClickListener(v -> {
+ TriggerConnector connector = trigger.getConnector();
+ connector.add(connector.pos(trigger) + 1, trigger.duplicate());
+ connector.simplify().rebuildView(getFM());
+ });
+ buttonLayout.addView(buttonCopy);
+ }
+
+ public void rebuild(FragmentManager fragmentManager) {
+ destroy();
+ build(fragmentManager);
+ }
+
+ public static void changeConnector(final FragmentManager fragmentManager, final Trigger trigger, final TriggerConnector connector, final TriggerConnector.Type newConnectorType) {
+ if (connector.size() > 2) {
+ // split connector
+ int pos = connector.pos(trigger) - 1;
+
+ TriggerConnector newConnector = new TriggerConnector(newConnectorType);
+
+ // move trigger from pos and pos+1 into new connector
+ for (int i = 0; i < 2; ++i) {
+ Trigger t = connector.get(pos);
+ newConnector.add(t);
+ connector.remove(t);
+ }
+
+ connector.add(pos, newConnector);
+ } else {
+ connector.changeConnectorType(newConnectorType);
+ }
+
+ connector.simplify().rebuildView(fragmentManager);
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/Comparator.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/Comparator.java
new file mode 100644
index 0000000000..334adfcc01
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/Comparator.java
@@ -0,0 +1,123 @@
+package info.nightscout.androidaps.plugins.general.automation.elements;
+
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.LinearLayout;
+import android.widget.Spinner;
+
+import androidx.annotation.StringRes;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+
+public class Comparator extends Element {
+ public enum Compare {
+ IS_LESSER,
+ IS_EQUAL_OR_LESSER,
+ IS_EQUAL,
+ IS_EQUAL_OR_GREATER,
+ IS_GREATER,
+ IS_NOT_AVAILABLE;
+
+ public @StringRes
+ int getStringRes() {
+ switch (this) {
+ case IS_LESSER:
+ return R.string.islesser;
+ case IS_EQUAL_OR_LESSER:
+ return R.string.isequalorlesser;
+ case IS_EQUAL:
+ return R.string.isequal;
+ case IS_EQUAL_OR_GREATER:
+ return R.string.isequalorgreater;
+ case IS_GREATER:
+ return R.string.isgreater;
+ case IS_NOT_AVAILABLE:
+ return R.string.isnotavailable;
+ default:
+ return R.string.unknown;
+ }
+ }
+
+ public boolean check(T obj1, T obj2) {
+ if (obj1 == null || obj2 == null)
+ return this.equals(IS_NOT_AVAILABLE);
+
+ int comparison = obj1.compareTo(obj2);
+ switch (this) {
+ case IS_LESSER:
+ return comparison < 0;
+ case IS_EQUAL_OR_LESSER:
+ return comparison <= 0;
+ case IS_EQUAL:
+ return comparison == 0;
+ case IS_EQUAL_OR_GREATER:
+ return comparison >= 0;
+ case IS_GREATER:
+ return comparison > 0;
+ default:
+ return false;
+ }
+ }
+
+ public static List labels() {
+ List list = new ArrayList<>();
+ for (Compare c : Compare.values()) {
+ list.add(MainApp.gs(c.getStringRes()));
+ }
+ return list;
+ }
+ }
+
+ private Compare compare = Compare.IS_EQUAL;
+
+ public Comparator() {
+ super();
+ }
+
+ public Comparator(Comparator another) {
+ super();
+ compare = another.getValue();
+ }
+
+ @Override
+ public void addToLayout(LinearLayout root) {
+ Spinner spinner = new Spinner(root.getContext());
+ ArrayAdapter spinnerArrayAdapter = new ArrayAdapter<>(root.getContext(), android.R.layout.simple_spinner_item, Compare.labels());
+ spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ spinner.setAdapter(spinnerArrayAdapter);
+ LinearLayout.LayoutParams spinnerParams = new LinearLayout.LayoutParams(
+ LinearLayout.LayoutParams.MATCH_PARENT,
+ LinearLayout.LayoutParams.WRAP_CONTENT
+ );
+ spinnerParams.setMargins(0, MainApp.dpToPx(4), 0, MainApp.dpToPx(4));
+ spinner.setLayoutParams(spinnerParams);
+ spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView> parent, View view, int position, long id) {
+ compare = Compare.values()[position];
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView> parent) {
+ }
+ });
+ spinner.setSelection(compare.ordinal());
+ root.addView(spinner);
+
+ }
+
+ public Compare getValue() {
+ return compare;
+ }
+
+ public Comparator setValue(Compare compare) {
+ this.compare = compare;
+ return this;
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/ComparatorExists.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/ComparatorExists.java
new file mode 100644
index 0000000000..2bde0cb842
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/ComparatorExists.java
@@ -0,0 +1,90 @@
+package info.nightscout.androidaps.plugins.general.automation.elements;
+
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.LinearLayout;
+import android.widget.Spinner;
+
+import androidx.annotation.StringRes;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+
+public class ComparatorExists extends Element {
+ public enum Compare {
+ EXISTS,
+ NOT_EXISTS;
+
+ public @StringRes
+ int getStringRes() {
+ switch (this) {
+ case EXISTS:
+ return R.string.exists;
+ case NOT_EXISTS:
+ return R.string.notexists;
+ default:
+ return R.string.unknown;
+ }
+ }
+
+ public static List labels() {
+ List list = new ArrayList<>();
+ for (Compare c : Compare.values()) {
+ list.add(MainApp.gs(c.getStringRes()));
+ }
+ return list;
+ }
+ }
+
+ private Compare compare = Compare.EXISTS;
+
+ public ComparatorExists() {
+ super();
+ }
+
+ public ComparatorExists(ComparatorExists another) {
+ super();
+ compare = another.getValue();
+ }
+
+ @Override
+ public void addToLayout(LinearLayout root) {
+ Spinner spinner = new Spinner(root.getContext());
+ ArrayAdapter spinnerArrayAdapter = new ArrayAdapter<>(root.getContext(), android.R.layout.simple_spinner_item, Compare.labels());
+ spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ spinner.setAdapter(spinnerArrayAdapter);
+ LinearLayout.LayoutParams spinnerParams = new LinearLayout.LayoutParams(
+ LinearLayout.LayoutParams.MATCH_PARENT,
+ LinearLayout.LayoutParams.WRAP_CONTENT
+ );
+ spinnerParams.setMargins(0, MainApp.dpToPx(4), 0, MainApp.dpToPx(4));
+ spinner.setLayoutParams(spinnerParams);
+ spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView> parent, View view, int position, long id) {
+ compare = Compare.values()[position];
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView> parent) {
+ }
+ });
+ spinner.setSelection(compare.ordinal());
+ root.addView(spinner);
+
+ }
+
+ public Compare getValue() {
+ return compare;
+ }
+
+ public ComparatorExists setValue(Compare compare) {
+ this.compare = compare;
+ return this;
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/Element.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/Element.java
new file mode 100644
index 0000000000..a853fde1e7
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/Element.java
@@ -0,0 +1,7 @@
+package info.nightscout.androidaps.plugins.general.automation.elements;
+
+import android.widget.LinearLayout;
+
+public abstract class Element {
+ public abstract void addToLayout(LinearLayout root);
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputBg.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputBg.java
new file mode 100644
index 0000000000..0809ed96d8
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputBg.java
@@ -0,0 +1,83 @@
+package info.nightscout.androidaps.plugins.general.automation.elements;
+
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.widget.LinearLayout;
+
+import java.text.DecimalFormat;
+
+import info.nightscout.androidaps.Constants;
+import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
+import info.nightscout.androidaps.utils.NumberPicker;
+
+public class InputBg extends Element {
+ static final int MMOL_MIN = 3;
+ static final int MMOL_MAX = 20;
+ static final int MGDL_MIN = 54;
+ static final int MGDL_MAX = 360;
+
+ private String units = Constants.MGDL;
+ private double value;
+ double minValue;
+ private double maxValue;
+ private double step;
+ private DecimalFormat decimalFormat;
+
+ public InputBg() {
+ super();
+ setUnits(ProfileFunctions.getInstance().getProfileUnits());
+ if (getUnits().equals(Constants.MMOL))
+ value = MMOL_MIN;
+ else
+ value = MGDL_MIN;
+ }
+
+ public InputBg(InputBg another) {
+ super();
+ value = another.getValue();
+ setUnits(another.getUnits());
+ }
+
+
+ @Override
+ public void addToLayout(LinearLayout root) {
+ NumberPicker numberPicker = new NumberPicker(root.getContext(), null);
+ numberPicker.setParams(value, minValue, maxValue, step, decimalFormat, true, null, null);
+ numberPicker.setOnValueChangedListener(value -> this.value = value);
+ root.addView(numberPicker);
+ }
+
+ public String getUnits() {
+ return units;
+ }
+
+ public InputBg setUnits(String units) {
+ // set default initial value
+ if (units.equals(Constants.MMOL)) {
+ // mmol
+ minValue = MMOL_MIN;
+ maxValue = MMOL_MAX;
+ step = 0.1;
+ decimalFormat = new DecimalFormat("0.0");
+ } else {
+ // mg/dL
+ minValue = MGDL_MIN;
+ maxValue = MGDL_MAX;
+ step = 1;
+ decimalFormat = new DecimalFormat("0");
+ }
+
+ this.units = units;
+ return this;
+ }
+
+ public InputBg setValue(double value) {
+ this.value = value;
+ return this;
+ }
+
+ public double getValue() {
+ return value;
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputButton.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputButton.java
new file mode 100644
index 0000000000..6b0406abe0
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputButton.java
@@ -0,0 +1,28 @@
+package info.nightscout.androidaps.plugins.general.automation.elements;
+
+import android.widget.Button;
+import android.widget.LinearLayout;
+
+public class InputButton extends Element {
+
+ String text;
+ Runnable runnable;
+
+ public InputButton(String text, Runnable runnable) {
+ this.text = text;
+ this.runnable = runnable;
+ }
+
+ @Override
+ public void addToLayout(LinearLayout root) {
+ Button button = new Button(root.getContext());
+
+ button.setText(text);
+ button.setOnClickListener(view -> {
+ if (runnable != null)
+ runnable.run();
+ });
+
+ root.addView(button);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputDelta.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputDelta.java
new file mode 100644
index 0000000000..ad0e84bec4
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputDelta.java
@@ -0,0 +1,138 @@
+package info.nightscout.androidaps.plugins.general.automation.elements;
+
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.LinearLayout;
+import android.widget.Spinner;
+
+import androidx.annotation.StringRes;
+
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.utils.NumberPicker;
+
+public class InputDelta extends Element {
+ private Comparator.Compare compare = Comparator.Compare.IS_EQUAL;
+
+ public enum DeltaType {
+ DELTA,
+ SHORT_AVERAGE,
+ LONG_AVERAGE;
+
+ public @StringRes
+ int getStringRes() {
+ switch (this) {
+ case DELTA:
+ return R.string.delta;
+ case SHORT_AVERAGE:
+ return R.string.short_avgdelta;
+ case LONG_AVERAGE:
+ return R.string.long_avgdelta;
+ default:
+ return R.string.unknown;
+ }
+ }
+
+ public static List labels() {
+ List list = new ArrayList<>();
+ for (DeltaType d : DeltaType.values()) {
+ list.add(MainApp.gs(d.getStringRes()));
+ }
+ return list;
+ }
+ }
+
+ private double value;
+ double minValue;
+ double maxValue;
+ private double step;
+ private DecimalFormat decimalFormat;
+ private DeltaType deltaType;
+
+ NumberPicker numberPicker;
+
+ public InputDelta() {
+ super();
+ }
+
+ public InputDelta(double value, double minValue, double maxValue, double step, DecimalFormat decimalFormat, DeltaType deltaType) {
+ super();
+ this.value = value;
+ this.minValue = minValue;
+ this.maxValue = maxValue;
+ this.step = step;
+ this.decimalFormat = decimalFormat;
+ this.deltaType = deltaType;
+ }
+
+ public InputDelta(InputDelta another) {
+ super();
+ value = another.getValue();
+ minValue = another.minValue;
+ maxValue = another.maxValue;
+ step = another.step;
+ decimalFormat = another.decimalFormat;
+ deltaType = another.deltaType;
+ }
+
+
+ @Override
+ public void addToLayout(LinearLayout root) {
+ Spinner spinner = new Spinner(root.getContext());
+ ArrayAdapter spinnerArrayAdapter = new ArrayAdapter<>(root.getContext(), android.R.layout.simple_spinner_item, DeltaType.labels());
+ spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ spinner.setAdapter(spinnerArrayAdapter);
+ LinearLayout.LayoutParams spinnerParams = new LinearLayout.LayoutParams(
+ LinearLayout.LayoutParams.WRAP_CONTENT,
+ LinearLayout.LayoutParams.WRAP_CONTENT
+ );
+ spinnerParams.setMargins(0, MainApp.dpToPx(4), 0, MainApp.dpToPx(4));
+ spinner.setLayoutParams(spinnerParams);
+ spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView> parent, View view, int position, long id) {
+ deltaType = DeltaType.values()[position];
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView> parent) {
+ }
+ });
+ spinner.setSelection(this.deltaType.ordinal());
+// root.addView(spinner);
+ numberPicker = new NumberPicker(root.getContext(), null);
+ numberPicker.setParams(value, minValue, maxValue, step, decimalFormat, true, null, null);
+ numberPicker.setOnValueChangedListener(value -> this.value = value);
+ LinearLayout l = new LinearLayout(root.getContext());
+ l.setOrientation(LinearLayout.VERTICAL);
+ l.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
+ l.addView(spinner);
+ l.addView(numberPicker);
+ root.addView(l);
+ }
+
+ public InputDelta setValue(double value, DeltaType type) {
+ this.value = value;
+ this.deltaType = type;
+ if (numberPicker != null)
+ numberPicker.setValue(value);
+ return this;
+ }
+
+ public double getValue() {
+ return value;
+ }
+
+ public DeltaType getDeltaType() {
+ return deltaType;
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputDouble.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputDouble.java
new file mode 100644
index 0000000000..518b00f5b4
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputDouble.java
@@ -0,0 +1,77 @@
+package info.nightscout.androidaps.plugins.general.automation.elements;
+
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.widget.LinearLayout;
+
+import java.text.DecimalFormat;
+
+import info.nightscout.androidaps.utils.NumberPicker;
+
+public class InputDouble extends Element {
+
+ final TextWatcher textWatcher = new TextWatcher() {
+ @Override
+ public void afterTextChanged(Editable s) {
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ }
+ };
+
+ private double value;
+ private double minValue;
+ private double maxValue;
+ private double step;
+ private DecimalFormat decimalFormat;
+
+ NumberPicker numberPicker;
+
+ public InputDouble() {
+ super();
+ }
+
+ public InputDouble(double value, double minValue, double maxValue, double step, DecimalFormat decimalFormat) {
+ super();
+ this.value = value;
+ this.minValue = minValue;
+ this.maxValue = maxValue;
+ this.step = step;
+ this.decimalFormat = decimalFormat;
+ }
+
+ public InputDouble(InputDouble another) {
+ super();
+ value = another.getValue();
+ minValue = another.minValue;
+ maxValue = another.maxValue;
+ step = another.step;
+ decimalFormat = another.decimalFormat;
+ }
+
+
+ @Override
+ public void addToLayout(LinearLayout root) {
+ numberPicker = new NumberPicker(root.getContext(), null);
+ numberPicker.setParams(value, minValue, maxValue, step, decimalFormat, true, null, textWatcher);
+ numberPicker.setOnValueChangedListener(value -> this.value = value);
+ root.addView(numberPicker);
+ }
+
+ public InputDouble setValue(double value) {
+ this.value = value;
+ if (numberPicker != null)
+ numberPicker.setValue(value);
+ return this;
+ }
+
+ public double getValue() {
+ return value;
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputDuration.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputDuration.java
new file mode 100644
index 0000000000..aa19896471
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputDuration.java
@@ -0,0 +1,66 @@
+package info.nightscout.androidaps.plugins.general.automation.elements;
+
+import android.widget.LinearLayout;
+
+import java.text.DecimalFormat;
+
+import info.nightscout.androidaps.utils.NumberPicker;
+
+public class InputDuration extends Element {
+ public enum TimeUnit {
+ MINUTES,
+ HOURS
+ }
+
+ private TimeUnit unit;
+ private int value;
+
+ public InputDuration(int value, TimeUnit unit) {
+ this.unit = unit;
+ this.value = value;
+ }
+
+ public InputDuration(InputDuration another) {
+ unit = another.unit;
+ value = another.value;
+ }
+
+ @Override
+ public void addToLayout(LinearLayout root) {
+ NumberPicker numberPicker = new NumberPicker(root.getContext(), null);
+ if (unit.equals(TimeUnit.MINUTES)) {
+ // Minutes
+ numberPicker.setParams(0d, 0d, 24 * 60d, 10d, new DecimalFormat("0"), false, null);
+ } else {
+ // Hours
+ numberPicker.setParams(0d, 0d, 24d, 1d, new DecimalFormat("0"), false, null);
+ }
+ numberPicker.setValue((double) value);
+ numberPicker.setOnValueChangedListener(value -> this.value = (int) value);
+ root.addView(numberPicker);
+ }
+
+ TimeUnit getUnit() {
+ return unit;
+ }
+
+ public double getValue() {
+ return value;
+ }
+
+ public void setMinutes(int value) {
+ if (unit.equals(TimeUnit.MINUTES)) {
+ this.value = value;
+ } else {
+ this.value = value / 60;
+ }
+ }
+
+ public int getMinutes() {
+ if (unit.equals(TimeUnit.MINUTES)) {
+ return value;
+ } else {
+ return value * 60;
+ }
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputInsulin.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputInsulin.java
new file mode 100644
index 0000000000..8cf89d3b42
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputInsulin.java
@@ -0,0 +1,57 @@
+package info.nightscout.androidaps.plugins.general.automation.elements;
+
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.widget.LinearLayout;
+
+import java.text.DecimalFormat;
+
+import info.nightscout.androidaps.utils.NumberPicker;
+
+public class InputInsulin extends Element {
+
+ final TextWatcher textWatcher = new TextWatcher() {
+ @Override
+ public void afterTextChanged(Editable s) {
+ value = Math.max(value, -20d);
+ value = Math.min(value, 20d);
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ }
+ };
+
+ private double value;
+
+ public InputInsulin() {
+ super();
+ }
+
+ public InputInsulin(InputInsulin another) {
+ super();
+ value = another.getValue();
+ }
+
+ @Override
+ public void addToLayout(LinearLayout root) {
+ NumberPicker numberPicker = new NumberPicker(root.getContext(), null);
+ numberPicker.setParams(0d, -20d, 20d, 0.1, new DecimalFormat("0.0"), true, null, textWatcher);
+ numberPicker.setValue(value);
+ numberPicker.setOnValueChangedListener(value -> this.value = value);
+ root.addView(numberPicker);
+ }
+
+ public double getValue() {
+ return value;
+ }
+
+ public InputInsulin setValue(double value) {
+ this.value = value;
+ return this;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputPercent.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputPercent.java
new file mode 100644
index 0000000000..bade9082a3
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputPercent.java
@@ -0,0 +1,58 @@
+package info.nightscout.androidaps.plugins.general.automation.elements;
+
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.widget.LinearLayout;
+
+import java.text.DecimalFormat;
+
+import info.nightscout.androidaps.utils.NumberPicker;
+
+public class InputPercent extends Element {
+
+ final TextWatcher textWatcher = new TextWatcher() {
+ @Override
+ public void afterTextChanged(Editable s) {
+ value = Math.max(value, 70d);
+ value = Math.min(value, 130d);
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ }
+ };
+
+ private double value;
+
+ public InputPercent() {
+ super();
+ value = 100d;
+ }
+
+ public InputPercent(InputPercent another) {
+ super();
+ value = another.getValue();
+ }
+
+ @Override
+ public void addToLayout(LinearLayout root) {
+ NumberPicker numberPicker = new NumberPicker(root.getContext(), null);
+ numberPicker.setParams(100d, 70d, 130d, 5d, new DecimalFormat("0"), true, null, textWatcher);
+ numberPicker.setValue(value);
+ numberPicker.setOnValueChangedListener(value -> this.value = value);
+ root.addView(numberPicker);
+ }
+
+ public double getValue() {
+ return value;
+ }
+
+ public InputPercent setValue(double value) {
+ this.value = value;
+ return this;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputProfileName.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputProfileName.java
new file mode 100644
index 0000000000..5431f47ede
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputProfileName.java
@@ -0,0 +1,99 @@
+package info.nightscout.androidaps.plugins.general.automation.elements;
+
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.LinearLayout;
+import android.widget.Spinner;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.data.Profile;
+import info.nightscout.androidaps.data.ProfileStore;
+import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
+
+public class InputProfileName extends Element {
+ private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
+ ProfileStore profileStore;
+
+ String profileName;
+
+ public InputProfileName(String name) {
+ super();
+ this.profileName = name;
+ }
+
+ public InputProfileName(InputProfileName another) {
+ super();
+ profileName = another.getValue();
+ }
+
+
+ @Override
+ public void addToLayout(LinearLayout root) {
+ ArrayList profileList = new ArrayList<>();
+ profileStore = ConfigBuilderPlugin.getPlugin().getActiveProfileInterface().getProfile();
+ if (profileStore == null) {
+ log.error("ProfileStore is empty");
+ } else {
+ profileList = profileStore.getProfileList();
+ }
+ ArrayAdapter adapter = new ArrayAdapter<>(root.getContext(),
+ R.layout.spinner_centered, profileList);
+ Spinner spinner = new Spinner(root.getContext());
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ spinner.setAdapter(adapter);
+ LinearLayout.LayoutParams spinnerParams = new LinearLayout.LayoutParams(
+ LinearLayout.LayoutParams.WRAP_CONTENT,
+ LinearLayout.LayoutParams.WRAP_CONTENT
+ );
+ spinnerParams.setMargins(0, MainApp.dpToPx(4), 0, MainApp.dpToPx(4));
+ spinner.setLayoutParams(spinnerParams);
+ spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView> parent, View view, int position, long id) {
+ setValue(listNames().get(position).toString());
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView> parent) {
+ }
+ });
+ spinner.setSelection(0);
+ LinearLayout l = new LinearLayout(root.getContext());
+ l.setOrientation(LinearLayout.VERTICAL);
+ l.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
+ l.addView(spinner);
+ root.addView(l);
+ }
+
+ public InputProfileName setValue(String name) {
+ this.profileName = name;
+ return this;
+ }
+
+ public String getValue() {
+ return profileName;
+ }
+
+ public ArrayList listNames(){
+ ArrayList profileList = new ArrayList<>();
+ // profile
+ profileStore = ConfigBuilderPlugin.getPlugin().getActiveProfileInterface().getProfile();
+ if (profileStore == null) {
+ log.error("ProfileStore is empty");
+ } else {
+ profileList = profileStore.getProfileList();
+ }
+ return profileList;
+ }
+
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputString.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputString.java
new file mode 100644
index 0000000000..75ddb4b61a
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputString.java
@@ -0,0 +1,56 @@
+package info.nightscout.androidaps.plugins.general.automation.elements;
+
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.ViewGroup;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+
+public class InputString extends Element {
+
+ TextWatcher textWatcher = new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ value = s.toString();
+ }
+ };
+
+ private String value = "";
+
+ public InputString() {
+ super();
+ }
+
+ public InputString(InputString another) {
+ super();
+ value = another.getValue();
+ }
+
+
+ @Override
+ public void addToLayout(LinearLayout root) {
+ EditText editText = new EditText(root.getContext());
+ editText.setText(value);
+ editText.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
+ editText.addTextChangedListener(textWatcher);
+ root.addView(editText);
+ }
+
+ public InputString setValue(String value) {
+ this.value = value;
+ return this;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputTempTarget.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputTempTarget.java
new file mode 100644
index 0000000000..7e9207c0e1
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputTempTarget.java
@@ -0,0 +1,95 @@
+package info.nightscout.androidaps.plugins.general.automation.elements;
+
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.widget.LinearLayout;
+
+import java.text.DecimalFormat;
+
+import info.nightscout.androidaps.Constants;
+import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
+import info.nightscout.androidaps.utils.NumberPicker;
+
+public class InputTempTarget extends Element {
+
+ private String units = Constants.MGDL;
+ private double value;
+ double minValue;
+ private double maxValue;
+ private double step;
+ private DecimalFormat decimalFormat;
+
+ private final TextWatcher textWatcher = new TextWatcher() {
+ @Override
+ public void afterTextChanged(Editable s) {
+ value = Math.max(minValue, value);
+ value = Math.min(maxValue, value);
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ }
+ };
+
+ public InputTempTarget() {
+ super();
+ setUnits(ProfileFunctions.getInstance().getProfileUnits());
+ if (getUnits().equals(Constants.MMOL))
+ value = 6;
+ else
+ value = 110;
+ }
+
+ public InputTempTarget(InputTempTarget another) {
+ super();
+ value = another.getValue();
+ setUnits(another.getUnits());
+ }
+
+
+ @Override
+ public void addToLayout(LinearLayout root) {
+ NumberPicker numberPicker = new NumberPicker(root.getContext(), null);
+ numberPicker.setParams(value, minValue, maxValue, step, decimalFormat, true, null, textWatcher);
+ numberPicker.setOnValueChangedListener(value -> this.value = value);
+ root.addView(numberPicker);
+ }
+
+ public String getUnits() {
+ return units;
+ }
+
+ public InputTempTarget setUnits(String units) {
+ // set default initial value
+ if (units.equals(Constants.MMOL)) {
+ // mmol
+ minValue = Constants.MIN_TT_MMOL;
+ maxValue = Constants.MAX_TT_MMOL;
+ step = 0.1;
+ decimalFormat = new DecimalFormat("0.0");
+ } else {
+ // mg/dL
+ minValue = Constants.MIN_TT_MGDL;
+ maxValue = Constants.MAX_TT_MGDL;
+ step = 1;
+ decimalFormat = new DecimalFormat("0");
+ }
+
+ this.units = units;
+ return this;
+ }
+
+ public InputTempTarget setValue(double value) {
+ this.value = value;
+ return this;
+ }
+
+ public double getValue() {
+ return value;
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/LabelWithElement.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/LabelWithElement.java
new file mode 100644
index 0000000000..145d8c2d2c
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/LabelWithElement.java
@@ -0,0 +1,64 @@
+package info.nightscout.androidaps.plugins.general.automation.elements;
+
+import android.graphics.Typeface;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.TableLayout;
+import android.widget.TextView;
+
+import info.nightscout.androidaps.MainApp;
+
+public class LabelWithElement extends Element {
+ final Element element;
+ final String textPre;
+ final String textPost;
+
+ public LabelWithElement(String textPre, String textPost, Element element) {
+ this.element = element;
+ this.textPre = textPre;
+ this.textPost = textPost;
+ }
+
+ @Override
+ public void addToLayout(LinearLayout root) {
+ // container layout
+ LinearLayout layout = new LinearLayout(root.getContext());
+ layout.setOrientation(LinearLayout.HORIZONTAL);
+ layout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT));
+
+ // text view pre element
+ int px = MainApp.dpToPx(10);
+ TextView textViewPre = new TextView(root.getContext());
+ textViewPre.setText(textPre);
+ textViewPre.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT));
+ //textViewPre.setWidth(MainApp.dpToPx(120));
+ textViewPre.setPadding(px, px, px, px);
+ textViewPre.setTypeface(textViewPre.getTypeface(), Typeface.BOLD);
+ layout.addView(textViewPre);
+
+ TextView spacer = new TextView(root.getContext());
+ spacer.setLayoutParams(new TableLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1f));
+ layout.addView(spacer);
+
+ // add element to layout
+ element.addToLayout(layout);
+
+ // text view post element
+ if (textPost != null) {
+ px = MainApp.dpToPx(5);
+ TextView textViewPost = new TextView(root.getContext());
+ textViewPost.setText(textPost);
+ textViewPost.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT));
+ //textViewPost.setWidth(MainApp.dpToPx(45));
+ textViewPost.setPadding(px, px, px, px);
+ textViewPost.setTypeface(textViewPost.getTypeface(), Typeface.BOLD);
+ layout.addView(textViewPost);
+ }
+
+ // add layout to root layout
+ root.addView(layout);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/LayoutBuilder.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/LayoutBuilder.java
new file mode 100644
index 0000000000..5853e50be0
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/LayoutBuilder.java
@@ -0,0 +1,26 @@
+package info.nightscout.androidaps.plugins.general.automation.elements;
+
+import android.widget.LinearLayout;
+
+import java.util.ArrayList;
+
+public class LayoutBuilder {
+ ArrayList mElements = new ArrayList<>();
+
+ public LayoutBuilder add(Element element) {
+ mElements.add(element);
+ return this;
+ }
+
+ public LayoutBuilder add(Element element, boolean condition) {
+ if (condition) mElements.add(element);
+ return this;
+ }
+
+ public void build(LinearLayout layout) {
+ for (Element e : mElements) {
+ e.addToLayout(layout);
+ }
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/StaticLabel.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/StaticLabel.java
new file mode 100644
index 0000000000..3c8cf38074
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/StaticLabel.java
@@ -0,0 +1,36 @@
+package info.nightscout.androidaps.plugins.general.automation.elements;
+
+import android.graphics.Typeface;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+
+public class StaticLabel extends Element {
+ String label;
+
+ public StaticLabel(String label) {
+ super();
+ this.label = label;
+ }
+
+ public StaticLabel(int resourceId) {
+ super();
+ this.label = MainApp.gs(resourceId);
+ }
+
+ @Override
+ public void addToLayout(LinearLayout root) {
+ // text view pre element
+ int px = MainApp.dpToPx(10);
+ TextView textView = new TextView(root.getContext());
+ textView.setText(label);
+// textViewPre.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
+ textView.setPadding(px, px, px, px);
+ textView.setTypeface(textView.getTypeface(), Typeface.BOLD);
+ textView.setBackgroundColor(MainApp.gc(R.color.mdtp_line_dark));
+ // add element to layout
+ root.addView(textView);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/events/EventAutomationAddAction.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/events/EventAutomationAddAction.kt
new file mode 100644
index 0000000000..867550e2f4
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/events/EventAutomationAddAction.kt
@@ -0,0 +1,6 @@
+package info.nightscout.androidaps.plugins.general.automation.events
+
+import info.nightscout.androidaps.events.Event
+import info.nightscout.androidaps.plugins.general.automation.actions.Action
+
+class EventAutomationAddAction(val action: Action) : Event()
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/events/EventAutomationDataChanged.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/events/EventAutomationDataChanged.kt
new file mode 100644
index 0000000000..d017468dbb
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/events/EventAutomationDataChanged.kt
@@ -0,0 +1,5 @@
+package info.nightscout.androidaps.plugins.general.automation.events
+
+import info.nightscout.androidaps.events.Event
+
+class EventAutomationDataChanged : Event()
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/events/EventAutomationUpdateAction.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/events/EventAutomationUpdateAction.kt
new file mode 100644
index 0000000000..6fa6709cf1
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/events/EventAutomationUpdateAction.kt
@@ -0,0 +1,7 @@
+package info.nightscout.androidaps.plugins.general.automation.events
+
+import info.nightscout.androidaps.events.Event
+import info.nightscout.androidaps.plugins.general.automation.actions.Action
+
+class EventAutomationUpdateAction(val action: Action, val position : Int) : Event() {
+}
\ No newline at end of file
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/events/EventAutomationUpdateGui.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/events/EventAutomationUpdateGui.kt
new file mode 100644
index 0000000000..1326701b93
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/events/EventAutomationUpdateGui.kt
@@ -0,0 +1,5 @@
+package info.nightscout.androidaps.plugins.general.automation.events
+
+import info.nightscout.androidaps.events.Event
+
+class EventAutomationUpdateGui : Event()
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/events/EventAutomationUpdateTrigger.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/events/EventAutomationUpdateTrigger.kt
new file mode 100644
index 0000000000..f9b67a74de
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/events/EventAutomationUpdateTrigger.kt
@@ -0,0 +1,6 @@
+package info.nightscout.androidaps.plugins.general.automation.events
+
+import info.nightscout.androidaps.events.Event
+import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger
+
+class EventAutomationUpdateTrigger(val trigger: Trigger) : Event()
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/Trigger.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/Trigger.java
new file mode 100644
index 0000000000..f6ba6b6f67
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/Trigger.java
@@ -0,0 +1,94 @@
+package info.nightscout.androidaps.plugins.general.automation.triggers;
+
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.fragment.app.FragmentManager;
+
+import com.google.common.base.Optional;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import javax.annotation.Nullable;
+
+public abstract class Trigger {
+
+ TriggerConnector connector = null;
+ long lastRun;
+
+ Trigger() {
+ }
+
+ public TriggerConnector getConnector() {
+ return connector;
+ }
+
+ public abstract boolean shouldRun();
+
+
+ public abstract String toJSON();
+
+ /*package*/
+ abstract Trigger fromJSON(String data);
+
+ public abstract int friendlyName();
+
+ public abstract String friendlyDescription();
+
+ public abstract Optional icon();
+
+ public void executed(long time) {
+ lastRun = time;
+ }
+
+ public long getLastRun() {
+ return lastRun;
+ }
+
+ public abstract Trigger duplicate();
+
+ public static Trigger instantiate(String json) {
+ try {
+ return instantiate(new JSONObject(json));
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ @Nullable
+ public static Trigger instantiate(JSONObject object) {
+ try {
+ String type = object.getString("type");
+ JSONObject data = object.getJSONObject("data");
+ Class clazz = Class.forName(type);
+ return ((Trigger) clazz.newInstance()).fromJSON(data.toString());
+ } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | JSONException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
+ TextView title = new TextView(root.getContext());
+ title.setText(friendlyName());
+ root.addView(title);
+ }
+
+ @Nullable
+ Activity scanForActivity(Context cont) {
+ if (cont == null)
+ return null;
+ else if (cont instanceof Activity)
+ return (Activity) cont;
+ else if (cont instanceof ContextWrapper)
+ return scanForActivity(((ContextWrapper) cont).getBaseContext());
+
+ return null;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerAutosensValue.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerAutosensValue.java
new file mode 100644
index 0000000000..da850b187d
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerAutosensValue.java
@@ -0,0 +1,153 @@
+package info.nightscout.androidaps.plugins.general.automation.triggers;
+
+
+import android.widget.LinearLayout;
+
+import androidx.fragment.app.FragmentManager;
+
+import com.google.common.base.Optional;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.text.DecimalFormat;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.general.automation.elements.Comparator;
+import info.nightscout.androidaps.plugins.general.automation.elements.InputDouble;
+import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement;
+import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
+import info.nightscout.androidaps.plugins.general.automation.elements.StaticLabel;
+import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensData;
+import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
+import info.nightscout.androidaps.utils.DateUtil;
+import info.nightscout.androidaps.utils.JsonHelper;
+import info.nightscout.androidaps.utils.SP;
+import info.nightscout.androidaps.utils.T;
+
+public class TriggerAutosensValue extends Trigger {
+ private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
+ private final int minValue = (int) (SP.getDouble("openapsama_autosens_min", 0.7d) * 100);
+ private final int maxValue = (int) (SP.getDouble("openapsama_autosens_max", 1.2d) * 100);
+ private final double step = 1;
+ private DecimalFormat decimalFormat = new DecimalFormat("1");
+ private InputDouble value = new InputDouble(100, (double) minValue, (double) maxValue, step, decimalFormat);
+ private Comparator comparator = new Comparator();
+
+ public TriggerAutosensValue() {
+ super();
+ }
+
+ private TriggerAutosensValue(TriggerAutosensValue triggerAutosensValue) {
+ super();
+ value = new InputDouble(triggerAutosensValue.value);
+ lastRun = triggerAutosensValue.lastRun;
+ comparator = new Comparator(triggerAutosensValue.comparator);
+ }
+
+ public double getValue() {
+ return value.getValue();
+ }
+
+ public Comparator getComparator() {
+ return comparator;
+ }
+
+ @Override
+ public synchronized boolean shouldRun() {
+ AutosensData autosensData = IobCobCalculatorPlugin.getPlugin().getLastAutosensData("Automation trigger");
+ if (autosensData == null)
+ if (comparator.getValue() == Comparator.Compare.IS_NOT_AVAILABLE)
+ return true;
+ else
+ return false;
+
+ if (lastRun > DateUtil.now() - T.mins(5).msecs())
+ return false;
+
+ boolean doRun = comparator.getValue().check((autosensData.autosensResult.ratio), getValue() / 100d);
+ if (doRun) {
+ if (L.isEnabled(L.AUTOMATION))
+ log.debug("Ready for execution: " + friendlyDescription());
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public synchronized String toJSON() {
+ JSONObject o = new JSONObject();
+ try {
+ o.put("type", TriggerAutosensValue.class.getName());
+ JSONObject data = new JSONObject();
+ data.put("value", getValue());
+ data.put("lastRun", lastRun);
+ data.put("comparator", comparator.getValue().toString());
+ o.put("data", data);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return o.toString();
+ }
+
+ @Override
+ Trigger fromJSON(String data) {
+ try {
+ JSONObject d = new JSONObject(data);
+ value.setValue(JsonHelper.safeGetDouble(d, "value"));
+ lastRun = JsonHelper.safeGetLong(d, "lastRun");
+ comparator.setValue(Comparator.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return this;
+ }
+
+ @Override
+ public int friendlyName() {
+ return R.string.autosenslabel;
+ }
+
+ @Override
+ public String friendlyDescription() {
+ return MainApp.gs(R.string.autosenscompared, MainApp.gs(comparator.getValue().getStringRes()), getValue());
+ }
+
+ @Override
+ public Optional icon() {
+ return Optional.of(R.drawable.as);
+ }
+
+ @Override
+ public Trigger duplicate() {
+ return new TriggerAutosensValue(this);
+ }
+
+ TriggerAutosensValue setValue(int requestedValue) {
+ this.value.setValue(requestedValue);
+ return this;
+ }
+
+ TriggerAutosensValue lastRun(long lastRun) {
+ this.lastRun = lastRun;
+ return this;
+ }
+
+ TriggerAutosensValue comparator(Comparator.Compare compare) {
+ this.comparator = new Comparator().setValue(compare);
+ return this;
+ }
+
+ @Override
+ public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
+ new LayoutBuilder()
+ .add(new StaticLabel(R.string.autosenslabel))
+ .add(comparator)
+ .add(new LabelWithElement(MainApp.gs(R.string.autosenslabel) + ": ", "", value))
+ .build(root);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerBg.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerBg.java
new file mode 100644
index 0000000000..1636377bf2
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerBg.java
@@ -0,0 +1,178 @@
+package info.nightscout.androidaps.plugins.general.automation.triggers;
+
+import android.widget.LinearLayout;
+
+import androidx.fragment.app.FragmentManager;
+
+import com.google.common.base.Optional;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+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.logging.L;
+import info.nightscout.androidaps.plugins.general.automation.elements.Comparator;
+import info.nightscout.androidaps.plugins.general.automation.elements.InputBg;
+import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement;
+import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
+import info.nightscout.androidaps.plugins.general.automation.elements.StaticLabel;
+import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus;
+import info.nightscout.androidaps.utils.DateUtil;
+import info.nightscout.androidaps.utils.JsonHelper;
+import info.nightscout.androidaps.utils.T;
+
+public class TriggerBg extends Trigger {
+ private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
+
+ private InputBg bg = new InputBg();
+ private Comparator comparator = new Comparator();
+
+ public TriggerBg() {
+ super();
+ }
+
+ private TriggerBg(TriggerBg triggerBg) {
+ super();
+ bg = new InputBg(triggerBg.bg);
+ comparator = new Comparator(triggerBg.comparator);
+ lastRun = triggerBg.lastRun;
+ }
+
+ public double getValue() {
+ return bg.getValue();
+ }
+
+ public Comparator getComparator() {
+ return comparator;
+ }
+
+ public String getUnits() {
+ return bg.getUnits();
+ }
+
+ public long getLastRun() {
+ return lastRun;
+ }
+
+ @Override
+ public synchronized boolean shouldRun() {
+ GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
+
+ if (lastRun > DateUtil.now() - T.mins(5).msecs()) {
+ if (L.isEnabled(L.AUTOMATION))
+ log.debug("NOT ready for execution: " + friendlyDescription());
+ return false;
+ }
+
+ if (glucoseStatus == null && comparator.getValue().equals(Comparator.Compare.IS_NOT_AVAILABLE)) {
+ if (L.isEnabled(L.AUTOMATION))
+ log.debug("Ready for execution: " + friendlyDescription());
+ return true;
+ }
+ if (glucoseStatus == null) {
+ if (L.isEnabled(L.AUTOMATION))
+ log.debug("NOT ready for execution: " + friendlyDescription());
+ return false;
+ }
+
+ boolean doRun = comparator.getValue().check(glucoseStatus.glucose, Profile.toMgdl(bg.getValue(), bg.getUnits()));
+ if (doRun) {
+ if (L.isEnabled(L.AUTOMATION))
+ log.debug("Ready for execution: " + friendlyDescription());
+ return true;
+ }
+
+ if (L.isEnabled(L.AUTOMATION))
+ log.debug("NOT ready for execution: " + friendlyDescription());
+ return false;
+ }
+
+ @Override
+ public synchronized String toJSON() {
+ JSONObject o = new JSONObject();
+ try {
+ o.put("type", TriggerBg.class.getName());
+ JSONObject data = new JSONObject();
+ data.put("bg", bg.getValue());
+ data.put("lastRun", lastRun);
+ data.put("comparator", comparator.getValue().toString());
+ data.put("units", bg.getUnits());
+ o.put("data", data);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return o.toString();
+ }
+
+ @Override
+ Trigger fromJSON(String data) {
+ try {
+ JSONObject d = new JSONObject(data);
+ bg.setUnits(JsonHelper.safeGetString(d, "units"));
+ bg.setValue(JsonHelper.safeGetDouble(d, "bg"));
+ lastRun = JsonHelper.safeGetLong(d, "lastRun");
+ comparator.setValue(Comparator.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return this;
+ }
+
+ @Override
+ public int friendlyName() {
+ return R.string.glucose;
+ }
+
+ @Override
+ public String friendlyDescription() {
+ if (comparator.getValue().equals(Comparator.Compare.IS_NOT_AVAILABLE))
+ return MainApp.gs(R.string.glucoseisnotavailable);
+ else {
+ return MainApp.gs(bg.getUnits().equals(Constants.MGDL) ? R.string.glucosecomparedmgdl : R.string.glucosecomparedmmol, MainApp.gs(comparator.getValue().getStringRes()), bg.getValue(), bg.getUnits());
+ }
+ }
+
+ @Override
+ public Optional icon() {
+ return Optional.of(R.drawable.icon_cp_bgcheck);
+ }
+
+ @Override
+ public Trigger duplicate() {
+ return new TriggerBg(this);
+ }
+
+ TriggerBg setValue(double value) {
+ bg.setValue(value);
+ return this;
+ }
+
+ TriggerBg lastRun(long lastRun) {
+ this.lastRun = lastRun;
+ return this;
+ }
+
+ TriggerBg comparator(Comparator.Compare compare) {
+ this.comparator = new Comparator().setValue(compare);
+ return this;
+ }
+
+ TriggerBg setUnits(String units) {
+ bg.setUnits(units);
+ return this;
+ }
+
+ @Override
+ public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
+ new LayoutBuilder()
+ .add(new StaticLabel(R.string.glucose))
+ .add(comparator)
+ .add(new LabelWithElement(MainApp.gs(R.string.glucose_u, bg.getUnits()), "", bg))
+ .build(root);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerBolusAgo.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerBolusAgo.java
new file mode 100644
index 0000000000..0ad9f75ab2
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerBolusAgo.java
@@ -0,0 +1,150 @@
+package info.nightscout.androidaps.plugins.general.automation.triggers;
+
+import android.widget.LinearLayout;
+
+import androidx.fragment.app.FragmentManager;
+
+import com.google.common.base.Optional;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.general.automation.elements.Comparator;
+import info.nightscout.androidaps.plugins.general.automation.elements.InputDuration;
+import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement;
+import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
+import info.nightscout.androidaps.plugins.general.automation.elements.StaticLabel;
+import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
+import info.nightscout.androidaps.utils.DateUtil;
+import info.nightscout.androidaps.utils.JsonHelper;
+import info.nightscout.androidaps.utils.T;
+
+public class TriggerBolusAgo extends Trigger {
+ private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
+ private InputDuration minutesAgo = new InputDuration(0, InputDuration.TimeUnit.MINUTES);
+ private Comparator comparator = new Comparator();
+
+ public TriggerBolusAgo() {
+ super();
+ }
+
+ private TriggerBolusAgo(TriggerBolusAgo triggerBolusAgo) {
+ super();
+ minutesAgo = new InputDuration(triggerBolusAgo.minutesAgo);
+ lastRun = triggerBolusAgo.lastRun;
+ comparator = new Comparator(triggerBolusAgo.comparator);
+ }
+
+ public double getValue() {
+ return minutesAgo.getValue();
+ }
+
+ public Comparator getComparator() {
+ return comparator;
+ }
+
+ @Override
+ public synchronized boolean shouldRun() {
+
+ if (lastRun > DateUtil.now() - T.mins(5).msecs())
+ return false;
+
+ long lastBolusTime = TreatmentsPlugin.getPlugin().getLastBolusTime(false);
+
+ if (lastBolusTime == 0)
+ if (comparator.getValue() == Comparator.Compare.IS_NOT_AVAILABLE)
+ return true;
+ else
+ return false;
+
+ double minutesAgo = (double) (DateUtil.now() - lastBolusTime) / (60 * 1000);
+ if (L.isEnabled(L.AUTOMATION))
+ log.debug("LastBolus min ago: " + minutesAgo);
+
+ boolean doRun = comparator.getValue().check((minutesAgo), getValue());
+ if (doRun) {
+ if (L.isEnabled(L.AUTOMATION))
+ log.debug("Ready for execution: " + friendlyDescription());
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public synchronized String toJSON() {
+ JSONObject o = new JSONObject();
+ try {
+ o.put("type", TriggerBolusAgo.class.getName());
+ JSONObject data = new JSONObject();
+ data.put("minutesAgo", getValue());
+ data.put("lastRun", lastRun);
+ data.put("comparator", comparator.getValue().toString());
+ o.put("data", data);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return o.toString();
+ }
+
+ @Override
+ Trigger fromJSON(String data) {
+ try {
+ JSONObject d = new JSONObject(data);
+ minutesAgo.setMinutes(JsonHelper.safeGetInt(d, "minutesAgo"));
+ lastRun = JsonHelper.safeGetLong(d, "lastRun");
+ comparator.setValue(Comparator.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return this;
+ }
+
+ @Override
+ public int friendlyName() {
+ return R.string.lastboluslabel;
+ }
+
+ @Override
+ public String friendlyDescription() {
+ return MainApp.gs(R.string.lastboluscompared, MainApp.gs(comparator.getValue().getStringRes()), (int) getValue());
+ }
+
+ @Override
+ public Optional icon() {
+ return Optional.of(R.drawable.icon_bolus);
+ }
+
+ @Override
+ public Trigger duplicate() {
+ return new TriggerBolusAgo(this);
+ }
+
+ TriggerBolusAgo setValue(int requestedValue) {
+ this.minutesAgo.setMinutes(requestedValue);
+ return this;
+ }
+
+ TriggerBolusAgo lastRun(long lastRun) {
+ this.lastRun = lastRun;
+ return this;
+ }
+
+ TriggerBolusAgo comparator(Comparator.Compare compare) {
+ this.comparator = new Comparator().setValue(compare);
+ return this;
+ }
+
+ @Override
+ public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
+ new LayoutBuilder()
+ .add(new StaticLabel(R.string.lastboluslabel))
+ .add(comparator)
+ .add(new LabelWithElement(MainApp.gs(R.string.lastboluslabel) + ": ", "", minutesAgo))
+ .build(root);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerCOB.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerCOB.java
new file mode 100644
index 0000000000..4ddeb4299a
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerCOB.java
@@ -0,0 +1,151 @@
+package info.nightscout.androidaps.plugins.general.automation.triggers;
+
+
+import android.widget.LinearLayout;
+
+import androidx.fragment.app.FragmentManager;
+
+import com.google.common.base.Optional;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.text.DecimalFormat;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.general.automation.elements.Comparator;
+import info.nightscout.androidaps.plugins.general.automation.elements.InputDouble;
+import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement;
+import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
+import info.nightscout.androidaps.plugins.general.automation.elements.StaticLabel;
+import info.nightscout.androidaps.plugins.iob.iobCobCalculator.CobInfo;
+import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
+import info.nightscout.androidaps.utils.DateUtil;
+import info.nightscout.androidaps.utils.JsonHelper;
+import info.nightscout.androidaps.utils.SP;
+import info.nightscout.androidaps.utils.T;
+
+public class TriggerCOB extends Trigger {
+ private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
+ private final int minValue = 0;
+ private final int maxValue = SP.getInt(R.string.key_treatmentssafety_maxcarbs, 48);
+ private InputDouble value = new InputDouble(0, (double) minValue, (double) maxValue, 1, new DecimalFormat("1"));
+ private Comparator comparator = new Comparator();
+
+ public TriggerCOB() {
+ super();
+ }
+
+ private TriggerCOB(TriggerCOB triggerCOB) {
+ super();
+ value = new InputDouble(triggerCOB.value);
+ lastRun = triggerCOB.lastRun;
+ comparator = new Comparator(triggerCOB.comparator);
+ }
+
+ public double getValue() {
+ return value.getValue();
+ }
+
+ public Comparator getComparator() {
+ return comparator;
+ }
+
+ @Override
+ public synchronized boolean shouldRun() {
+ CobInfo cobInfo = IobCobCalculatorPlugin.getPlugin().getCobInfo(false, "AutomationTriggerCOB");
+ if (cobInfo == null)
+ if (comparator.getValue() == Comparator.Compare.IS_NOT_AVAILABLE)
+ return true;
+ else
+ return false;
+
+ if (lastRun > DateUtil.now() - T.mins(5).msecs())
+ return false;
+
+ boolean doRun = comparator.getValue().check((cobInfo.displayCob), getValue());
+ if (doRun) {
+ if (L.isEnabled(L.AUTOMATION))
+ log.debug("Ready for execution: " + friendlyDescription());
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public synchronized String toJSON() {
+ JSONObject o = new JSONObject();
+ try {
+ o.put("type", TriggerCOB.class.getName());
+ JSONObject data = new JSONObject();
+ data.put("carbs", getValue());
+ data.put("lastRun", lastRun);
+ data.put("comparator", comparator.getValue().toString());
+ o.put("data", data);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return o.toString();
+ }
+
+ @Override
+ Trigger fromJSON(String data) {
+ try {
+ JSONObject d = new JSONObject(data);
+ value.setValue(JsonHelper.safeGetDouble(d, "carbs"));
+ lastRun = JsonHelper.safeGetLong(d, "lastRun");
+ comparator.setValue(Comparator.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return this;
+ }
+
+ @Override
+ public int friendlyName() {
+ return R.string.triggercoblabel;
+ }
+
+ @Override
+ public String friendlyDescription() {
+ return MainApp.gs(R.string.cobcompared, MainApp.gs(comparator.getValue().getStringRes()), getValue());
+ }
+
+ @Override
+ public Optional icon() {
+ return Optional.of(R.drawable.icon_cp_bolus_carbs);
+ }
+
+ @Override
+ public Trigger duplicate() {
+ return new TriggerCOB(this);
+ }
+
+ TriggerCOB setValue(int requestedValue) {
+ this.value.setValue(requestedValue);
+ return this;
+ }
+
+ TriggerCOB lastRun(long lastRun) {
+ this.lastRun = lastRun;
+ return this;
+ }
+
+ TriggerCOB comparator(Comparator.Compare compare) {
+ this.comparator = new Comparator().setValue(compare);
+ return this;
+ }
+
+ @Override
+ public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
+ new LayoutBuilder()
+ .add(new StaticLabel(R.string.triggercoblabel))
+ .add(comparator)
+ .add(new LabelWithElement(MainApp.gs(R.string.triggercoblabel) + ": ", "", value))
+ .build(root);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerConnector.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerConnector.java
new file mode 100644
index 0000000000..ae4bd35ad5
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerConnector.java
@@ -0,0 +1,277 @@
+package info.nightscout.androidaps.plugins.general.automation.triggers;
+
+
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+
+import androidx.annotation.StringRes;
+import androidx.fragment.app.FragmentManager;
+
+import com.google.common.base.Optional;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.general.automation.dialogs.TriggerListAdapter;
+import info.nightscout.androidaps.utils.JsonHelper;
+
+public class TriggerConnector extends Trigger {
+ private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
+
+ public enum Type {
+ AND,
+ OR,
+ XOR;
+
+ public boolean apply(boolean a, boolean b) {
+ switch (this) {
+ case AND:
+ return a && b;
+ case OR:
+ return a || b;
+ case XOR:
+ return a ^ b;
+ }
+ return false;
+ }
+
+ public @StringRes
+ int getStringRes() {
+ switch (this) {
+ case OR:
+ return R.string.or;
+ case XOR:
+ return R.string.xor;
+
+ default:
+ case AND:
+ return R.string.and;
+ }
+ }
+
+ public static List labels() {
+ List list = new ArrayList<>();
+ for (Type t : values()) {
+ list.add(MainApp.gs(t.getStringRes()));
+ }
+ return list;
+ }
+ }
+
+ public static void fillIconSet(TriggerConnector connector, HashSet set) {
+ for (Trigger t : connector.list) {
+ if (t instanceof TriggerConnector) {
+ fillIconSet((TriggerConnector) t, set);
+ } else {
+ Optional icon = t.icon();
+ if (icon.isPresent()) {
+ set.add(icon.get());
+ }
+ }
+ }
+ }
+
+ protected List list = new ArrayList<>();
+ private Type connectorType;
+
+ public TriggerConnector() {
+ connectorType = Type.AND;
+ }
+
+ public TriggerConnector(Type connectorType) {
+ this.connectorType = connectorType;
+ }
+
+ public void changeConnectorType(Type type) {
+ this.connectorType = type;
+ }
+
+ public Type getConnectorType() {
+ return connectorType;
+ }
+
+ public synchronized void add(Trigger t) {
+ list.add(t);
+ t.connector = this;
+ }
+
+ public synchronized void add(int pos, Trigger t) {
+ list.add(pos, t);
+ t.connector = this;
+ }
+
+ public synchronized boolean remove(Trigger t) {
+ return list.remove(t);
+ }
+
+ public int size() {
+ return list.size();
+ }
+
+ public Trigger get(int i) {
+ return list.get(i);
+ }
+
+ public int pos(Trigger trigger) {
+ for (int i = 0; i < list.size(); ++i) {
+ if (list.get(i) == trigger) return i;
+ }
+ return -1;
+ }
+
+ @Override
+ public synchronized boolean shouldRun() {
+ boolean result = true;
+
+ // check first trigger
+ if (list.size() > 0)
+ result = list.get(0).shouldRun();
+
+ // check all others
+ for (int i = 1; i < list.size(); ++i) {
+ result = connectorType.apply(result, list.get(i).shouldRun());
+ }
+ if (result)
+ if (L.isEnabled(L.AUTOMATION))
+ log.debug("Ready for execution: " + friendlyDescription().replace("\n", " "));
+
+ return result;
+ }
+
+ @Override
+ public synchronized String toJSON() {
+ JSONObject o = new JSONObject();
+ try {
+ o.put("type", TriggerConnector.class.getName());
+ JSONObject data = new JSONObject();
+ data.put("connectorType", connectorType.toString());
+ JSONArray array = new JSONArray();
+ for (Trigger t : list) {
+ array.put(t.toJSON());
+ }
+ data.put("triggerList", array);
+ o.put("data", data);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return o.toString();
+ }
+
+ @Override
+ Trigger fromJSON(String data) {
+ try {
+ JSONObject d = new JSONObject(data);
+ connectorType = Type.valueOf(JsonHelper.safeGetString(d, "connectorType"));
+ JSONArray array = d.getJSONArray("triggerList");
+ list.clear();
+ for (int i = 0; i < array.length(); i++) {
+ Trigger newItem = instantiate(new JSONObject(array.getString(i)));
+ add(newItem);
+ }
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return this;
+ }
+
+ @Override
+ public int friendlyName() {
+ return connectorType.getStringRes();
+ }
+
+ @Override
+ public String friendlyDescription() {
+ int counter = 0;
+ StringBuilder result = new StringBuilder();
+ for (Trigger t : list) {
+ if (counter++ > 0) result.append("\n").append(MainApp.gs(friendlyName())).append("\n");
+ result.append(t.friendlyDescription());
+ }
+ return result.toString();
+ }
+
+ @Override
+ public Optional icon() {
+ return Optional.absent();
+ }
+
+ @Override
+ public void executed(long time) {
+ for (int i = 0; i < list.size(); ++i) {
+ list.get(i).executed(time);
+ }
+ }
+
+ @Override
+ public Trigger duplicate() {
+ return null;
+ }
+
+ private TriggerListAdapter adapter;
+
+ public void rebuildView(FragmentManager fragmentManager) {
+ if (adapter != null)
+ adapter.rebuild(fragmentManager);
+ }
+
+ @Override
+ public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
+ final int padding = MainApp.dpToPx(5);
+
+ root.setPadding(padding, padding, padding, padding);
+ root.setBackgroundResource(R.drawable.border_automation_unit);
+
+ LinearLayout triggerListLayout = new LinearLayout(root.getContext());
+ triggerListLayout.setOrientation(LinearLayout.VERTICAL);
+ triggerListLayout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
+ root.addView(triggerListLayout);
+
+ adapter = new TriggerListAdapter(fragmentManager, root.getContext(), triggerListLayout, this);
+ }
+
+ public TriggerConnector simplify() {
+ // simplify children
+ for (int i = 0; i < size(); ++i) {
+ if (get(i) instanceof TriggerConnector) {
+ TriggerConnector t = (TriggerConnector) get(i);
+ t.simplify();
+ }
+ }
+
+ // drop connector with only 1 element
+ if (size() == 1 && get(0) instanceof TriggerConnector) {
+ TriggerConnector c = (TriggerConnector) get(0);
+ remove(c);
+ changeConnectorType(c.getConnectorType());
+ for (Trigger t : c.list) {
+ add(t);
+ }
+ c.list.clear();
+ return simplify();
+ }
+
+ // merge connectors
+ if (connector != null && (connector.getConnectorType().equals(connectorType) || size() == 1)) {
+ final int pos = connector.pos(this);
+ connector.remove(this);
+ // move triggers of child connector into parent connector
+ for (int i = size() - 1; i >= 0; --i) {
+ connector.add(pos, get(i));
+ }
+ list.clear();
+ return connector.simplify();
+ }
+
+ return this;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerDelta.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerDelta.java
new file mode 100644
index 0000000000..a3939a60b7
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerDelta.java
@@ -0,0 +1,202 @@
+package info.nightscout.androidaps.plugins.general.automation.triggers;
+
+
+import android.widget.LinearLayout;
+
+import androidx.fragment.app.FragmentManager;
+
+import com.google.common.base.Optional;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.text.DecimalFormat;
+
+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.logging.L;
+import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
+import info.nightscout.androidaps.plugins.general.automation.elements.Comparator;
+import info.nightscout.androidaps.plugins.general.automation.elements.InputDelta;
+import info.nightscout.androidaps.plugins.general.automation.elements.InputDelta.DeltaType;
+import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement;
+import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
+import info.nightscout.androidaps.plugins.general.automation.elements.StaticLabel;
+import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus;
+import info.nightscout.androidaps.utils.DateUtil;
+import info.nightscout.androidaps.utils.JsonHelper;
+import info.nightscout.androidaps.utils.T;
+
+public class TriggerDelta extends Trigger {
+ private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
+
+ private final int MMOL_MAX = 4;
+ private final int MGDL_MAX = 72;
+
+ private String units;
+ private DeltaType deltaType;
+
+ private InputDelta value;
+ private Comparator comparator;
+
+ public TriggerDelta() {
+ super();
+ this.units = ProfileFunctions.getInstance().getProfileUnits();
+ initializer();
+ }
+
+ private TriggerDelta(TriggerDelta triggerDelta) {
+ super();
+ lastRun = triggerDelta.lastRun;
+ this.units = triggerDelta.units;
+ deltaType = triggerDelta.deltaType;
+ value = new InputDelta(triggerDelta.value);
+ comparator = new Comparator(triggerDelta.comparator);
+ }
+
+ public double getValue() {
+ deltaType = value.getDeltaType();
+ return value.getValue();
+ }
+
+ private void initializer() {
+ this.deltaType = DeltaType.DELTA;
+ comparator = new Comparator();
+ if (units.equals(Constants.MMOL))
+ value = new InputDelta(0, -MMOL_MAX, MMOL_MAX, 0.1d, new DecimalFormat("0.1"), DeltaType.DELTA);
+ else
+ value = new InputDelta(0, -MGDL_MAX, MGDL_MAX, 1d, new DecimalFormat("1"), DeltaType.DELTA);
+ }
+
+
+ public DeltaType getType() {
+ return deltaType;
+ }
+
+ public String getUnits() {
+ return this.units;
+ }
+
+ public Comparator getComparator() {
+ return comparator;
+ }
+
+ @Override
+ public synchronized boolean shouldRun() {
+ GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
+ if (glucoseStatus == null)
+ if (comparator.getValue() == Comparator.Compare.IS_NOT_AVAILABLE)
+ return true;
+ else
+ return false;
+
+ // Setting type of delta
+ double delta;
+
+ if (deltaType == DeltaType.SHORT_AVERAGE)
+ delta = glucoseStatus.short_avgdelta;
+ else if (deltaType == DeltaType.LONG_AVERAGE)
+ delta = glucoseStatus.long_avgdelta;
+ else
+ delta = glucoseStatus.delta;
+
+ if (lastRun > DateUtil.now() - T.mins(5).msecs())
+ return false;
+
+ boolean doRun = comparator.getValue().check(delta, Profile.toMgdl(value.getValue(), this.units));
+ if (doRun) {
+ if (L.isEnabled(L.AUTOMATION))
+ log.debug("Ready for execution: delta is " + delta + " " + friendlyDescription());
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public synchronized String toJSON() {
+ JSONObject o = new JSONObject();
+ try {
+ o.put("type", TriggerDelta.class.getName());
+ JSONObject data = new JSONObject();
+ data.put("value", getValue());
+ data.put("units", units);
+ data.put("lastRun", lastRun);
+ data.put("deltaType", getType());
+ data.put("comparator", comparator.getValue().toString());
+ o.put("data", data);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return o.toString();
+ }
+
+ @Override
+ Trigger fromJSON(String data) {
+ try {
+ JSONObject d = new JSONObject(data);
+ units = JsonHelper.safeGetString(d, "units");
+ deltaType = DeltaType.valueOf(JsonHelper.safeGetString(d, "deltaType", ""));
+ value.setValue(JsonHelper.safeGetDouble(d, "value"), deltaType);
+ lastRun = JsonHelper.safeGetLong(d, "lastRun");
+ comparator.setValue(Comparator.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return this;
+ }
+
+ @Override
+ public int friendlyName() {
+ return R.string.deltalabel;
+ }
+
+ @Override
+ public String friendlyDescription() {
+ return MainApp.gs(R.string.deltacompared, MainApp.gs(comparator.getValue().getStringRes()), getValue(), MainApp.gs(deltaType.getStringRes()));
+ }
+
+ @Override
+ public Optional icon() {
+ return Optional.of(R.drawable.icon_auto_delta);
+ }
+
+ @Override
+ public Trigger duplicate() {
+ return new TriggerDelta(this);
+ }
+
+ TriggerDelta setValue(double requestedValue, DeltaType requestedType) {
+ this.value.setValue(requestedValue, requestedType);
+ this.deltaType = requestedType;
+ return this;
+ }
+
+ TriggerDelta setUnits(String units) {
+ this.units = units;
+ return this;
+ }
+
+ TriggerDelta lastRun(long lastRun) {
+ this.lastRun = lastRun;
+ return this;
+ }
+
+ TriggerDelta comparator(Comparator.Compare compare) {
+ this.comparator = new Comparator().setValue(compare);
+ return this;
+ }
+
+ @Override
+ public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
+ new LayoutBuilder()
+ .add(new StaticLabel(R.string.deltalabel))
+ .add(comparator)
+ .add(new LabelWithElement(MainApp.gs(R.string.deltalabel_u, getUnits()) + ": ", "", value))
+ .build(root);
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerIob.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerIob.java
new file mode 100644
index 0000000000..c4003af861
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerIob.java
@@ -0,0 +1,146 @@
+package info.nightscout.androidaps.plugins.general.automation.triggers;
+
+import android.widget.LinearLayout;
+
+import androidx.fragment.app.FragmentManager;
+
+import com.google.common.base.Optional;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+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.logging.L;
+import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
+import info.nightscout.androidaps.plugins.general.automation.elements.Comparator;
+import info.nightscout.androidaps.plugins.general.automation.elements.InputInsulin;
+import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement;
+import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
+import info.nightscout.androidaps.plugins.general.automation.elements.StaticLabel;
+import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
+import info.nightscout.androidaps.utils.DateUtil;
+import info.nightscout.androidaps.utils.JsonHelper;
+import info.nightscout.androidaps.utils.T;
+
+public class TriggerIob extends Trigger {
+ private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
+
+ private InputInsulin insulin = new InputInsulin();
+ private Comparator comparator = new Comparator();
+
+ public TriggerIob() {
+ super();
+ }
+
+ private TriggerIob(TriggerIob triggerIob) {
+ super();
+ insulin = new InputInsulin(triggerIob.insulin);
+ comparator = new Comparator(triggerIob.comparator);
+ lastRun = triggerIob.lastRun;
+ }
+
+ public double getValue() {
+ return insulin.getValue();
+ }
+
+ public Comparator getComparator() {
+ return comparator;
+ }
+
+ @Override
+ public synchronized boolean shouldRun() {
+ Profile profile = ProfileFunctions.getInstance().getProfile();
+ if (profile == null)
+ return false;
+ IobTotal iob = IobCobCalculatorPlugin.getPlugin().calculateFromTreatmentsAndTempsSynchronized(DateUtil.now(), profile);
+
+ if (lastRun > DateUtil.now() - T.mins(5).msecs())
+ return false;
+
+ boolean doRun = comparator.getValue().check(iob.iob, getValue());
+ if (doRun) {
+ if (L.isEnabled(L.AUTOMATION))
+ log.debug("Ready for execution: " + friendlyDescription());
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public synchronized String toJSON() {
+ JSONObject o = new JSONObject();
+ try {
+ o.put("type", TriggerIob.class.getName());
+ JSONObject data = new JSONObject();
+ data.put("insulin", getValue());
+ data.put("lastRun", lastRun);
+ data.put("comparator", comparator.getValue().toString());
+ o.put("data", data);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return o.toString();
+ }
+
+ @Override
+ Trigger fromJSON(String data) {
+ try {
+ JSONObject d = new JSONObject(data);
+ insulin.setValue(JsonHelper.safeGetDouble(d, "insulin"));
+ lastRun = JsonHelper.safeGetLong(d, "lastRun");
+ comparator.setValue(Comparator.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return this;
+ }
+
+ @Override
+ public int friendlyName() {
+ return R.string.iob;
+ }
+
+ @Override
+ public String friendlyDescription() {
+ return MainApp.gs(R.string.iobcompared, MainApp.gs(comparator.getValue().getStringRes()), getValue());
+ }
+
+ @Override
+ public Optional icon() {
+ return Optional.of(R.drawable.ic_keyboard_capslock);
+ }
+
+ @Override
+ public Trigger duplicate() {
+ return new TriggerIob(this);
+ }
+
+ TriggerIob setValue(double threshold) {
+ insulin.setValue(threshold);
+ return this;
+ }
+
+ TriggerIob lastRun(long lastRun) {
+ this.lastRun = lastRun;
+ return this;
+ }
+
+ TriggerIob comparator(Comparator.Compare compare) {
+ this.comparator = new Comparator().setValue(compare);
+ return this;
+ }
+
+ @Override
+ public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
+ new LayoutBuilder()
+ .add(new StaticLabel(R.string.iob))
+ .add(comparator)
+ .add(new LabelWithElement(MainApp.gs(R.string.iob_u), "", insulin))
+ .build(root);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerLocation.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerLocation.java
new file mode 100644
index 0000000000..4772d29112
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerLocation.java
@@ -0,0 +1,168 @@
+package info.nightscout.androidaps.plugins.general.automation.triggers;
+
+import android.location.Location;
+import android.widget.LinearLayout;
+
+import androidx.fragment.app.FragmentManager;
+
+import com.google.common.base.Optional;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.text.DecimalFormat;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.general.automation.elements.InputButton;
+import info.nightscout.androidaps.plugins.general.automation.elements.InputDouble;
+import info.nightscout.androidaps.plugins.general.automation.elements.InputString;
+import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement;
+import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
+import info.nightscout.androidaps.plugins.general.automation.elements.StaticLabel;
+import info.nightscout.androidaps.services.LocationService;
+import info.nightscout.androidaps.utils.DateUtil;
+import info.nightscout.androidaps.utils.JsonHelper;
+import info.nightscout.androidaps.utils.T;
+
+public class TriggerLocation extends Trigger {
+ private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
+
+ InputDouble latitude = new InputDouble(0d, -90d, +90d, 0.000001d, new DecimalFormat("0.000000"));
+ InputDouble longitude = new InputDouble(0d, -180d, +180d, 0.000001d, new DecimalFormat("0.000000"));
+ InputDouble distance = new InputDouble(200d, 0, 100000, 10d, new DecimalFormat("0"));
+ InputString name = new InputString();
+
+ private Runnable buttonAction = () -> {
+ Location location = LocationService.getLastLocation();
+ if (location != null) {
+ latitude.setValue(location.getLatitude());
+ longitude.setValue(location.getLongitude());
+ log.debug(String.format("Grabbed location: %f %f", latitude.getValue(), longitude.getValue()));
+ }
+ };
+
+ public TriggerLocation() {
+ super();
+ }
+
+ private TriggerLocation(TriggerLocation triggerLocation) {
+ super();
+ latitude = new InputDouble(triggerLocation.latitude);
+ longitude = new InputDouble(triggerLocation.longitude);
+ distance = new InputDouble(triggerLocation.distance);
+ lastRun = triggerLocation.lastRun;
+ name = triggerLocation.name;
+ }
+
+ @Override
+ public synchronized boolean shouldRun() {
+ Location location = LocationService.getLastLocation();
+ if (location == null)
+ return false;
+
+ if (lastRun > DateUtil.now() - T.mins(5).msecs())
+ return false;
+
+ Location a = new Location("Trigger");
+ a.setLatitude(latitude.getValue());
+ a.setLongitude(longitude.getValue());
+ double calculatedDistance = location.distanceTo(a);
+
+ if (calculatedDistance < distance.getValue()) {
+ if (L.isEnabled(L.AUTOMATION))
+ log.debug("Ready for execution: " + friendlyDescription());
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public synchronized String toJSON() {
+ JSONObject o = new JSONObject();
+ try {
+ o.put("type", TriggerLocation.class.getName());
+ JSONObject data = new JSONObject();
+ data.put("latitude", latitude.getValue());
+ data.put("longitude", longitude.getValue());
+ data.put("distance", distance.getValue());
+ data.put("name", name.getValue());
+ data.put("lastRun", lastRun);
+ o.put("data", data);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return o.toString();
+ }
+
+ @Override
+ Trigger fromJSON(String data) {
+ try {
+ JSONObject d = new JSONObject(data);
+ latitude.setValue(JsonHelper.safeGetDouble(d, "latitude"));
+ longitude.setValue(JsonHelper.safeGetDouble(d, "longitude"));
+ distance.setValue(JsonHelper.safeGetDouble(d, "distance"));
+ name.setValue(JsonHelper.safeGetString(d, "name"));
+ lastRun = JsonHelper.safeGetLong(d, "lastRun");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return this;
+ }
+
+ @Override
+ public int friendlyName() {
+ return R.string.location;
+ }
+
+ @Override
+ public String friendlyDescription() {
+ return MainApp.gs(R.string.locationis, name.getValue());
+ }
+
+ @Override
+ public Optional icon() {
+ return Optional.of(R.drawable.ic_location_on);
+ }
+
+ @Override
+ public Trigger duplicate() {
+ return new TriggerLocation(this);
+ }
+
+
+ TriggerLocation setLatitude(double value) {
+ latitude.setValue(value);
+ return this;
+ }
+
+ TriggerLocation setLongitude(double value) {
+ longitude.setValue(value);
+ return this;
+ }
+
+ TriggerLocation setdistance(double value) {
+ distance.setValue(value);
+ return this;
+ }
+
+ TriggerLocation lastRun(long lastRun) {
+ this.lastRun = lastRun;
+ return this;
+ }
+
+ @Override
+ public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
+ new LayoutBuilder()
+ .add(new StaticLabel(R.string.location))
+ .add(new LabelWithElement(MainApp.gs(R.string.name_short), "", name))
+ .add(new LabelWithElement(MainApp.gs(R.string.latitude_short), "", latitude))
+ .add(new LabelWithElement(MainApp.gs(R.string.longitude_short), "", longitude))
+ .add(new LabelWithElement(MainApp.gs(R.string.distance_short), "", distance))
+ .add(new InputButton(MainApp.gs(R.string.currentlocation), buttonAction), LocationService.getLastLocation() != null)
+ .build(root);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerProfilePercent.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerProfilePercent.java
new file mode 100644
index 0000000000..d86bc35cb8
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerProfilePercent.java
@@ -0,0 +1,152 @@
+package info.nightscout.androidaps.plugins.general.automation.triggers;
+
+import android.widget.LinearLayout;
+
+import androidx.fragment.app.FragmentManager;
+
+import com.google.common.base.Optional;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.data.Profile;
+import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
+import info.nightscout.androidaps.plugins.general.automation.elements.Comparator;
+import info.nightscout.androidaps.plugins.general.automation.elements.InputPercent;
+import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement;
+import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
+import info.nightscout.androidaps.plugins.general.automation.elements.StaticLabel;
+import info.nightscout.androidaps.utils.DateUtil;
+import info.nightscout.androidaps.utils.JsonHelper;
+import info.nightscout.androidaps.utils.T;
+
+public class TriggerProfilePercent extends Trigger {
+ private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
+
+ private InputPercent pct = new InputPercent();
+ private Comparator comparator = new Comparator();
+
+ public TriggerProfilePercent() {
+ super();
+ }
+
+ private TriggerProfilePercent(TriggerProfilePercent triggerProfilePercent) {
+ super();
+ pct = new InputPercent(triggerProfilePercent.pct);
+ comparator = new Comparator(triggerProfilePercent.comparator);
+ lastRun = triggerProfilePercent.lastRun;
+ }
+
+ public double getValue() {
+ return pct.getValue();
+ }
+
+ public Comparator getComparator() {
+ return comparator;
+ }
+
+ public long getLastRun() {
+ return lastRun;
+ }
+
+ @Override
+ public synchronized boolean shouldRun() {
+ if (lastRun > DateUtil.now() - T.mins(5).msecs())
+ return false;
+
+ Profile profile = ProfileFunctions.getInstance().getProfile();
+ if (profile == null && comparator.getValue().equals(Comparator.Compare.IS_NOT_AVAILABLE)) {
+ if (L.isEnabled(L.AUTOMATION))
+ log.debug("Ready for execution: " + friendlyDescription());
+ return true;
+ }
+ if (profile == null)
+ return false;
+
+ boolean doRun = comparator.getValue().check((double) profile.getPercentage(), pct.getValue());
+ if (doRun) {
+ if (L.isEnabled(L.AUTOMATION))
+ log.debug("Ready for execution: " + friendlyDescription());
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public synchronized String toJSON() {
+ JSONObject o = new JSONObject();
+ try {
+ o.put("type", TriggerProfilePercent.class.getName());
+ JSONObject data = new JSONObject();
+ data.put("percentage", pct.getValue());
+ data.put("lastRun", lastRun);
+ data.put("comparator", comparator.getValue().toString());
+ o.put("data", data);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return o.toString();
+ }
+
+ @Override
+ Trigger fromJSON(String data) {
+ try {
+ JSONObject d = new JSONObject(data);
+ pct.setValue(JsonHelper.safeGetDouble(d, "percentage"));
+ lastRun = JsonHelper.safeGetLong(d, "lastRun");
+ comparator.setValue(Comparator.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return this;
+ }
+
+ @Override
+ public int friendlyName() {
+ return R.string.profilepercentage;
+ }
+
+ @Override
+ public String friendlyDescription() {
+ return MainApp.gs(R.string.percentagecompared, MainApp.gs(comparator.getValue().getStringRes()), (int) pct.getValue());
+ }
+
+ @Override
+ public Optional icon() {
+ return Optional.of(R.drawable.icon_actions_profileswitch);
+ }
+
+ @Override
+ public Trigger duplicate() {
+ return new TriggerProfilePercent(this);
+ }
+
+ public TriggerProfilePercent setValue(double value) {
+ pct.setValue(value);
+ return this;
+ }
+
+ TriggerProfilePercent lastRun(long lastRun) {
+ this.lastRun = lastRun;
+ return this;
+ }
+
+ public TriggerProfilePercent comparator(Comparator.Compare compare) {
+ this.comparator = new Comparator().setValue(compare);
+ return this;
+ }
+
+ @Override
+ public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
+ new LayoutBuilder()
+ .add(new StaticLabel(R.string.profilepercentage))
+ .add(comparator)
+ .add(new LabelWithElement(MainApp.gs(R.string.percent_u), "", pct))
+ .build(root);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerPumpLastConnection.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerPumpLastConnection.java
new file mode 100644
index 0000000000..8cec3bdf44
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerPumpLastConnection.java
@@ -0,0 +1,146 @@
+package info.nightscout.androidaps.plugins.general.automation.triggers;
+
+import android.widget.LinearLayout;
+
+import androidx.fragment.app.FragmentManager;
+
+import com.google.common.base.Optional;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
+import info.nightscout.androidaps.plugins.general.automation.elements.Comparator;
+import info.nightscout.androidaps.plugins.general.automation.elements.InputDuration;
+import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement;
+import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
+import info.nightscout.androidaps.plugins.general.automation.elements.StaticLabel;
+import info.nightscout.androidaps.utils.DateUtil;
+import info.nightscout.androidaps.utils.JsonHelper;
+import info.nightscout.androidaps.utils.T;
+
+public class TriggerPumpLastConnection extends Trigger {
+ private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
+ private InputDuration minutesAgo = new InputDuration(0, InputDuration.TimeUnit.MINUTES);
+ private Comparator comparator = new Comparator();
+
+ public TriggerPumpLastConnection() {
+ super();
+ }
+
+ private TriggerPumpLastConnection(TriggerPumpLastConnection triggerPumpLastConnection) {
+ super();
+ minutesAgo = new InputDuration(triggerPumpLastConnection.minutesAgo);
+ lastRun = triggerPumpLastConnection.lastRun;
+ comparator = new Comparator(triggerPumpLastConnection.comparator);
+ }
+
+ public double getValue() {
+ return minutesAgo.getValue();
+ }
+
+ public Comparator getComparator() {
+ return comparator;
+ }
+
+ @Override
+ public synchronized boolean shouldRun() {
+
+ if (lastRun > DateUtil.now() - T.mins(5).msecs())
+ return false;
+ long lastConnection = ConfigBuilderPlugin.getPlugin().getActivePump().lastDataTime();
+
+ if (lastConnection == 0 && comparator.getValue() == Comparator.Compare.IS_NOT_AVAILABLE)
+ return true;
+
+ double minutesAgo = (double) (DateUtil.now() - lastConnection) / (60 * 1000);
+ if (L.isEnabled(L.AUTOMATION))
+ log.debug("Last connection min ago: " + minutesAgo);
+
+ boolean doRun = comparator.getValue().check((minutesAgo), getValue());
+ if (doRun) {
+ if (L.isEnabled(L.AUTOMATION))
+ log.debug("Ready for execution: " + friendlyDescription());
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public synchronized String toJSON() {
+ JSONObject o = new JSONObject();
+ try {
+ o.put("type", TriggerPumpLastConnection.class.getName());
+ JSONObject data = new JSONObject();
+ data.put("minutesAgo", getValue());
+ data.put("lastRun", lastRun);
+ data.put("comparator", comparator.getValue().toString());
+ o.put("data", data);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return o.toString();
+ }
+
+ @Override
+ Trigger fromJSON(String data) {
+ try {
+ JSONObject d = new JSONObject(data);
+ minutesAgo.setMinutes(JsonHelper.safeGetInt(d, "minutesAgo"));
+ lastRun = JsonHelper.safeGetLong(d, "lastRun");
+ comparator.setValue(Comparator.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return this;
+ }
+
+ @Override
+ public int friendlyName() {
+ return R.string.automation_trigger_pump_last_connection_label;
+ }
+
+ @Override
+ public String friendlyDescription() {
+ return MainApp.gs(R.string.automation_trigger_pump_last_connection_compared, MainApp.gs(comparator.getValue().getStringRes()), (int) getValue());
+ }
+
+ @Override
+ public Optional icon() {
+ return Optional.of(R.drawable.remove);
+ }
+
+ @Override
+ public Trigger duplicate() {
+ return new TriggerPumpLastConnection(this);
+ }
+
+ TriggerPumpLastConnection setValue(int requestedValue) {
+ this.minutesAgo.setMinutes(requestedValue);
+ return this;
+ }
+
+ TriggerPumpLastConnection lastRun(long lastRun) {
+ this.lastRun = lastRun;
+ return this;
+ }
+
+ TriggerPumpLastConnection comparator(Comparator.Compare compare) {
+ this.comparator = new Comparator().setValue(compare);
+ return this;
+ }
+
+ @Override
+ public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
+ new LayoutBuilder()
+ .add(new StaticLabel(R.string.automation_trigger_pump_last_connection_label))
+ .add(comparator)
+ .add(new LabelWithElement(MainApp.gs(R.string.automation_trigger_pump_last_connection_description) + ": ", "", minutesAgo))
+ .build(root);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerRecurringTime.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerRecurringTime.java
new file mode 100644
index 0000000000..a145253b36
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerRecurringTime.java
@@ -0,0 +1,317 @@
+package info.nightscout.androidaps.plugins.general.automation.triggers;
+
+import android.app.Activity;
+import android.graphics.Typeface;
+import android.text.format.DateFormat;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.StringRes;
+import androidx.fragment.app.FragmentManager;
+
+import com.dpro.widgets.WeekdaysPicker;
+import com.google.common.base.Optional;
+import com.wdullaer.materialdatetimepicker.time.TimePickerDialog;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.List;
+import java.util.Objects;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.utils.DateUtil;
+import info.nightscout.androidaps.utils.JsonHelper;
+import info.nightscout.androidaps.utils.T;
+
+public class TriggerRecurringTime extends Trigger {
+ private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
+
+ public enum DayOfWeek {
+ MONDAY,
+ TUESDAY,
+ WEDNESDAY,
+ THURSDAY,
+ FRIDAY,
+ SATURDAY,
+ SUNDAY;
+
+ private static final int[] calendarInts = new int[]{
+ Calendar.MONDAY,
+ Calendar.TUESDAY,
+ Calendar.WEDNESDAY,
+ Calendar.THURSDAY,
+ Calendar.FRIDAY,
+ Calendar.SATURDAY,
+ Calendar.SUNDAY
+ };
+
+ private static final int[] shortNames = new int[]{
+ R.string.weekday_monday_short,
+ R.string.weekday_tuesday_short,
+ R.string.weekday_wednesday_short,
+ R.string.weekday_thursday_short,
+ R.string.weekday_friday_short,
+ R.string.weekday_saturday_short,
+ R.string.weekday_sunday_short
+ };
+
+ public int toCalendarInt() {
+ return calendarInts[ordinal()];
+ }
+
+ @Nullable
+ public static DayOfWeek fromCalendarInt(int day) {
+ for (int i = 0; i < calendarInts.length; ++i) {
+ if (calendarInts[i] == day)
+ return values()[i];
+ }
+ return null;
+ }
+
+ public @StringRes
+ int getShortName() {
+ return shortNames[ordinal()];
+ }
+ }
+
+ private final boolean[] weekdays = new boolean[DayOfWeek.values().length];
+
+ // Recurring
+ private int hour;
+ private int minute;
+
+ private long validTo;
+
+ public TriggerRecurringTime() {
+ super();
+ setAll(false);
+ }
+
+ private TriggerRecurringTime(TriggerRecurringTime triggerTime) {
+ super();
+ lastRun = triggerTime.lastRun;
+ hour = triggerTime.hour;
+ minute = triggerTime.minute;
+ validTo = triggerTime.validTo;
+
+ if (weekdays.length >= 0)
+ System.arraycopy(triggerTime.weekdays, 0, weekdays, 0, weekdays.length);
+ }
+
+ public void setAll(boolean value) {
+ for (DayOfWeek day : DayOfWeek.values()) {
+ set(day, value);
+ }
+ }
+
+ public TriggerRecurringTime set(DayOfWeek day, boolean value) {
+ weekdays[day.ordinal()] = value;
+ return this;
+ }
+
+ private boolean isSet(DayOfWeek day) {
+ return weekdays[day.ordinal()];
+ }
+
+ @Override
+ public boolean shouldRun() {
+ if (validTo != 0 && DateUtil.now() > validTo)
+ return false;
+ Calendar c = Calendar.getInstance();
+ int scheduledDayOfWeek = c.get(Calendar.DAY_OF_WEEK);
+
+ Calendar scheduledCal = DateUtil.gregorianCalendar();
+ scheduledCal.set(Calendar.HOUR_OF_DAY, hour);
+ scheduledCal.set(Calendar.MINUTE, minute);
+ scheduledCal.set(Calendar.SECOND, 0);
+ long scheduled = scheduledCal.getTimeInMillis();
+
+ if (isSet(Objects.requireNonNull(DayOfWeek.fromCalendarInt(scheduledDayOfWeek)))) {
+ if (DateUtil.now() >= scheduled && DateUtil.now() - scheduled < T.mins(5).msecs()) {
+ if (lastRun < scheduled) {
+ if (L.isEnabled(L.AUTOMATION))
+ log.debug("Ready for execution: " + friendlyDescription());
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String toJSON() {
+ JSONObject object = new JSONObject();
+ JSONObject data = new JSONObject();
+ try {
+ data.put("lastRun", lastRun);
+ for (int i = 0; i < weekdays.length; ++i) {
+ data.put(DayOfWeek.values()[i].name(), weekdays[i]);
+ }
+ data.put("hour", hour);
+ data.put("minute", minute);
+ data.put("validTo", validTo);
+ object.put("type", TriggerRecurringTime.class.getName());
+ object.put("data", data);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return object.toString();
+ }
+
+ @Override
+ Trigger fromJSON(String data) {
+ JSONObject o;
+ try {
+ o = new JSONObject(data);
+ lastRun = JsonHelper.safeGetLong(o, "lastRun");
+ for (int i = 0; i < weekdays.length; ++i) {
+ weekdays[i] = JsonHelper.safeGetBoolean(o, DayOfWeek.values()[i].name());
+ }
+ hour = JsonHelper.safeGetInt(o, "hour");
+ minute = JsonHelper.safeGetInt(o, "minute");
+ validTo = JsonHelper.safeGetLong(o, "validTo");
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return this;
+ }
+
+ @Override
+ public int friendlyName() {
+ return R.string.recurringTime;
+ }
+
+ @Override
+ public String friendlyDescription() {
+ int counter = 0;
+ StringBuilder sb = new StringBuilder();
+ sb.append(MainApp.gs(R.string.every));
+ sb.append(" ");
+ for (Integer i : getSelectedDays()) {
+ if (counter > 0)
+ sb.append(",");
+ sb.append(MainApp.gs(Objects.requireNonNull(DayOfWeek.fromCalendarInt(i)).getShortName()));
+ counter++;
+ }
+ sb.append(" ");
+
+ Calendar scheduledCal = DateUtil.gregorianCalendar();
+ scheduledCal.set(Calendar.HOUR_OF_DAY, hour);
+ scheduledCal.set(Calendar.MINUTE, minute);
+ scheduledCal.set(Calendar.SECOND, 0);
+ long scheduled = scheduledCal.getTimeInMillis();
+
+ sb.append(DateUtil.timeString(scheduled));
+
+ if (counter == 0)
+ return MainApp.gs(R.string.never);
+ return sb.toString();
+ }
+
+ @Override
+ public Optional icon() {
+ return Optional.of(R.drawable.ic_access_alarm_24dp);
+ }
+
+ @Override
+ public Trigger duplicate() {
+ return new TriggerRecurringTime(this);
+ }
+
+ TriggerRecurringTime lastRun(long lastRun) {
+ this.lastRun = lastRun;
+ return this;
+ }
+
+ @SuppressWarnings("SameParameterValue")
+ TriggerRecurringTime validTo(long validTo) {
+ this.validTo = validTo;
+ return this;
+ }
+
+ TriggerRecurringTime hour(int hour) {
+ this.hour = hour;
+ return this;
+ }
+
+ TriggerRecurringTime minute(int minute) {
+ this.minute = minute;
+ return this;
+ }
+
+ private List getSelectedDays() {
+ List selectedDays = new ArrayList<>();
+ for (int i = 0; i < weekdays.length; ++i) {
+ DayOfWeek day = DayOfWeek.values()[i];
+ boolean selected = weekdays[i];
+ if (selected) selectedDays.add(day.toCalendarInt());
+ }
+ return selectedDays;
+ }
+
+ @Override
+ public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
+ TextView label = new TextView(root.getContext());
+
+ // TODO: Replace external tool WeekdaysPicker with a self-made GUI element
+ WeekdaysPicker weekdaysPicker = new WeekdaysPicker(root.getContext());
+ weekdaysPicker.setEditable(true);
+ weekdaysPicker.setSelectedDays(getSelectedDays());
+ weekdaysPicker.setOnWeekdaysChangeListener((view, i, list) -> set(DayOfWeek.fromCalendarInt(i), list.contains(i)));
+ weekdaysPicker.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
+
+ root.addView(weekdaysPicker);
+
+ TextView timeButton = new TextView(root.getContext());
+
+ GregorianCalendar runAt = new GregorianCalendar();
+ //Date runAt = new Date();
+ runAt.set(Calendar.HOUR_OF_DAY, hour);
+ runAt.set(Calendar.MINUTE, minute);
+ timeButton.setText(DateUtil.timeString(runAt.getTimeInMillis()));
+ timeButton.setOnClickListener(view -> {
+ TimePickerDialog tpd = TimePickerDialog.newInstance(
+ (view12, hourOfDay, minute, second) -> {
+ hour(hourOfDay);
+ minute(minute);
+ runAt.set(Calendar.HOUR_OF_DAY, hour);
+ runAt.set(Calendar.MINUTE, minute);
+ timeButton.setText(DateUtil.timeString(runAt.getTimeInMillis()));
+ },
+ runAt.get(Calendar.HOUR_OF_DAY),
+ runAt.get(Calendar.MINUTE),
+ DateFormat.is24HourFormat(root.getContext())
+ );
+ tpd.setThemeDark(true);
+ tpd.dismissOnPause(true);
+ Activity a = scanForActivity(root.getContext());
+ if (a != null)
+ tpd.show(a.getFragmentManager(), "TimePickerDialog");
+ });
+
+ int px = MainApp.dpToPx(10);
+ label.setText(MainApp.gs(R.string.atspecifiedtime, ""));
+ label.setTypeface(label.getTypeface(), Typeface.BOLD);
+ label.setPadding(px, px, px, px);
+ timeButton.setPadding(px, px, px, px);
+
+ LinearLayout l = new LinearLayout(root.getContext());
+ l.setOrientation(LinearLayout.HORIZONTAL);
+ l.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
+
+ l.addView(label);
+ l.addView(timeButton);
+ root.addView(l);
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerTempTarget.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerTempTarget.java
new file mode 100644
index 0000000000..378652ed2a
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerTempTarget.java
@@ -0,0 +1,131 @@
+package info.nightscout.androidaps.plugins.general.automation.triggers;
+
+import android.widget.LinearLayout;
+
+import androidx.fragment.app.FragmentManager;
+
+import com.google.common.base.Optional;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.db.TempTarget;
+import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.general.automation.elements.ComparatorExists;
+import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
+import info.nightscout.androidaps.plugins.general.automation.elements.StaticLabel;
+import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
+import info.nightscout.androidaps.utils.DateUtil;
+import info.nightscout.androidaps.utils.JsonHelper;
+import info.nightscout.androidaps.utils.T;
+
+public class TriggerTempTarget extends Trigger {
+ private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
+
+ private ComparatorExists comparator = new ComparatorExists();
+
+ public TriggerTempTarget() {
+ super();
+ }
+
+ private TriggerTempTarget(TriggerTempTarget triggerTempTarget) {
+ super();
+ comparator = new ComparatorExists(triggerTempTarget.comparator);
+ lastRun = triggerTempTarget.lastRun;
+ }
+
+ public ComparatorExists getComparator() {
+ return comparator;
+ }
+
+ @Override
+ public synchronized boolean shouldRun() {
+ TempTarget tt = TreatmentsPlugin.getPlugin().getTempTargetFromHistory();
+
+ if (lastRun > DateUtil.now() - T.mins(5).msecs())
+ return false;
+
+ if (tt == null && comparator.getValue() == ComparatorExists.Compare.NOT_EXISTS) {
+ if (L.isEnabled(L.AUTOMATION))
+ log.debug("Ready for execution: " + friendlyDescription());
+ return true;
+ }
+
+ if (tt != null && comparator.getValue() == ComparatorExists.Compare.EXISTS) {
+ if (L.isEnabled(L.AUTOMATION))
+ log.debug("Ready for execution: " + friendlyDescription());
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ public synchronized String toJSON() {
+ JSONObject o = new JSONObject();
+ try {
+ o.put("type", TriggerTempTarget.class.getName());
+ JSONObject data = new JSONObject();
+ data.put("lastRun", lastRun);
+ data.put("comparator", comparator.getValue().toString());
+ o.put("data", data);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return o.toString();
+ }
+
+ @Override
+ Trigger fromJSON(String data) {
+ try {
+ JSONObject d = new JSONObject(data);
+ lastRun = JsonHelper.safeGetLong(d, "lastRun");
+ comparator.setValue(ComparatorExists.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return this;
+ }
+
+ @Override
+ public int friendlyName() {
+ return R.string.temptarget;
+ }
+
+ @Override
+ public String friendlyDescription() {
+ return MainApp.gs(R.string.temptargetcompared, MainApp.gs(comparator.getValue().getStringRes()));
+ }
+
+ @Override
+ public Optional icon() {
+ return Optional.of(R.drawable.ic_keyboard_tab);
+ }
+
+ @Override
+ public Trigger duplicate() {
+ return new TriggerTempTarget(this);
+ }
+
+ TriggerTempTarget lastRun(long lastRun) {
+ this.lastRun = lastRun;
+ return this;
+ }
+
+ public TriggerTempTarget comparator(ComparatorExists.Compare compare) {
+ this.comparator = new ComparatorExists().setValue(compare);
+ return this;
+ }
+
+ @Override
+ public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
+ new LayoutBuilder()
+ .add(new StaticLabel(R.string.temptarget))
+ .add(comparator)
+ .build(root);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerTime.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerTime.java
new file mode 100644
index 0000000000..261783b99c
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerTime.java
@@ -0,0 +1,186 @@
+package info.nightscout.androidaps.plugins.general.automation.triggers;
+
+import android.app.Activity;
+import android.graphics.Typeface;
+import android.text.format.DateFormat;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.fragment.app.FragmentManager;
+
+import com.google.common.base.Optional;
+import com.wdullaer.materialdatetimepicker.date.DatePickerDialog;
+import com.wdullaer.materialdatetimepicker.time.TimePickerDialog;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.utils.DateUtil;
+import info.nightscout.androidaps.utils.JsonHelper;
+import info.nightscout.androidaps.utils.T;
+
+public class TriggerTime extends Trigger {
+ private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
+
+ private long runAt;
+
+ public TriggerTime() {
+ runAt = DateUtil.now();
+ }
+
+ private TriggerTime(TriggerTime triggerTime) {
+ super();
+ lastRun = triggerTime.lastRun;
+ runAt = triggerTime.runAt;
+ }
+
+ @Override
+ public boolean shouldRun() {
+ long now = DateUtil.now();
+ if (now >= runAt && now - runAt < T.mins(5).msecs())
+ if (lastRun < runAt) {
+ if (L.isEnabled(L.AUTOMATION))
+ log.debug("Ready for execution: " + friendlyDescription());
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public String toJSON() {
+ JSONObject object = new JSONObject();
+ JSONObject data = new JSONObject();
+ try {
+ data.put("runAt", runAt);
+ data.put("lastRun", lastRun);
+ object.put("type", TriggerTime.class.getName());
+ object.put("data", data);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return object.toString();
+ }
+
+ @Override
+ Trigger fromJSON(String data) {
+ JSONObject o;
+ try {
+ o = new JSONObject(data);
+ lastRun = JsonHelper.safeGetLong(o, "lastRun");
+ runAt = JsonHelper.safeGetLong(o, "runAt");
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return this;
+ }
+
+ @Override
+ public int friendlyName() {
+ return R.string.time;
+ }
+
+ @Override
+ public String friendlyDescription() {
+ return MainApp.gs(R.string.atspecifiedtime, DateUtil.dateAndTimeString(runAt));
+ }
+
+ @Override
+ public Optional icon() {
+ return Optional.of(R.drawable.ic_access_alarm_24dp);
+ }
+
+ TriggerTime runAt(long runAt) {
+ this.runAt = runAt;
+ return this;
+ }
+
+ TriggerTime lastRun(long lastRun) {
+ this.lastRun = lastRun;
+ return this;
+ }
+
+ @Override
+ public Trigger duplicate() {
+ return new TriggerTime(this);
+ }
+
+ long getRunAt() {
+ return runAt;
+ }
+
+ @Override
+ public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
+ TextView label = new TextView(root.getContext());
+ TextView dateButton = new TextView(root.getContext());
+ TextView timeButton = new TextView(root.getContext());
+
+ dateButton.setText(DateUtil.dateString(runAt));
+ timeButton.setText(DateUtil.timeString(runAt));
+ dateButton.setOnClickListener(view -> {
+ GregorianCalendar calendar = new GregorianCalendar();
+ calendar.setTimeInMillis(runAt);
+ DatePickerDialog dpd = DatePickerDialog.newInstance(
+ (view1, year, monthOfYear, dayOfMonth) -> {
+ calendar.set(Calendar.YEAR, year);
+ calendar.set(Calendar.MONTH, monthOfYear);
+ calendar.set(Calendar.DAY_OF_MONTH, dayOfMonth);
+ runAt = calendar.getTimeInMillis();
+ dateButton.setText(DateUtil.dateString(runAt));
+ },
+ calendar.get(Calendar.YEAR),
+ calendar.get(Calendar.MONTH),
+ calendar.get(Calendar.DAY_OF_MONTH)
+ );
+ dpd.setThemeDark(true);
+ dpd.dismissOnPause(true);
+ Activity a = scanForActivity(root.getContext());
+ if (a != null)
+ dpd.show(a.getFragmentManager(), "DatePickerDialog");
+ });
+ timeButton.setOnClickListener(view -> {
+ GregorianCalendar calendar = new GregorianCalendar();
+ calendar.setTimeInMillis(runAt);
+ TimePickerDialog tpd = TimePickerDialog.newInstance(
+ (view12, hourOfDay, minute, second) -> {
+ calendar.set(Calendar.HOUR_OF_DAY, hourOfDay);
+ calendar.set(Calendar.MINUTE, minute);
+ runAt = calendar.getTimeInMillis();
+ timeButton.setText(DateUtil.timeString(runAt));
+ },
+ calendar.get(Calendar.HOUR_OF_DAY),
+ calendar.get(Calendar.MINUTE),
+ DateFormat.is24HourFormat(root.getContext())
+ );
+ tpd.setThemeDark(true);
+ tpd.dismissOnPause(true);
+ Activity a = scanForActivity(root.getContext());
+ if (a != null)
+ tpd.show(a.getFragmentManager(), "TimePickerDialog");
+ });
+
+ int px = MainApp.dpToPx(10);
+ label.setText(MainApp.gs(R.string.atspecifiedtime, ""));
+ label.setTypeface(label.getTypeface(), Typeface.BOLD);
+ label.setPadding(px, px, px, px);
+ dateButton.setPadding(px, px, px, px);
+ timeButton.setPadding(px, px, px, px);
+
+ LinearLayout l = new LinearLayout(root.getContext());
+ l.setOrientation(LinearLayout.HORIZONTAL);
+ l.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
+
+ l.addView(label);
+ l.addView(dateButton);
+ l.addView(timeButton);
+ root.addView(l);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerTimeRange.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerTimeRange.java
new file mode 100644
index 0000000000..8755c3559c
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerTimeRange.java
@@ -0,0 +1,236 @@
+package info.nightscout.androidaps.plugins.general.automation.triggers;
+
+import android.app.Activity;
+import android.graphics.Typeface;
+import android.text.format.DateFormat;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.fragment.app.FragmentManager;
+
+import com.google.common.base.Optional;
+import com.wdullaer.materialdatetimepicker.time.TimePickerDialog;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.utils.DateUtil;
+import info.nightscout.androidaps.utils.JsonHelper;
+import info.nightscout.androidaps.utils.T;
+
+
+// Trigger for time range ( from 10:00AM till 13:00PM )
+
+public class TriggerTimeRange extends Trigger {
+ private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
+
+ // in minutes since midnight 60 means 1AM
+ private int start;
+ private int end;
+ long timeZoneOffset = DateUtil.getTimeZoneOffsetMs();
+
+ public TriggerTimeRange() {
+
+ start = getMinSinceMidnight(DateUtil.now());
+ end = getMinSinceMidnight(DateUtil.now());
+ }
+
+ private TriggerTimeRange(TriggerTimeRange triggerTimeRange) {
+ super();
+ lastRun = triggerTimeRange.lastRun;
+ start = triggerTimeRange.start;
+ end = triggerTimeRange.end;
+ }
+
+ @Override
+ public boolean shouldRun() {
+ int currentMinSinceMidnight = getMinSinceMidnight(DateUtil.now());
+
+ if (lastRun > DateUtil.now() - T.mins(5).msecs())
+ return false;
+
+ boolean doRun = false;
+ if ( start < end && start < currentMinSinceMidnight && currentMinSinceMidnight < end)
+ doRun = true;
+
+ // handle cases like 10PM to 6AM
+ else if ( start > end && (start < currentMinSinceMidnight || currentMinSinceMidnight < end))
+ doRun = true;
+
+ if (doRun) {
+ if (L.isEnabled(L.AUTOMATION))
+ log.debug("Ready for execution: " + friendlyDescription());
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public String toJSON() {
+ JSONObject object = new JSONObject();
+ JSONObject data = new JSONObject();
+
+ // check for too big values
+ if (start > 1440)
+ start = getMinSinceMidnight(start);
+ if (end > 1440)
+ end = getMinSinceMidnight(end);
+
+ try {
+ data.put("start", getMinSinceMidnight(start));
+ data.put("end", getMinSinceMidnight(end));
+ data.put("lastRun", lastRun);
+ object.put("type", TriggerTimeRange.class.getName());
+ object.put("data", data);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ log.debug(object.toString());
+ return object.toString();
+ }
+
+ @Override
+ TriggerTimeRange fromJSON(String data) {
+ JSONObject o;
+ try {
+ o = new JSONObject(data);
+ lastRun = JsonHelper.safeGetLong(o, "lastRun");
+ start = JsonHelper.safeGetInt(o, "start");
+ end = JsonHelper.safeGetInt(o, "end");
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return this;
+ }
+
+ @Override
+ public int friendlyName() {
+ return R.string.time_range;
+ }
+
+ @Override
+ public String friendlyDescription() {
+ return MainApp.gs(R.string.timerange_value, DateUtil.timeString(toMilis(start) - timeZoneOffset), DateUtil.timeString(toMilis(end) - timeZoneOffset));
+ }
+
+ @Override
+ public Optional icon() {
+ return Optional.of(R.drawable.ic_access_alarm_24dp);
+ }
+
+ TriggerTimeRange period(int start, int end) {
+ this.start = getMinSinceMidnight(start*60000);
+ this.end = getMinSinceMidnight(end*60000);
+ return this;
+ }
+
+ TriggerTimeRange lastRun(long lastRun) {
+ this.lastRun = lastRun;
+ return this;
+ }
+
+ @Override
+ public Trigger duplicate() {
+ return new TriggerTimeRange(this);
+ }
+
+ long toMilis(long minutesSinceMidnight) {
+ return minutesSinceMidnight*60*1000;
+ }
+
+ public int getMinSinceMidnight(long time) {
+ // if passed argument is smaller than 1440 ( 24 h * 60 min ) that value is already converted
+ if (0 < time && time < 1441)
+ return (int) time;
+ Calendar calendar = DateUtil.gregorianCalendar();
+ calendar.setTimeInMillis(time);
+ return (calendar.get(Calendar.HOUR_OF_DAY) * 60) + calendar.get(Calendar.MINUTE);
+ }
+
+ int getStart(){
+ return start;
+ }
+
+ int getEnd(){
+ return end;
+ }
+
+ @Override
+ public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
+ TextView label = new TextView(root.getContext());
+ TextView startButton = new TextView(root.getContext());
+ TextView endButton = new TextView(root.getContext());
+ log.debug("Start is: " + start );
+ log.debug("End is: " + end );
+ startButton.setText(DateUtil.timeString(toMilis(start) - timeZoneOffset));
+ endButton.setText(MainApp.gs(R.string.and) + " " + DateUtil.timeString(toMilis(end) - timeZoneOffset));
+
+ startButton.setOnClickListener(view -> {
+ GregorianCalendar calendar = new GregorianCalendar();
+ //setTimeInMillis sets time in milliseconds after
+ // * January 1, 1970, 0:00:00 GMT., but our time contains timezone offsset
+ calendar.setTimeInMillis(toMilis(start) - timeZoneOffset);
+ TimePickerDialog tpd = TimePickerDialog.newInstance(
+ (view12, hourOfDay, minute, second) -> {
+ calendar.set(Calendar.HOUR_OF_DAY, hourOfDay);
+ calendar.set(Calendar.MINUTE, minute);
+ start = getMinSinceMidnight(calendar.getTimeInMillis());
+ startButton.setText(DateUtil.timeString(toMilis(start) - timeZoneOffset));
+ },
+ calendar.get(Calendar.HOUR_OF_DAY),
+ calendar.get(Calendar.MINUTE),
+ DateFormat.is24HourFormat(root.getContext())
+ );
+ tpd.setThemeDark(true);
+ tpd.dismissOnPause(true);
+ Activity a = scanForActivity(root.getContext());
+ if (a != null)
+ tpd.show(a.getFragmentManager(), "TimePickerDialog");
+ });
+ endButton.setOnClickListener(view -> {
+ GregorianCalendar calendar = new GregorianCalendar();
+ calendar.setTimeInMillis(toMilis(end) - timeZoneOffset);
+ TimePickerDialog tpd = TimePickerDialog.newInstance(
+ (view12, hourOfDay, minute, second) -> {
+ calendar.set(Calendar.HOUR_OF_DAY, hourOfDay);
+ calendar.set(Calendar.MINUTE, minute);
+ end = getMinSinceMidnight(calendar.getTimeInMillis());
+ endButton.setText(MainApp.gs(R.string.and) + " " + DateUtil.timeString(toMilis(end) - timeZoneOffset));
+ },
+ calendar.get(Calendar.HOUR_OF_DAY),
+ calendar.get(Calendar.MINUTE),
+ DateFormat.is24HourFormat(root.getContext())
+ );
+ tpd.setThemeDark(true);
+ tpd.dismissOnPause(true);
+ Activity a = scanForActivity(root.getContext());
+ if (a != null)
+ tpd.show(a.getFragmentManager(), "TimePickerDialog");
+ });
+
+ int px = MainApp.dpToPx(10);
+ label.setText(MainApp.gs(R.string.between));
+ label.setTypeface(label.getTypeface(), Typeface.BOLD);
+ startButton.setPadding(px, px, px, px);
+ endButton.setPadding(px, px, px, px);
+
+ LinearLayout l = new LinearLayout(root.getContext());
+ l.setOrientation(LinearLayout.HORIZONTAL);
+ l.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
+
+ l.addView(label);
+ l.addView(startButton);
+ l.addView(endButton);
+ root.addView(l);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerWifiSsid.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerWifiSsid.java
new file mode 100644
index 0000000000..ba10e81583
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerWifiSsid.java
@@ -0,0 +1,149 @@
+package info.nightscout.androidaps.plugins.general.automation.triggers;
+
+import android.widget.LinearLayout;
+
+import androidx.fragment.app.FragmentManager;
+
+import com.google.common.base.Optional;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.events.EventNetworkChange;
+import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.general.automation.elements.Comparator;
+import info.nightscout.androidaps.plugins.general.automation.elements.InputString;
+import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement;
+import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
+import info.nightscout.androidaps.plugins.general.automation.elements.StaticLabel;
+import info.nightscout.androidaps.receivers.NetworkChangeReceiver;
+import info.nightscout.androidaps.utils.DateUtil;
+import info.nightscout.androidaps.utils.JsonHelper;
+import info.nightscout.androidaps.utils.T;
+
+public class TriggerWifiSsid extends Trigger {
+ private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
+
+ private InputString ssid = new InputString();
+ private Comparator comparator = new Comparator();
+
+ public TriggerWifiSsid() {
+ super();
+ }
+
+ private TriggerWifiSsid(TriggerWifiSsid triggerWifiSsid) {
+ super();
+ ssid = new InputString(triggerWifiSsid.ssid);
+ comparator = new Comparator(triggerWifiSsid.comparator);
+ lastRun = triggerWifiSsid.lastRun;
+ }
+
+ public String getValue() {
+ return ssid.getValue();
+ }
+
+ public Comparator getComparator() {
+ return comparator;
+ }
+
+ @Override
+ public synchronized boolean shouldRun() {
+ EventNetworkChange eventNetworkChange = NetworkChangeReceiver.getLastEvent();
+ if (eventNetworkChange == null)
+ return false;
+
+ if (lastRun > DateUtil.now() - T.mins(5).msecs())
+ return false;
+
+ if (!eventNetworkChange.getWifiConnected() && comparator.getValue() == Comparator.Compare.IS_NOT_AVAILABLE) {
+ if (L.isEnabled(L.AUTOMATION))
+ log.debug("Ready for execution: " + friendlyDescription());
+ return true;
+ }
+
+ boolean doRun = eventNetworkChange.getWifiConnected() && comparator.getValue().check(eventNetworkChange.connectedSsid(), getValue());
+ if (doRun) {
+ if (L.isEnabled(L.AUTOMATION))
+ log.debug("Ready for execution: " + friendlyDescription());
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public synchronized String toJSON() {
+ JSONObject o = new JSONObject();
+ try {
+ o.put("type", TriggerWifiSsid.class.getName());
+ JSONObject data = new JSONObject();
+ data.put("ssid", getValue());
+ data.put("lastRun", lastRun);
+ data.put("comparator", comparator.getValue().toString());
+ o.put("data", data);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return o.toString();
+ }
+
+ @Override
+ Trigger fromJSON(String data) {
+ try {
+ JSONObject d = new JSONObject(data);
+ ssid.setValue(JsonHelper.safeGetString(d, "ssid"));
+ lastRun = JsonHelper.safeGetLong(d, "lastRun");
+ comparator.setValue(Comparator.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return this;
+ }
+
+ @Override
+ public int friendlyName() {
+ return R.string.ns_wifi_ssids;
+ }
+
+ @Override
+ public String friendlyDescription() {
+ return MainApp.gs(R.string.wifissidcompared, MainApp.gs(comparator.getValue().getStringRes()), getValue());
+ }
+
+ @Override
+ public Optional icon() {
+ return Optional.of(R.drawable.ic_network_wifi);
+ }
+
+ @Override
+ public Trigger duplicate() {
+ return new TriggerWifiSsid(this);
+ }
+
+ TriggerWifiSsid setValue(String value) {
+ ssid.setValue(value);
+ return this;
+ }
+
+ TriggerWifiSsid lastRun(long lastRun) {
+ this.lastRun = lastRun;
+ return this;
+ }
+
+ TriggerWifiSsid comparator(Comparator.Compare compare) {
+ this.comparator = new Comparator().setValue(compare);
+ return this;
+ }
+
+ @Override
+ public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
+ new LayoutBuilder()
+ .add(new StaticLabel(R.string.ns_wifi_ssids))
+ .add(comparator)
+ .add(new LabelWithElement(MainApp.gs(R.string.ns_wifi_ssids) + ": ", "", ssid))
+ .build(root);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/careportal/CareportalFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/careportal/CareportalFragment.java
index 991fc962ee..42ae7fd6fc 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/careportal/CareportalFragment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/careportal/CareportalFragment.java
@@ -4,14 +4,14 @@ package info.nightscout.androidaps.plugins.general.careportal;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
-import android.support.v4.app.FragmentManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
-import com.squareup.otto.Subscribe;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -22,15 +22,18 @@ import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.events.EventCareportalEventChange;
-import info.nightscout.androidaps.plugins.general.careportal.Dialogs.NewNSTreatmentDialog;
-import info.nightscout.androidaps.plugins.common.SubscriberFragment;
+import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
+import info.nightscout.androidaps.plugins.general.careportal.Dialogs.NewNSTreatmentDialog;
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus;
import info.nightscout.androidaps.plugins.general.overview.OverviewFragment;
import info.nightscout.androidaps.utils.FabricPrivacy;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.disposables.CompositeDisposable;
-public class CareportalFragment extends SubscriberFragment implements View.OnClickListener {
+public class CareportalFragment extends Fragment implements View.OnClickListener {
private static Logger log = LoggerFactory.getLogger(CareportalFragment.class);
+ private CompositeDisposable disposable = new CompositeDisposable();
TextView iage;
TextView cage;
@@ -67,59 +70,69 @@ public class CareportalFragment extends SubscriberFragment implements View.OnCli
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
- try {
- View view = inflater.inflate(R.layout.careportal_fragment, container, false);
+ View view = inflater.inflate(R.layout.careportal_fragment, container, false);
- view.findViewById(R.id.careportal_bgcheck).setOnClickListener(this);
- view.findViewById(R.id.careportal_announcement).setOnClickListener(this);
- view.findViewById(R.id.careportal_cgmsensorinsert).setOnClickListener(this);
- view.findViewById(R.id.careportal_cgmsensorstart).setOnClickListener(this);
- view.findViewById(R.id.careportal_combobolus).setOnClickListener(this);
- view.findViewById(R.id.careportal_correctionbolus).setOnClickListener(this);
- view.findViewById(R.id.careportal_carbscorrection).setOnClickListener(this);
- view.findViewById(R.id.careportal_exercise).setOnClickListener(this);
- view.findViewById(R.id.careportal_insulincartridgechange).setOnClickListener(this);
- view.findViewById(R.id.careportal_pumpbatterychange).setOnClickListener(this);
- view.findViewById(R.id.careportal_mealbolus).setOnClickListener(this);
- view.findViewById(R.id.careportal_note).setOnClickListener(this);
- view.findViewById(R.id.careportal_profileswitch).setOnClickListener(this);
- view.findViewById(R.id.careportal_pumpsitechange).setOnClickListener(this);
- view.findViewById(R.id.careportal_question).setOnClickListener(this);
- view.findViewById(R.id.careportal_snackbolus).setOnClickListener(this);
- view.findViewById(R.id.careportal_tempbasalend).setOnClickListener(this);
- view.findViewById(R.id.careportal_tempbasalstart).setOnClickListener(this);
- view.findViewById(R.id.careportal_openapsoffline).setOnClickListener(this);
- view.findViewById(R.id.careportal_temporarytarget).setOnClickListener(this);
+ view.findViewById(R.id.careportal_bgcheck).setOnClickListener(this);
+ view.findViewById(R.id.careportal_announcement).setOnClickListener(this);
+ view.findViewById(R.id.careportal_cgmsensorinsert).setOnClickListener(this);
+ view.findViewById(R.id.careportal_cgmsensorstart).setOnClickListener(this);
+ view.findViewById(R.id.careportal_combobolus).setOnClickListener(this);
+ view.findViewById(R.id.careportal_correctionbolus).setOnClickListener(this);
+ view.findViewById(R.id.careportal_carbscorrection).setOnClickListener(this);
+ view.findViewById(R.id.careportal_exercise).setOnClickListener(this);
+ view.findViewById(R.id.careportal_insulincartridgechange).setOnClickListener(this);
+ view.findViewById(R.id.careportal_pumpbatterychange).setOnClickListener(this);
+ view.findViewById(R.id.careportal_mealbolus).setOnClickListener(this);
+ view.findViewById(R.id.careportal_note).setOnClickListener(this);
+ view.findViewById(R.id.careportal_profileswitch).setOnClickListener(this);
+ view.findViewById(R.id.careportal_pumpsitechange).setOnClickListener(this);
+ view.findViewById(R.id.careportal_question).setOnClickListener(this);
+ view.findViewById(R.id.careportal_snackbolus).setOnClickListener(this);
+ view.findViewById(R.id.careportal_tempbasalend).setOnClickListener(this);
+ view.findViewById(R.id.careportal_tempbasalstart).setOnClickListener(this);
+ view.findViewById(R.id.careportal_openapsoffline).setOnClickListener(this);
+ view.findViewById(R.id.careportal_temporarytarget).setOnClickListener(this);
- iage = (TextView) view.findViewById(R.id.careportal_insulinage);
- cage = (TextView) view.findViewById(R.id.careportal_canulaage);
- sage = (TextView) view.findViewById(R.id.careportal_sensorage);
- pbage = (TextView) view.findViewById(R.id.careportal_pbage);
+ iage = view.findViewById(R.id.careportal_insulinage);
+ cage = view.findViewById(R.id.careportal_canulaage);
+ sage = view.findViewById(R.id.careportal_sensorage);
+ pbage = view.findViewById(R.id.careportal_pbage);
- statsLayout = view.findViewById(R.id.careportal_stats);
+ statsLayout = view.findViewById(R.id.careportal_stats);
- noProfileView = view.findViewById(R.id.profileview_noprofile);
- butonsLayout = (LinearLayout) view.findViewById(R.id.careportal_buttons);
+ noProfileView = view.findViewById(R.id.profileview_noprofile);
+ butonsLayout = view.findViewById(R.id.careportal_buttons);
- ProfileStore profileStore = ConfigBuilderPlugin.getPlugin().getActiveProfileInterface() != null ? ConfigBuilderPlugin.getPlugin().getActiveProfileInterface().getProfile() : null;
- if (profileStore == null) {
- noProfileView.setVisibility(View.VISIBLE);
- butonsLayout.setVisibility(View.GONE);
- } else {
- noProfileView.setVisibility(View.GONE);
- butonsLayout.setVisibility(View.VISIBLE);
- }
-
- if (Config.NSCLIENT)
- statsLayout.setVisibility(View.GONE); // visible on overview
-
- updateGUI();
- return view;
- } catch (Exception e) {
- FabricPrivacy.logException(e);
+ ProfileStore profileStore = ConfigBuilderPlugin.getPlugin().getActiveProfileInterface() != null ? ConfigBuilderPlugin.getPlugin().getActiveProfileInterface().getProfile() : null;
+ if (profileStore == null) {
+ noProfileView.setVisibility(View.VISIBLE);
+ butonsLayout.setVisibility(View.GONE);
+ } else {
+ noProfileView.setVisibility(View.GONE);
+ butonsLayout.setVisibility(View.VISIBLE);
}
- return null;
+ if (Config.NSCLIENT)
+ statsLayout.setVisibility(View.GONE); // visible on overview
+
+ return view;
+ }
+
+ @Override
+ public synchronized void onResume() {
+ super.onResume();
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventCareportalEventChange.class)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(event -> updateGUI(), FabricPrivacy::logException)
+ );
+ updateGUI();
+ }
+
+ @Override
+ public synchronized void onPause() {
+ super.onPause();
+ disposable.clear();
}
@Override
@@ -199,12 +212,6 @@ public class CareportalFragment extends SubscriberFragment implements View.OnCli
newDialog.show(manager, "NewNSTreatmentDialog");
}
- @Subscribe
- public void onStatusEvent(final EventCareportalEventChange c) {
- updateGUI();
- }
-
- @Override
protected void updateGUI() {
Activity activity = getActivity();
updateAge(activity, sage, iage, cage, pbage);
@@ -249,13 +256,17 @@ public class CareportalFragment extends SubscriberFragment implements View.OnCli
}
private static TextView handleAge(final TextView age, String eventType, double warnThreshold, double urgentThreshold) {
- String notavailable = OverviewFragment.shorttextmode ? "-" : MainApp.gs(R.string.notavailable);
+ return handleAge(age, "", eventType, warnThreshold, urgentThreshold, OverviewFragment.shorttextmode);
+ }
+
+ public static TextView handleAge(final TextView age, String prefix, String eventType, double warnThreshold, double urgentThreshold, boolean useShortText) {
+ String notavailable = useShortText ? "-" : MainApp.gs(R.string.notavailable);
if (age != null) {
CareportalEvent careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(eventType);
if (careportalEvent != null) {
age.setTextColor(CareportalFragment.determineTextColor(careportalEvent, warnThreshold, urgentThreshold));
- age.setText(careportalEvent.age());
+ age.setText(prefix + careportalEvent.age(useShortText));
} else {
age.setText(notavailable);
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/careportal/Dialogs/NewNSTreatmentDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/careportal/Dialogs/NewNSTreatmentDialog.java
index 57414927b4..8818638201 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/careportal/Dialogs/NewNSTreatmentDialog.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/careportal/Dialogs/NewNSTreatmentDialog.java
@@ -3,8 +3,8 @@ package info.nightscout.androidaps.plugins.general.careportal.Dialogs;
import android.app.Activity;
import android.os.Bundle;
-import android.support.v4.app.DialogFragment;
-import android.support.v7.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
+import androidx.appcompat.app.AlertDialog;
import android.text.Editable;
import android.text.TextWatcher;
import android.text.format.DateFormat;
@@ -263,17 +263,17 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
if (sensorRadioButton.isChecked()) meterRadioButton.setChecked(true);
}
};
- editBg = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_bginput);
- editTemptarget = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_temptarget);
+ editBg = view.findViewById(R.id.careportal_newnstreatment_bginput);
+ editTemptarget = view.findViewById(R.id.careportal_newnstreatment_temptarget);
if (profile == null) {
- editBg.setParams(bg, 0d, 500d, 0.1d, new DecimalFormat("0.0"), false, bgTextWatcher);
- editTemptarget.setParams(bg, 0d, 500d, 0.1d, new DecimalFormat("0.0"), false);
+ editBg.setParams(bg, 0d, 500d, 0.1d, new DecimalFormat("0"), false, view.findViewById(R.id.ok), bgTextWatcher);
+ editTemptarget.setParams(Constants.MIN_TT_MGDL, Constants.MIN_TT_MGDL, Constants.MAX_TT_MGDL, 0.1d, new DecimalFormat("0.0"), false, view.findViewById(R.id.ok));
} else if (units.equals(Constants.MMOL)) {
- editBg.setParams(bg, 0d, 30d, 0.1d, new DecimalFormat("0.0"), false, bgTextWatcher);
- editTemptarget.setParams(bg, 0d, 30d, 0.1d, new DecimalFormat("0.0"), false);
+ editBg.setParams(bg, 0d, 30d, 0.1d, new DecimalFormat("0.0"), false, view.findViewById(R.id.ok), bgTextWatcher);
+ editTemptarget.setParams(Constants.MIN_TT_MMOL, Constants.MIN_TT_MMOL, Constants.MAX_TT_MMOL, 0.1d, new DecimalFormat("0.0"), false, view.findViewById(R.id.ok));
} else {
- editBg.setParams(bg, 0d, 500d, 1d, new DecimalFormat("0"), false, bgTextWatcher);
- editTemptarget.setParams(bg, 0d, 500d, 1d, new DecimalFormat("0"), false);
+ editBg.setParams(bg, 0d, 500d, 1d, new DecimalFormat("0"), false, view.findViewById(R.id.ok), bgTextWatcher);
+ editTemptarget.setParams(Constants.MIN_TT_MGDL, Constants.MIN_TT_MGDL, Constants.MAX_TT_MGDL, 1d, new DecimalFormat("0"), false, view.findViewById(R.id.ok));
}
sensorRadioButton.setOnCheckedChangeListener((buttonView, isChecked) -> {
@@ -287,16 +287,16 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
Integer maxCarbs = MainApp.getConstraintChecker().getMaxCarbsAllowed().value();
editCarbs = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_carbsinput);
- editCarbs.setParams(0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false);
+ editCarbs.setParams(0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false, view.findViewById(R.id.ok));
Double maxInsulin = MainApp.getConstraintChecker().getMaxBolusAllowed().value();
editInsulin = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_insulininput);
- editInsulin.setParams(0d, 0d, maxInsulin, 0.05d, new DecimalFormat("0.00"), false);
+ editInsulin.setParams(0d, 0d, maxInsulin, 0.05d, new DecimalFormat("0.00"), false, view.findViewById(R.id.ok));
editSplit = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_splitinput);
- editSplit.setParams(100d, 0d, 100d, 5d, new DecimalFormat("0"), true);
+ editSplit.setParams(100d, 0d, 100d, 5d, new DecimalFormat("0"), true, view.findViewById(R.id.ok));
editDuration = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_durationinput);
- editDuration.setParams(0d, 0d, 24 * 60d, 10d, new DecimalFormat("0"), false);
+ editDuration.setParams(0d, 0d, Constants.MAX_PROFILE_SWITCH_DURATION, 10d, new DecimalFormat("0"), false, view.findViewById(R.id.ok));
TextWatcher percentTextWatcher = new TextWatcher() {
@Override
@@ -320,7 +320,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
if (profile != null)
maxPercent = MainApp.getConstraintChecker().getMaxBasalPercentAllowed(profile).value();
editPercent = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_percentinput);
- editPercent.setParams(0d, -100d, (double) maxPercent, 5d, new DecimalFormat("0"), true, percentTextWatcher);
+ editPercent.setParams(0d, -100d, (double) maxPercent, 5d, new DecimalFormat("0"), true, view.findViewById(R.id.ok), percentTextWatcher);
TextWatcher absoluteTextWatcher = new TextWatcher() {
@Override
@@ -344,16 +344,16 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
if (profile != null)
maxAbsolute = MainApp.getConstraintChecker().getMaxBasalAllowed(profile).value();
editAbsolute = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_absoluteinput);
- editAbsolute.setParams(0d, 0d, maxAbsolute, 0.05d, new DecimalFormat("0.00"), true, absoluteTextWatcher);
+ editAbsolute.setParams(0d, 0d, maxAbsolute, 0.05d, new DecimalFormat("0.00"), true, view.findViewById(R.id.ok), absoluteTextWatcher);
editCarbTime = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_carbtimeinput);
- editCarbTime.setParams(0d, -60d, 60d, 5d, new DecimalFormat("0"), false);
+ editCarbTime.setParams(0d, -60d, 60d, 5d, new DecimalFormat("0"), false, view.findViewById(R.id.ok));
editPercentage = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_percentage);
- editPercentage.setParams(100d, (double) Constants.CPP_MIN_PERCENTAGE, (double) Constants.CPP_MAX_PERCENTAGE, 1d, new DecimalFormat("0"), false);
+ editPercentage.setParams(100d, (double) Constants.CPP_MIN_PERCENTAGE, (double) Constants.CPP_MAX_PERCENTAGE, 1d, new DecimalFormat("0"), false, view.findViewById(R.id.ok));
editTimeshift = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_timeshift);
- editTimeshift.setParams(0d, (double) Constants.CPP_MIN_TIMESHIFT, (double) Constants.CPP_MAX_TIMESHIFT, 1d, new DecimalFormat("0"), false);
+ editTimeshift.setParams(0d, (double) Constants.CPP_MIN_TIMESHIFT, (double) Constants.CPP_MAX_TIMESHIFT, 1d, new DecimalFormat("0"), false, view.findViewById(R.id.ok));
ProfileSwitch ps = TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(DateUtil.now());
if (ps != null && ps.isCPP) {
@@ -741,6 +741,8 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
}
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget);
}
+ if (duration == 10)
+ SP.putBoolean(R.string.key_objectiveusetemptarget, true);
} else {
if (JsonHelper.safeGetString(data, "eventType").equals(CareportalEvent.PROFILESWITCH)) {
ProfileSwitch profileSwitch = ProfileFunctions.prepareProfileSwitch(
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/food/FoodFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/food/FoodFragment.java
index 6eb55db266..997c6b0ba9 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/food/FoodFragment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/food/FoodFragment.java
@@ -1,12 +1,8 @@
package info.nightscout.androidaps.plugins.general.food;
-import android.app.Activity;
import android.content.DialogInterface;
import android.graphics.Paint;
import android.os.Bundle;
-import android.support.v7.app.AlertDialog;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
@@ -18,7 +14,10 @@ import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
-import com.squareup.otto.Subscribe;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.Fragment;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -31,17 +30,20 @@ import java.util.Set;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.events.EventFoodDatabaseChanged;
-import info.nightscout.androidaps.plugins.common.SubscriberFragment;
-import info.nightscout.androidaps.utils.FabricPrivacy;
+import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
+import info.nightscout.androidaps.utils.FabricPrivacy;
import info.nightscout.androidaps.utils.SpinnerHelper;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.disposables.CompositeDisposable;
/**
* Created by mike on 16.10.2017.
*/
-public class FoodFragment extends SubscriberFragment {
+public class FoodFragment extends Fragment {
private static Logger log = LoggerFactory.getLogger(FoodFragment.class);
+ private CompositeDisposable disposable = new CompositeDisposable();
EditText filter;
ImageView clearFilter;
@@ -59,93 +61,96 @@ public class FoodFragment extends SubscriberFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
- try {
- View view = inflater.inflate(R.layout.food_fragment, container, false);
- filter = (EditText) view.findViewById(R.id.food_filter);
- clearFilter = (ImageView) view.findViewById(R.id.food_clearfilter);
- category = new SpinnerHelper(view.findViewById(R.id.food_category));
- subcategory = new SpinnerHelper(view.findViewById(R.id.food_subcategory));
- recyclerView = (RecyclerView) view.findViewById(R.id.food_recyclerview);
- recyclerView.setHasFixedSize(true);
- LinearLayoutManager llm = new LinearLayoutManager(view.getContext());
- recyclerView.setLayoutManager(llm);
+ View view = inflater.inflate(R.layout.food_fragment, container, false);
+ filter = (EditText) view.findViewById(R.id.food_filter);
+ clearFilter = (ImageView) view.findViewById(R.id.food_clearfilter);
+ category = new SpinnerHelper(view.findViewById(R.id.food_category));
+ subcategory = new SpinnerHelper(view.findViewById(R.id.food_subcategory));
+ recyclerView = (RecyclerView) view.findViewById(R.id.food_recyclerview);
+ recyclerView.setHasFixedSize(true);
+ LinearLayoutManager llm = new LinearLayoutManager(view.getContext());
+ recyclerView.setLayoutManager(llm);
- clearFilter.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- filter.setText("");
- category.setSelection(0);
- subcategory.setSelection(0);
- filterData();
- }
- });
+ clearFilter.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ filter.setText("");
+ category.setSelection(0);
+ subcategory.setSelection(0);
+ filterData();
+ }
+ });
- category.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
- @Override
- public void onItemSelected(AdapterView> parent, View view, int position, long id) {
- fillSubcategories();
- filterData();
- }
+ category.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView> parent, View view, int position, long id) {
+ fillSubcategories();
+ filterData();
+ }
- @Override
- public void onNothingSelected(AdapterView> parent) {
- fillSubcategories();
- filterData();
- }
- });
+ @Override
+ public void onNothingSelected(AdapterView> parent) {
+ fillSubcategories();
+ filterData();
+ }
+ });
- subcategory.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
- @Override
- public void onItemSelected(AdapterView> parent, View view, int position, long id) {
- filterData();
- }
+ subcategory.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView> parent, View view, int position, long id) {
+ filterData();
+ }
- @Override
- public void onNothingSelected(AdapterView> parent) {
- filterData();
- }
- });
+ @Override
+ public void onNothingSelected(AdapterView> parent) {
+ filterData();
+ }
+ });
- filter.addTextChangedListener(new TextWatcher() {
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- }
+ filter.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- filterData();
- }
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ filterData();
+ }
- @Override
- public void afterTextChanged(Editable s) {
- }
- });
+ @Override
+ public void afterTextChanged(Editable s) {
+ }
+ });
- RecyclerViewAdapter adapter = new RecyclerViewAdapter(MainApp
- .getSpecificPlugin(FoodPlugin.class).getService().getFoodData());
- recyclerView.setAdapter(adapter);
+ RecyclerViewAdapter adapter = new RecyclerViewAdapter(FoodPlugin.getPlugin().getService().getFoodData());
+ recyclerView.setAdapter(adapter);
- loadData();
- fillCategories();
- fillSubcategories();
- filterData();
- return view;
- } catch (Exception e) {
- FabricPrivacy.logException(e);
- }
-
- return null;
+ loadData();
+ fillCategories();
+ fillSubcategories();
+ filterData();
+ return view;
}
- @Subscribe
- @SuppressWarnings("unused")
- public void onStatusEvent(final EventFoodDatabaseChanged ev) {
- loadData();
- filterData();
+ @Override
+ public synchronized void onResume() {
+ super.onResume();
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventFoodDatabaseChanged.class)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(event -> updateGui(), FabricPrivacy::logException)
+ );
+ updateGui();
+ }
+
+ @Override
+ public synchronized void onPause() {
+ super.onPause();
+ disposable.clear();
}
void loadData() {
- unfiltered = MainApp.getSpecificPlugin(FoodPlugin.class).getService().getFoodData();
+ unfiltered = FoodPlugin.getPlugin().getService().getFoodData();
}
void fillCategories() {
@@ -207,19 +212,11 @@ public class FoodFragment extends SubscriberFragment {
filtered.add(f);
}
- updateGUI();
+ updateGui();
}
- @Override
- protected void updateGUI() {
- Activity activity = getActivity();
- if (activity != null)
- activity.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- recyclerView.swapAdapter(new FoodFragment.RecyclerViewAdapter(filtered), true);
- }
- });
+ protected void updateGui() {
+ recyclerView.swapAdapter(new FoodFragment.RecyclerViewAdapter(filtered), true);
}
public class RecyclerViewAdapter extends RecyclerView.Adapter {
@@ -299,7 +296,7 @@ public class FoodFragment extends SubscriberFragment {
if (_id != null && !_id.equals("")) {
NSUpload.removeFoodFromNS(_id);
}
- MainApp.getSpecificPlugin(FoodPlugin.class).getService().delete(food);
+ FoodPlugin.getPlugin().getService().delete(food);
}
});
builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/food/FoodService.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/food/FoodService.java
index 2d8d5f847b..065c74eabb 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/food/FoodService.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/food/FoodService.java
@@ -3,7 +3,8 @@ package info.nightscout.androidaps.plugins.general.food;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
-import android.support.annotation.Nullable;
+
+import androidx.annotation.Nullable;
import com.j256.ormlite.android.apptools.OpenHelperManager;
import com.j256.ormlite.android.apptools.OrmLiteBaseService;
@@ -11,7 +12,6 @@ import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.dao.DaoManager;
import com.j256.ormlite.support.ConnectionSource;
import com.j256.ormlite.table.TableUtils;
-import com.squareup.otto.Subscribe;
import org.json.JSONArray;
import org.json.JSONException;
@@ -34,6 +34,10 @@ import info.nightscout.androidaps.events.Event;
import info.nightscout.androidaps.events.EventFoodDatabaseChanged;
import info.nightscout.androidaps.events.EventNsFood;
import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.bus.RxBus;
+import info.nightscout.androidaps.utils.FabricPrivacy;
+import io.reactivex.disposables.CompositeDisposable;
+import io.reactivex.schedulers.Schedulers;
/**
* Created by mike on 24.09.2017.
@@ -41,6 +45,7 @@ import info.nightscout.androidaps.logging.L;
public class FoodService extends OrmLiteBaseService {
private Logger log = LoggerFactory.getLogger(L.DATAFOOD);
+ private CompositeDisposable disposable = new CompositeDisposable();
private static final ScheduledExecutorService foodEventWorker = Executors.newSingleThreadScheduledExecutor();
private static ScheduledFuture> scheduledFoodEventPost = null;
@@ -48,7 +53,34 @@ public class FoodService extends OrmLiteBaseService {
public FoodService() {
onCreate();
dbInitialize();
- MainApp.bus().register(this);
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventNsFood.class)
+ .observeOn(Schedulers.io())
+ .subscribe(event -> {
+ int mode = event.getMode();
+ Bundle payload = event.getPayload();
+
+ try {
+ if (payload.containsKey("food")) {
+ JSONObject json = new JSONObject(payload.getString("food"));
+ if (mode == EventNsFood.Companion.getADD() || mode == EventNsFood.Companion.getUPDATE())
+ this.createFoodFromJsonIfNotExists(json);
+ else
+ this.deleteNS(json);
+ }
+
+ if (payload.containsKey("foods")) {
+ JSONArray array = new JSONArray(payload.getString("foods"));
+ if (mode == EventNsFood.Companion.getADD() || mode == EventNsFood.Companion.getUPDATE())
+ this.createFoodFromJsonIfNotExists(array);
+ else
+ this.deleteNS(array);
+ }
+ } catch (JSONException e) {
+ log.error("Unhandled Exception", e);
+ }
+ }, FabricPrivacy::logException)
+ );
}
/**
@@ -79,34 +111,6 @@ public class FoodService extends OrmLiteBaseService {
return null;
}
- @Subscribe
- public void handleNsEvent(EventNsFood event) {
- int mode = event.getMode();
- Bundle payload = event.getPayload();
-
- try {
- if (payload.containsKey("food")) {
- JSONObject json = new JSONObject(payload.getString("food"));
- if (mode == EventNsFood.ADD || mode == EventNsFood.UPDATE) {
- this.createFoodFromJsonIfNotExists(json);
- } else {
- this.deleteNS(json);
- }
- }
-
- if (payload.containsKey("foods")) {
- JSONArray array = new JSONArray(payload.getString("foods"));
- if (mode == EventNsFood.ADD || mode == EventNsFood.UPDATE) {
- this.createFoodFromJsonIfNotExists(array);
- } else {
- this.deleteNS(array);
- }
- }
- } catch (JSONException e) {
- log.error("Unhandled Exception", e);
- }
- }
-
@Override
public void onCreate() {
super.onCreate();
@@ -162,7 +166,7 @@ public class FoodService extends OrmLiteBaseService {
public void run() {
if (L.isEnabled(L.DATAFOOD))
log.debug("Firing EventFoodChange");
- MainApp.bus().post(event);
+ RxBus.INSTANCE.send(event);
callback.setPost(null);
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/ImportExportPrefs.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/ImportExportPrefs.java
index 67bf604f41..7a801a44c0 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/ImportExportPrefs.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/ImportExportPrefs.java
@@ -8,9 +8,9 @@ import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.os.Environment;
import android.preference.PreferenceManager;
-import android.support.v4.app.ActivityCompat;
-import android.support.v4.app.Fragment;
-import android.support.v4.content.ContextCompat;
+import androidx.core.app.ActivityCompat;
+import androidx.fragment.app.Fragment;
+import androidx.core.content.ContextCompat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -28,6 +28,7 @@ import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.events.EventAppExit;
import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.utils.OKDialog;
import info.nightscout.androidaps.utils.ToastUtils;
@@ -136,7 +137,7 @@ public class ImportExportPrefs {
OKDialog.show(context, MainApp.gs(R.string.setting_imported), MainApp.gs(R.string.restartingapp), () -> {
log.debug("Exiting");
MainApp.instance().stopKeepAliveService();
- MainApp.bus().post(new EventAppExit());
+ RxBus.INSTANCE.send(new EventAppExit());
MainApp.closeDbHelper();
if (context instanceof Activity) {
((Activity)context).finish();
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.java
index e0e9b58253..6b8863242a 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.java
@@ -2,8 +2,8 @@ package info.nightscout.androidaps.plugins.general.maintenance;
import android.content.Intent;
import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.support.v7.app.AlertDialog;
+import androidx.fragment.app.Fragment;
+import androidx.appcompat.app.AlertDialog;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenancePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenancePlugin.java
index 35bd9f9d06..f9a55f53dd 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenancePlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenancePlugin.java
@@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.general.maintenance;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
-import android.support.v4.content.FileProvider;
+import androidx.core.content.FileProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -62,7 +62,7 @@ public class MaintenancePlugin extends PluginBase {
super(new PluginDescription()
.mainType(PluginType.GENERAL)
.fragmentClass(MaintenanceFragment.class.getName())
- .alwayVisible(false)
+ .alwaysVisible(false)
.alwaysEnabled(true)
.pluginName(R.string.maintenance)
.shortName(R.string.maintenance_shortname)
@@ -178,7 +178,7 @@ public class MaintenancePlugin extends PluginBase {
* @return
*/
public String constructName() {
- return "AndroidAPS_LOG_" + String.valueOf(new Date().getTime()) + LoggerUtils.SUFFIX;
+ return "AndroidAPS_LOG_" + new Date().getTime() + LoggerUtils.SUFFIX;
}
public void zip(File zipFile, List files) throws IOException {
@@ -187,7 +187,7 @@ public class MaintenancePlugin extends PluginBase {
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile)));
for (File file : files) {
- byte data[] = new byte[BUFFER_SIZE];
+ byte[] data = new byte[BUFFER_SIZE];
try(FileInputStream fileInputStream = new FileInputStream( file )) {
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/activities/LogSettingActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/activities/LogSettingActivity.java
deleted file mode 100644
index 9d7681ae38..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/activities/LogSettingActivity.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package info.nightscout.androidaps.plugins.general.maintenance.activities;
-
-import android.os.Bundle;
-import android.support.v7.app.AppCompatActivity;
-import android.view.View;
-import android.widget.CheckBox;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import java.util.List;
-
-import butterknife.BindView;
-import butterknife.ButterKnife;
-import butterknife.OnClick;
-import butterknife.Unbinder;
-import info.nightscout.androidaps.R;
-import info.nightscout.androidaps.logging.L;
-
-public class LogSettingActivity extends AppCompatActivity {
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_logsetting);
- ButterKnife.bind(this);
-
- createViewsForSettings(L.getLogElements());
- }
-
- private void createViewsForSettings(List elements) {
- if (elements.size() == 0) return;
- LinearLayout container = (LinearLayout) findViewById(R.id.logsettings_placeholder);
- container.removeAllViews();
- for (L.LogElement element : elements) {
- PluginViewHolder pluginViewHolder = new PluginViewHolder(element);
- container.addView(pluginViewHolder.getBaseView());
- }
- }
-
- @OnClick(R.id.logsettings_reset)
- public void onResetClick() {
- L.resetToDefaults();
- createViewsForSettings(L.getLogElements());
- }
-
- public class PluginViewHolder {
-
- private Unbinder unbinder;
- private L.LogElement element;
-
- LinearLayout baseView;
- @BindView(R.id.logsettings_description)
- TextView description;
- @BindView(R.id.logsettings_visibility)
- CheckBox enabled;
-
- public PluginViewHolder(L.LogElement element) {
- this.element = element;
- baseView = (LinearLayout) getLayoutInflater().inflate(R.layout.logsettings_item, null);
- unbinder = ButterKnife.bind(this, baseView);
-
- description.setText(element.name);
- enabled.setChecked(element.enabled);
- }
-
- public View getBaseView() {
- return baseView;
- }
-
- @OnClick(R.id.logsettings_visibility)
- void onEnagledChanged() {
- element.setEnabled(enabled.isChecked());
- }
-
- public void unbind() {
- unbinder.unbind();
- }
- }
-
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/activities/LogSettingActivity.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/activities/LogSettingActivity.kt
new file mode 100644
index 0000000000..f47bb03513
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/activities/LogSettingActivity.kt
@@ -0,0 +1,47 @@
+package info.nightscout.androidaps.plugins.general.maintenance.activities
+
+import android.os.Bundle
+import android.view.View
+import android.widget.CheckBox
+import android.widget.LinearLayout
+import android.widget.TextView
+import info.nightscout.androidaps.R
+import info.nightscout.androidaps.activities.NoSplashActivity
+import info.nightscout.androidaps.logging.L
+import kotlinx.android.synthetic.main.activity_logsetting.*
+
+class LogSettingActivity : NoSplashActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_logsetting)
+
+ createViewsForSettings()
+
+ logsettings_reset.setOnClickListener {
+ L.resetToDefaults()
+ createViewsForSettings()
+ }
+ }
+
+ private fun createViewsForSettings() {
+ logsettings_placeholder.removeAllViews()
+ for (element in L.getLogElements()) {
+ val logViewHolder = LogViewHolder(element)
+ logsettings_placeholder.addView(logViewHolder.baseView)
+ }
+
+ }
+
+ internal inner class LogViewHolder(element: L.LogElement) {
+ var baseView: LinearLayout = layoutInflater.inflate(R.layout.logsettings_item, null) as LinearLayout
+
+ init {
+ (baseView.findViewById(R.id.logsettings_description) as TextView).text = element.name
+ val enabled = baseView.findViewById(R.id.logsettings_visibility)
+ enabled.isChecked = element.enabled
+ enabled.setOnClickListener { element.setEnabled(enabled.isChecked) }
+ }
+
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientFragment.java
index 50674c5a94..112eb9c951 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientFragment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientFragment.java
@@ -1,7 +1,6 @@
package info.nightscout.androidaps.plugins.general.nsclient;
-import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
@@ -17,18 +16,22 @@ import android.widget.CompoundButton;
import android.widget.ScrollView;
import android.widget.TextView;
-import com.squareup.otto.Subscribe;
+import androidx.fragment.app.Fragment;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
-import info.nightscout.androidaps.plugins.common.SubscriberFragment;
+import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientNewLog;
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart;
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientUpdateGUI;
import info.nightscout.androidaps.utils.FabricPrivacy;
import info.nightscout.androidaps.utils.SP;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.disposables.CompositeDisposable;
+
+public class NSClientFragment extends Fragment implements View.OnClickListener, CompoundButton.OnCheckedChangeListener {
+ private CompositeDisposable disposable = new CompositeDisposable();
-public class NSClientFragment extends SubscriberFragment implements View.OnClickListener, CompoundButton.OnCheckedChangeListener {
private TextView logTextView;
private TextView queueTextView;
private TextView urlTextView;
@@ -45,51 +48,61 @@ public class NSClientFragment extends SubscriberFragment implements View.OnClick
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
- try {
- View view = inflater.inflate(R.layout.nsclientinternal_fragment, container, false);
+ View view = inflater.inflate(R.layout.nsclientinternal_fragment, container, false);
- logScrollview = (ScrollView) view.findViewById(R.id.nsclientinternal_logscrollview);
- autoscrollCheckbox = (CheckBox) view.findViewById(R.id.nsclientinternal_autoscroll);
- autoscrollCheckbox.setChecked(NSClientPlugin.getPlugin().autoscroll);
- autoscrollCheckbox.setOnCheckedChangeListener(this);
- pausedCheckbox = (CheckBox) view.findViewById(R.id.nsclientinternal_paused);
- pausedCheckbox.setChecked(NSClientPlugin.getPlugin().paused);
- pausedCheckbox.setOnCheckedChangeListener(this);
- logTextView = (TextView) view.findViewById(R.id.nsclientinternal_log);
- queueTextView = (TextView) view.findViewById(R.id.nsclientinternal_queue);
- urlTextView = (TextView) view.findViewById(R.id.nsclientinternal_url);
- statusTextView = (TextView) view.findViewById(R.id.nsclientinternal_status);
+ logScrollview = (ScrollView) view.findViewById(R.id.nsclientinternal_logscrollview);
+ autoscrollCheckbox = (CheckBox) view.findViewById(R.id.nsclientinternal_autoscroll);
+ autoscrollCheckbox.setChecked(NSClientPlugin.getPlugin().autoscroll);
+ autoscrollCheckbox.setOnCheckedChangeListener(this);
+ pausedCheckbox = (CheckBox) view.findViewById(R.id.nsclientinternal_paused);
+ pausedCheckbox.setChecked(NSClientPlugin.getPlugin().paused);
+ pausedCheckbox.setOnCheckedChangeListener(this);
+ logTextView = (TextView) view.findViewById(R.id.nsclientinternal_log);
+ queueTextView = (TextView) view.findViewById(R.id.nsclientinternal_queue);
+ urlTextView = (TextView) view.findViewById(R.id.nsclientinternal_url);
+ statusTextView = (TextView) view.findViewById(R.id.nsclientinternal_status);
- clearlog = (TextView) view.findViewById(R.id.nsclientinternal_clearlog);
- clearlog.setOnClickListener(this);
- clearlog.setPaintFlags(clearlog.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
- restart = (TextView) view.findViewById(R.id.nsclientinternal_restart);
- restart.setOnClickListener(this);
- restart.setPaintFlags(restart.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
- delivernow = (TextView) view.findViewById(R.id.nsclientinternal_delivernow);
- delivernow.setOnClickListener(this);
- delivernow.setPaintFlags(delivernow.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
- clearqueue = (TextView) view.findViewById(R.id.nsclientinternal_clearqueue);
- clearqueue.setOnClickListener(this);
- clearqueue.setPaintFlags(clearqueue.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
- showqueue = (TextView) view.findViewById(R.id.nsclientinternal_showqueue);
- showqueue.setOnClickListener(this);
- showqueue.setPaintFlags(showqueue.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
+ clearlog = (TextView) view.findViewById(R.id.nsclientinternal_clearlog);
+ clearlog.setOnClickListener(this);
+ clearlog.setPaintFlags(clearlog.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
+ restart = (TextView) view.findViewById(R.id.nsclientinternal_restart);
+ restart.setOnClickListener(this);
+ restart.setPaintFlags(restart.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
+ delivernow = (TextView) view.findViewById(R.id.nsclientinternal_delivernow);
+ delivernow.setOnClickListener(this);
+ delivernow.setPaintFlags(delivernow.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
+ clearqueue = (TextView) view.findViewById(R.id.nsclientinternal_clearqueue);
+ clearqueue.setOnClickListener(this);
+ clearqueue.setPaintFlags(clearqueue.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
+ showqueue = (TextView) view.findViewById(R.id.nsclientinternal_showqueue);
+ showqueue.setOnClickListener(this);
+ showqueue.setPaintFlags(showqueue.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
- updateGUI();
- return view;
- } catch (Exception e) {
- FabricPrivacy.logException(e);
- }
+ return view;
+ }
- return null;
+ @Override
+ public synchronized void onResume() {
+ super.onResume();
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventNSClientUpdateGUI.class)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(event -> updateGui(), FabricPrivacy::logException)
+ );
+ updateGui();
+ }
+
+ @Override
+ public synchronized void onPause() {
+ super.onPause();
+ disposable.clear();
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.nsclientinternal_restart:
- MainApp.bus().post(new EventNSClientRestart());
+ RxBus.INSTANCE.send(new EventNSClientRestart());
FabricPrivacy.getInstance().logCustom("NSClientRestart");
break;
case R.id.nsclientinternal_delivernow:
@@ -108,7 +121,7 @@ public class NSClientFragment extends SubscriberFragment implements View.OnClick
builder.setPositiveButton(MainApp.gs(R.string.ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
UploadQueue.clearQueue();
- updateGUI();
+ updateGui();
FabricPrivacy.getInstance().logCustom("NSClientClearQueue");
}
});
@@ -116,7 +129,7 @@ public class NSClientFragment extends SubscriberFragment implements View.OnClick
builder.show();
break;
case R.id.nsclientinternal_showqueue:
- MainApp.bus().post(new EventNSClientNewLog("QUEUE", NSClientPlugin.getPlugin().queue().textList()));
+ RxBus.INSTANCE.send(new EventNSClientNewLog("QUEUE", NSClientPlugin.getPlugin().queue().textList()));
break;
}
}
@@ -126,38 +139,28 @@ public class NSClientFragment extends SubscriberFragment implements View.OnClick
switch (buttonView.getId()) {
case R.id.nsclientinternal_paused:
NSClientPlugin.getPlugin().pause(isChecked);
- updateGUI();
+ updateGui();
FabricPrivacy.getInstance().logCustom("NSClientPause");
break;
case R.id.nsclientinternal_autoscroll:
SP.putBoolean(R.string.key_nsclientinternal_autoscroll, isChecked);
NSClientPlugin.getPlugin().autoscroll = isChecked;
- updateGUI();
+ updateGui();
break;
}
}
- @Subscribe
- public void onStatusEvent(final EventNSClientUpdateGUI ev) {
- updateGUI();
- }
-
- @Override
- protected void updateGUI() {
- Activity activity = getActivity();
- if (activity != null)
- activity.runOnUiThread(() -> {
- NSClientPlugin.getPlugin().updateLog();
- pausedCheckbox.setChecked(SP.getBoolean(R.string.key_nsclientinternal_paused, false));
- logTextView.setText(NSClientPlugin.getPlugin().textLog);
- if (NSClientPlugin.getPlugin().autoscroll) {
- logScrollview.fullScroll(ScrollView.FOCUS_DOWN);
- }
- urlTextView.setText(NSClientPlugin.getPlugin().url());
- Spanned queuetext = Html.fromHtml(MainApp.gs(R.string.queue) + " " + UploadQueue.size() + " ");
- queueTextView.setText(queuetext);
- statusTextView.setText(NSClientPlugin.getPlugin().status);
- });
+ protected void updateGui() {
+ NSClientPlugin.getPlugin().updateLog();
+ pausedCheckbox.setChecked(SP.getBoolean(R.string.key_nsclientinternal_paused, false));
+ logTextView.setText(NSClientPlugin.getPlugin().textLog);
+ if (NSClientPlugin.getPlugin().autoscroll) {
+ logScrollview.fullScroll(ScrollView.FOCUS_DOWN);
+ }
+ urlTextView.setText(NSClientPlugin.getPlugin().url());
+ Spanned queuetext = Html.fromHtml(MainApp.gs(R.string.queue) + " " + UploadQueue.size() + " ");
+ queueTextView.setText(queuetext);
+ statusTextView.setText(NSClientPlugin.getPlugin().status);
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientPlugin.java
index 1947c5911d..ae5d090211 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientPlugin.java
@@ -10,8 +10,6 @@ import android.os.IBinder;
import android.text.Html;
import android.text.Spanned;
-import com.squareup.otto.Subscribe;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -30,15 +28,20 @@ import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientNewLog;
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientStatus;
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientUpdateGUI;
import info.nightscout.androidaps.plugins.general.nsclient.services.NSClientService;
+import info.nightscout.androidaps.utils.FabricPrivacy;
import info.nightscout.androidaps.utils.SP;
import info.nightscout.androidaps.utils.ToastUtils;
+import io.reactivex.disposables.CompositeDisposable;
+import io.reactivex.schedulers.Schedulers;
public class NSClientPlugin extends PluginBase {
private Logger log = LoggerFactory.getLogger(L.NSCLIENT);
+ private CompositeDisposable disposable = new CompositeDisposable();
static NSClientPlugin nsClientPlugin;
@@ -86,7 +89,7 @@ public class NSClientPlugin extends PluginBase {
}
nsClientReceiverDelegate =
- new NsClientReceiverDelegate(MainApp.instance().getApplicationContext(), MainApp.bus());
+ new NsClientReceiverDelegate(MainApp.instance().getApplicationContext());
}
public boolean isAllowed() {
@@ -96,40 +99,64 @@ public class NSClientPlugin extends PluginBase {
@Override
protected void onStart() {
- MainApp.bus().register(this);
Context context = MainApp.instance().getApplicationContext();
Intent intent = new Intent(context, NSClientService.class);
context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
super.onStart();
nsClientReceiverDelegate.registerReceivers();
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventNSClientStatus.class)
+ .observeOn(Schedulers.io())
+ .subscribe(event -> {
+ status = event.getStatus();
+ RxBus.INSTANCE.send(new EventNSClientUpdateGUI());
+ }, FabricPrivacy::logException)
+ );
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventNetworkChange.class)
+ .observeOn(Schedulers.io())
+ .subscribe(event -> nsClientReceiverDelegate.onStatusEvent(event), FabricPrivacy::logException)
+ );
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventPreferenceChange.class)
+ .observeOn(Schedulers.io())
+ .subscribe(event -> nsClientReceiverDelegate.onStatusEvent(event), FabricPrivacy::logException)
+ );
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventAppExit.class)
+ .observeOn(Schedulers.io())
+ .subscribe(event -> {
+ if (nsClientService != null) {
+ MainApp.instance().getApplicationContext().unbindService(mConnection);
+ nsClientReceiverDelegate.unregisterReceivers();
+ }
+ }, FabricPrivacy::logException)
+ );
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventNSClientNewLog.class)
+ .observeOn(Schedulers.io())
+ .subscribe(event -> {
+ addToLog(event);
+ if (L.isEnabled(L.NSCLIENT))
+ log.debug(event.getAction() + " " + event.getLogText());
+ }, FabricPrivacy::logException)
+ );
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventChargingState.class)
+ .observeOn(Schedulers.io())
+ .subscribe(event -> nsClientReceiverDelegate.onStatusEvent(event), FabricPrivacy::logException)
+ );
}
@Override
protected void onStop() {
- MainApp.bus().unregister(this);
- Context context = MainApp.instance().getApplicationContext();
- context.unbindService(mConnection);
-
+ MainApp.instance().getApplicationContext().unbindService(mConnection);
nsClientReceiverDelegate.unregisterReceivers();
+ disposable.clear();
+ super.onStop();
}
- @Subscribe
- public void onStatusEvent(EventPreferenceChange ev) {
- nsClientReceiverDelegate.onStatusEvent(ev);
- }
-
- @Subscribe
- public void onStatusEvent(final EventChargingState ev) {
- nsClientReceiverDelegate.onStatusEvent(ev);
- }
-
- @Subscribe
- public void onStatusEvent(final EventNetworkChange ev) {
- nsClientReceiverDelegate.onStatusEvent(ev);
- }
-
-
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceDisconnected(ComponentName name) {
@@ -147,33 +174,12 @@ public class NSClientPlugin extends PluginBase {
}
};
- @Subscribe
- public void onStatusEvent(final EventAppExit ignored) {
- if (nsClientService != null) {
- MainApp.instance().getApplicationContext().unbindService(mConnection);
- nsClientReceiverDelegate.unregisterReceivers();
- }
- }
-
- @Subscribe
- public void onStatusEvent(final EventNSClientNewLog ev) {
- addToLog(ev);
- if (L.isEnabled(L.NSCLIENT))
- log.debug(ev.action + " " + ev.logText);
- }
-
- @Subscribe
- public void onStatusEvent(final EventNSClientStatus ev) {
- status = ev.status;
- MainApp.bus().post(new EventNSClientUpdateGUI());
- }
-
synchronized void clearLog() {
handler.post(() -> {
synchronized (listLog) {
listLog.clear();
}
- MainApp.bus().post(new EventNSClientUpdateGUI());
+ RxBus.INSTANCE.send(new EventNSClientUpdateGUI());
});
}
@@ -186,7 +192,7 @@ public class NSClientPlugin extends PluginBase {
listLog.remove(0);
}
}
- MainApp.bus().post(new EventNSClientUpdateGUI());
+ RxBus.INSTANCE.send(new EventNSClientUpdateGUI());
});
}
@@ -212,7 +218,7 @@ public class NSClientPlugin extends PluginBase {
public void pause(boolean newState) {
SP.putBoolean(R.string.key_nsclientinternal_paused, newState);
paused = newState;
- MainApp.bus().post(new EventPreferenceChange(R.string.key_nsclientinternal_paused));
+ RxBus.INSTANCE.send(new EventPreferenceChange(R.string.key_nsclientinternal_paused));
}
public UploadQueue queue() {
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSUpload.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSUpload.java
index 40a411694b..881593b32a 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSUpload.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSUpload.java
@@ -7,8 +7,8 @@ import android.content.pm.ResolveInfo;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
-import android.support.annotation.Nullable;
-import android.support.v4.content.LocalBroadcastManager;
+import androidx.annotation.Nullable;
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONArray;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NsClientReceiverDelegate.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NsClientReceiverDelegate.java
index 8eeee8c43c..0efbf35545 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NsClientReceiverDelegate.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NsClientReceiverDelegate.java
@@ -6,13 +6,12 @@ import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.wifi.WifiManager;
-import com.squareup.otto.Bus;
-
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.events.EventChargingState;
import info.nightscout.androidaps.events.EventNetworkChange;
import info.nightscout.androidaps.events.EventPreferenceChange;
+import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.receivers.ChargingStateReceiver;
import info.nightscout.androidaps.receivers.NetworkChangeReceiver;
import info.nightscout.androidaps.utils.SP;
@@ -20,18 +19,16 @@ import info.nightscout.androidaps.utils.SP;
class NsClientReceiverDelegate {
private final Context context;
- private final Bus bus;
- private NetworkChangeReceiver networkChangeReceiver = new NetworkChangeReceiver();
+ private NetworkChangeReceiver networkChangeReceiver = NetworkChangeReceiver.instance;
private ChargingStateReceiver chargingStateReceiver = new ChargingStateReceiver();
private boolean allowedChargingState = true;
private boolean allowedNetworkState = true;
boolean allowed = true;
- NsClientReceiverDelegate(Context context, Bus bus) {
+ NsClientReceiverDelegate(Context context) {
this.context = context;
- this.bus = bus;
}
void registerReceivers() {
@@ -45,14 +42,14 @@ class NsClientReceiverDelegate {
EventNetworkChange event = networkChangeReceiver.grabNetworkStatus(context);
if (event != null)
- bus.post(event);
+ RxBus.INSTANCE.send(event);
context.registerReceiver(chargingStateReceiver,
new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
EventChargingState eventChargingState = chargingStateReceiver.grabChargingState(context);
if (eventChargingState != null)
- bus.post(eventChargingState);
+ RxBus.INSTANCE.send(eventChargingState);
}
@@ -65,14 +62,14 @@ class NsClientReceiverDelegate {
if (ev.isChanged(R.string.key_ns_wifionly) ||
ev.isChanged(R.string.key_ns_wifi_ssids) ||
ev.isChanged(R.string.key_ns_allowroaming)
- ) {
+ ) {
EventNetworkChange event = networkChangeReceiver.grabNetworkStatus(MainApp.instance().getApplicationContext());
if (event != null)
- bus.post(event);
+ RxBus.INSTANCE.send(event);
} else if (ev.isChanged(R.string.key_ns_chargingonly)) {
EventChargingState event = chargingStateReceiver.grabChargingState(MainApp.instance().getApplicationContext());
if (event != null)
- bus.post(event);
+ RxBus.INSTANCE.send(event);
}
}
@@ -98,7 +95,7 @@ class NsClientReceiverDelegate {
boolean newAllowedState = allowedChargingState && allowedNetworkState;
if (newAllowedState != allowed) {
allowed = newAllowedState;
- bus.post(new EventPreferenceChange(R.string.key_nsclientinternal_paused));
+ RxBus.INSTANCE.send(new EventPreferenceChange(R.string.key_nsclientinternal_paused));
}
}
@@ -107,7 +104,7 @@ class NsClientReceiverDelegate {
boolean newAllowedState = true;
- if (!ev.isCharging && chargingOnly) {
+ if (!ev.isCharging() && chargingOnly) {
newAllowedState = false;
}
@@ -121,13 +118,13 @@ class NsClientReceiverDelegate {
boolean newAllowedState = true;
- if (ev.wifiConnected) {
+ if (ev.getWifiConnected()) {
if (!allowedSSIDs.trim().isEmpty() &&
- (!allowedSSIDs.contains(ev.getSsid()) && !allowedSSIDs.contains(ev.ssid))) {
+ (!allowedSSIDs.contains(ev.connectedSsid()) && !allowedSSIDs.contains(ev.getSsid()))) {
newAllowedState = false;
}
} else {
- if ((!allowRoaming && ev.roaming) || wifiOnly) {
+ if ((!allowRoaming && ev.getRoaming()) || wifiOnly) {
newAllowedState = false;
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/acks/NSAddAck.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/acks/NSAddAck.java
index ead373d61d..01d1f26c33 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/acks/NSAddAck.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/acks/NSAddAck.java
@@ -5,9 +5,9 @@ import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.events.Event;
import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart;
import io.socket.client.Ack;
@@ -33,7 +33,7 @@ public class NSAddAck extends Event implements Ack {
nsClientID = response.getString("NSCLIENT_ID");
}
}
- MainApp.bus().post(this);
+ RxBus.INSTANCE.send(this);
return;
} catch (Exception e) {
log.error("Unhandled exception", e);
@@ -44,7 +44,7 @@ public class NSAddAck extends Event implements Ack {
if (response.has("result")) {
_id = null;
if (response.getString("result").contains("Not")) {
- MainApp.bus().post(new EventNSClientRestart());
+ RxBus.INSTANCE.send(new EventNSClientRestart());
return;
}
if (L.isEnabled(L.NSCLIENT))
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/acks/NSAuthAck.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/acks/NSAuthAck.java
index 62c1cf7f5d..754ff6684b 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/acks/NSAuthAck.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/acks/NSAuthAck.java
@@ -2,13 +2,10 @@ package info.nightscout.androidaps.plugins.general.nsclient.acks;
import org.json.JSONObject;
-import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.events.Event;
+import info.nightscout.androidaps.plugins.bus.RxBus;
import io.socket.client.Ack;
-/**
- * Created by mike on 02.01.2016.
- */
public class NSAuthAck extends Event implements Ack{
public boolean read = false;
public boolean write = false;
@@ -19,6 +16,6 @@ public class NSAuthAck extends Event implements Ack{
read = response.optBoolean("read");
write = response.optBoolean("write");
write_treatment = response.optBoolean("write_treatment");
- MainApp.bus().post(this);
+ RxBus.INSTANCE.send(this);
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/acks/NSUpdateAck.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/acks/NSUpdateAck.java
index 68ce3d9a37..2a4022980d 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/acks/NSUpdateAck.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/acks/NSUpdateAck.java
@@ -5,9 +5,9 @@ import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.events.Event;
import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.bus.RxBus;
import io.socket.client.Ack;
/**
@@ -28,7 +28,7 @@ public class NSUpdateAck extends Event implements Ack {
result = true;
log.debug("Internal error: Missing _id returned on dbUpdate ack");
}
- MainApp.bus().post(this);
+ RxBus.INSTANCE.send(this);
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastAckAlarm.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastAckAlarm.java
index 6873b59515..7179231068 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastAckAlarm.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastAckAlarm.java
@@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.general.nsclient.broadcasts;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
-import android.support.v4.content.LocalBroadcastManager;
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastAlarm.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastAlarm.java
index 9c1e3e7ae2..ce1de70900 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastAlarm.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastAlarm.java
@@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.general.nsclient.broadcasts;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
-import android.support.v4.content.LocalBroadcastManager;
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import org.json.JSONObject;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastAnnouncement.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastAnnouncement.java
index b26c055851..f97f750287 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastAnnouncement.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastAnnouncement.java
@@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.general.nsclient.broadcasts;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
-import android.support.v4.content.LocalBroadcastManager;
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import org.json.JSONObject;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastCals.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastCals.java
index 7d5dcddadc..83f3c0a0e4 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastCals.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastCals.java
@@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.general.nsclient.broadcasts;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
-import android.support.v4.content.LocalBroadcastManager;
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import org.json.JSONArray;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastClearAlarm.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastClearAlarm.java
index fe9a194ca2..3f0586e65e 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastClearAlarm.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastClearAlarm.java
@@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.general.nsclient.broadcasts;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
-import android.support.v4.content.LocalBroadcastManager;
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import org.json.JSONObject;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastDeviceStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastDeviceStatus.java
index 412c321817..4631834d9b 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastDeviceStatus.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastDeviceStatus.java
@@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.general.nsclient.broadcasts;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
-import android.support.v4.content.LocalBroadcastManager;
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import org.json.JSONArray;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastFood.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastFood.java
index 0a8c21251b..35a2315ff2 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastFood.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastFood.java
@@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.general.nsclient.broadcasts;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
-import android.support.v4.content.LocalBroadcastManager;
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import org.json.JSONArray;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastMbgs.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastMbgs.java
index 9c059ae8a2..248e5d627f 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastMbgs.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastMbgs.java
@@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.general.nsclient.broadcasts;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
-import android.support.v4.content.LocalBroadcastManager;
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import org.json.JSONArray;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastProfile.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastProfile.java
index 9411ed6e9e..d6d051e327 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastProfile.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastProfile.java
@@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.general.nsclient.broadcasts;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
-import android.support.v4.content.LocalBroadcastManager;
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastSgvs.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastSgvs.java
index 04e957811d..06fd3c0a35 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastSgvs.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastSgvs.java
@@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.general.nsclient.broadcasts;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
-import android.support.v4.content.LocalBroadcastManager;
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import org.json.JSONArray;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastStatus.java
index c037acc9bb..81de2248e4 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastStatus.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastStatus.java
@@ -4,7 +4,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
-import android.support.v4.content.LocalBroadcastManager;
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastTreatment.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastTreatment.java
index e4ca7b577f..a364d0d4ae 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastTreatment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastTreatment.java
@@ -2,7 +2,7 @@ package info.nightscout.androidaps.plugins.general.nsclient.broadcasts;
import android.content.Intent;
import android.os.Bundle;
-import android.support.v4.content.LocalBroadcastManager;
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import org.json.JSONArray;
import org.json.JSONException;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastUrgentAlarm.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastUrgentAlarm.java
index 676dbe909d..b6b1c4f8d9 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastUrgentAlarm.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastUrgentAlarm.java
@@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.general.nsclient.broadcasts;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
-import android.support.v4.content.LocalBroadcastManager;
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import org.json.JSONObject;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/data/NSDeviceStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/data/NSDeviceStatus.java
index b2539a716e..ea7a8c34bd 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/data/NSDeviceStatus.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/data/NSDeviceStatus.java
@@ -17,10 +17,9 @@ import java.util.Map;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
-import info.nightscout.androidaps.logging.L;
-import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin;
-import info.nightscout.androidaps.plugins.aps.loop.APSResult;
import info.nightscout.androidaps.logging.BundleLogger;
+import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.aps.loop.APSResult;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.Round;
import info.nightscout.androidaps.utils.SP;
@@ -108,8 +107,7 @@ public class NSDeviceStatus {
setData(devicestatusJson);
if (devicestatusJson.has("pump")) {
// Objectives 0
- ObjectivesPlugin.getPlugin().pumpStatusIsAvailableInNS = true;
- ObjectivesPlugin.getPlugin().saveProgress();
+ SP.putBoolean(R.string.key_ObjectivespumpStatusIsAvailableInNS, true);
}
}
if (bundle.containsKey("devicestatuses")) {
@@ -120,8 +118,7 @@ public class NSDeviceStatus {
setData(devicestatusJson);
if (devicestatusJson.has("pump")) {
// Objectives 0
- ObjectivesPlugin.getPlugin().pumpStatusIsAvailableInNS = true;
- ObjectivesPlugin.getPlugin().saveProgress();
+ SP.putBoolean(R.string.key_ObjectivespumpStatusIsAvailableInNS, true);
}
}
}
@@ -194,7 +191,7 @@ public class NSDeviceStatus {
level = Levels.URGENT;
else if (!deviceStatusPumpData.isPercent && deviceStatusPumpData.voltage < NSSettingsStatus.getInstance().extendedPumpSettings("urgentBattV"))
level = Levels.URGENT;
- else if (deviceStatusPumpData.clock + NSSettingsStatus.getInstance().extendedPumpSettings("warnClock") < now)
+ else if (deviceStatusPumpData.clock + NSSettingsStatus.getInstance().extendedPumpSettings("warnClock") * 60 * 1000L < now)
level = Levels.WARN;
else if (deviceStatusPumpData.reservoir < NSSettingsStatus.getInstance().extendedPumpSettings("warnRes"))
level = Levels.WARN;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/data/NSSettingsStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/data/NSSettingsStatus.java
index 8511247e42..ba59c6297a 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/data/NSSettingsStatus.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/data/NSSettingsStatus.java
@@ -3,7 +3,8 @@ package info.nightscout.androidaps.plugins.general.nsclient.data;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
-import android.support.annotation.Nullable;
+
+import androidx.annotation.Nullable;
import org.json.JSONException;
import org.json.JSONObject;
@@ -16,12 +17,13 @@ import java.util.Objects;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.logging.BundleLogger;
import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.general.overview.OverviewPlugin;
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification;
-import info.nightscout.androidaps.logging.BundleLogger;
/*
{
@@ -154,22 +156,22 @@ public class NSSettingsStatus {
try {
if (nsClientVersionCode < MainApp.instance().getPackageManager().getPackageInfo(MainApp.instance().getPackageName(), 0).versionCode) {
Notification notification = new Notification(Notification.OLD_NSCLIENT, MainApp.gs(R.string.unsupportedclientver), Notification.URGENT);
- MainApp.bus().post(new EventNewNotification(notification));
+ RxBus.INSTANCE.send(new EventNewNotification(notification));
} else {
- MainApp.bus().post(new EventDismissNotification(Notification.OLD_NSCLIENT));
+ RxBus.INSTANCE.send(new EventDismissNotification(Notification.OLD_NSCLIENT));
}
} catch (PackageManager.NameNotFoundException e) {
log.error("Unhandled exception", e);
}
if (nightscoutVersionCode < Config.SUPPORTEDNSVERSION) {
Notification notification = new Notification(Notification.OLD_NS, MainApp.gs(R.string.unsupportednsversion), Notification.NORMAL);
- MainApp.bus().post(new EventNewNotification(notification));
+ RxBus.INSTANCE.send(new EventNewNotification(notification));
} else {
- MainApp.bus().post(new EventDismissNotification(Notification.OLD_NS));
+ RxBus.INSTANCE.send(new EventDismissNotification(Notification.OLD_NS));
}
} else {
Notification notification = new Notification(Notification.OLD_NSCLIENT, MainApp.gs(R.string.unsupportedclientver), Notification.URGENT);
- MainApp.bus().post(new EventNewNotification(notification));
+ RxBus.INSTANCE.send(new EventNewNotification(notification));
}
if (bundle.containsKey("status")) {
try {
@@ -180,9 +182,9 @@ public class NSSettingsStatus {
Double targetHigh = getThreshold("bgTargetTop");
Double targetlow = getThreshold("bgTargetBottom");
if (targetHigh != null)
- OverviewPlugin.bgTargetHigh = targetHigh;
+ OverviewPlugin.INSTANCE.setBgTargetHigh(targetHigh);
if (targetlow != null)
- OverviewPlugin.bgTargetLow = targetlow;
+ OverviewPlugin.INSTANCE.setBgTargetLow(targetlow);
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/events/EventNSClientNewLog.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/events/EventNSClientNewLog.java
deleted file mode 100644
index 121085cb94..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/events/EventNSClientNewLog.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package info.nightscout.androidaps.plugins.general.nsclient.events;
-
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
-import info.nightscout.androidaps.events.Event;
-
-/**
- * Created by mike on 15.02.2017.
- */
-
-public class EventNSClientNewLog extends Event {
- public Date date = new Date();
- public String action;
- public String logText;
- public EventNSClientNewLog(String action, String logText) {
- this.action = action;
- this.logText = logText;
- }
-
- SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
-
- public StringBuilder toPreparedHtml() {
- StringBuilder stringBuilder = new StringBuilder();
- stringBuilder.append(timeFormat.format(date));
- stringBuilder.append(" ");
- stringBuilder.append(action);
- stringBuilder.append(" ");
- stringBuilder.append(logText);
- stringBuilder.append(" ");
- return stringBuilder;
- }
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/events/EventNSClientNewLog.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/events/EventNSClientNewLog.kt
new file mode 100644
index 0000000000..38d6bcfd0f
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/events/EventNSClientNewLog.kt
@@ -0,0 +1,22 @@
+package info.nightscout.androidaps.plugins.general.nsclient.events
+
+import info.nightscout.androidaps.events.Event
+import java.text.SimpleDateFormat
+import java.util.*
+
+class EventNSClientNewLog(var action: String, var logText: String) : Event() {
+ var date = Date()
+
+ private var timeFormat = SimpleDateFormat("HH:mm:ss", Locale.getDefault())
+
+ fun toPreparedHtml(): StringBuilder {
+ val stringBuilder = StringBuilder()
+ stringBuilder.append(timeFormat.format(date))
+ stringBuilder.append(" ")
+ stringBuilder.append(action)
+ stringBuilder.append(" ")
+ stringBuilder.append(logText)
+ stringBuilder.append(" ")
+ return stringBuilder
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/events/EventNSClientRestart.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/events/EventNSClientRestart.java
deleted file mode 100644
index b5481ce741..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/events/EventNSClientRestart.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package info.nightscout.androidaps.plugins.general.nsclient.events;
-
-import info.nightscout.androidaps.events.Event;
-
-/**
- * Created by mike on 15.02.2017.
- */
-
-public class EventNSClientRestart extends Event {
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/events/EventNSClientRestart.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/events/EventNSClientRestart.kt
new file mode 100644
index 0000000000..49333b6840
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/events/EventNSClientRestart.kt
@@ -0,0 +1,5 @@
+package info.nightscout.androidaps.plugins.general.nsclient.events
+
+import info.nightscout.androidaps.events.Event
+
+class EventNSClientRestart : Event()
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/events/EventNSClientStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/events/EventNSClientStatus.java
deleted file mode 100644
index c3bf74321c..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/events/EventNSClientStatus.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package info.nightscout.androidaps.plugins.general.nsclient.events;
-
-import info.nightscout.androidaps.events.Event;
-
-/**
- * Created by mike on 02.01.2016.
- */
-public class EventNSClientStatus extends Event {
- public String status = "";
-
- public EventNSClientStatus(String status) {
- this.status = status;
- }
-
- public EventNSClientStatus() {
- }
-
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/events/EventNSClientStatus.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/events/EventNSClientStatus.kt
new file mode 100644
index 0000000000..4d0c9dcd6e
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/events/EventNSClientStatus.kt
@@ -0,0 +1,7 @@
+package info.nightscout.androidaps.plugins.general.nsclient.events
+
+import info.nightscout.androidaps.events.EventStatus
+
+class EventNSClientStatus(var text: String) : EventStatus() {
+ override fun getStatus(): String = text
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/events/EventNSClientUpdateGUI.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/events/EventNSClientUpdateGUI.java
deleted file mode 100644
index 60d74a249d..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/events/EventNSClientUpdateGUI.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package info.nightscout.androidaps.plugins.general.nsclient.events;
-
-import info.nightscout.androidaps.events.EventUpdateGui;
-
-/**
- * Created by mike on 17.02.2017.
- */
-
-public class EventNSClientUpdateGUI extends EventUpdateGui {
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/events/EventNSClientUpdateGUI.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/events/EventNSClientUpdateGUI.kt
new file mode 100644
index 0000000000..891e61895c
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/events/EventNSClientUpdateGUI.kt
@@ -0,0 +1,5 @@
+package info.nightscout.androidaps.plugins.general.nsclient.events
+
+import info.nightscout.androidaps.events.EventUpdateGui
+
+class EventNSClientUpdateGUI : EventUpdateGui()
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/receivers/AckAlarmReceiver.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/receivers/AckAlarmReceiver.java
index 7185072692..1c46716d69 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/receivers/AckAlarmReceiver.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/receivers/AckAlarmReceiver.java
@@ -27,7 +27,7 @@ public class AckAlarmReceiver extends BroadcastReceiver {
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
AckAlarmReceiver.class.getSimpleName());
- NSClientPlugin nsClientPlugin = MainApp.getSpecificPlugin(NSClientPlugin.class);
+ NSClientPlugin nsClientPlugin = NSClientPlugin.getPlugin();
if (!nsClientPlugin.isEnabled(PluginType.GENERAL)) {
return;
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/receivers/AutoStartReceiver.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/receivers/AutoStartReceiver.java
index e91e203175..6c8c7ae159 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/receivers/AutoStartReceiver.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/receivers/AutoStartReceiver.java
@@ -3,8 +3,9 @@ package info.nightscout.androidaps.plugins.general.nsclient.receivers;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.os.Build;
-import info.nightscout.androidaps.plugins.general.nsclient.services.NSClientService;
+import info.nightscout.androidaps.plugins.general.persistentNotification.DummyService;
public class AutoStartReceiver extends BroadcastReceiver {
public AutoStartReceiver() {
@@ -12,6 +13,9 @@ public class AutoStartReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
- context.startService(new Intent(context, NSClientService.class));
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
+ context.startForegroundService(new Intent(context, DummyService.class));
+ else
+ context.startService(new Intent(context, DummyService.class));
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/receivers/DBAccessReceiver.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/receivers/DBAccessReceiver.java
index 4d8b7eba2a..4838c178ef 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/receivers/DBAccessReceiver.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/receivers/DBAccessReceiver.java
@@ -118,7 +118,7 @@ public class DBAccessReceiver extends BroadcastReceiver {
}
public boolean shouldUpload() {
- NSClientPlugin nsClientPlugin = MainApp.getSpecificPlugin(NSClientPlugin.class);
+ NSClientPlugin nsClientPlugin = NSClientPlugin.getPlugin();
return nsClientPlugin.isEnabled(PluginType.GENERAL) && !SP.getBoolean(R.string.key_ns_noupload, false);
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/receivers/RestartReceiver.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/receivers/RestartReceiver.java
deleted file mode 100644
index 0b221ee456..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/receivers/RestartReceiver.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package info.nightscout.androidaps.plugins.general.nsclient.receivers;
-
-import android.content.Context;
-import android.content.Intent;
-import android.support.v4.content.WakefulBroadcastReceiver;
-
-import info.nightscout.androidaps.MainApp;
-import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart;
-import info.nightscout.androidaps.plugins.general.nsclient.services.NSClientService;
-
-public class RestartReceiver extends WakefulBroadcastReceiver {
- public RestartReceiver() {
- }
-
- @Override
- public void onReceive(Context context, Intent intent) {
- startWakefulService(context, new Intent(context, NSClientService.class)
- .setAction(intent.getAction())
- .putExtras(intent));
-
- MainApp.bus().post(new EventNSClientRestart());
- completeWakefulIntent(intent);
- }
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/services/NSClientService.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/services/NSClientService.java
index c14a3382b3..e1c57cc7c2 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/services/NSClientService.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/services/NSClientService.java
@@ -13,7 +13,6 @@ import android.os.SystemClock;
import com.google.common.base.Charsets;
import com.google.common.hash.Hashing;
import com.j256.ormlite.dao.CloseableIterator;
-import com.squareup.otto.Subscribe;
import org.json.JSONArray;
import org.json.JSONException;
@@ -35,6 +34,7 @@ import info.nightscout.androidaps.events.EventConfigBuilderChange;
import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin;
import info.nightscout.androidaps.plugins.general.nsclient.UploadQueue;
import info.nightscout.androidaps.plugins.general.nsclient.acks.NSAddAck;
@@ -68,12 +68,15 @@ import info.nightscout.androidaps.utils.FabricPrivacy;
import info.nightscout.androidaps.utils.JsonHelper;
import info.nightscout.androidaps.utils.SP;
import info.nightscout.androidaps.utils.T;
+import io.reactivex.disposables.CompositeDisposable;
+import io.reactivex.schedulers.Schedulers;
import io.socket.client.IO;
import io.socket.client.Socket;
import io.socket.emitter.Emitter;
public class NSClientService extends Service {
private static Logger log = LoggerFactory.getLogger(L.NSCLIENT);
+ private CompositeDisposable disposable = new CompositeDisposable();
static public PowerManager.WakeLock mWakeLock;
private IBinder mBinder = new NSClientService.LocalBinder();
@@ -112,7 +115,6 @@ public class NSClientService extends Service {
private int WATCHDOG_MAXCONNECTIONS = 5;
public NSClientService() {
- registerBus();
if (handler == null) {
HandlerThread handlerThread = new HandlerThread(NSClientService.class.getSimpleName() + "Handler");
handlerThread.start();
@@ -128,14 +130,115 @@ public class NSClientService extends Service {
public void onCreate() {
super.onCreate();
mWakeLock.acquire();
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventConfigBuilderChange.class)
+ .observeOn(Schedulers.io())
+ .subscribe(event -> {
+ if (nsEnabled != NSClientPlugin.getPlugin().isEnabled(PluginType.GENERAL)) {
+ latestDateInReceivedData = 0;
+ destroy();
+ initialize();
+ }
+ }, FabricPrivacy::logException)
+ );
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventPreferenceChange.class)
+ .observeOn(Schedulers.io())
+ .subscribe(event -> {
+ if (event.isChanged(R.string.key_nsclientinternal_url) ||
+ event.isChanged(R.string.key_nsclientinternal_api_secret) ||
+ event.isChanged(R.string.key_nsclientinternal_paused)
+ ) {
+ latestDateInReceivedData = 0;
+ destroy();
+ initialize();
+ }
+ }, FabricPrivacy::logException)
+ );
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventAppExit.class)
+ .observeOn(Schedulers.io())
+ .subscribe(event -> {
+ if (L.isEnabled(L.NSCLIENT))
+ log.debug("EventAppExit received");
+ destroy();
+ stopSelf();
+ }, FabricPrivacy::logException)
+ );
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventNSClientRestart.class)
+ .observeOn(Schedulers.io())
+ .subscribe(event -> {
+ latestDateInReceivedData = 0;
+ restart();
+ }, FabricPrivacy::logException)
+ );
+ disposable.add(RxBus.INSTANCE
+ .toObservable(NSAuthAck.class)
+ .observeOn(Schedulers.io())
+ .subscribe(event -> processAuthAck(event), FabricPrivacy::logException)
+ );
+ disposable.add(RxBus.INSTANCE
+ .toObservable(NSUpdateAck.class)
+ .observeOn(Schedulers.io())
+ .subscribe(event -> processUpdateAck(event), FabricPrivacy::logException)
+ );
+ disposable.add(RxBus.INSTANCE
+ .toObservable(NSAddAck.class)
+ .observeOn(Schedulers.io())
+ .subscribe(event -> processAddAck(event), FabricPrivacy::logException)
+ );
}
@Override
public void onDestroy() {
super.onDestroy();
+ disposable.clear();
if (mWakeLock.isHeld()) mWakeLock.release();
}
+ public void processAddAck(NSAddAck ack) {
+ if (ack.nsClientID != null) {
+ uploadQueue.removeID(ack.json);
+ RxBus.INSTANCE.send(new EventNSClientNewLog("DBADD", "Acked " + ack.nsClientID));
+ } else {
+ RxBus.INSTANCE.send(new EventNSClientNewLog("ERROR", "DBADD Unknown response"));
+ }
+ }
+
+ public void processUpdateAck(NSUpdateAck ack) {
+ if (ack.result) {
+ uploadQueue.removeID(ack.action, ack._id);
+ RxBus.INSTANCE.send(new EventNSClientNewLog("DBUPDATE/DBREMOVE", "Acked " + ack._id));
+ } else {
+ RxBus.INSTANCE.send(new EventNSClientNewLog("ERROR", "DBUPDATE/DBREMOVE Unknown response"));
+ }
+ }
+
+ public void processAuthAck(NSAuthAck ack) {
+ String connectionStatus = "Authenticated (";
+ if (ack.read) connectionStatus += "R";
+ if (ack.write) connectionStatus += "W";
+ if (ack.write_treatment) connectionStatus += "T";
+ connectionStatus += ')';
+ isConnected = true;
+ hasWriteAuth = ack.write && ack.write_treatment;
+ RxBus.INSTANCE.send(new EventNSClientStatus(connectionStatus));
+ RxBus.INSTANCE.send(new EventNSClientNewLog("AUTH", connectionStatus));
+ if (!ack.write) {
+ RxBus.INSTANCE.send(new EventNSClientNewLog("ERROR", "Write permission not granted !!!!"));
+ }
+ if (!ack.write_treatment) {
+ RxBus.INSTANCE.send(new EventNSClientNewLog("ERROR", "Write treatment permission not granted !!!!"));
+ }
+ if (!hasWriteAuth) {
+ Notification noperm = new Notification(Notification.NSCLIENT_NO_WRITE_PERMISSION, MainApp.gs(R.string.nowritepermission), Notification.URGENT);
+ RxBus.INSTANCE.send(new EventNewNotification(noperm));
+ } else {
+ RxBus.INSTANCE.send(new EventDismissNotification(Notification.NSCLIENT_NO_WRITE_PERMISSION));
+ }
+ }
+
public class LocalBinder extends Binder {
public NSClientService getServiceInstance() {
return NSClientService.this;
@@ -153,52 +256,6 @@ public class NSClientService extends Service {
return START_STICKY;
}
- private void registerBus() {
- try {
- MainApp.bus().unregister(this);
- } catch (RuntimeException x) {
- // Ignore
- }
- MainApp.bus().register(this);
- }
-
- @Subscribe
- public void onStatusEvent(EventAppExit event) {
- if (L.isEnabled(L.NSCLIENT))
- log.debug("EventAppExit received");
-
- destroy();
-
- stopSelf();
- }
-
- @Subscribe
- public void onStatusEvent(EventPreferenceChange ev) {
- if (ev.isChanged(R.string.key_nsclientinternal_url) ||
- ev.isChanged(R.string.key_nsclientinternal_api_secret) ||
- ev.isChanged(R.string.key_nsclientinternal_paused)
- ) {
- latestDateInReceivedData = 0;
- destroy();
- initialize();
- }
- }
-
- @Subscribe
- public void onStatusEvent(EventConfigBuilderChange ev) {
- if (nsEnabled != MainApp.getSpecificPlugin(NSClientPlugin.class).isEnabled(PluginType.GENERAL)) {
- latestDateInReceivedData = 0;
- destroy();
- initialize();
- }
- }
-
- @Subscribe
- public void onStatusEvent(final EventNSClientRestart ev) {
- latestDateInReceivedData = 0;
- restart();
- }
-
public void initialize() {
dataCounter = 0;
@@ -207,19 +264,19 @@ public class NSClientService extends Service {
if (!nsAPISecret.equals(""))
nsAPIhashCode = Hashing.sha1().hashString(nsAPISecret, Charsets.UTF_8).toString();
- MainApp.bus().post(new EventNSClientStatus("Initializing"));
- if (!MainApp.getSpecificPlugin(NSClientPlugin.class).isAllowed()) {
- MainApp.bus().post(new EventNSClientNewLog("NSCLIENT", "not allowed"));
- MainApp.bus().post(new EventNSClientStatus("Not allowed"));
- } else if (MainApp.getSpecificPlugin(NSClientPlugin.class).paused) {
- MainApp.bus().post(new EventNSClientNewLog("NSCLIENT", "paused"));
- MainApp.bus().post(new EventNSClientStatus("Paused"));
+ RxBus.INSTANCE.send(new EventNSClientStatus("Initializing"));
+ if (!NSClientPlugin.getPlugin().isAllowed()) {
+ RxBus.INSTANCE.send(new EventNSClientNewLog("NSCLIENT", "not allowed"));
+ RxBus.INSTANCE.send(new EventNSClientStatus("Not allowed"));
+ } else if (NSClientPlugin.getPlugin().paused) {
+ RxBus.INSTANCE.send(new EventNSClientNewLog("NSCLIENT", "paused"));
+ RxBus.INSTANCE.send(new EventNSClientStatus("Paused"));
} else if (!nsEnabled) {
- MainApp.bus().post(new EventNSClientNewLog("NSCLIENT", "disabled"));
- MainApp.bus().post(new EventNSClientStatus("Disabled"));
+ RxBus.INSTANCE.send(new EventNSClientNewLog("NSCLIENT", "disabled"));
+ RxBus.INSTANCE.send(new EventNSClientStatus("Disabled"));
} else if (!nsURL.equals("")) {
try {
- MainApp.bus().post(new EventNSClientStatus("Connecting ..."));
+ RxBus.INSTANCE.send(new EventNSClientStatus("Connecting ..."));
IO.Options opt = new IO.Options();
opt.forceNew = true;
opt.reconnection = true;
@@ -227,7 +284,7 @@ public class NSClientService extends Service {
mSocket.on(Socket.EVENT_CONNECT, onConnect);
mSocket.on(Socket.EVENT_DISCONNECT, onDisconnect);
mSocket.on(Socket.EVENT_PING, onPing);
- MainApp.bus().post(new EventNSClientNewLog("NSCLIENT", "do connect"));
+ RxBus.INSTANCE.send(new EventNSClientNewLog("NSCLIENT", "do connect"));
mSocket.connect();
mSocket.on("dataUpdate", onDataUpdate);
mSocket.on("announcement", onAnnouncement);
@@ -235,12 +292,12 @@ public class NSClientService extends Service {
mSocket.on("urgent_alarm", onUrgentAlarm);
mSocket.on("clear_alarm", onClearAlarm);
} catch (URISyntaxException | RuntimeException e) {
- MainApp.bus().post(new EventNSClientNewLog("NSCLIENT", "Wrong URL syntax"));
- MainApp.bus().post(new EventNSClientStatus("Wrong URL syntax"));
+ RxBus.INSTANCE.send(new EventNSClientNewLog("NSCLIENT", "Wrong URL syntax"));
+ RxBus.INSTANCE.send(new EventNSClientStatus("Wrong URL syntax"));
}
} else {
- MainApp.bus().post(new EventNSClientNewLog("NSCLIENT", "No NS URL specified"));
- MainApp.bus().post(new EventNSClientStatus("Not configured"));
+ RxBus.INSTANCE.send(new EventNSClientNewLog("NSCLIENT", "No NS URL specified"));
+ RxBus.INSTANCE.send(new EventNSClientStatus("Not configured"));
}
}
@@ -249,7 +306,7 @@ public class NSClientService extends Service {
public void call(Object... args) {
connectCounter++;
String socketId = mSocket != null ? mSocket.id() : "NULL";
- MainApp.bus().post(new EventNSClientNewLog("NSCLIENT", "connect #" + connectCounter + " event. ID: " + socketId));
+ RxBus.INSTANCE.send(new EventNSClientNewLog("NSCLIENT", "connect #" + connectCounter + " event. ID: " + socketId));
if (mSocket != null)
sendAuthMessage(new NSAuthAck());
watchdog();
@@ -266,16 +323,16 @@ public class NSClientService extends Service {
reconnections.remove(r);
}
}
- MainApp.bus().post(new EventNSClientNewLog("WATCHDOG", "connections in last " + WATCHDOG_INTERVAL_MINUTES + " mins: " + reconnections.size() + "/" + WATCHDOG_MAXCONNECTIONS));
+ RxBus.INSTANCE.send(new EventNSClientNewLog("WATCHDOG", "connections in last " + WATCHDOG_INTERVAL_MINUTES + " mins: " + reconnections.size() + "/" + WATCHDOG_MAXCONNECTIONS));
if (reconnections.size() >= WATCHDOG_MAXCONNECTIONS) {
Notification n = new Notification(Notification.NSMALFUNCTION, MainApp.gs(R.string.nsmalfunction), Notification.URGENT);
- MainApp.bus().post(new EventNewNotification(n));
- MainApp.bus().post(new EventNSClientNewLog("WATCHDOG", "pausing for " + WATCHDOG_RECONNECT_IN + " mins"));
+ RxBus.INSTANCE.send(new EventNewNotification(n));
+ RxBus.INSTANCE.send(new EventNSClientNewLog("WATCHDOG", "pausing for " + WATCHDOG_RECONNECT_IN + " mins"));
NSClientPlugin.getPlugin().pause(true);
- MainApp.bus().post(new EventNSClientUpdateGUI());
+ RxBus.INSTANCE.send(new EventNSClientUpdateGUI());
new Thread(() -> {
SystemClock.sleep(T.mins(WATCHDOG_RECONNECT_IN).msecs());
- MainApp.bus().post(new EventNSClientNewLog("WATCHDOG", "reenabling NSClient"));
+ RxBus.INSTANCE.send(new EventNSClientNewLog("WATCHDOG", "reenabling NSClient"));
NSClientPlugin.getPlugin().pause(false);
}).start();
}
@@ -287,7 +344,7 @@ public class NSClientService extends Service {
public void call(Object... args) {
if (L.isEnabled(L.NSCLIENT))
log.debug("disconnect reason: {}", args);
- MainApp.bus().post(new EventNSClientNewLog("NSCLIENT", "disconnect event"));
+ RxBus.INSTANCE.send(new EventNSClientNewLog("NSCLIENT", "disconnect event"));
}
};
@@ -302,7 +359,7 @@ public class NSClientService extends Service {
mSocket.off("urgent_alarm");
mSocket.off("clear_alarm");
- MainApp.bus().post(new EventNSClientNewLog("NSCLIENT", "destroy"));
+ RxBus.INSTANCE.send(new EventNSClientNewLog("NSCLIENT", "destroy"));
isConnected = false;
hasWriteAuth = false;
mSocket.disconnect();
@@ -323,38 +380,13 @@ public class NSClientService extends Service {
log.error("Unhandled exception", e);
return;
}
- MainApp.bus().post(new EventNSClientNewLog("AUTH", "requesting auth"));
+ RxBus.INSTANCE.send(new EventNSClientNewLog("AUTH", "requesting auth"));
if (mSocket != null)
mSocket.emit("authorize", authMessage, ack);
}
- @Subscribe
- public void onStatusEvent(NSAuthAck ack) {
- String connectionStatus = "Authenticated (";
- if (ack.read) connectionStatus += "R";
- if (ack.write) connectionStatus += "W";
- if (ack.write_treatment) connectionStatus += "T";
- connectionStatus += ')';
- isConnected = true;
- hasWriteAuth = ack.write && ack.write_treatment;
- MainApp.bus().post(new EventNSClientStatus(connectionStatus));
- MainApp.bus().post(new EventNSClientNewLog("AUTH", connectionStatus));
- if (!ack.write) {
- MainApp.bus().post(new EventNSClientNewLog("ERROR", "Write permission not granted !!!!"));
- }
- if (!ack.write_treatment) {
- MainApp.bus().post(new EventNSClientNewLog("ERROR", "Write treatment permission not granted !!!!"));
- }
- if (!hasWriteAuth) {
- Notification noperm = new Notification(Notification.NSCLIENT_NO_WRITE_PERMISSION, MainApp.gs(R.string.nowritepermission), Notification.URGENT);
- MainApp.bus().post(new EventNewNotification(noperm));
- } else {
- MainApp.bus().post(new EventDismissNotification(Notification.NSCLIENT_NO_WRITE_PERMISSION));
- }
- }
-
public void readPreferences() {
- nsEnabled = MainApp.getSpecificPlugin(NSClientPlugin.class).isEnabled(PluginType.GENERAL);
+ nsEnabled = NSClientPlugin.getPlugin().isEnabled(PluginType.GENERAL);
nsURL = SP.getString(R.string.key_nsclientinternal_url, "");
nsAPISecret = SP.getString(R.string.key_nsclientinternal_api_secret, "");
nsDevice = SP.getString("careportal_enteredby", "");
@@ -363,7 +395,7 @@ public class NSClientService extends Service {
private Emitter.Listener onPing = new Emitter.Listener() {
@Override
public void call(final Object... args) {
- MainApp.bus().post(new EventNSClientNewLog("PING", "received"));
+ RxBus.INSTANCE.send(new EventNSClientNewLog("PING", "received"));
// send data if there is something waiting
resend("Ping received");
}
@@ -392,7 +424,7 @@ public class NSClientService extends Service {
return;
}
try {
- MainApp.bus().post(new EventNSClientNewLog("ANNOUNCEMENT", JsonHelper.safeGetString(data, "message", "received")));
+ RxBus.INSTANCE.send(new EventNSClientNewLog("ANNOUNCEMENT", JsonHelper.safeGetString(data, "message", "received")));
} catch (Exception e) {
FabricPrivacy.logException(e);
log.error("Unhandled exception", e);
@@ -419,7 +451,7 @@ public class NSClientService extends Service {
*/
@Override
public void call(final Object... args) {
- MainApp.bus().post(new EventNSClientNewLog("ALARM", "received"));
+ RxBus.INSTANCE.send(new EventNSClientNewLog("ALARM", "received"));
JSONObject data;
try {
data = (JSONObject) args[0];
@@ -458,7 +490,7 @@ public class NSClientService extends Service {
log.error("Unhandled exception", e);
return;
}
- MainApp.bus().post(new EventNSClientNewLog("URGENTALARM", "received"));
+ RxBus.INSTANCE.send(new EventNSClientNewLog("URGENTALARM", "received"));
BroadcastUrgentAlarm.handleUrgentAlarm(data, getApplicationContext());
if (L.isEnabled(L.NSCLIENT))
log.debug(data.toString());
@@ -484,7 +516,7 @@ public class NSClientService extends Service {
log.error("Unhandled exception", e);
return;
}
- MainApp.bus().post(new EventNSClientNewLog("CLEARALARM", "received"));
+ RxBus.INSTANCE.send(new EventNSClientNewLog("CLEARALARM", "received"));
BroadcastClearAlarm.handleClearAlarm(data, getApplicationContext());
if (L.isEnabled(L.NSCLIENT))
log.debug(data.toString());
@@ -509,7 +541,7 @@ public class NSClientService extends Service {
// delta means only increment/changes are comming
boolean isDelta = data.has("delta");
boolean isFull = !isDelta;
- MainApp.bus().post(new EventNSClientNewLog("DATA", "Data packet #" + dataCounter++ + (isDelta ? " delta" : " full")));
+ RxBus.INSTANCE.send(new EventNSClientNewLog("DATA", "Data packet #" + dataCounter++ + (isDelta ? " delta" : " full")));
if (data.has("profiles")) {
JSONArray profiles = data.getJSONArray("profiles");
@@ -517,7 +549,7 @@ public class NSClientService extends Service {
JSONObject profile = (JSONObject) profiles.get(profiles.length() - 1);
profileStore = new ProfileStore(profile);
broadcastProfile = true;
- MainApp.bus().post(new EventNSClientNewLog("PROFILE", "profile received"));
+ RxBus.INSTANCE.send(new EventNSClientNewLog("PROFILE", "profile received"));
}
}
@@ -527,7 +559,7 @@ public class NSClientService extends Service {
if (!status.has("versionNum")) {
if (status.getInt("versionNum") < Config.SUPPORTEDNSVERSION) {
- MainApp.bus().post(new EventNSClientNewLog("ERROR", "Unsupported Nightscout version !!!!"));
+ RxBus.INSTANCE.send(new EventNSClientNewLog("ERROR", "Unsupported Nightscout version !!!!"));
}
} else {
nightscoutVersionName = nsSettingsStatus.getVersion();
@@ -552,13 +584,13 @@ public class NSClientService extends Service {
}
*/
} else if (!isDelta) {
- MainApp.bus().post(new EventNSClientNewLog("ERROR", "Unsupported Nightscout version !!!!"));
+ RxBus.INSTANCE.send(new EventNSClientNewLog("ERROR", "Unsupported Nightscout version !!!!"));
}
// If new profile received or change detected broadcast it
if (broadcastProfile && profileStore != null) {
BroadcastProfile.handleNewTreatment(profileStore, MainApp.instance().getApplicationContext(), isDelta);
- MainApp.bus().post(new EventNSClientNewLog("PROFILE", "broadcasting"));
+ RxBus.INSTANCE.send(new EventNSClientNewLog("PROFILE", "broadcasting"));
}
if (data.has("treatments")) {
@@ -567,7 +599,7 @@ public class NSClientService extends Service {
JSONArray updatedTreatments = new JSONArray();
JSONArray addedTreatments = new JSONArray();
if (treatments.length() > 0)
- MainApp.bus().post(new EventNSClientNewLog("DATA", "received " + treatments.length() + " treatments"));
+ RxBus.INSTANCE.send(new EventNSClientNewLog("DATA", "received " + treatments.length() + " treatments"));
for (Integer index = 0; index < treatments.length(); index++) {
JSONObject jsonTreatment = treatments.getJSONObject(index);
NSTreatment treatment = new NSTreatment(jsonTreatment);
@@ -601,7 +633,7 @@ public class NSClientService extends Service {
if (data.has("devicestatus")) {
JSONArray devicestatuses = data.getJSONArray("devicestatus");
if (devicestatuses.length() > 0) {
- MainApp.bus().post(new EventNSClientNewLog("DATA", "received " + devicestatuses.length() + " devicestatuses"));
+ RxBus.INSTANCE.send(new EventNSClientNewLog("DATA", "received " + devicestatuses.length() + " devicestatuses"));
for (Integer index = 0; index < devicestatuses.length(); index++) {
JSONObject jsonStatus = devicestatuses.getJSONObject(index);
// remove from upload queue if Ack is failing
@@ -616,7 +648,7 @@ public class NSClientService extends Service {
JSONArray updatedFoods = new JSONArray();
JSONArray addedFoods = new JSONArray();
if (foods.length() > 0)
- MainApp.bus().post(new EventNSClientNewLog("DATA", "received " + foods.length() + " foods"));
+ RxBus.INSTANCE.send(new EventNSClientNewLog("DATA", "received " + foods.length() + " foods"));
for (Integer index = 0; index < foods.length(); index++) {
JSONObject jsonFood = foods.getJSONObject(index);
@@ -646,7 +678,7 @@ public class NSClientService extends Service {
if (data.has("mbgs")) {
JSONArray mbgs = data.getJSONArray("mbgs");
if (mbgs.length() > 0)
- MainApp.bus().post(new EventNSClientNewLog("DATA", "received " + mbgs.length() + " mbgs"));
+ RxBus.INSTANCE.send(new EventNSClientNewLog("DATA", "received " + mbgs.length() + " mbgs"));
for (Integer index = 0; index < mbgs.length(); index++) {
JSONObject jsonMbg = mbgs.getJSONObject(index);
// remove from upload queue if Ack is failing
@@ -657,7 +689,7 @@ public class NSClientService extends Service {
if (data.has("cals")) {
JSONArray cals = data.getJSONArray("cals");
if (cals.length() > 0)
- MainApp.bus().post(new EventNSClientNewLog("DATA", "received " + cals.length() + " cals"));
+ RxBus.INSTANCE.send(new EventNSClientNewLog("DATA", "received " + cals.length() + " cals"));
// Retreive actual calibration
for (Integer index = 0; index < cals.length(); index++) {
// remove from upload queue if Ack is failing
@@ -668,10 +700,10 @@ public class NSClientService extends Service {
if (data.has("sgvs")) {
JSONArray sgvs = data.getJSONArray("sgvs");
if (sgvs.length() > 0)
- MainApp.bus().post(new EventNSClientNewLog("DATA", "received " + sgvs.length() + " sgvs"));
+ RxBus.INSTANCE.send(new EventNSClientNewLog("DATA", "received " + sgvs.length() + " sgvs"));
for (Integer index = 0; index < sgvs.length(); index++) {
JSONObject jsonSgv = sgvs.getJSONObject(index);
- // MainApp.bus().post(new EventNSClientNewLog("DATA", "svg " + sgvs.getJSONObject(index).toString());
+ // RxBus.INSTANCE.send(new EventNSClientNewLog("DATA", "svg " + sgvs.getJSONObject(index).toString());
NSSgv sgv = new NSSgv(jsonSgv);
// Handle new sgv here
// remove from upload queue if Ack is failing
@@ -686,15 +718,15 @@ public class NSClientService extends Service {
if ((System.currentTimeMillis() - latestDateInReceivedData) / (60 * 1000L) < 15L)
lessThan15MinAgo = true;
if (Notification.isAlarmForStaleData() && lessThan15MinAgo) {
- MainApp.bus().post(new EventDismissNotification(Notification.NSALARM));
+ RxBus.INSTANCE.send(new EventDismissNotification(Notification.NSALARM));
}
BroadcastSgvs.handleNewSgv(sgvs, MainApp.instance().getApplicationContext(), isDelta);
}
- MainApp.bus().post(new EventNSClientNewLog("LAST", DateUtil.dateAndTimeString(latestDateInReceivedData)));
+ RxBus.INSTANCE.send(new EventNSClientNewLog("LAST", DateUtil.dateAndTimeString(latestDateInReceivedData)));
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
- //MainApp.bus().post(new EventNSClientNewLog("NSCLIENT", "onDataUpdate end");
+ //RxBus.INSTANCE.send(new EventNSClientNewLog("NSCLIENT", "onDataUpdate end");
} finally {
if (wakeLock.isHeld()) wakeLock.release();
}
@@ -712,7 +744,7 @@ public class NSClientService extends Service {
message.put("_id", dbr._id);
message.put("data", new JSONObject(dbr.data));
mSocket.emit("dbUpdate", message, ack);
- MainApp.bus().post(new EventNSClientNewLog("DBUPDATE " + dbr.collection, "Sent " + dbr._id));
+ RxBus.INSTANCE.send(new EventNSClientNewLog("DBUPDATE " + dbr.collection, "Sent " + dbr._id));
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
@@ -726,7 +758,7 @@ public class NSClientService extends Service {
message.put("_id", dbr._id);
message.put("data", new JSONObject(dbr.data));
mSocket.emit("dbUpdateUnset", message, ack);
- MainApp.bus().post(new EventNSClientNewLog("DBUPDATEUNSET " + dbr.collection, "Sent " + dbr._id));
+ RxBus.INSTANCE.send(new EventNSClientNewLog("DBUPDATEUNSET " + dbr.collection, "Sent " + dbr._id));
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
@@ -739,22 +771,12 @@ public class NSClientService extends Service {
message.put("collection", dbr.collection);
message.put("_id", dbr._id);
mSocket.emit("dbRemove", message, ack);
- MainApp.bus().post(new EventNSClientNewLog("DBREMOVE " + dbr.collection, "Sent " + dbr._id));
+ RxBus.INSTANCE.send(new EventNSClientNewLog("DBREMOVE " + dbr.collection, "Sent " + dbr._id));
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
}
- @Subscribe
- public void onStatusEvent(NSUpdateAck ack) {
- if (ack.result) {
- uploadQueue.removeID(ack.action, ack._id);
- MainApp.bus().post(new EventNSClientNewLog("DBUPDATE/DBREMOVE", "Acked " + ack._id));
- } else {
- MainApp.bus().post(new EventNSClientNewLog("ERROR", "DBUPDATE/DBREMOVE Unknown response"));
- }
- }
-
public void dbAdd(DbRequest dbr, NSAddAck ack) {
try {
if (!isConnected || !hasWriteAuth) return;
@@ -762,7 +784,7 @@ public class NSClientService extends Service {
message.put("collection", dbr.collection);
message.put("data", new JSONObject(dbr.data));
mSocket.emit("dbAdd", message, ack);
- MainApp.bus().post(new EventNSClientNewLog("DBADD " + dbr.collection, "Sent " + dbr.nsClientID));
+ RxBus.INSTANCE.send(new EventNSClientNewLog("DBADD " + dbr.collection, "Sent " + dbr.nsClientID));
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
@@ -771,17 +793,7 @@ public class NSClientService extends Service {
public void sendAlarmAck(AlarmAck alarmAck) {
if (!isConnected || !hasWriteAuth) return;
mSocket.emit("ack", alarmAck.level, alarmAck.group, alarmAck.silenceTime);
- MainApp.bus().post(new EventNSClientNewLog("ALARMACK ", alarmAck.level + " " + alarmAck.group + " " + alarmAck.silenceTime));
- }
-
- @Subscribe
- public void onStatusEvent(NSAddAck ack) {
- if (ack.nsClientID != null) {
- uploadQueue.removeID(ack.json);
- MainApp.bus().post(new EventNSClientNewLog("DBADD", "Acked " + ack.nsClientID));
- } else {
- MainApp.bus().post(new EventNSClientNewLog("ERROR", "DBADD Unknown response"));
- }
+ RxBus.INSTANCE.send(new EventNSClientNewLog("ALARMACK ", alarmAck.level + " " + alarmAck.group + " " + alarmAck.silenceTime));
}
public void resend(final String reason) {
@@ -802,7 +814,7 @@ public class NSClientService extends Service {
}
lastResendTime = System.currentTimeMillis();
- MainApp.bus().post(new EventNSClientNewLog("QUEUE", "Resend started: " + reason));
+ RxBus.INSTANCE.send(new EventNSClientNewLog("QUEUE", "Resend started: " + reason));
CloseableIterator iterator = null;
int maxcount = 30;
@@ -833,7 +845,7 @@ public class NSClientService extends Service {
log.error("Unhandled exception", e);
}
- MainApp.bus().post(new EventNSClientNewLog("QUEUE", "Resend ended: " + reason));
+ RxBus.INSTANCE.send(new EventNSClientNewLog("QUEUE", "Resend ended: " + reason));
}
});
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.java
index 6d41303540..5c2a7cac84 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.java
@@ -3,7 +3,6 @@ package info.nightscout.androidaps.plugins.general.overview;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.NotificationManager;
-import android.arch.core.util.Function;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
@@ -12,14 +11,6 @@ import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.os.Handler;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentActivity;
-import android.support.v4.app.FragmentManager;
-import android.support.v4.content.res.ResourcesCompat;
-import android.support.v7.app.AlertDialog;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.PopupMenu;
-import android.support.v7.widget.RecyclerView;
import android.text.SpannableString;
import android.text.style.ForegroundColorSpan;
import android.util.DisplayMetrics;
@@ -34,15 +25,20 @@ import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
-import com.jjoe64.graphview.GraphView;
-import com.squareup.otto.Subscribe;
+import androidx.appcompat.app.AlertDialog;
+import androidx.appcompat.widget.PopupMenu;
+import androidx.core.content.res.ResourcesCompat;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentActivity;
+import androidx.fragment.app.FragmentManager;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.jjoe64.graphview.GraphView;
-import org.json.JSONException;
-import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.text.DecimalFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
@@ -55,13 +51,11 @@ 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.DetailedBolusInfo;
-import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus;
import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.Profile;
+import info.nightscout.androidaps.data.QuickWizard;
import info.nightscout.androidaps.data.QuickWizardEntry;
import info.nightscout.androidaps.db.BgReading;
-import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.db.DatabaseHelper;
import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.Source;
@@ -86,6 +80,7 @@ import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.aps.loop.APSResult;
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
import info.nightscout.androidaps.plugins.aps.loop.events.EventNewOpenLoopNotification;
+import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
import info.nightscout.androidaps.plugins.general.careportal.CareportalFragment;
@@ -93,25 +88,21 @@ import info.nightscout.androidaps.plugins.general.careportal.Dialogs.NewNSTreatm
import info.nightscout.androidaps.plugins.general.careportal.OptionsToShow;
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus;
-import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus;
+import info.nightscout.androidaps.plugins.general.overview.activities.QuickWizardListActivity;
import info.nightscout.androidaps.plugins.general.overview.dialogs.CalibrationDialog;
-import info.nightscout.androidaps.plugins.general.overview.dialogs.ErrorHelperActivity;
import info.nightscout.androidaps.plugins.general.overview.dialogs.NewCarbsDialog;
import info.nightscout.androidaps.plugins.general.overview.dialogs.NewInsulinDialog;
import info.nightscout.androidaps.plugins.general.overview.dialogs.NewTreatmentDialog;
import info.nightscout.androidaps.plugins.general.overview.dialogs.WizardDialog;
-import info.nightscout.androidaps.plugins.general.overview.activities.QuickWizardListActivity;
import info.nightscout.androidaps.plugins.general.overview.graphData.GraphData;
-import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationRecyclerViewAdapter;
-import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationStore;
import info.nightscout.androidaps.plugins.general.wear.ActionStringHandler;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensData;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.CobInfo;
+import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress;
-import info.nightscout.androidaps.plugins.source.SourceDexcomG5Plugin;
-import info.nightscout.androidaps.plugins.source.SourceDexcomG6Plugin;
+import info.nightscout.androidaps.plugins.source.SourceDexcomPlugin;
import info.nightscout.androidaps.plugins.source.SourceXdripPlugin;
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
import info.nightscout.androidaps.plugins.treatments.fragments.ProfileViewerDialog;
@@ -120,18 +111,23 @@ import info.nightscout.androidaps.utils.BolusWizard;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.DecimalFormatter;
import info.nightscout.androidaps.utils.DefaultValueHelper;
+import info.nightscout.androidaps.utils.FabricPrivacy;
import info.nightscout.androidaps.utils.OKDialog;
import info.nightscout.androidaps.utils.Profiler;
import info.nightscout.androidaps.utils.SP;
import info.nightscout.androidaps.utils.SingleClickButton;
import info.nightscout.androidaps.utils.T;
import info.nightscout.androidaps.utils.ToastUtils;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.disposables.CompositeDisposable;
import static info.nightscout.androidaps.utils.DateUtil.now;
public class OverviewFragment extends Fragment implements View.OnClickListener, View.OnLongClickListener {
private static Logger log = LoggerFactory.getLogger(L.OVERVIEW);
+ private CompositeDisposable disposable = new CompositeDisposable();
+
TextView timeView;
TextView bgView;
TextView arrowView;
@@ -197,7 +193,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
Handler sLoopHandler = new Handler();
Runnable sRefreshLoop = null;
- public enum CHARTTYPE {PRE, BAS, IOB, COB, DEV, SEN, DEVSLOPE}
+ public enum CHARTTYPE {PRE, BAS, IOB, COB, DEV, SEN, ACTPRIM, ACTSEC, DEVSLOPE}
private static final ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor();
private static ScheduledFuture> scheduledUpdate = null;
@@ -262,17 +258,17 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
apsModeView = (TextView) view.findViewById(R.id.overview_apsmode);
tempTargetView = (TextView) view.findViewById(R.id.overview_temptarget);
- iage = (TextView) view.findViewById(R.id.careportal_insulinage);
- cage = (TextView) view.findViewById(R.id.careportal_canulaage);
- sage = (TextView) view.findViewById(R.id.careportal_sensorage);
- pbage = (TextView) view.findViewById(R.id.careportal_pbage);
+ iage = view.findViewById(R.id.careportal_insulinage);
+ cage = view.findViewById(R.id.careportal_canulaage);
+ sage = view.findViewById(R.id.careportal_sensorage);
+ pbage = view.findViewById(R.id.careportal_pbage);
- iageView = (TextView) view.findViewById(R.id.overview_insulinage);
- cageView = (TextView) view.findViewById(R.id.overview_canulaage);
- reservoirView = (TextView) view.findViewById(R.id.overview_reservoirlevel);
- sageView = (TextView) view.findViewById(R.id.overview_sensorage);
- batteryView = (TextView) view.findViewById(R.id.overview_batterylevel);
- statuslightsLayout = (LinearLayout) view.findViewById(R.id.overview_statuslights);
+ iageView = view.findViewById(R.id.overview_insulinage);
+ cageView = view.findViewById(R.id.overview_canulaage);
+ reservoirView = view.findViewById(R.id.overview_reservoirlevel);
+ sageView = view.findViewById(R.id.overview_sensorage);
+ batteryView = view.findViewById(R.id.overview_batterylevel);
+ statuslightsLayout = view.findViewById(R.id.overview_statuslights);
bgGraph = (GraphView) view.findViewById(R.id.overview_bggraph);
iobGraph = (GraphView) view.findViewById(R.id.overview_iobgraph);
@@ -338,6 +334,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
rangeToDisplay = rangeToDisplay > 24 ? 6 : rangeToDisplay;
SP.putInt(R.string.key_rangetodisplay, rangeToDisplay);
updateGUI("rangeChange");
+ SP.putBoolean(R.string.key_objectiveusescale, true);
return false;
});
@@ -346,6 +343,117 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
return view;
}
+ @Override
+ public void onPause() {
+ super.onPause();
+ disposable.clear();
+ sLoopHandler.removeCallbacksAndMessages(null);
+ unregisterForContextMenu(apsModeView);
+ unregisterForContextMenu(activeProfileView);
+ unregisterForContextMenu(tempTargetView);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventRefreshOverview.class)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(eventOpenAPSUpdateGui -> scheduleUpdateGUI(eventOpenAPSUpdateGui.getFrom()),
+ FabricPrivacy::logException
+ ));
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventExtendedBolusChange.class)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(event -> scheduleUpdateGUI("EventExtendedBolusChange"),
+ FabricPrivacy::logException
+ ));
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventTempBasalChange.class)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(event -> scheduleUpdateGUI("EventTempBasalChange"),
+ FabricPrivacy::logException
+ ));
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventTreatmentChange.class)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(event -> scheduleUpdateGUI("EventTreatmentChange"),
+ FabricPrivacy::logException
+ ));
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventTempTargetChange.class)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(event -> scheduleUpdateGUI("EventTempTargetChange"),
+ FabricPrivacy::logException
+ ));
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventAcceptOpenLoopChange.class)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(event -> scheduleUpdateGUI("EventAcceptOpenLoopChange"),
+ FabricPrivacy::logException
+ ));
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventCareportalEventChange.class)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(event -> scheduleUpdateGUI("EventCareportalEventChange"),
+ FabricPrivacy::logException
+ ));
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventInitializationChanged.class)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(event -> scheduleUpdateGUI("EventInitializationChanged"),
+ FabricPrivacy::logException
+ ));
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventAutosensCalculationFinished.class)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(event -> scheduleUpdateGUI("EventAutosensCalculationFinished"),
+ FabricPrivacy::logException
+ ));
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventProfileNeedsUpdate.class)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(event -> scheduleUpdateGUI("EventProfileNeedsUpdate"),
+ FabricPrivacy::logException
+ ));
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventPreferenceChange.class)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(event -> scheduleUpdateGUI("EventPreferenceChange"),
+ FabricPrivacy::logException
+ ));
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventNewOpenLoopNotification.class)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(event -> scheduleUpdateGUI("EventNewOpenLoopNotification"),
+ FabricPrivacy::logException
+ ));
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventPumpStatusChanged.class)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(event -> updatePumpStatus(event.getStatus()),
+ FabricPrivacy::logException
+ ));
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventIobCalculationProgress.class)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(event -> {
+ if (iobCalculationProgressView != null)
+ iobCalculationProgressView.setText(event.getProgress());
+ },
+ FabricPrivacy::logException
+ ));
+ sRefreshLoop = () -> {
+ scheduleUpdateGUI("refreshLoop");
+ sLoopHandler.postDelayed(sRefreshLoop, 60 * 1000L);
+ };
+ sLoopHandler.postDelayed(sRefreshLoop, 60 * 1000L);
+ registerForContextMenu(apsModeView);
+ registerForContextMenu(activeProfileView);
+ registerForContextMenu(tempTargetView);
+ updateGUI("onResume");
+ }
+
private void setupChartMenu(View view) {
chartButton = (ImageButton) view.findViewById(R.id.overview_chartMenuButton);
chartButton.setOnClickListener(v -> {
@@ -358,14 +466,15 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
else
predictionsAvailable = false;
- MenuItem item;
+ MenuItem item, dividerItem;
CharSequence title;
+ int titleMaxChars = 0;
SpannableString s;
PopupMenu popup = new PopupMenu(v.getContext(), v);
-
if (predictionsAvailable) {
item = popup.getMenu().add(Menu.NONE, CHARTTYPE.PRE.ordinal(), Menu.NONE, "Predictions");
title = item.getTitle();
+ if (titleMaxChars < title.length()) titleMaxChars = title.length();
s = new SpannableString(title);
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.prediction, null)), 0, s.length(), 0);
item.setTitle(s);
@@ -375,14 +484,28 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
item = popup.getMenu().add(Menu.NONE, CHARTTYPE.BAS.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_basals));
title = item.getTitle();
+ if (titleMaxChars < title.length()) titleMaxChars = title.length();
s = new SpannableString(title);
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.basal, null)), 0, s.length(), 0);
item.setTitle(s);
item.setCheckable(true);
item.setChecked(SP.getBoolean("showbasals", true));
+ item = popup.getMenu().add(Menu.NONE, CHARTTYPE.ACTPRIM.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_activity));
+ title = item.getTitle();
+ if (titleMaxChars < title.length()) titleMaxChars = title.length();
+ s = new SpannableString(title);
+ s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.activity, null)), 0, s.length(), 0);
+ item.setTitle(s);
+ item.setCheckable(true);
+ item.setChecked(SP.getBoolean("showactivityprimary", true));
+
+ dividerItem = popup.getMenu().add("");
+ dividerItem.setEnabled(false);
+
item = popup.getMenu().add(Menu.NONE, CHARTTYPE.IOB.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_iob));
title = item.getTitle();
+ if (titleMaxChars < title.length()) titleMaxChars = title.length();
s = new SpannableString(title);
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.iob, null)), 0, s.length(), 0);
item.setTitle(s);
@@ -391,6 +514,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
item = popup.getMenu().add(Menu.NONE, CHARTTYPE.COB.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_cob));
title = item.getTitle();
+ if (titleMaxChars < title.length()) titleMaxChars = title.length();
s = new SpannableString(title);
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.cob, null)), 0, s.length(), 0);
item.setTitle(s);
@@ -399,6 +523,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
item = popup.getMenu().add(Menu.NONE, CHARTTYPE.DEV.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_deviations));
title = item.getTitle();
+ if (titleMaxChars < title.length()) titleMaxChars = title.length();
s = new SpannableString(title);
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.deviations, null)), 0, s.length(), 0);
item.setTitle(s);
@@ -407,15 +532,26 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
item = popup.getMenu().add(Menu.NONE, CHARTTYPE.SEN.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_sensitivity));
title = item.getTitle();
+ if (titleMaxChars < title.length()) titleMaxChars = title.length();
s = new SpannableString(title);
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.ratio, null)), 0, s.length(), 0);
item.setTitle(s);
item.setCheckable(true);
item.setChecked(SP.getBoolean("showratios", false));
+ item = popup.getMenu().add(Menu.NONE, CHARTTYPE.ACTSEC.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_activity));
+ title = item.getTitle();
+ if (titleMaxChars < title.length()) titleMaxChars = title.length();
+ s = new SpannableString(title);
+ s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.activity, null)), 0, s.length(), 0);
+ item.setTitle(s);
+ item.setCheckable(true);
+ item.setChecked(SP.getBoolean("showactivitysecondary", true));
+
if (MainApp.devBranch) {
item = popup.getMenu().add(Menu.NONE, CHARTTYPE.DEVSLOPE.ordinal(), Menu.NONE, "Deviation slope");
title = item.getTitle();
+ if (titleMaxChars < title.length()) titleMaxChars = title.length();
s = new SpannableString(title);
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.devslopepos, null)), 0, s.length(), 0);
item.setTitle(s);
@@ -423,6 +559,10 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
item.setChecked(SP.getBoolean("showdevslope", false));
}
+ // Fairly good guestimate for required divider text size...
+ title = new String(new char[titleMaxChars + 10]).replace("\0", "_");
+ dividerItem.setTitle(title);
+
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
@@ -438,6 +578,10 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
SP.putBoolean("showdeviations", !item.isChecked());
} else if (item.getItemId() == CHARTTYPE.SEN.ordinal()) {
SP.putBoolean("showratios", !item.isChecked());
+ } else if (item.getItemId() == CHARTTYPE.ACTPRIM.ordinal()) {
+ SP.putBoolean("showactivityprimary", !item.isChecked());
+ } else if (item.getItemId() == CHARTTYPE.ACTSEC.ordinal()) {
+ SP.putBoolean("showactivitysecondary", !item.isChecked());
} else if (item.getItemId() == CHARTTYPE.DEVSLOPE.ordinal()) {
SP.putBoolean("showdevslope", !item.isChecked());
}
@@ -509,8 +653,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
}
}
- private void showSuspendtPump(ContextMenu menu,
- PumpDescription pumpDescription) {
+ private void showSuspendtPump(ContextMenu menu, PumpDescription pumpDescription) {
if (pumpDescription.tempDurationStep15mAllowed)
menu.add(MainApp.gs(R.string.disconnectpumpfor15m));
if (pumpDescription.tempDurationStep30mAllowed)
@@ -560,6 +703,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
}
}
});
+ SP.putBoolean(R.string.key_objectiveusereconnect, true);
NSUpload.uploadOpenAPSOffline(0);
return true;
} else if (item.getTitle().equals(MainApp.gs(R.string.suspendloopfor1h))) {
@@ -588,6 +732,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
return true;
} else if (item.getTitle().equals(MainApp.gs(R.string.disconnectpumpfor1h))) {
LoopPlugin.getPlugin().disconnectPump(60, profile);
+ SP.putBoolean(R.string.key_objectiveusedisconnect, true);
updateGUI("suspendmenu");
return true;
} else if (item.getTitle().equals(MainApp.gs(R.string.disconnectpumpfor2h))) {
@@ -605,9 +750,14 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
newDialog.setOptions(profileswitch, R.string.careportal_profileswitch);
newDialog.show(getFragmentManager(), "NewNSTreatmentDialog");
} else if (item.getTitle().equals(MainApp.gs(R.string.danar_viewprofile))) {
- ProfileViewerDialog pvd = ProfileViewerDialog.newInstance(System.currentTimeMillis());
+ Bundle args = new Bundle();
+ args.putLong("time", DateUtil.now());
+ args.putInt("mode", ProfileViewerDialog.Mode.RUNNING_PROFILE.ordinal());
+ ProfileViewerDialog pvd = new ProfileViewerDialog();
+ pvd.setArguments(args);
FragmentManager manager = getFragmentManager();
- pvd.show(manager, "ProfileViewDialog");
+ if (manager != null)
+ pvd.show(manager, "ProfileViewDialog");
} else if (item.getTitle().equals(MainApp.gs(R.string.eatingsoon))) {
DefaultValueHelper defHelper = new DefaultValueHelper();
double target = defHelper.determineEatingSoonTT(profile.getUnits());
@@ -663,8 +813,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
@Override
public void onClick(View v) {
boolean xdrip = SourceXdripPlugin.getPlugin().isEnabled(PluginType.BGSOURCE);
- boolean g5 = SourceDexcomG5Plugin.getPlugin().isEnabled(PluginType.BGSOURCE);
- boolean g6 = SourceDexcomG6Plugin.getPlugin().isEnabled(PluginType.BGSOURCE);
+ boolean dexcom = SourceDexcomPlugin.INSTANCE.isEnabled(PluginType.BGSOURCE);
String units = ProfileFunctions.getInstance().getProfileUnits();
FragmentManager manager = getFragmentManager();
@@ -687,10 +836,16 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
if (xdrip) {
CalibrationDialog calibrationDialog = new CalibrationDialog();
calibrationDialog.show(manager, "CalibrationDialog");
- } else if (g5 || g6) {
+ } else if (dexcom) {
try {
- Intent i = new Intent("com.dexcom.cgm.activities.MeterEntryActivity");
- startActivity(i);
+ String packageName = SourceDexcomPlugin.INSTANCE.findDexcomPackageName();
+ if (packageName != null) {
+ Intent i = new Intent("com.dexcom.cgm.activities.MeterEntryActivity");
+ i.setPackage(packageName);
+ startActivity(i);
+ } else {
+ ToastUtils.showToastInUiThread(getActivity(), MainApp.gs(R.string.dexcom_app_not_installed));
+ }
} catch (ActivityNotFoundException e) {
ToastUtils.showToastInUiThread(getActivity(), MainApp.gs(R.string.g5appnotdetected));
}
@@ -699,14 +854,14 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
case R.id.overview_cgmbutton:
if (xdrip)
openCgmApp("com.eveningoutpost.dexdrip");
- else if (g5 && units.equals(Constants.MGDL))
- openCgmApp("com.dexcom.cgm.region5.mgdl");
- else if (g5 && units.equals(Constants.MMOL))
- openCgmApp("com.dexcom.cgm.region5.mmol");
- else if (g6 && units.equals(Constants.MGDL))
- openCgmApp("com.dexcom.g6.region3.mgdl");
- else if (g6 && units.equals(Constants.MMOL))
- openCgmApp("com.dexcom.g6.region3.mmol");
+ else if (dexcom) {
+ String packageName = SourceDexcomPlugin.INSTANCE.findDexcomPackageName();
+ if (packageName != null) {
+ openCgmApp(packageName);
+ } else {
+ ToastUtils.showToastInUiThread(getActivity(), MainApp.gs(R.string.dexcom_app_not_installed));
+ }
+ }
break;
case R.id.overview_treatmentbutton:
NewTreatmentDialog treatmentDialogFragment = new NewTreatmentDialog();
@@ -783,224 +938,25 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
void onClickQuickwizard() {
final BgReading actualBg = DatabaseHelper.actualBg();
final Profile profile = ProfileFunctions.getInstance().getProfile();
- final TempTarget tempTarget = TreatmentsPlugin.getPlugin().getTempTargetFromHistory();
+ final String profileName = ProfileFunctions.getInstance().getProfileName();
+ final PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
- final QuickWizardEntry quickWizardEntry = OverviewPlugin.getPlugin().quickWizard.getActive();
- if (quickWizardEntry != null && actualBg != null && profile != null) {
+ final QuickWizardEntry quickWizardEntry = QuickWizard.INSTANCE.getActive();
+ if (quickWizardEntry != null && actualBg != null && profile != null && pump != null) {
quickWizardButton.setVisibility(View.VISIBLE);
- final BolusWizard wizard = quickWizardEntry.doCalc(profile, tempTarget, actualBg, true);
+ final BolusWizard wizard = quickWizardEntry.doCalc(profile, profileName, actualBg, true);
- final JSONObject boluscalcJSON = new JSONObject();
- try {
- boluscalcJSON.put("eventTime", DateUtil.toISOString(new Date()));
- boluscalcJSON.put("targetBGLow", wizard.targetBGLow);
- boluscalcJSON.put("targetBGHigh", wizard.targetBGHigh);
- boluscalcJSON.put("isf", wizard.sens);
- boluscalcJSON.put("ic", wizard.ic);
- boluscalcJSON.put("iob", -(wizard.insulingFromBolusIOB + wizard.insulingFromBasalsIOB));
- boluscalcJSON.put("bolusiobused", true);
- boluscalcJSON.put("basaliobused", true);
- boluscalcJSON.put("bg", actualBg.valueToUnits(profile.getUnits()));
- boluscalcJSON.put("insulinbg", wizard.insulinFromBG);
- boluscalcJSON.put("insulinbgused", true);
- boluscalcJSON.put("bgdiff", wizard.bgDiff);
- boluscalcJSON.put("insulincarbs", wizard.insulinFromCarbs);
- boluscalcJSON.put("carbs", quickWizardEntry.carbs());
- boluscalcJSON.put("othercorrection", 0d);
- boluscalcJSON.put("insulintrend", wizard.insulinFromTrend);
- boluscalcJSON.put("insulin", wizard.calculatedTotalInsulin);
- } catch (JSONException e) {
- log.error("Unhandled exception", e);
- }
- if (wizard.calculatedTotalInsulin > 0d && quickWizardEntry.carbs() > 0d) {
- DecimalFormat formatNumber2decimalplaces = new DecimalFormat("0.00");
- String confirmMessage = MainApp.gs(R.string.entertreatmentquestion);
-
- Double insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(wizard.calculatedTotalInsulin)).value();
+ if (wizard.getCalculatedTotalInsulin() > 0d && quickWizardEntry.carbs() > 0d) {
Integer carbsAfterConstraints = MainApp.getConstraintChecker().applyCarbsConstraints(new Constraint<>(quickWizardEntry.carbs())).value();
- confirmMessage += "\n" + MainApp.gs(R.string.bolus) + ": " + formatNumber2decimalplaces.format(insulinAfterConstraints) + "U";
- confirmMessage += "\n" + MainApp.gs(R.string.carbs) + ": " + carbsAfterConstraints + "g";
-
- if (Math.abs(insulinAfterConstraints - wizard.calculatedTotalInsulin) >= 0.01 || !carbsAfterConstraints.equals(quickWizardEntry.carbs())) {
- AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
- builder.setTitle(MainApp.gs(R.string.treatmentdeliveryerror));
- builder.setMessage(MainApp.gs(R.string.constraints_violation) + "\n" + MainApp.gs(R.string.changeyourinput));
- builder.setPositiveButton(MainApp.gs(R.string.ok), null);
- builder.show();
+ if (Math.abs(wizard.getInsulinAfterConstraints() - wizard.getCalculatedTotalInsulin()) >= pump.getPumpDescription().pumpType.determineCorrectBolusStepSize(wizard.getInsulinAfterConstraints()) || !carbsAfterConstraints.equals(quickWizardEntry.carbs())) {
+ OKDialog.show(getContext(), MainApp.gs(R.string.treatmentdeliveryerror), MainApp.gs(R.string.constraints_violation) + "\n" + MainApp.gs(R.string.changeyourinput), null);
return;
}
- final Double finalInsulinAfterConstraints = insulinAfterConstraints;
- final Integer finalCarbsAfterConstraints = carbsAfterConstraints;
- final Context context = getContext();
- final AlertDialog.Builder builder = new AlertDialog.Builder(context);
- accepted = false;
- builder.setTitle(MainApp.gs(R.string.confirmation));
- builder.setMessage(confirmMessage);
- builder.setPositiveButton(MainApp.gs(R.string.ok), (dialog, id) -> {
- synchronized (builder) {
- if (accepted) {
- if (L.isEnabled(L.OVERVIEW))
- log.debug("guarding: already accepted");
- return;
- }
- accepted = true;
- if (Math.abs(insulinAfterConstraints - wizard.calculatedTotalInsulin) >= 0.01 || finalCarbsAfterConstraints > 0) {
- if (wizard.superBolus) {
- final LoopPlugin loopPlugin = LoopPlugin.getPlugin();
- if (loopPlugin.isEnabled(PluginType.LOOP)) {
- loopPlugin.superBolusTo(System.currentTimeMillis() + T.hours(2).msecs());
- MainApp.bus().post(new EventRefreshOverview("WizardDialog"));
- }
- ConfigBuilderPlugin.getPlugin().getCommandQueue().tempBasalPercent(0, 120, true, profile, new Callback() {
- @Override
- public void run() {
- if (!result.success) {
- Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
- i.putExtra("soundid", R.raw.boluserror);
- i.putExtra("status", result.comment);
- i.putExtra("title", MainApp.gs(R.string.tempbasaldeliveryerror));
- i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- MainApp.instance().startActivity(i);
- }
- }
- });
- }
- DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
- detailedBolusInfo.eventType = CareportalEvent.BOLUSWIZARD;
- detailedBolusInfo.insulin = finalInsulinAfterConstraints;
- detailedBolusInfo.carbs = finalCarbsAfterConstraints;
- detailedBolusInfo.context = context;
- detailedBolusInfo.boluscalc = boluscalcJSON;
- detailedBolusInfo.source = Source.USER;
- if (finalInsulinAfterConstraints > 0 || ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().storesCarbInfo) {
- ConfigBuilderPlugin.getPlugin().getCommandQueue().bolus(detailedBolusInfo, new Callback() {
- @Override
- public void run() {
- if (!result.success) {
- Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
- i.putExtra("soundid", R.raw.boluserror);
- i.putExtra("status", result.comment);
- i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror));
- i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- MainApp.instance().startActivity(i);
- }
- }
- });
- } else {
- TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false);
- }
- }
- }
- });
- builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
- builder.show();
+ wizard.confirmAndExecute(getContext());
}
}
-
- }
-
- @Override
- public void onPause() {
- super.onPause();
- MainApp.bus().unregister(this);
- sLoopHandler.removeCallbacksAndMessages(null);
- unregisterForContextMenu(apsModeView);
- unregisterForContextMenu(activeProfileView);
- unregisterForContextMenu(tempTargetView);
- }
-
- @Override
- public void onResume() {
- super.onResume();
- MainApp.bus().register(this);
- sRefreshLoop = () -> {
- scheduleUpdateGUI("refreshLoop");
- sLoopHandler.postDelayed(sRefreshLoop, 60 * 1000L);
- };
- sLoopHandler.postDelayed(sRefreshLoop, 60 * 1000L);
- registerForContextMenu(apsModeView);
- registerForContextMenu(activeProfileView);
- registerForContextMenu(tempTargetView);
- updateGUI("onResume");
- }
-
- @Subscribe
- public void onStatusEvent(final EventInitializationChanged ev) {
- scheduleUpdateGUI("EventInitializationChanged");
- }
-
- @Subscribe
- public void onStatusEvent(final EventPreferenceChange ev) {
- scheduleUpdateGUI("EventPreferenceChange");
- }
-
- @Subscribe
- public void onStatusEvent(final EventRefreshOverview ev) {
- scheduleUpdateGUI(ev.from);
- }
-
- @Subscribe
- public void onStatusEvent(final EventAutosensCalculationFinished ev) {
- scheduleUpdateGUI("EventAutosensCalculationFinished");
- }
-
- @Subscribe
- public void onStatusEvent(final EventTreatmentChange ev) {
- scheduleUpdateGUI("EventTreatmentChange");
- }
-
- @Subscribe
- public void onStatusEvent(final EventCareportalEventChange ev) {
- scheduleUpdateGUI("EventCareportalEventChange");
- }
-
- @Subscribe
- public void onStatusEvent(final EventTempBasalChange ev) {
- scheduleUpdateGUI("EventTempBasalChange");
- }
-
- @Subscribe
- public void onStatusEvent(final EventExtendedBolusChange ev) {
- scheduleUpdateGUI("EventExtendedBolusChange");
- }
-
- @Subscribe
- public void onStatusEvent(final EventNewOpenLoopNotification ev) {
- scheduleUpdateGUI("EventNewOpenLoopNotification");
- }
-
- @Subscribe
- public void onStatusEvent(final EventAcceptOpenLoopChange ev) {
- scheduleUpdateGUI("EventAcceptOpenLoopChange");
- }
-
- @Subscribe
- public void onStatusEvent(final EventTempTargetChange ev) {
- scheduleUpdateGUI("EventTempTargetChange");
- }
-
- @Subscribe
- public void onStatusEvent(final EventProfileNeedsUpdate ev) {
- scheduleUpdateGUI("EventProfileNeedsUpdate");
- }
-
- @Subscribe
- public void onStatusEvent(final EventPumpStatusChanged s) {
- Activity activity = getActivity();
- if (activity != null)
- activity.runOnUiThread(() -> updatePumpStatus(s.textStatus()));
- }
-
- @Subscribe
- public void onStatusEvent(final EventIobCalculationProgress e) {
- Activity activity = getActivity();
- if (activity != null)
- activity.runOnUiThread(() -> {
- if (iobCalculationProgressView != null)
- iobCalculationProgressView.setText(e.progress);
- });
}
private void hideTempRecommendation() {
@@ -1064,7 +1020,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
timeView.setText(DateUtil.timeString(new Date()));
}
- updateNotifications();
+ OverviewPlugin.INSTANCE.getNotificationStore().updateNotifications(notificationsView);
pumpStatusLayout.setVisibility(View.GONE);
loopStatusLayout.setVisibility(View.GONE);
@@ -1083,10 +1039,11 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
final PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
final Profile profile = ProfileFunctions.getInstance().getProfile();
+ final String profileName = ProfileFunctions.getInstance().getProfileName();
final String units = profile.getUnits();
- final double lowLine = OverviewPlugin.getPlugin().determineLowLine(units);
- final double highLine = OverviewPlugin.getPlugin().determineHighLine(units);
+ final double lowLine = OverviewPlugin.INSTANCE.determineLowLine(units);
+ final double highLine = OverviewPlugin.INSTANCE.determineHighLine(units);
//Start with updating the BG as it is unaffected by loop.
// **** BG value ****
@@ -1189,11 +1146,11 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
}
// **** Calibration & CGM buttons ****
- boolean xDripIsBgSource = MainApp.getSpecificPlugin(SourceXdripPlugin.class) != null && MainApp.getSpecificPlugin(SourceXdripPlugin.class).isEnabled(PluginType.BGSOURCE);
- boolean g5IsBgSource = MainApp.getSpecificPlugin(SourceDexcomG5Plugin.class) != null && MainApp.getSpecificPlugin(SourceDexcomG5Plugin.class).isEnabled(PluginType.BGSOURCE);
+ boolean xDripIsBgSource = SourceXdripPlugin.getPlugin().isEnabled(PluginType.BGSOURCE);
+ boolean dexcomIsSource = SourceDexcomPlugin.INSTANCE.isEnabled(PluginType.BGSOURCE);
boolean bgAvailable = DatabaseHelper.actualBg() != null;
if (calibrationButton != null) {
- if ((xDripIsBgSource || g5IsBgSource) && bgAvailable && SP.getBoolean(R.string.key_show_calibration_button, true)) {
+ if ((xDripIsBgSource || dexcomIsSource) && bgAvailable && SP.getBoolean(R.string.key_show_calibration_button, true)) {
calibrationButton.setVisibility(View.VISIBLE);
} else {
calibrationButton.setVisibility(View.GONE);
@@ -1202,7 +1159,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
if (cgmButton != null) {
if (xDripIsBgSource && SP.getBoolean(R.string.key_show_cgm_button, false)) {
cgmButton.setVisibility(View.VISIBLE);
- } else if (g5IsBgSource && SP.getBoolean(R.string.key_show_cgm_button, false)) {
+ } else if (dexcomIsSource && SP.getBoolean(R.string.key_show_cgm_button, false)) {
cgmButton.setVisibility(View.VISIBLE);
} else {
cgmButton.setVisibility(View.GONE);
@@ -1276,14 +1233,14 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
}
// QuickWizard button
- QuickWizardEntry quickWizardEntry = OverviewPlugin.getPlugin().quickWizard.getActive();
+ QuickWizardEntry quickWizardEntry = QuickWizard.INSTANCE.getActive();
if (quickWizardEntry != null && lastBG != null && pump.isInitialized() && !pump.isSuspended()) {
quickWizardButton.setVisibility(View.VISIBLE);
String text = quickWizardEntry.buttonText() + "\n" + DecimalFormatter.to0Decimal(quickWizardEntry.carbs()) + "g";
- BolusWizard wizard = quickWizardEntry.doCalc(profile, tempTarget, lastBG, false);
- text += " " + DecimalFormatter.toPumpSupportedBolus(wizard.calculatedTotalInsulin) + "U";
+ BolusWizard wizard = quickWizardEntry.doCalc(profile, profileName, lastBG, false);
+ text += " " + DecimalFormatter.toPumpSupportedBolus(wizard.getCalculatedTotalInsulin()) + "U";
quickWizardButton.setText(text);
- if (wizard.calculatedTotalInsulin <= 0)
+ if (wizard.getCalculatedTotalInsulin() <= 0)
quickWizardButton.setVisibility(View.GONE);
} else
quickWizardButton.setVisibility(View.GONE);
@@ -1378,55 +1335,19 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
cobView.setText(cobText);
}
- if (statuslightsLayout != null) {
+ if (statuslightsLayout != null)
if (SP.getBoolean(R.string.key_show_statuslights, false)) {
- CareportalEvent careportalEvent;
- NSSettingsStatus nsSettings = new NSSettingsStatus().getInstance();
- double iageUrgent = nsSettings.getExtendedWarnValue("iage", "urgent", 96);
- double iageWarn = nsSettings.getExtendedWarnValue("iage", "warn", 72);
- double cageUrgent = nsSettings.getExtendedWarnValue("cage", "urgent", 72);
- double cageWarn = nsSettings.getExtendedWarnValue("cage", "warn", 48);
- double sageUrgent = nsSettings.getExtendedWarnValue("sage", "urgent", 166);
- double sageWarn = nsSettings.getExtendedWarnValue("sage", "warn", 164);
- //double pbageUrgent = nsSettings.getExtendedWarnValue("pgage", "urgent", 360);
- //double pbageWarn = nsSettings.getExtendedWarnValue("pgage", "warn", 240);
- double batUrgent = SP.getDouble(R.string.key_statuslights_bat_critical, 5.0);
- double batWarn = SP.getDouble(R.string.key_statuslights_bat_warning, 25.0);
- double resUrgent = SP.getDouble(R.string.key_statuslights_res_critical, 10.0);
- double resWarn = SP.getDouble(R.string.key_statuslights_res_warning, 80.0);
-
- if (cageView != null) {
- careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.SITECHANGE);
- double canAge = careportalEvent != null ? careportalEvent.getHoursFromStart() : Double.MAX_VALUE;
- applyStatuslight(cageView, "CAN", canAge, cageWarn, cageUrgent, Double.MAX_VALUE, true);
+ StatuslightHandler handler = new StatuslightHandler();
+ if (SP.getBoolean(R.string.key_show_statuslights_extended, false)) {
+ handler.extendedStatuslight(cageView, iageView, reservoirView, sageView, batteryView);
+ statuslightsLayout.setVisibility(View.VISIBLE);
+ } else {
+ handler.statuslight(cageView, iageView, reservoirView, sageView, batteryView);
+ statuslightsLayout.setVisibility(View.VISIBLE);
}
-
- if (iageView != null) {
- careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.INSULINCHANGE);
- double insulinAge = careportalEvent != null ? careportalEvent.getHoursFromStart() : Double.MAX_VALUE;
- applyStatuslight(iageView, "INS", insulinAge, iageWarn, iageUrgent, Double.MAX_VALUE, true);
- }
-
- if (reservoirView != null) {
- double reservoirLevel = pump.isInitialized() ? pump.getReservoirLevel() : -1;
- applyStatuslight(reservoirView, "RES", reservoirLevel, resWarn, resUrgent, -1, false);
- }
-
- if (sageView != null) {
- careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.SENSORCHANGE);
- double sensorAge = careportalEvent != null ? careportalEvent.getHoursFromStart() : Double.MAX_VALUE;
- applyStatuslight(sageView, "SEN", sensorAge, sageWarn, sageUrgent, Double.MAX_VALUE, true);
- }
-
- if (batteryView != null) {
- double batteryLevel = pump.isInitialized() ? pump.getBatteryLevel() : -1;
- applyStatuslight(batteryView, "BAT", batteryLevel, batWarn, batUrgent, -1, false);
- }
- statuslightsLayout.setVisibility(View.VISIBLE);
} else {
statuslightsLayout.setVisibility(View.GONE);
}
- }
boolean predictionsAvailable;
if (Config.APS)
@@ -1526,6 +1447,10 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
// Treatments
graphData.addTreatments(fromTime, endTime);
+ if (SP.getBoolean("showactivityprimary", true)) {
+ graphData.addActivity(fromTime, endTime, false, 0.8d);
+ }
+
// add basal data
if (pump.getPumpDescription().isTempBasalCapable && SP.getBoolean("showbasals", true)) {
graphData.addBasals(fromTime, now, lowLine / graphData.maxY / 1.2d);
@@ -1548,6 +1473,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
boolean useDevForScale = false;
boolean useRatioForScale = false;
boolean useDSForScale = false;
+ boolean useIAForScale = false;
if (SP.getBoolean("showiob", true)) {
useIobForScale = true;
@@ -1557,18 +1483,22 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
useDevForScale = true;
} else if (SP.getBoolean("showratios", false)) {
useRatioForScale = true;
+ } else if (SP.getBoolean("showactivitysecondary", false)) {
+ useIAForScale = true;
} else if (SP.getBoolean("showdevslope", false)) {
useDSForScale = true;
}
if (SP.getBoolean("showiob", true))
- secondGraphData.addIob(fromTime, now, useIobForScale, 1d);
+ secondGraphData.addIob(fromTime, now, useIobForScale, 1d, SP.getBoolean("showprediction", false));
if (SP.getBoolean("showcob", true))
secondGraphData.addCob(fromTime, now, useCobForScale, useCobForScale ? 1d : 0.5d);
if (SP.getBoolean("showdeviations", false))
secondGraphData.addDeviations(fromTime, now, useDevForScale, 1d);
if (SP.getBoolean("showratios", false))
secondGraphData.addRatio(fromTime, now, useRatioForScale, 1d);
+ if (SP.getBoolean("showactivitysecondary", true))
+ secondGraphData.addActivity(fromTime, endTime, useIAForScale, 0.8d);
if (SP.getBoolean("showdevslope", false) && MainApp.devBranch)
secondGraphData.addDeviationSlope(fromTime, now, useDSForScale, 1d);
@@ -1585,6 +1515,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|| SP.getBoolean("showcob", true)
|| SP.getBoolean("showdeviations", false)
|| SP.getBoolean("showratios", false)
+ || SP.getBoolean("showactivitysecondary", false)
|| SP.getBoolean("showdevslope", false)) {
iobGraph.setVisibility(View.VISIBLE);
} else {
@@ -1603,36 +1534,5 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
Profiler.log(log, from, updateGUIStart);
}
- //Notifications
- void updateNotifications() {
- NotificationStore nstore = OverviewPlugin.getPlugin().notificationStore;
- nstore.removeExpired();
- nstore.unSnooze();
- if (nstore.store.size() > 0) {
- NotificationRecyclerViewAdapter adapter = new NotificationRecyclerViewAdapter(nstore.store);
- notificationsView.setAdapter(adapter);
- notificationsView.setVisibility(View.VISIBLE);
- } else {
- notificationsView.setVisibility(View.GONE);
- }
- }
-
- public static void applyStatuslight(TextView view, String text, double value, double warnThreshold, double urgentThreshold, double invalid, boolean checkAscending) {
- Function check = checkAscending ? (Double threshold) -> value >= threshold : (Double threshold) -> value <= threshold;
- if (value != invalid) {
- view.setText(text);
- if (check.apply(urgentThreshold)) {
- view.setTextColor(MainApp.gc(R.color.ribbonCritical));
- } else if (check.apply(warnThreshold)) {
- view.setTextColor(MainApp.gc(R.color.ribbonWarning));
- } else {
- view.setTextColor(MainApp.gc(R.color.ribbonDefault));
- }
- view.setVisibility(View.VISIBLE);
- } else {
- view.setVisibility(View.GONE);
- }
-
- }
-}
+}
\ No newline at end of file
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewPlugin.java
deleted file mode 100644
index b0981cc6ce..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewPlugin.java
+++ /dev/null
@@ -1,110 +0,0 @@
-package info.nightscout.androidaps.plugins.general.overview;
-
-import com.squareup.otto.Subscribe;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import info.nightscout.androidaps.MainApp;
-import info.nightscout.androidaps.R;
-import info.nightscout.androidaps.data.Profile;
-import info.nightscout.androidaps.data.QuickWizard;
-import info.nightscout.androidaps.events.EventRefreshOverview;
-import info.nightscout.androidaps.interfaces.PluginBase;
-import info.nightscout.androidaps.interfaces.PluginDescription;
-import info.nightscout.androidaps.interfaces.PluginType;
-import info.nightscout.androidaps.logging.L;
-import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
-import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification;
-import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification;
-import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationStore;
-import info.nightscout.androidaps.utils.SP;
-
-/**
- * Created by mike on 05.08.2016.
- */
-public class OverviewPlugin extends PluginBase {
- private static Logger log = LoggerFactory.getLogger(L.OVERVIEW);
-
- private static OverviewPlugin overviewPlugin = new OverviewPlugin();
-
- public static OverviewPlugin getPlugin() {
- if (overviewPlugin == null)
- overviewPlugin = new OverviewPlugin();
- return overviewPlugin;
- }
-
- public static double bgTargetLow = 80d;
- public static double bgTargetHigh = 180d;
-
- public QuickWizard quickWizard = new QuickWizard();
-
- public NotificationStore notificationStore = new NotificationStore();
-
- public OverviewPlugin() {
- super(new PluginDescription()
- .mainType(PluginType.GENERAL)
- .fragmentClass(OverviewFragment.class.getName())
- .alwayVisible(true)
- .alwaysEnabled(true)
- .pluginName(R.string.overview)
- .shortName(R.string.overview_shortname)
- .preferencesId(R.xml.pref_overview)
- .description(R.string.description_overview)
- );
- String storedData = SP.getString("QuickWizard", "[]");
- try {
- quickWizard.setData(new JSONArray(storedData));
- } catch (JSONException e) {
- log.error("Unhandled exception", e);
- }
- }
-
- @Override
- protected void onStart() {
- MainApp.bus().register(this);
- super.onStart();
- }
-
- @Override
- protected void onStop() {
- MainApp.bus().unregister(this);
- }
-
- @Subscribe
- public void onStatusEvent(final EventNewNotification n) {
- if (notificationStore.add(n.notification))
- MainApp.bus().post(new EventRefreshOverview("EventNewNotification"));
- }
-
- @Subscribe
- public void onStatusEvent(final EventDismissNotification n) {
- if (notificationStore.remove(n.id))
- MainApp.bus().post(new EventRefreshOverview("EventDismissNotification"));
- }
-
- public double determineHighLine(String units) {
- double highLineSetting = SP.getDouble("high_mark", Profile.fromMgdlToUnits(OverviewPlugin.bgTargetHigh, units));
- if (highLineSetting < 1)
- highLineSetting = Profile.fromMgdlToUnits(180d, units);
- return highLineSetting;
- }
-
- public double determineLowLine() {
- Profile profile = ProfileFunctions.getInstance().getProfile();
- if (profile == null) {
- return bgTargetLow;
- }
- return determineLowLine(profile.getUnits());
- }
-
- public double determineLowLine(String units) {
- double lowLineSetting = SP.getDouble("low_mark", Profile.fromMgdlToUnits(OverviewPlugin.bgTargetLow, units));
- if (lowLineSetting < 1)
- lowLineSetting = Profile.fromMgdlToUnits(76d, units);
- return lowLineSetting;
- }
-
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewPlugin.kt
new file mode 100644
index 0000000000..cece359f22
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewPlugin.kt
@@ -0,0 +1,86 @@
+package info.nightscout.androidaps.plugins.general.overview
+
+import info.nightscout.androidaps.MainApp
+import info.nightscout.androidaps.R
+import info.nightscout.androidaps.data.Profile
+import info.nightscout.androidaps.events.EventRefreshOverview
+import info.nightscout.androidaps.interfaces.PluginBase
+import info.nightscout.androidaps.interfaces.PluginDescription
+import info.nightscout.androidaps.interfaces.PluginType
+import info.nightscout.androidaps.logging.L
+import info.nightscout.androidaps.plugins.bus.RxBus
+import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions
+import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification
+import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
+import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationStore
+import info.nightscout.androidaps.utils.FabricPrivacy
+import info.nightscout.androidaps.utils.SP
+import info.nightscout.androidaps.utils.plusAssign
+import io.reactivex.disposables.CompositeDisposable
+import io.reactivex.schedulers.Schedulers
+import org.slf4j.LoggerFactory
+
+object OverviewPlugin : PluginBase(PluginDescription()
+ .mainType(PluginType.GENERAL)
+ .fragmentClass(OverviewFragment::class.qualifiedName)
+ .alwaysVisible(true)
+ .alwaysEnabled(true)
+ .pluginName(R.string.overview)
+ .shortName(R.string.overview_shortname)
+ .preferencesId(R.xml.pref_overview)
+ .description(R.string.description_overview)) {
+
+ private val log = LoggerFactory.getLogger(L.OVERVIEW)
+ private var disposable: CompositeDisposable = CompositeDisposable()
+
+ var bgTargetLow = 80.0
+ var bgTargetHigh = 180.0
+
+ var notificationStore = NotificationStore()
+
+ override fun onStart() {
+ super.onStart()
+ disposable += RxBus
+ .toObservable(EventNewNotification::class.java)
+ .observeOn(Schedulers.io())
+ .subscribe({ n ->
+ if (notificationStore.add(n.notification))
+ RxBus.send(EventRefreshOverview("EventNewNotification"))
+ }, {
+ FabricPrivacy.logException(it)
+ })
+ disposable += RxBus
+ .toObservable(EventDismissNotification::class.java)
+ .observeOn(Schedulers.io())
+ .subscribe({ n ->
+ if (notificationStore.remove(n.id))
+ RxBus.send(EventRefreshOverview("EventDismissNotification"))
+ }, {
+ FabricPrivacy.logException(it)
+ })
+ }
+
+ override fun onStop() {
+ disposable.clear()
+ super.onStop()
+ }
+
+ fun determineHighLine(units: String): Double {
+ var highLineSetting = SP.getDouble("high_mark", Profile.fromMgdlToUnits(bgTargetHigh, units))!!
+ if (highLineSetting < 1)
+ highLineSetting = Profile.fromMgdlToUnits(180.0, units)
+ return highLineSetting
+ }
+
+ fun determineLowLine(): Double {
+ val profile = ProfileFunctions.getInstance().profile ?: return bgTargetLow
+ return determineLowLine(profile.units)
+ }
+
+ fun determineLowLine(units: String): Double {
+ var lowLineSetting = SP.getDouble("low_mark", Profile.fromMgdlToUnits(bgTargetLow, units))!!
+ if (lowLineSetting < 1)
+ lowLineSetting = Profile.fromMgdlToUnits(76.0, units)
+ return lowLineSetting
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/StatuslightHandler.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/StatuslightHandler.java
new file mode 100644
index 0000000000..23c3fd2cec
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/StatuslightHandler.java
@@ -0,0 +1,135 @@
+package info.nightscout.androidaps.plugins.general.overview;
+
+import android.view.View;
+import android.widget.TextView;
+
+import androidx.arch.core.util.Function;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.db.CareportalEvent;
+import info.nightscout.androidaps.interfaces.PumpInterface;
+import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
+import info.nightscout.androidaps.plugins.general.careportal.CareportalFragment;
+import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus;
+import info.nightscout.androidaps.utils.DecimalFormatter;
+import info.nightscout.androidaps.utils.SP;
+import info.nightscout.androidaps.utils.SetWarnColor;
+
+class StatuslightHandler {
+
+ /**
+ * applies the statuslight subview on the overview fragement
+ */
+ void statuslight(TextView cageView, TextView iageView, TextView reservoirView,
+ TextView sageView, TextView batteryView) {
+ PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
+
+ applyStatuslight("cage", CareportalEvent.SITECHANGE, cageView, "CAN", 48, 72);
+ applyStatuslight("iage", CareportalEvent.INSULINCHANGE, iageView, "INS", 72, 96);
+
+ double reservoirLevel = pump.isInitialized() ? pump.getReservoirLevel() : -1;
+ applyStatuslightLevel(R.string.key_statuslights_res_critical, 10.0,
+ R.string.key_statuslights_res_warning, 80.0, reservoirView, "RES", reservoirLevel);
+
+ applyStatuslight("sage", CareportalEvent.SENSORCHANGE, sageView, "SEN", 164, 166);
+
+ double batteryLevel = pump.isInitialized() ? pump.getBatteryLevel() : -1;
+ applyStatuslightLevel(R.string.key_statuslights_bat_critical, 5.0,
+ R.string.key_statuslights_bat_warning, 22.0,
+ batteryView, "BAT", batteryLevel);
+
+ }
+
+ void applyStatuslight(String nsSettingPlugin, String eventName, TextView view, String text,
+ int defaultWarnThreshold, int defaultUrgentThreshold) {
+ NSSettingsStatus nsSettings = NSSettingsStatus.getInstance();
+
+ if (view != null) {
+ double urgent = nsSettings.getExtendedWarnValue(nsSettingPlugin, "urgent", defaultUrgentThreshold);
+ double warn = nsSettings.getExtendedWarnValue(nsSettingPlugin, "warn", defaultWarnThreshold);
+ CareportalEvent event = MainApp.getDbHelper().getLastCareportalEvent(eventName);
+ double age = event != null ? event.getHoursFromStart() : Double.MAX_VALUE;
+ applyStatuslight(view, text, age, warn, urgent, Double.MAX_VALUE, true);
+ }
+ }
+
+ void applyStatuslightLevel(int criticalSetting, double criticalDefaultValue,
+ int warnSetting, double warnDefaultValue,
+ TextView view, String text, double level) {
+ if (view != null) {
+ double resUrgent = SP.getDouble(criticalSetting, criticalDefaultValue);
+ double resWarn = SP.getDouble(warnSetting, warnDefaultValue);
+ applyStatuslight(view, text, level, resWarn, resUrgent, -1, false);
+ }
+ }
+
+ void applyStatuslight(TextView view, String text, double value, double warnThreshold,
+ double urgentThreshold, double invalid, boolean checkAscending) {
+ Function check = checkAscending ? (Double threshold) -> value >= threshold :
+ (Double threshold) -> value <= threshold;
+ if (value != invalid) {
+ view.setText(text);
+ if (check.apply(urgentThreshold)) {
+ view.setTextColor(MainApp.gc(R.color.ribbonCritical));
+ } else if (check.apply(warnThreshold)) {
+ view.setTextColor(MainApp.gc(R.color.ribbonWarning));
+ } else {
+ view.setTextColor(MainApp.gc(R.color.ribbonDefault));
+ }
+ view.setVisibility(View.VISIBLE);
+ } else {
+ view.setVisibility(View.GONE);
+ }
+
+ }
+
+ /**
+ * applies the extended statuslight subview on the overview fragement
+ */
+ void extendedStatuslight(TextView cageView, TextView iageView,
+ TextView reservoirView, TextView sageView,
+ TextView batteryView) {
+ PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
+
+ handleAge("cage", CareportalEvent.SITECHANGE, cageView, "CAN ",
+ 48, 72);
+
+ handleAge("iage", CareportalEvent.INSULINCHANGE, iageView, "INS ",
+ 72, 96);
+
+ handleLevel(R.string.key_statuslights_res_critical, 10.0,
+ R.string.key_statuslights_res_warning, 80.0,
+ reservoirView, "RES ", pump.getReservoirLevel());
+
+ handleAge("sage", CareportalEvent.SENSORCHANGE, sageView, "SEN ",
+ 164, 166);
+
+ handleLevel(R.string.key_statuslights_bat_critical, 26.0,
+ R.string.key_statuslights_bat_warning, 51.0,
+ batteryView, "BAT ", pump.getBatteryLevel());
+ }
+
+ void handleAge(String nsSettingPlugin, String eventName, TextView view, String text,
+ int defaultUrgentThreshold, int defaultWarnThreshold) {
+ NSSettingsStatus nsSettings = new NSSettingsStatus().getInstance();
+
+ if (view != null) {
+ double urgent = nsSettings.getExtendedWarnValue(nsSettingPlugin, "urgent", defaultUrgentThreshold);
+ double warn = nsSettings.getExtendedWarnValue(nsSettingPlugin, "warn", defaultWarnThreshold);
+ CareportalFragment.handleAge(view, text, eventName, warn, urgent, true);
+ }
+ }
+
+ void handleLevel(int criticalSetting, double criticalDefaultValue,
+ int warnSetting, double warnDefaultValue,
+ TextView view, String text, double level) {
+ if (view != null) {
+ double resUrgent = SP.getDouble(criticalSetting, criticalDefaultValue);
+ double resWarn = SP.getDouble(warnSetting, warnDefaultValue);
+ view.setText(text + DecimalFormatter.to0Decimal(level));
+ SetWarnColor.setColorInverse(view, level, resWarn, resUrgent);
+ }
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/activities/QuickWizardListActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/activities/QuickWizardListActivity.java
deleted file mode 100644
index d7eb9c86dd..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/activities/QuickWizardListActivity.java
+++ /dev/null
@@ -1,172 +0,0 @@
-package info.nightscout.androidaps.plugins.general.overview.activities;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.support.v4.app.FragmentManager;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.CardView;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.TextView;
-
-import com.squareup.otto.Subscribe;
-
-import info.nightscout.androidaps.MainApp;
-import info.nightscout.androidaps.R;
-import info.nightscout.androidaps.data.QuickWizard;
-import info.nightscout.androidaps.plugins.general.overview.dialogs.EditQuickWizardDialog;
-import info.nightscout.androidaps.plugins.general.overview.OverviewPlugin;
-import info.nightscout.androidaps.plugins.general.overview.events.EventQuickWizardChange;
-import info.nightscout.androidaps.utils.DateUtil;
-import info.nightscout.androidaps.utils.DecimalFormatter;
-
-public class QuickWizardListActivity extends AppCompatActivity implements View.OnClickListener {
-
- RecyclerView recyclerView;
- LinearLayoutManager llm;
-
- Button adButton;
-
- public static class RecyclerViewAdapter extends RecyclerView.Adapter {
-
- QuickWizard qvData;
- FragmentManager fragmentManager;
-
- RecyclerViewAdapter(QuickWizard data, FragmentManager fragmentManager) {
- this.qvData = data;
- this.fragmentManager = fragmentManager;
- }
-
- @Override
- public QuickWizardEntryViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
- View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.overview_quickwizardlist_item, viewGroup, false);
- QuickWizardEntryViewHolder quickWizardEntryViewHolder = new QuickWizardEntryViewHolder(v, fragmentManager, qvData);
- return quickWizardEntryViewHolder;
- }
-
- @Override
- public void onBindViewHolder(QuickWizardEntryViewHolder holder, int position) {
- holder.from.setText(DateUtil.timeString(qvData.get(position).validFromDate()));
- holder.to.setText(DateUtil.timeString(qvData.get(position).validToDate()));
- holder.buttonText.setText(qvData.get(position).buttonText());
- holder.carbs.setText(DecimalFormatter.to0Decimal(qvData.get(position).carbs()) + " g");
- }
-
- @Override
- public int getItemCount() {
- return qvData.size();
- }
-
- @Override
- public void onAttachedToRecyclerView(RecyclerView recyclerView) {
- super.onAttachedToRecyclerView(recyclerView);
- }
-
- public static class QuickWizardEntryViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
- CardView cv;
- TextView buttonText;
- TextView carbs;
- TextView from;
- TextView to;
- Button editButton;
- Button removeButton;
- FragmentManager fragmentManager;
- QuickWizard qvData;
-
- QuickWizardEntryViewHolder(View itemView, FragmentManager fragmentManager, QuickWizard qvData) {
- super(itemView);
- cv = (CardView) itemView.findViewById(R.id.overview_quickwizard_cardview);
- buttonText = (TextView) itemView.findViewById(R.id.overview_quickwizard_item_buttonText);
- carbs = (TextView) itemView.findViewById(R.id.overview_quickwizard_item_carbs);
- from = (TextView) itemView.findViewById(R.id.overview_quickwizard_item_from);
- to = (TextView) itemView.findViewById(R.id.overview_quickwizard_item_to);
- editButton = (Button) itemView.findViewById(R.id.overview_quickwizard_item_edit_button);
- removeButton = (Button) itemView.findViewById(R.id.overview_quickwizard_item_remove_button);
- editButton.setOnClickListener(this);
- removeButton.setOnClickListener(this);
- this.fragmentManager = fragmentManager;
- this.qvData = qvData;
- }
-
- @Override
- public void onClick(View v) {
- int position = getAdapterPosition();
- switch (v.getId()) {
- case R.id.overview_quickwizard_item_edit_button:
- FragmentManager manager = fragmentManager;
- EditQuickWizardDialog editQuickWizardDialog = new EditQuickWizardDialog();
- editQuickWizardDialog.setData(qvData.get(position));
- editQuickWizardDialog.show(manager, "EditQuickWizardDialog");
- break;
- case R.id.overview_quickwizard_item_remove_button:
- qvData.remove(position);
- MainApp.bus().post(new EventQuickWizardChange());
- break;
- }
- }
- }
- }
-
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.overview_quickwizardlist_activity);
-
- recyclerView = (RecyclerView) findViewById(R.id.overview_quickwizardactivity_recyclerview);
- recyclerView.setHasFixedSize(true);
- llm = new LinearLayoutManager(this);
- recyclerView.setLayoutManager(llm);
-
- RecyclerViewAdapter adapter = new RecyclerViewAdapter(MainApp.getSpecificPlugin(OverviewPlugin.class).quickWizard, getSupportFragmentManager());
- recyclerView.setAdapter(adapter);
-
- adButton = (Button) findViewById(R.id.overview_quickwizardactivity_add_button);
- adButton.setOnClickListener(this);
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- MainApp.bus().register(this);
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- MainApp.bus().unregister(this);
- }
-
- @Override
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id.overview_quickwizardactivity_add_button:
- FragmentManager manager = getSupportFragmentManager();
- EditQuickWizardDialog editQuickWizardDialog = new EditQuickWizardDialog();
- editQuickWizardDialog.show(manager, "EditQuickWizardDialog");
- break;
- }
- }
-
- @Subscribe
- public void onStatusEvent(final EventQuickWizardChange ev) {
- updateGUI();
- }
-
- public void updateGUI() {
- Activity activity = this;
- if (activity != null && recyclerView != null) {
- activity.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- RecyclerViewAdapter adapter = new RecyclerViewAdapter(MainApp.getSpecificPlugin(OverviewPlugin.class).quickWizard, getSupportFragmentManager());
- recyclerView.swapAdapter(adapter, false);
- }
- });
- }
- }
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/activities/QuickWizardListActivity.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/activities/QuickWizardListActivity.kt
new file mode 100644
index 0000000000..9aa1e29978
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/activities/QuickWizardListActivity.kt
@@ -0,0 +1,100 @@
+package info.nightscout.androidaps.plugins.general.overview.activities
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Button
+import android.widget.TextView
+import androidx.fragment.app.FragmentManager
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import info.nightscout.androidaps.R
+import info.nightscout.androidaps.activities.NoSplashAppCompatActivity
+import info.nightscout.androidaps.data.QuickWizard
+import info.nightscout.androidaps.plugins.bus.RxBus
+import info.nightscout.androidaps.plugins.general.overview.dialogs.EditQuickWizardDialog
+import info.nightscout.androidaps.plugins.general.overview.events.EventQuickWizardChange
+import info.nightscout.androidaps.utils.DateUtil
+import info.nightscout.androidaps.utils.DecimalFormatter
+import info.nightscout.androidaps.utils.FabricPrivacy
+import info.nightscout.androidaps.utils.plusAssign
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.disposables.CompositeDisposable
+import kotlinx.android.synthetic.main.overview_quickwizardlist_activity.*
+
+class QuickWizardListActivity : NoSplashAppCompatActivity() {
+
+ private var disposable: CompositeDisposable = CompositeDisposable()
+
+ private inner class RecyclerViewAdapter internal constructor(internal var fragmentManager: FragmentManager) : RecyclerView.Adapter() {
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QuickWizardEntryViewHolder {
+ return QuickWizardEntryViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.overview_quickwizardlist_item, parent, false), fragmentManager)
+ }
+
+ override fun onBindViewHolder(holder: QuickWizardEntryViewHolder, position: Int) {
+ holder.from.text = DateUtil.timeString(QuickWizard[position].validFromDate())
+ holder.to.text = DateUtil.timeString(QuickWizard[position].validToDate())
+ holder.buttonText.text = QuickWizard[position].buttonText()
+ holder.carbs.text = DecimalFormatter.to0Decimal(QuickWizard[position].carbs().toDouble()) + " g"
+ }
+
+ override fun getItemCount(): Int = QuickWizard.size()
+
+ private inner class QuickWizardEntryViewHolder internal constructor(itemView: View, internal var fragmentManager: FragmentManager) : RecyclerView.ViewHolder(itemView) {
+ val buttonText: TextView = itemView.findViewById(R.id.overview_quickwizard_item_buttonText)
+ val carbs: TextView = itemView.findViewById(R.id.overview_quickwizard_item_carbs)
+ val from: TextView = itemView.findViewById(R.id.overview_quickwizard_item_from)
+ val to: TextView = itemView.findViewById(R.id.overview_quickwizard_item_to)
+ private val editButton: Button = itemView.findViewById(R.id.overview_quickwizard_item_edit_button)
+ private val removeButton: Button = itemView.findViewById(R.id.overview_quickwizard_item_remove_button)
+
+ init {
+ editButton.setOnClickListener {
+ val manager = fragmentManager
+ val editQuickWizardDialog = EditQuickWizardDialog()
+ editQuickWizardDialog.entry = QuickWizard[adapterPosition]
+ editQuickWizardDialog.show(manager, "EditQuickWizardDialog")
+ }
+ removeButton.setOnClickListener {
+ QuickWizard.remove(adapterPosition)
+ RxBus.send(EventQuickWizardChange())
+ }
+ }
+ }
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.overview_quickwizardlist_activity)
+
+ overview_quickwizardactivity_recyclerview?.setHasFixedSize(true)
+ overview_quickwizardactivity_recyclerview?.layoutManager = LinearLayoutManager(this)
+ overview_quickwizardactivity_recyclerview?.adapter = RecyclerViewAdapter(supportFragmentManager)
+
+ overview_quickwizardactivity_add_button.setOnClickListener {
+ val manager = supportFragmentManager
+ val editQuickWizardDialog = EditQuickWizardDialog()
+ editQuickWizardDialog.show(manager, "EditQuickWizardDialog")
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ disposable += RxBus
+ .toObservable(EventQuickWizardChange::class.java)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe({
+ val adapter = RecyclerViewAdapter(supportFragmentManager)
+ overview_quickwizardactivity_recyclerview?.swapAdapter(adapter, false)
+ }, {
+ FabricPrivacy.logException(it)
+ })
+ }
+
+ override fun onPause() {
+ disposable.clear()
+ super.onPause()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/BolusProgressDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/BolusProgressDialog.java
index 4189fcdcdb..645f6d2b19 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/BolusProgressDialog.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/BolusProgressDialog.java
@@ -4,7 +4,6 @@ package info.nightscout.androidaps.plugins.general.overview.dialogs;
import android.app.Activity;
import android.os.Bundle;
import android.os.SystemClock;
-import android.support.v4.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -12,7 +11,8 @@ import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
-import com.squareup.otto.Subscribe;
+import androidx.annotation.NonNull;
+import androidx.fragment.app.DialogFragment;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -21,12 +21,18 @@ import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.events.EventPumpStatusChanged;
import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
-import info.nightscout.androidaps.plugins.general.overview.events.EventDismissBolusprogressIfRunning;
+import info.nightscout.androidaps.plugins.general.overview.events.EventDismissBolusProgressIfRunning;
import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress;
+import info.nightscout.androidaps.utils.FabricPrivacy;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.disposables.CompositeDisposable;
public class BolusProgressDialog extends DialogFragment implements View.OnClickListener {
private static Logger log = LoggerFactory.getLogger(L.UI);
+ private CompositeDisposable disposable = new CompositeDisposable();
+
Button stopButton;
TextView statusView;
TextView stopPressedView;
@@ -38,6 +44,9 @@ public class BolusProgressDialog extends DialogFragment implements View.OnClickL
public static boolean running = true;
public static boolean stopPressed = false;
+ private String state;
+ private final static String DEFAULT_STATE = MainApp.gs(R.string.waitingforpump);
+
public BolusProgressDialog() {
super();
}
@@ -62,7 +71,8 @@ public class BolusProgressDialog extends DialogFragment implements View.OnClickL
progressBar = view.findViewById(R.id.overview_bolusprogress_progressbar);
stopButton.setOnClickListener(this);
progressBar.setMax(100);
- statusView.setText(MainApp.gs(R.string.waitingforpump));
+ state = savedInstanceState != null ? savedInstanceState.getString("state", DEFAULT_STATE) : DEFAULT_STATE;
+ statusView.setText(state);
setCancelable(false);
stopPressed = false;
return view;
@@ -81,11 +91,38 @@ public class BolusProgressDialog extends DialogFragment implements View.OnClickL
} else {
if (getDialog() != null)
getDialog().getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
- MainApp.subscribe(this);
running = true;
if (L.isEnabled(L.UI))
log.debug("onResume running");
}
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventPumpStatusChanged.class)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(event -> statusView.setText(event.getStatus()), FabricPrivacy::logException)
+ );
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventDismissBolusProgressIfRunning.class)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(event -> {
+ if (L.isEnabled(L.UI)) log.debug("EventDismissBolusProgressIfRunning");
+ if (BolusProgressDialog.running) dismiss();
+ }, FabricPrivacy::logException)
+ );
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventOverviewBolusProgress.class)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(event -> {
+ if (L.isEnabled(L.UI))
+ log.debug("Status: " + event.getStatus() + " Percent: " + event.getPercent());
+ statusView.setText(event.getStatus());
+ progressBar.setProgress(event.getPercent());
+ if (event.getPercent() == 100) {
+ stopButton.setVisibility(View.INVISIBLE);
+ scheduleDismiss();
+ }
+ state = event.getStatus();
+ }, FabricPrivacy::logException)
+ );
}
@Override
@@ -107,11 +144,18 @@ public class BolusProgressDialog extends DialogFragment implements View.OnClickL
@Override
public void onPause() {
- running = false;
- super.onPause();
- MainApp.unsubscribe(this);
if (L.isEnabled(L.UI))
log.debug("onPause");
+ running = false;
+ super.onPause();
+ disposable.clear();
+ }
+
+ @Override
+ public void onSaveInstanceState(@NonNull Bundle outState) {
+ outState.putString("state", state);
+ log.debug("storing state: " + state);
+ super.onSaveInstanceState(outState);
}
@Override
@@ -128,42 +172,6 @@ public class BolusProgressDialog extends DialogFragment implements View.OnClickL
}
}
- @Subscribe
- public void onStatusEvent(final EventOverviewBolusProgress ev) {
- Activity activity = getActivity();
- if (activity != null) {
- activity.runOnUiThread(() -> {
- if (L.isEnabled(L.UI))
- log.debug("Status: " + ev.status + " Percent: " + ev.percent);
- statusView.setText(ev.status);
- progressBar.setProgress(ev.percent);
- if (ev.percent == 100) {
- stopButton.setVisibility(View.INVISIBLE);
- scheduleDismiss();
- }
- });
- }
- }
-
- @Subscribe
- public void onStatusEvent(final EventDismissBolusprogressIfRunning ev) {
- if (L.isEnabled(L.UI))
- log.debug("EventDismissBolusprogressIfRunning");
- if (BolusProgressDialog.running) {
- dismiss();
- }
- }
-
- @Subscribe
- public void onStatusEvent(final EventPumpStatusChanged c) {
- if (L.isEnabled(L.UI))
- log.debug("EventPumpStatusChanged");
- Activity activity = getActivity();
- if (activity != null) {
- activity.runOnUiThread(() -> statusView.setText(c.textStatus()));
- }
- }
-
private void scheduleDismiss() {
if (L.isEnabled(L.UI))
log.debug("scheduleDismiss");
@@ -183,9 +191,6 @@ public class BolusProgressDialog extends DialogFragment implements View.OnClickL
log.error("Unhandled exception", e);
}
});
- } else {
- if (L.isEnabled(L.UI))
- log.debug("activity == null");
}
});
t.start();
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/BolusProgressHelperActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/BolusProgressHelperActivity.java
index fd1de6ce8c..54f6aa7688 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/BolusProgressHelperActivity.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/BolusProgressHelperActivity.java
@@ -1,24 +1,20 @@
package info.nightscout.androidaps.plugins.general.overview.dialogs;
import android.os.Bundle;
-import android.support.v7.app.AppCompatActivity;
-/**
- * Created by adrian on 09/02/17.
- */
+import info.nightscout.androidaps.activities.NoSplashAppCompatActivity;
-public class BolusProgressHelperActivity extends AppCompatActivity {
+public class BolusProgressHelperActivity extends NoSplashAppCompatActivity {
public BolusProgressHelperActivity() {
super();
}
@Override
public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- this.getIntent().getDoubleExtra("insulin", 0d);
- BolusProgressDialog bolusProgressDialog = new BolusProgressDialog();
- bolusProgressDialog.setHelperActivity(this);
- bolusProgressDialog.setInsulin(this.getIntent().getDoubleExtra("insulin", 0d));
- bolusProgressDialog.show(this.getSupportFragmentManager(), "BolusProgress");
+ super.onCreate(savedInstanceState);
+ BolusProgressDialog bolusProgressDialog = new BolusProgressDialog();
+ bolusProgressDialog.setHelperActivity(this);
+ bolusProgressDialog.setInsulin(getIntent().getDoubleExtra("insulin", 0d));
+ bolusProgressDialog.show(getSupportFragmentManager(), "BolusProgress");
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/CalibrationDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/CalibrationDialog.java
index 0ab1b98ff6..a82f94d2ff 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/CalibrationDialog.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/CalibrationDialog.java
@@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.general.overview.dialogs;
import android.content.Context;
import android.os.Bundle;
-import android.support.v4.app.DialogFragment;
+import androidx.fragment.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -66,9 +66,9 @@ public class CalibrationDialog extends DialogFragment implements View.OnClickLis
bgNumber = (NumberPicker) view.findViewById(R.id.overview_calibration_bg);
if (units.equals(Constants.MMOL))
- bgNumber.setParams(bg, 0d, 30d, 0.1d, new DecimalFormat("0.0"), false);
+ bgNumber.setParams(bg, 0d, 30d, 0.1d, new DecimalFormat("0.0"), false, view.findViewById(R.id.ok));
else
- bgNumber.setParams(bg, 0d, 500d, 1d, new DecimalFormat("0"), false);
+ bgNumber.setParams(bg, 0d, 500d, 1d, new DecimalFormat("0"), false, view.findViewById(R.id.ok));
unitsView = (TextView) view.findViewById(R.id.overview_calibration_units);
unitsView.setText(units);
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/EditQuickWizardDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/EditQuickWizardDialog.java
deleted file mode 100644
index 9cd1277961..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/EditQuickWizardDialog.java
+++ /dev/null
@@ -1,190 +0,0 @@
-package info.nightscout.androidaps.plugins.general.overview.dialogs;
-
-
-import android.os.Bundle;
-import android.support.v4.app.DialogFragment;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.Window;
-import android.view.WindowManager;
-import android.widget.ArrayAdapter;
-import android.widget.EditText;
-import android.widget.Spinner;
-
-import org.json.JSONException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.ArrayList;
-
-import info.nightscout.androidaps.MainApp;
-import info.nightscout.androidaps.R;
-import info.nightscout.androidaps.data.QuickWizard;
-import info.nightscout.androidaps.data.QuickWizardEntry;
-import info.nightscout.androidaps.plugins.general.overview.OverviewPlugin;
-import info.nightscout.androidaps.plugins.general.overview.events.EventQuickWizardChange;
-import info.nightscout.androidaps.utils.DateUtil;
-import info.nightscout.androidaps.utils.SafeParse;
-
-public class EditQuickWizardDialog extends DialogFragment implements View.OnClickListener {
- private static Logger log = LoggerFactory.getLogger(EditQuickWizardDialog.class);
-
- QuickWizardEntry entry = new QuickWizard().newEmptyItem();
- QuickWizard quickWizard = MainApp.getSpecificPlugin(OverviewPlugin.class).quickWizard;
-
- EditText buttonEdit;
- EditText carbsEdit;
- Spinner fromSpinner;
- Spinner toSpinner;
- Spinner useBGSpinner;
- Spinner useCOBSpinner;
- Spinner useBolusIOBSpinner;
- Spinner useBasalIOBSpinner;
- Spinner useTrendSpinner;
- Spinner useSuperBolusSpinner;
- Spinner useTempTargetSpinner;
-
- public EditQuickWizardDialog() {
- }
-
- public void setData(QuickWizardEntry data) {
- entry = data;
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
- getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
-
- View view = inflater.inflate(R.layout.overview_editquickwizard_dialog, container, false);
- buttonEdit = (EditText) view.findViewById(R.id.overview_editquickwizard_button_edit);
- carbsEdit = (EditText) view.findViewById(R.id.overview_editquickwizard_carbs_edit);
- fromSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_from_spinner);
- toSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_to_spinner);
- useBGSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_usebg_spinner);
- useCOBSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_usecob_spinner);
- useBolusIOBSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_usebolusiob_spinner);
- useBasalIOBSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_usebasaliob_spinner);
- useTrendSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_usetrend_spinner);
- useSuperBolusSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_usesuperbolus_spinner);
- useTempTargetSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_usetemptarget_spinner);
-
- view.findViewById(R.id.ok).setOnClickListener(this);
- view.findViewById(R.id.cancel).setOnClickListener(this);
-
- int posFrom = 0;
- int posTo = 95;
- ArrayList timeList = new ArrayList<>();
- int pos = 0;
- for (int t = 0; t < 24 * 60 * 60; t += 15 * 60) {
- timeList.add(DateUtil.timeString(DateUtil.toDate(t)));
- if (entry.validFrom() == t) posFrom = pos;
- if (entry.validTo() == t) posTo = pos;
- pos++;
- }
- timeList.add(DateUtil.timeString(DateUtil.toDate(24 * 60 * 60 - 60)));
-
- ArrayAdapter adapter = new ArrayAdapter(getContext(),
- R.layout.spinner_centered, timeList);
- fromSpinner.setAdapter(adapter);
- toSpinner.setAdapter(adapter);
-
- buttonEdit.setText(entry.buttonText());
- carbsEdit.setText(entry.carbs().toString());
- fromSpinner.setSelection(posFrom);
- toSpinner.setSelection(posTo);
-
- setSelection(useBGSpinner, entry.useBG());
- setSelection(useCOBSpinner, entry.useCOB());
- setSelection(useBolusIOBSpinner, entry.useBolusIOB());
- setSelection(useBasalIOBSpinner, entry.useBasalIOB());
- setSelection(useTrendSpinner, entry.useTrend());
- setSelection(useSuperBolusSpinner, entry.useSuperBolus());
- setSelection(useTempTargetSpinner, entry.useTempTarget());
-
- return view;
- }
-
- @Override
- public void onResume() {
- super.onResume();
- if (getDialog() != null)
- getDialog().getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
- }
-
- @Override
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id.ok:
- if (fromSpinner.getSelectedItem() == null) return;
- if (toSpinner.getSelectedItem() == null) return;
- try {
- entry.storage.put("buttonText", buttonEdit.getText().toString());
- entry.storage.put("carbs", SafeParse.stringToInt(carbsEdit.getText().toString()));
- int validFromInt = DateUtil.toSeconds(fromSpinner.getSelectedItem().toString());
- entry.storage.put("validFrom", validFromInt);
- int validToInt = DateUtil.toSeconds(toSpinner.getSelectedItem().toString());
- entry.storage.put("validTo", validToInt);
- entry.storage.put("useBG", getSelection(useBGSpinner));
- entry.storage.put("useCOB", getSelection(useCOBSpinner));
- entry.storage.put("useBolusIOB", getSelection(useBolusIOBSpinner));
- entry.storage.put("useBasalIOB", getSelection(useBasalIOBSpinner));
- entry.storage.put("useTrend", getSelection(useTrendSpinner));
- entry.storage.put("useSuperBolus", getSelection(useSuperBolusSpinner));
- entry.storage.put("useTempTarget", getSelection(useTempTargetSpinner));
- } catch (JSONException e) {
- log.error("Unhandled exception", e);
- }
- quickWizard.addOrUpdate(entry);
- dismiss();
- MainApp.bus().post(new EventQuickWizardChange());
- break;
- case R.id.cancel:
- dismiss();
- break;
- }
- }
-
- int getSelection(Spinner spinner) {
- String value = spinner.getSelectedItem().toString();
- if (value.equals(MainApp.gs(R.string.yes)))
- return QuickWizardEntry.YES;
- if (value.equals(MainApp.gs(R.string.no)))
- return QuickWizardEntry.NO;
- if (value.equals(MainApp.gs(R.string.positiveonly)))
- return QuickWizardEntry.POSITIVE_ONLY;
- if (value.equals(MainApp.gs(R.string.negativeonly)))
- return QuickWizardEntry.NEGATIVE_ONLY;
- return QuickWizardEntry.NO;
- }
-
- void setSelection(Spinner spinner, int value) {
- String selection;
- switch (value) {
- case QuickWizardEntry.YES:
- selection = MainApp.gs(R.string.yes);
- break;
- case QuickWizardEntry.NO:
- selection = MainApp.gs(R.string.no);
- break;
- case QuickWizardEntry.POSITIVE_ONLY:
- selection = MainApp.gs(R.string.positiveonly);
- break;
- case QuickWizardEntry.NEGATIVE_ONLY:
- selection = MainApp.gs(R.string.negativeonly);
- break;
- default:
- selection = MainApp.gs(R.string.no);
- break;
- }
-
- for (int i = 0; i < spinner.getCount(); i++) {
- if (spinner.getItemAtPosition(i).toString().equalsIgnoreCase(selection)) {
- spinner.setSelection(i);
- break;
- }
- }
- }
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/EditQuickWizardDialog.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/EditQuickWizardDialog.kt
new file mode 100644
index 0000000000..8b70c637fa
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/EditQuickWizardDialog.kt
@@ -0,0 +1,118 @@
+package info.nightscout.androidaps.plugins.general.overview.dialogs
+
+
+import android.os.Bundle
+import android.view.*
+import android.widget.AdapterView
+import android.widget.ArrayAdapter
+import androidx.fragment.app.DialogFragment
+import info.nightscout.androidaps.R
+import info.nightscout.androidaps.data.QuickWizard
+import info.nightscout.androidaps.data.QuickWizardEntry
+import info.nightscout.androidaps.plugins.bus.RxBus
+import info.nightscout.androidaps.plugins.general.overview.events.EventQuickWizardChange
+import info.nightscout.androidaps.utils.DateUtil
+import info.nightscout.androidaps.utils.SafeParse
+import kotlinx.android.synthetic.main.okcancel.*
+import kotlinx.android.synthetic.main.overview_editquickwizard_dialog.*
+import org.json.JSONException
+import org.slf4j.LoggerFactory
+import java.util.*
+
+
+class EditQuickWizardDialog : DialogFragment() {
+ private val log = LoggerFactory.getLogger(EditQuickWizardDialog::class.java)
+ internal var entry = QuickWizard.newEmptyItem()
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?): View? {
+ dialog?.window?.requestFeature(Window.FEATURE_NO_TITLE)
+ dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)
+ isCancelable = true
+ dialog?.setCanceledOnTouchOutside(false)
+ return inflater.inflate(R.layout.overview_editquickwizard_dialog, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ ok.setOnClickListener {
+ if (overview_editquickwizard_from_spinner.selectedItem == null) return@setOnClickListener
+ if (overview_editquickwizard_to_spinner.selectedItem == null) return@setOnClickListener
+ try {
+ entry.storage.put("buttonText", overview_editquickwizard_button_edit.text.toString())
+ entry.storage.put("carbs", SafeParse.stringToInt(overview_editquickwizard_carbs_edit.text.toString()))
+ val validFromInt = DateUtil.toSeconds(overview_editquickwizard_from_spinner.selectedItem.toString())
+ entry.storage.put("validFrom", validFromInt)
+ val validToInt = DateUtil.toSeconds(overview_editquickwizard_to_spinner.selectedItem.toString())
+ entry.storage.put("validTo", validToInt)
+ entry.storage.put("useBG", overview_editquickwizard_usebg_spinner.selectedItemPosition)
+ entry.storage.put("useCOB", overview_editquickwizard_usecob_spinner.selectedItemPosition)
+ entry.storage.put("useBolusIOB", overview_editquickwizard_usebolusiob_spinner.selectedItemPosition)
+ entry.storage.put("useBasalIOB", overview_editquickwizard_usebasaliob_spinner.selectedItemPosition)
+ entry.storage.put("useTrend", overview_editquickwizard_usetrend_spinner.selectedItemPosition)
+ entry.storage.put("useSuperBolus", overview_editquickwizard_usesuperbolus_spinner.selectedItemPosition)
+ entry.storage.put("useTempTarget", overview_editquickwizard_usetemptarget_spinner.selectedItemPosition)
+ } catch (e: JSONException) {
+ log.error("Unhandled exception", e)
+ }
+
+ QuickWizard.addOrUpdate(entry)
+ RxBus.send(EventQuickWizardChange())
+ dismiss()
+ }
+ cancel.setOnClickListener { dismiss() }
+
+ var posFrom = 0
+ var posTo = 95
+ val timeList = ArrayList()
+ var pos = 0
+ var t = 0
+ while (t < 24 * 60 * 60) {
+ timeList.add(DateUtil.timeString(DateUtil.toDate(t)))
+ if (entry.validFrom() == t) posFrom = pos
+ if (entry.validTo() == t) posTo = pos
+ pos++
+ t += 15 * 60
+ }
+ timeList.add(DateUtil.timeString(DateUtil.toDate(24 * 60 * 60 - 60)))
+
+ val adapter = context?.let { context -> ArrayAdapter(context, R.layout.spinner_centered, timeList) }
+ overview_editquickwizard_from_spinner.adapter = adapter
+ overview_editquickwizard_to_spinner.adapter = adapter
+
+ overview_editquickwizard_button_edit.setText(entry.buttonText())
+ overview_editquickwizard_carbs_edit.setText(entry.carbs().toString())
+ overview_editquickwizard_from_spinner.setSelection(posFrom)
+ overview_editquickwizard_to_spinner.setSelection(posTo)
+
+ overview_editquickwizard_usebg_spinner.setSelection(entry.useBG())
+ overview_editquickwizard_usecob_spinner.setSelection(entry.useCOB())
+ overview_editquickwizard_usebolusiob_spinner.setSelection(entry.useBolusIOB())
+ overview_editquickwizard_usebasaliob_spinner.setSelection(entry.useBasalIOB())
+ overview_editquickwizard_usetrend_spinner.setSelection(entry.useTrend())
+ overview_editquickwizard_usesuperbolus_spinner.setSelection(entry.useSuperBolus())
+ overview_editquickwizard_usetemptarget_spinner.setSelection(entry.useTempTarget())
+
+ overview_editquickwizard_usecob_spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
+ override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) = processCob()
+ override fun onNothingSelected(parent: AdapterView<*>) {}
+ }
+ processCob()
+ }
+
+ override fun onResume() {
+ super.onResume()
+ dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
+ }
+
+ private fun processCob() {
+ if (overview_editquickwizard_usecob_spinner.selectedItemPosition == QuickWizardEntry.YES) {
+ overview_editquickwizard_usebolusiob_spinner.isEnabled = false
+ overview_editquickwizard_usebasaliob_spinner.isEnabled = false
+ overview_editquickwizard_usebolusiob_spinner.setSelection(QuickWizardEntry.YES)
+ overview_editquickwizard_usebasaliob_spinner.setSelection(QuickWizardEntry.YES)
+ } else {
+ overview_editquickwizard_usebolusiob_spinner.isEnabled = true
+ overview_editquickwizard_usebasaliob_spinner.isEnabled = true
+ }
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/ErrorDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/ErrorDialog.java
deleted file mode 100644
index 209a585384..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/ErrorDialog.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package info.nightscout.androidaps.plugins.general.overview.dialogs;
-
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.v4.app.DialogFragment;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.TextView;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import info.nightscout.androidaps.MainApp;
-import info.nightscout.androidaps.R;
-import info.nightscout.androidaps.services.AlarmSoundService;
-
-public class ErrorDialog extends DialogFragment implements View.OnClickListener {
- private static Logger log = LoggerFactory.getLogger(ErrorDialog.class);
- Button muteButton;
- Button okButton;
- TextView statusView;
- ErrorHelperActivity helperActivity;
-
- static String status;
- static String title;
- static int soundId;
-
- public ErrorDialog() {
- super();
- }
-
- public void setStatus(String status) {
- this.status = status;
- }
-
- public void setTitle(String title) {
- this.title = title;
- }
-
- public void setSound(int soundId) {
- this.soundId = soundId;
- }
-
- public void setHelperActivity(ErrorHelperActivity activity) {
- this.helperActivity = activity;
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- getDialog().setTitle(title);
- View view = inflater.inflate(R.layout.overview_error_dialog, container, false);
- muteButton = (Button) view.findViewById(R.id.overview_error_mute);
- okButton = (Button) view.findViewById(R.id.overview_error_ok);
- statusView = (TextView) view.findViewById(R.id.overview_error_status);
- muteButton.setOnClickListener(this);
- okButton.setOnClickListener(this);
- setCancelable(false);
-
- startAlarm();
- return view;
- }
-
- @Override
- public void onResume() {
- super.onResume();
- if (getDialog() != null)
- getDialog().getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
- statusView.setText(status);
- }
-
- @Override
- public void dismiss() {
- super.dismissAllowingStateLoss();
- if (helperActivity != null) {
- helperActivity.finish();
- }
- stopAlarm();
- }
-
- @Override
- public void onClick(View view) {
- switch (view.getId()) {
- case R.id.overview_error_mute:
- log.debug("Error dialog mute button pressed");
- stopAlarm();
- break;
- case R.id.overview_error_ok:
- log.debug("Error dialog ok button pressed");
- dismiss();
- break;
- }
- }
-
- private void startAlarm() {
- Intent alarm = new Intent(MainApp.instance().getApplicationContext(), AlarmSoundService.class);
- alarm.putExtra("soundid", soundId);
- MainApp.instance().startService(alarm);
- }
-
- private void stopAlarm() {
- Intent alarm = new Intent(MainApp.instance().getApplicationContext(), AlarmSoundService.class);
- MainApp.instance().stopService(alarm);
- }
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/ErrorDialog.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/ErrorDialog.kt
new file mode 100644
index 0000000000..8ea499d4ef
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/ErrorDialog.kt
@@ -0,0 +1,85 @@
+package info.nightscout.androidaps.plugins.general.overview.dialogs
+
+
+import android.content.Intent
+import android.os.Build
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.DialogFragment
+import info.nightscout.androidaps.MainApp
+import info.nightscout.androidaps.R
+import info.nightscout.androidaps.services.AlarmSoundService
+import kotlinx.android.synthetic.main.overview_error_dialog.*
+import org.slf4j.LoggerFactory
+
+class ErrorDialog : DialogFragment() {
+ private val log = LoggerFactory.getLogger(ErrorDialog::class.java)
+
+ var helperActivity: ErrorHelperActivity? = null
+ var status: String = ""
+ var title: String = ""
+ var sound: Int = 0
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?): View? {
+ dialog?.setTitle(title)
+ isCancelable = false
+
+ savedInstanceState?.let { bundle ->
+ bundle.getString("status")?.let { status = it }
+ bundle.getString("title")?.let { title = it }
+ sound = bundle.getInt("sound", R.raw.error)
+ }
+ return inflater.inflate(R.layout.overview_error_dialog, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ overview_error_ok.setOnClickListener {
+ log.debug("Error dialog ok button pressed")
+ dismiss()
+ }
+ overview_error_mute.setOnClickListener {
+ log.debug("Error dialog mute button pressed")
+ stopAlarm()
+ }
+ startAlarm()
+ }
+
+ override fun onSaveInstanceState(bundle: Bundle) {
+ super.onSaveInstanceState(bundle)
+ bundle.putString("status", status)
+ bundle.putString("title", title)
+ bundle.putInt("sound", sound)
+ }
+
+ override fun onResume() {
+ super.onResume()
+ dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
+ overview_error_status.text = status
+ }
+
+ override fun dismiss() {
+ super.dismissAllowingStateLoss()
+ helperActivity?.finish()
+ stopAlarm()
+ }
+
+ private fun startAlarm() {
+ if (sound != 0) {
+ val alarm = Intent(MainApp.instance().applicationContext, AlarmSoundService::class.java)
+ alarm.putExtra("soundid", sound)
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ MainApp.instance().startForegroundService(alarm)
+ } else {
+ MainApp.instance().startService(alarm)
+ }
+ }
+ }
+
+ private fun stopAlarm() =
+ MainApp.instance().stopService(Intent(MainApp.instance().applicationContext, AlarmSoundService::class.java))
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/ErrorHelperActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/ErrorHelperActivity.java
deleted file mode 100644
index 667cadf2b1..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/ErrorHelperActivity.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package info.nightscout.androidaps.plugins.general.overview.dialogs;
-
-import android.os.Bundle;
-import android.support.v7.app.AppCompatActivity;
-
-import info.nightscout.androidaps.R;
-import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
-import info.nightscout.androidaps.utils.SP;
-
-public class ErrorHelperActivity extends AppCompatActivity {
- public ErrorHelperActivity() {
- super();
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- ErrorDialog errorDialog = new ErrorDialog();
- errorDialog.setHelperActivity(this);
- errorDialog.setStatus(getIntent().getStringExtra("status"));
- errorDialog.setSound(getIntent().getIntExtra("soundid", 0));
- errorDialog.setTitle(getIntent().getStringExtra("title"));
- errorDialog.show(this.getSupportFragmentManager(), "Error");
-
- if (SP.getBoolean(R.string.key_ns_create_announcements_from_errors, true)) {
- NSUpload.uploadError(getIntent().getStringExtra("status"));
- }
- }
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/ErrorHelperActivity.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/ErrorHelperActivity.kt
new file mode 100644
index 0000000000..15840d3499
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/ErrorHelperActivity.kt
@@ -0,0 +1,25 @@
+package info.nightscout.androidaps.plugins.general.overview.dialogs
+
+import android.os.Bundle
+import info.nightscout.androidaps.R
+import info.nightscout.androidaps.activities.NoSplashAppCompatActivity
+import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
+import info.nightscout.androidaps.utils.SP
+
+class ErrorHelperActivity : NoSplashAppCompatActivity() {
+
+ @Override
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ val errorDialog = ErrorDialog()
+ errorDialog.helperActivity = this
+ errorDialog.status = intent.getStringExtra("status")
+ errorDialog.sound = intent.getIntExtra("soundid", R.raw.error)
+ errorDialog.title = intent.getStringExtra("title")
+ errorDialog.show(supportFragmentManager, "Error")
+
+ if (SP.getBoolean(R.string.key_ns_create_announcements_from_errors, true)) {
+ NSUpload.uploadError(intent.getStringExtra("status"))
+ }
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/NewCarbsDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/NewCarbsDialog.java
index 789ced1df3..23352f3d5b 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/NewCarbsDialog.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/NewCarbsDialog.java
@@ -2,8 +2,8 @@ package info.nightscout.androidaps.plugins.general.overview.dialogs;
import android.os.Bundle;
import android.os.HandlerThread;
-import android.support.v4.app.DialogFragment;
-import android.support.v7.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
+import androidx.appcompat.app.AlertDialog;
import android.text.Editable;
import android.text.Html;
import android.text.TextWatcher;
@@ -75,8 +75,6 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, C
private boolean okClicked;
public NewCarbsDialog() {
- HandlerThread mHandlerThread = new HandlerThread(NewCarbsDialog.class.getSimpleName());
- mHandlerThread.start();
}
final private TextWatcher textWatcher = new TextWatcher() {
@@ -130,15 +128,15 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, C
startHypoTTCheckbox = view.findViewById(R.id.newcarbs_hypo_tt);
editTime = view.findViewById(R.id.newcarbs_time);
- editTime.setParams(0d, -12 * 60d, 12 * 60d, 5d, new DecimalFormat("0"), false, textWatcher);
+ editTime.setParams(0d, -12 * 60d, 12 * 60d, 5d, new DecimalFormat("0"), false, view.findViewById(R.id.ok), textWatcher);
editDuration = view.findViewById(R.id.new_carbs_duration);
- editDuration.setParams(0d, 0d, 10d, 1d, new DecimalFormat("0"), false, textWatcher);
+ editDuration.setParams(0d, 0d, 10d, 1d, new DecimalFormat("0"), false, view.findViewById(R.id.ok), textWatcher);
maxCarbs = MainApp.getConstraintChecker().getMaxCarbsAllowed().value();
editCarbs = view.findViewById(R.id.newcarb_carbsamount);
- editCarbs.setParams(0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false, textWatcher);
+ editCarbs.setParams(0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false, view.findViewById(R.id.ok), textWatcher);
Button fav1Button = view.findViewById(R.id.newcarbs_plus1);
fav1Button.setOnClickListener(this);
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/NewInsulinDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/NewInsulinDialog.java
index 27e2e33ba7..d5d4308f63 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/NewInsulinDialog.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/NewInsulinDialog.java
@@ -4,8 +4,8 @@ import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.HandlerThread;
-import android.support.v4.app.DialogFragment;
-import android.support.v7.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
+import androidx.appcompat.app.AlertDialog;
import android.text.Editable;
import android.text.Html;
import android.text.TextWatcher;
@@ -75,8 +75,6 @@ public class NewInsulinDialog extends DialogFragment implements OnClickListener
private boolean okClicked;
public NewInsulinDialog() {
- HandlerThread mHandlerThread = new HandlerThread(NewInsulinDialog.class.getSimpleName());
- mHandlerThread.start();
}
final private TextWatcher textWatcher = new TextWatcher() {
@@ -126,12 +124,12 @@ public class NewInsulinDialog extends DialogFragment implements OnClickListener
editLayout = view.findViewById(R.id.newinsulin_time_layout);
editLayout.setVisibility(View.GONE);
editTime = view.findViewById(R.id.newinsulin_time);
- editTime.setParams(0d, -12 * 60d, 12 * 60d, 5d, new DecimalFormat("0"), false, textWatcher);
+ editTime.setParams(0d, -12 * 60d, 12 * 60d, 5d, new DecimalFormat("0"), false, view.findViewById(R.id.ok), textWatcher);
maxInsulin = MainApp.getConstraintChecker().getMaxBolusAllowed().value();
editInsulin = view.findViewById(R.id.newinsulin_amount);
- editInsulin.setParams(0d, 0d, maxInsulin, ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().bolusStep, DecimalFormatter.pumpSupportedBolusFormat(), false, textWatcher);
+ editInsulin.setParams(0d, 0d, maxInsulin, ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().bolusStep, DecimalFormatter.pumpSupportedBolusFormat(), false, view.findViewById(R.id.ok), textWatcher);
Button plus1Button = view.findViewById(R.id.newinsulin_plus05);
plus1Button.setOnClickListener(this);
@@ -225,8 +223,8 @@ public class NewInsulinDialog extends DialogFragment implements OnClickListener
}
}
- if (Math.abs(insulinAfterConstraints - insulin) > pump.getPumpDescription().pumpType.determineCorrectBolusSize(insulinAfterConstraints))
- actions.add("" + MainApp.gs(R.string.bolusconstraintapplied) + " ");
+ if (Math.abs(insulinAfterConstraints - insulin) > pump.getPumpDescription().pumpType.determineCorrectBolusStepSize(insulinAfterConstraints))
+ actions.add(MainApp.gs(R.string.bolusconstraintappliedwarning, MainApp.gc(R.color.warning), insulin, insulinAfterConstraints));
int eatingSoonTTDuration = SP.getInt(R.string.key_eatingsoon_duration, Constants.defaultEatingSoonTTDuration);
eatingSoonTTDuration = eatingSoonTTDuration > 0 ? eatingSoonTTDuration : Constants.defaultEatingSoonTTDuration;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/NewTreatmentDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/NewTreatmentDialog.java
index 837d206fb3..9f2f42b2d9 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/NewTreatmentDialog.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/NewTreatmentDialog.java
@@ -4,8 +4,8 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
-import android.support.v4.app.DialogFragment;
-import android.support.v7.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
+import androidx.appcompat.app.AlertDialog;
import android.text.Editable;
import android.text.Html;
import android.text.TextWatcher;
@@ -101,8 +101,8 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene
editCarbs = (NumberPicker) view.findViewById(R.id.treatments_newtreatment_carbsamount);
editInsulin = (NumberPicker) view.findViewById(R.id.treatments_newtreatment_insulinamount);
- editCarbs.setParams(0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false, textWatcher);
- editInsulin.setParams(0d, 0d, maxInsulin, ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().bolusStep, DecimalFormatter.pumpSupportedBolusFormat(), false, textWatcher);
+ editCarbs.setParams(0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false, view.findViewById(R.id.ok), textWatcher);
+ editInsulin.setParams(0d, 0d, maxInsulin, ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().bolusStep, DecimalFormatter.pumpSupportedBolusFormat(), false, view.findViewById(R.id.ok), textWatcher);
recordOnlyCheckbox = (CheckBox) view.findViewById(R.id.newtreatment_record_only);
@@ -141,8 +141,8 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene
if (recordOnlyCheckbox.isChecked()) {
confirmMessage += "" + MainApp.gs(R.string.bolusrecordedonly) + " ";
}
- if (Math.abs(insulinAfterConstraints - insulin) > pump.getPumpDescription().pumpType.determineCorrectBolusSize(insulinAfterConstraints) || !Objects.equals(carbsAfterConstraints, carbs))
- confirmMessage += "" + MainApp.gs(R.string.bolusconstraintapplied) + " ";
+ if (Math.abs(insulinAfterConstraints - insulin) > pump.getPumpDescription().pumpType.determineCorrectBolusStepSize(insulinAfterConstraints) || !Objects.equals(carbsAfterConstraints, carbs))
+ confirmMessage += " " + MainApp.gs(R.string.bolusconstraintappliedwarning, MainApp.gc(R.color.warning), insulin, insulinAfterConstraints);
}
if (carbsAfterConstraints > 0)
confirmMessage += " " + MainApp.gs(R.string.carbs) + ": " + "" + carbsAfterConstraints + "g" + " ";
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/WizardDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/WizardDialog.java
deleted file mode 100644
index b4a3de4271..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/WizardDialog.java
+++ /dev/null
@@ -1,597 +0,0 @@
-package info.nightscout.androidaps.plugins.general.overview.dialogs;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.v4.app.DialogFragment;
-import android.support.v7.app.AlertDialog;
-import android.text.Editable;
-import android.text.Html;
-import android.text.TextWatcher;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.view.Window;
-import android.view.WindowManager;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.Button;
-import android.widget.CheckBox;
-import android.widget.CompoundButton;
-import android.widget.EditText;
-import android.widget.LinearLayout;
-import android.widget.Spinner;
-import android.widget.TextView;
-
-import com.squareup.otto.Subscribe;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.text.DecimalFormat;
-import java.util.ArrayList;
-import java.util.Date;
-
-import info.nightscout.androidaps.Constants;
-import info.nightscout.androidaps.MainApp;
-import info.nightscout.androidaps.R;
-import info.nightscout.androidaps.data.DetailedBolusInfo;
-import info.nightscout.androidaps.data.IobTotal;
-import info.nightscout.androidaps.data.Profile;
-import info.nightscout.androidaps.data.ProfileStore;
-import info.nightscout.androidaps.db.BgReading;
-import info.nightscout.androidaps.db.CareportalEvent;
-import info.nightscout.androidaps.db.DatabaseHelper;
-import info.nightscout.androidaps.db.Source;
-import info.nightscout.androidaps.db.TempTarget;
-import info.nightscout.androidaps.events.EventFeatureRunning;
-import info.nightscout.androidaps.events.EventRefreshOverview;
-import info.nightscout.androidaps.interfaces.Constraint;
-import info.nightscout.androidaps.interfaces.PluginType;
-import info.nightscout.androidaps.interfaces.PumpInterface;
-import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
-import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
-import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
-import info.nightscout.androidaps.plugins.iob.iobCobCalculator.CobInfo;
-import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
-import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished;
-import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
-import info.nightscout.androidaps.queue.Callback;
-import info.nightscout.androidaps.utils.BolusWizard;
-import info.nightscout.androidaps.utils.DateUtil;
-import info.nightscout.androidaps.utils.DecimalFormatter;
-import info.nightscout.androidaps.utils.NumberPicker;
-import info.nightscout.androidaps.utils.SP;
-import info.nightscout.androidaps.utils.SafeParse;
-import info.nightscout.androidaps.utils.ToastUtils;
-
-public class WizardDialog extends DialogFragment implements OnClickListener, CompoundButton.OnCheckedChangeListener, Spinner.OnItemSelectedListener {
- private static Logger log = LoggerFactory.getLogger(WizardDialog.class);
-
- Button okButton;
- TextView bg;
- TextView bgInsulin;
- TextView bgUnits;
- CheckBox bgCheckbox;
- CheckBox ttCheckbox;
- TextView carbs;
- TextView carbsInsulin;
- TextView bolusIobInsulin;
- TextView basalIobInsulin;
- CheckBox bolusIobCheckbox;
- CheckBox basalIobCheckbox;
- TextView correctionInsulin;
- TextView total;
- Spinner profileSpinner;
- CheckBox superbolusCheckbox;
- TextView superbolus;
- TextView superbolusInsulin;
- CheckBox bgtrendCheckbox;
- TextView bgTrend;
- TextView bgTrendInsulin;
- LinearLayout cobLayout;
- CheckBox cobCheckbox;
- TextView cob;
- TextView cobInsulin;
-
- NumberPicker editBg;
- NumberPicker editCarbs;
- NumberPicker editCorr;
- NumberPicker editCarbTime;
-
- LinearLayout notesLayout;
- EditText notesEdit;
-
- Integer calculatedCarbs = 0;
- Double calculatedTotalInsulin = 0d;
- JSONObject boluscalcJSON;
-
- Context context;
-
- //one shot guards
- private boolean accepted;
- private boolean okClicked;
-
- public WizardDialog() {
- super();
- }
-
- @Override
- public void onAttach(Context context) {
- super.onAttach(context);
- this.context = context;
- }
-
- @Override
- public void onDetach() {
- super.onDetach();
- this.context = null;
- }
-
- @Override
- public void onResume() {
- super.onResume();
- MainApp.bus().register(this);
- MainApp.bus().post(new EventFeatureRunning(EventFeatureRunning.Feature.WIZARD));
- }
-
- @Override
- public void onPause() {
- super.onPause();
- MainApp.bus().unregister(this);
- }
-
- @Override
- public void onSaveInstanceState(Bundle savedInstanceState) {
- savedInstanceState.putBoolean("bgCheckbox", bgCheckbox.isChecked());
- savedInstanceState.putBoolean("ttCheckbox", ttCheckbox.isChecked());
- savedInstanceState.putBoolean("bolusIobCheckbox", bolusIobCheckbox.isChecked());
- savedInstanceState.putBoolean("basalIobCheckbox", basalIobCheckbox.isChecked());
- savedInstanceState.putBoolean("bgtrendCheckbox", bgtrendCheckbox.isChecked());
- savedInstanceState.putBoolean("cobCheckbox", cobCheckbox.isChecked());
- savedInstanceState.putDouble("editBg", editBg.getValue());
- savedInstanceState.putDouble("editCarbs", editCarbs.getValue());
- savedInstanceState.putDouble("editCorr", editCorr.getValue());
- savedInstanceState.putDouble("editCarbTime", editCarbTime.getValue());
- super.onSaveInstanceState(savedInstanceState);
- }
-
-
- @Subscribe
- public void onStatusEvent(final EventAutosensCalculationFinished e) {
- Activity activity = getActivity();
- if (activity != null)
- activity.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- calculateInsulin();
- }
- });
- }
-
- final private TextWatcher textWatcher = new TextWatcher() {
- @Override
- public void afterTextChanged(Editable s) {
- }
-
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- }
-
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- calculateInsulin();
- }
- };
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- View view = inflater.inflate(R.layout.overview_wizard_dialog, container, false);
-
- getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
- getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
-
- okButton = (Button) view.findViewById(R.id.ok);
- okButton.setOnClickListener(this);
- view.findViewById(R.id.cancel).setOnClickListener(this);
-
- bg = (TextView) view.findViewById(R.id.treatments_wizard_bg);
- bgInsulin = (TextView) view.findViewById(R.id.treatments_wizard_bginsulin);
- bgUnits = (TextView) view.findViewById(R.id.treatments_wizard_bgunits);
- carbs = (TextView) view.findViewById(R.id.treatments_wizard_carbs);
- carbsInsulin = (TextView) view.findViewById(R.id.treatments_wizard_carbsinsulin);
- bolusIobInsulin = (TextView) view.findViewById(R.id.treatments_wizard_bolusiobinsulin);
- basalIobInsulin = (TextView) view.findViewById(R.id.treatments_wizard_basaliobinsulin);
- correctionInsulin = (TextView) view.findViewById(R.id.treatments_wizard_correctioninsulin);
- total = (TextView) view.findViewById(R.id.treatments_wizard_total);
- superbolus = (TextView) view.findViewById(R.id.treatments_wizard_sb);
- superbolusInsulin = (TextView) view.findViewById(R.id.treatments_wizard_sbinsulin);
-
- notesLayout = view.findViewById(R.id.treatments_wizard_notes_layout);
- notesLayout.setVisibility(SP.getBoolean(R.string.key_show_notes_entry_dialogs, false) ? View.VISIBLE : View.GONE);
- notesEdit = (EditText) view.findViewById(R.id.treatment_wizard_notes);
-
- bgTrend = (TextView) view.findViewById(R.id.treatments_wizard_bgtrend);
- bgTrendInsulin = (TextView) view.findViewById(R.id.treatments_wizard_bgtrendinsulin);
- cobLayout = (LinearLayout) view.findViewById(R.id.treatments_wizard_cob_layout);
- cob = (TextView) view.findViewById(R.id.treatments_wizard_cob);
- cobInsulin = (TextView) view.findViewById(R.id.treatments_wizard_cobinsulin);
-
- bgCheckbox = (CheckBox) view.findViewById(R.id.treatments_wizard_bgcheckbox);
- ttCheckbox = (CheckBox) view.findViewById(R.id.treatments_wizard_ttcheckbox);
- bgtrendCheckbox = (CheckBox) view.findViewById(R.id.treatments_wizard_bgtrendcheckbox);
- cobCheckbox = (CheckBox) view.findViewById(R.id.treatments_wizard_cobcheckbox);
- bolusIobCheckbox = (CheckBox) view.findViewById(R.id.treatments_wizard_bolusiobcheckbox);
- basalIobCheckbox = (CheckBox) view.findViewById(R.id.treatments_wizard_basaliobcheckbox);
- superbolusCheckbox = (CheckBox) view.findViewById(R.id.treatments_wizard_sbcheckbox);
- loadCheckedStates();
-
- bgCheckbox.setOnCheckedChangeListener(this);
- ttCheckbox.setOnCheckedChangeListener(this);
- bgtrendCheckbox.setOnCheckedChangeListener(this);
- cobCheckbox.setOnCheckedChangeListener(this);
- basalIobCheckbox.setOnCheckedChangeListener(this);
- bolusIobCheckbox.setOnCheckedChangeListener(this);
- superbolusCheckbox.setOnCheckedChangeListener(this);
-
- profileSpinner = (Spinner) view.findViewById(R.id.treatments_wizard_profile);
- profileSpinner.setOnItemSelectedListener(this);
-
- editCarbTime = (NumberPicker) view.findViewById(R.id.treatments_wizard_carbtimeinput);
- editCorr = (NumberPicker) view.findViewById(R.id.treatments_wizard_correctioninput);
- editCarbs = (NumberPicker) view.findViewById(R.id.treatments_wizard_carbsinput);
- editBg = (NumberPicker) view.findViewById(R.id.treatments_wizard_bginput);
-
- superbolusCheckbox.setVisibility(SP.getBoolean(R.string.key_usesuperbolus, false) ? View.VISIBLE : View.GONE);
-
- Integer maxCarbs = MainApp.getConstraintChecker().getMaxCarbsAllowed().value();
- Double maxCorrection = MainApp.getConstraintChecker().getMaxBolusAllowed().value();
-
- editBg.setParams(0d, 0d, 500d, 0.1d, new DecimalFormat("0.0"), false, textWatcher);
- editCarbs.setParams(0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false, textWatcher);
- double bolusstep = ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().bolusStep;
- editCorr.setParams(0d, -maxCorrection, maxCorrection, bolusstep, DecimalFormatter.pumpSupportedBolusFormat(), false, textWatcher);
- editCarbTime.setParams(0d, -60d, 60d, 5d, new DecimalFormat("0"), false);
- initDialog();
-
- setCancelable(true);
- getDialog().setCanceledOnTouchOutside(false);
- //recovering state if there is something
- if (savedInstanceState != null) {
- editCarbs.setValue(savedInstanceState.getDouble("editCarbs"));
- editBg.setValue(savedInstanceState.getDouble("editBg"));
- editCarbTime.setValue(savedInstanceState.getDouble("editCarbTime"));
- editCorr.setValue(savedInstanceState.getDouble("editCorr"));
- }
- return view;
- }
-
- @Override
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- saveCheckedStates();
- ttCheckbox.setEnabled(bgCheckbox.isChecked() && TreatmentsPlugin.getPlugin().getTempTargetFromHistory() != null);
- calculateInsulin();
- }
-
- private void saveCheckedStates() {
- SP.putBoolean(MainApp.gs(R.string.key_wizard_include_cob), cobCheckbox.isChecked());
- SP.putBoolean(MainApp.gs(R.string.key_wizard_include_trend_bg), bgtrendCheckbox.isChecked());
- }
-
- private void loadCheckedStates() {
- bgtrendCheckbox.setChecked(SP.getBoolean(MainApp.gs(R.string.key_wizard_include_trend_bg), false));
- cobCheckbox.setChecked(SP.getBoolean(MainApp.gs(R.string.key_wizard_include_cob), false));
- }
-
- @Override
- public void onItemSelected(AdapterView> parent, View view, int position, long id) {
- calculateInsulin();
- okButton.setVisibility(View.VISIBLE);
- }
-
- @Override
- public void onNothingSelected(AdapterView> parent) {
- ToastUtils.showToastInUiThread(context, MainApp.gs(R.string.noprofileselected));
- okButton.setVisibility(View.GONE);
- }
-
- @Override
- public synchronized void onClick(View view) {
- switch (view.getId()) {
- case R.id.ok:
- if (okClicked) {
- log.debug("guarding: ok already clicked");
- dismiss();
- return;
- }
- okClicked = true;
- final Profile profile = ProfileFunctions.getInstance().getProfile();
- final PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
-
- if (pump != null && profile != null && (calculatedTotalInsulin > 0d || calculatedCarbs > 0d)) {
- String confirmMessage = MainApp.gs(R.string.entertreatmentquestion);
-
- Double insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(calculatedTotalInsulin)).value();
- Integer carbsAfterConstraints = MainApp.getConstraintChecker().applyCarbsConstraints(new Constraint<>(calculatedCarbs)).value();
-
- if (insulinAfterConstraints > 0)
- confirmMessage += " " + MainApp.gs(R.string.bolus) + ": " + "" + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints) + "U" + " ";
- if (carbsAfterConstraints > 0)
- confirmMessage += " " + MainApp.gs(R.string.carbs) + ": " + "" + carbsAfterConstraints + "g" + " ";
-
- if (Math.abs(insulinAfterConstraints - calculatedTotalInsulin) > pump.getPumpDescription().pumpType.determineCorrectBolusSize(insulinAfterConstraints) || !carbsAfterConstraints.equals(calculatedCarbs)) {
- confirmMessage += "" + MainApp.gs(R.string.bolusconstraintapplied) + " ";
- }
-
- final Double finalInsulinAfterConstraints = insulinAfterConstraints;
- final Integer finalCarbsAfterConstraints = carbsAfterConstraints;
- final Double bg = SafeParse.stringToDouble(editBg.getText());
- final int carbTime = SafeParse.stringToInt(editCarbTime.getText());
- final boolean useSuperBolus = superbolusCheckbox.isChecked();
- final String finalNotes = notesEdit.getText().toString();
-
- final AlertDialog.Builder builder = new AlertDialog.Builder(context);
- builder.setTitle(MainApp.gs(R.string.confirmation));
- builder.setMessage(Html.fromHtml(confirmMessage));
- builder.setPositiveButton(MainApp.gs(R.string.ok), new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- synchronized (builder) {
- if (accepted) {
- log.debug("guarding: already accepted");
- return;
- }
- accepted = true;
- if (finalInsulinAfterConstraints > 0 || finalCarbsAfterConstraints > 0) {
- if (useSuperBolus) {
- final LoopPlugin loopPlugin = LoopPlugin.getPlugin();
- if (loopPlugin.isEnabled(PluginType.LOOP)) {
- loopPlugin.superBolusTo(System.currentTimeMillis() + 2 * 60L * 60 * 1000);
- MainApp.bus().post(new EventRefreshOverview("WizardDialog"));
- }
- ConfigBuilderPlugin.getPlugin().getCommandQueue().tempBasalPercent(0, 120, true, profile, new Callback() {
- @Override
- public void run() {
- if (!result.success) {
- Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
- i.putExtra("soundid", R.raw.boluserror);
- i.putExtra("status", result.comment);
- i.putExtra("title", MainApp.gs(R.string.tempbasaldeliveryerror));
- i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- MainApp.instance().startActivity(i);
- }
- }
- });
- }
- DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
- detailedBolusInfo.eventType = CareportalEvent.BOLUSWIZARD;
- detailedBolusInfo.insulin = finalInsulinAfterConstraints;
- detailedBolusInfo.carbs = finalCarbsAfterConstraints;
- detailedBolusInfo.context = context;
- detailedBolusInfo.glucose = bg;
- detailedBolusInfo.glucoseType = "Manual";
- detailedBolusInfo.carbTime = carbTime;
- detailedBolusInfo.boluscalc = boluscalcJSON;
- detailedBolusInfo.source = Source.USER;
- detailedBolusInfo.notes = finalNotes;
- if (detailedBolusInfo.insulin > 0 || ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().storesCarbInfo) {
- ConfigBuilderPlugin.getPlugin().getCommandQueue().bolus(detailedBolusInfo, new Callback() {
- @Override
- public void run() {
- if (!result.success) {
- Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
- i.putExtra("soundid", R.raw.boluserror);
- i.putExtra("status", result.comment);
- i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror));
- i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- MainApp.instance().startActivity(i);
- }
- }
- });
- } else {
- TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false);
- }
- }
- }
- }
- });
- builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
- builder.show();
- dismiss();
- }
- break;
- case R.id.cancel:
- dismiss();
- break;
- }
- }
-
- private void initDialog() {
- Profile profile = ProfileFunctions.getInstance().getProfile();
- ProfileStore profileStore = ConfigBuilderPlugin.getPlugin().getActiveProfileInterface() != null ? ConfigBuilderPlugin.getPlugin().getActiveProfileInterface().getProfile() : null;
-
- if (profile == null || profileStore == null) {
- ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.noprofile));
- dismiss();
- return;
- }
-
- ArrayList profileList;
- profileList = profileStore.getProfileList();
- profileList.add(0, MainApp.gs(R.string.active));
- ArrayAdapter adapter = new ArrayAdapter<>(getContext(),
- R.layout.spinner_centered, profileList);
-
- profileSpinner.setAdapter(adapter);
-
- String units = profile.getUnits();
- bgUnits.setText(units);
- if (units.equals(Constants.MGDL)) editBg.setStep(1d);
- else editBg.setStep(0.1d);
-
- // Set BG if not old
- BgReading lastBg = DatabaseHelper.actualBg();
-
- if (lastBg != null) {
- editBg.setValue(lastBg.valueToUnits(units));
- } else {
- editBg.setValue(0d);
- }
- ttCheckbox.setEnabled(TreatmentsPlugin.getPlugin().getTempTargetFromHistory() != null);
-
- // IOB calculation
- TreatmentsPlugin.getPlugin().updateTotalIOBTreatments();
- IobTotal bolusIob = TreatmentsPlugin.getPlugin().getLastCalculationTreatments().round();
- TreatmentsPlugin.getPlugin().updateTotalIOBTempBasals();
- IobTotal basalIob = TreatmentsPlugin.getPlugin().getLastCalculationTempBasals().round();
-
- bolusIobInsulin.setText(DecimalFormatter.to2Decimal(-bolusIob.iob) + "U");
- basalIobInsulin.setText(DecimalFormatter.to2Decimal(-basalIob.basaliob) + "U");
-
- calculateInsulin();
- }
-
- private void calculateInsulin() {
- ProfileStore profileStore = ConfigBuilderPlugin.getPlugin().getActiveProfileInterface().getProfile();
- if (profileSpinner == null || profileSpinner.getSelectedItem() == null || profileStore == null)
- return; // not initialized yet
- String selectedAlternativeProfile = profileSpinner.getSelectedItem().toString();
- Profile specificProfile;
- if (selectedAlternativeProfile.equals(MainApp.gs(R.string.active))) {
- specificProfile = ProfileFunctions.getInstance().getProfile();
- selectedAlternativeProfile = ProfileFunctions.getInstance().getProfileName();
- } else
- specificProfile = profileStore.getSpecificProfile(selectedAlternativeProfile);
-
- // Entered values
- Double c_bg = SafeParse.stringToDouble(editBg.getText());
- Integer c_carbs = SafeParse.stringToInt(editCarbs.getText());
- Double c_correction = SafeParse.stringToDouble(editCorr.getText());
- Double corrAfterConstraint = c_correction;
- if (c_correction > 0)
- c_correction = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(c_correction)).value();
- if (Math.abs(c_correction - corrAfterConstraint) > 0.01d) { // c_correction != corrAfterConstraint doesn't work
- editCorr.setValue(0d);
- ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.bolusconstraintapplied));
- return;
- }
- Integer carbsAfterConstraint = MainApp.getConstraintChecker().applyCarbsConstraints(new Constraint<>(c_carbs)).value();
- if (Math.abs(c_carbs - carbsAfterConstraint) > 0.01d) {
- editCarbs.setValue(0d);
- ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.carbsconstraintapplied));
- return;
- }
-
- c_bg = bgCheckbox.isChecked() ? c_bg : 0d;
- TempTarget tempTarget = ttCheckbox.isChecked() ? TreatmentsPlugin.getPlugin().getTempTargetFromHistory() : null;
-
- // COB
- Double c_cob = 0d;
- if (cobCheckbox.isChecked()) {
- CobInfo cobInfo = IobCobCalculatorPlugin.getPlugin().getCobInfo(false, "Wizard COB");
- if (cobInfo != null && cobInfo.displayCob != null)
- c_cob = cobInfo.displayCob;
- }
-
- BolusWizard wizard = new BolusWizard();
- wizard.doCalc(specificProfile, tempTarget, carbsAfterConstraint, c_cob, c_bg, corrAfterConstraint, bolusIobCheckbox.isChecked(), basalIobCheckbox.isChecked(), superbolusCheckbox.isChecked(), bgtrendCheckbox.isChecked());
-
- bg.setText(c_bg + " ISF: " + DecimalFormatter.to1Decimal(wizard.sens));
- bgInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulinFromBG) + "U");
-
- carbs.setText(DecimalFormatter.to0Decimal(c_carbs) + "g IC: " + DecimalFormatter.to1Decimal(wizard.ic));
- carbsInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulinFromCarbs) + "U");
-
- bolusIobInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulingFromBolusIOB) + "U");
- basalIobInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulingFromBasalsIOB) + "U");
-
- correctionInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulinFromCorrection) + "U");
- calculatedTotalInsulin = wizard.calculatedTotalInsulin;
-
- calculatedCarbs = carbsAfterConstraint;
-
- // Superbolus
- if (superbolusCheckbox.isChecked()) {
- superbolus.setText("2h");
- } else {
- superbolus.setText("");
- }
- superbolusInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulinFromSuperBolus) + "U");
-
- // Trend
- if (bgtrendCheckbox.isChecked()) {
- if (wizard.glucoseStatus != null) {
- bgTrend.setText((wizard.glucoseStatus.avgdelta > 0 ? "+" : "") + Profile.toUnitsString(wizard.glucoseStatus.avgdelta * 3, wizard.glucoseStatus.avgdelta * 3 / 18, specificProfile.getUnits()) + " " + specificProfile.getUnits());
- } else {
- bgTrend.setText("");
- }
- } else {
- bgTrend.setText("");
- }
- bgTrendInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulinFromTrend) + "U");
-
- // COB
- if (cobCheckbox.isChecked()) {
- cob.setText(DecimalFormatter.to2Decimal(c_cob) + "g IC: " + DecimalFormatter.to1Decimal(wizard.ic));
- cobInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulinFromCOB) + "U");
- } else {
- cob.setText("");
- cobInsulin.setText("");
- }
-
- if (calculatedTotalInsulin > 0d || calculatedCarbs > 0d) {
- String insulinText = calculatedTotalInsulin > 0d ? (DecimalFormatter.toPumpSupportedBolus(calculatedTotalInsulin) + "U") : "";
- String carbsText = calculatedCarbs > 0d ? (DecimalFormatter.to0Decimal(calculatedCarbs) + "g") : "";
- total.setText(MainApp.gs(R.string.result) + ": " + insulinText + " " + carbsText);
- okButton.setVisibility(View.VISIBLE);
- } else {
- // TODO this should also be run when loading the dialog as the OK button is initially visible
- // but does nothing if neither carbs nor insulin is > 0
- total.setText(MainApp.gs(R.string.missing) + " " + DecimalFormatter.to0Decimal(wizard.carbsEquivalent) + "g");
- okButton.setVisibility(View.INVISIBLE);
- }
-
- boluscalcJSON = new JSONObject();
- try {
- boluscalcJSON.put("profile", selectedAlternativeProfile);
- boluscalcJSON.put("notes", notesEdit.getText());
- boluscalcJSON.put("eventTime", DateUtil.toISOString(new Date()));
- boluscalcJSON.put("targetBGLow", wizard.targetBGLow);
- boluscalcJSON.put("targetBGHigh", wizard.targetBGHigh);
- boluscalcJSON.put("isf", wizard.sens);
- boluscalcJSON.put("ic", wizard.ic);
- boluscalcJSON.put("iob", -(wizard.insulingFromBolusIOB + wizard.insulingFromBasalsIOB));
- boluscalcJSON.put("bolusiob", wizard.insulingFromBolusIOB);
- boluscalcJSON.put("basaliob", wizard.insulingFromBasalsIOB);
- boluscalcJSON.put("bolusiobused", bolusIobCheckbox.isChecked());
- boluscalcJSON.put("basaliobused", basalIobCheckbox.isChecked());
- boluscalcJSON.put("bg", c_bg);
- boluscalcJSON.put("insulinbg", wizard.insulinFromBG);
- boluscalcJSON.put("insulinbgused", bgCheckbox.isChecked());
- boluscalcJSON.put("bgdiff", wizard.bgDiff);
- boluscalcJSON.put("insulincarbs", wizard.insulinFromCarbs);
- boluscalcJSON.put("carbs", c_carbs);
- boluscalcJSON.put("cob", c_cob);
- boluscalcJSON.put("cobused", cobCheckbox.isChecked());
- boluscalcJSON.put("insulincob", wizard.insulinFromCOB);
- boluscalcJSON.put("othercorrection", corrAfterConstraint);
- boluscalcJSON.put("insulinsuperbolus", wizard.insulinFromSuperBolus);
- boluscalcJSON.put("insulintrend", wizard.insulinFromTrend);
- boluscalcJSON.put("insulin", calculatedTotalInsulin);
- boluscalcJSON.put("superbolusused", superbolusCheckbox.isChecked());
- boluscalcJSON.put("insulinsuperbolus", wizard.insulinFromSuperBolus);
- boluscalcJSON.put("trendused", bgtrendCheckbox.isChecked());
- boluscalcJSON.put("insulintrend", wizard.insulinFromTrend);
- boluscalcJSON.put("trend", bgTrend.getText());
- boluscalcJSON.put("ttused", ttCheckbox.isChecked());
- } catch (JSONException e) {
- log.error("Unhandled exception", e);
- }
- }
-
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/WizardDialog.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/WizardDialog.kt
new file mode 100644
index 0000000000..552ab502e7
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/WizardDialog.kt
@@ -0,0 +1,350 @@
+package info.nightscout.androidaps.plugins.general.overview.dialogs
+
+import android.content.Context
+import android.os.Bundle
+import android.text.Editable
+import android.text.TextWatcher
+import android.view.*
+import android.widget.AdapterView
+import android.widget.AdapterView.OnItemSelectedListener
+import android.widget.ArrayAdapter
+import android.widget.CompoundButton
+import androidx.fragment.app.DialogFragment
+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.db.BgReading
+import info.nightscout.androidaps.db.DatabaseHelper
+import info.nightscout.androidaps.interfaces.Constraint
+import info.nightscout.androidaps.plugins.bus.RxBus
+import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
+import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions
+import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
+import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished
+import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
+import info.nightscout.androidaps.utils.*
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.disposables.CompositeDisposable
+import kotlinx.android.synthetic.main.overview_wizard_dialog.*
+import org.slf4j.LoggerFactory
+import java.text.DecimalFormat
+import java.util.*
+import kotlin.math.abs
+
+class WizardDialog : DialogFragment() {
+ private val log = LoggerFactory.getLogger(WizardDialog::class.java)
+
+ private var wizard: BolusWizard? = null
+ private var parentContext: Context? = null
+
+ //one shot guards
+ private var okClicked: Boolean = false
+
+ private val textWatcher = object : TextWatcher {
+ override fun afterTextChanged(s: Editable) {}
+
+ override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
+
+ override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
+ calculateInsulin()
+ }
+ }
+
+ private var disposable: CompositeDisposable = CompositeDisposable()
+
+ override fun onAttach(context: Context) {
+ super.onAttach(context)
+ this.parentContext = context
+ }
+
+ override fun onStart() {
+ super.onStart()
+ dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
+ }
+
+ override fun onDetach() {
+ super.onDetach()
+ this.parentContext = null
+ }
+
+ override fun onSaveInstanceState(savedInstanceState: Bundle) {
+ super.onSaveInstanceState(savedInstanceState)
+ savedInstanceState.putDouble("treatments_wizard_bg_input", treatments_wizard_bg_input.value)
+ savedInstanceState.putDouble("treatments_wizard_carbs_input", treatments_wizard_carbs_input.value)
+ savedInstanceState.putDouble("treatments_wizard_correction_input", treatments_wizard_correction_input.value)
+ savedInstanceState.putDouble("treatments_wizard_carb_time_input", treatments_wizard_carb_time_input.value)
+ }
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?): View? {
+ dialog?.window?.requestFeature(Window.FEATURE_NO_TITLE)
+ dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)
+ isCancelable = true
+ dialog?.setCanceledOnTouchOutside(false)
+
+ return inflater.inflate(R.layout.overview_wizard_dialog, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ loadCheckedStates()
+ processCobCheckBox()
+ treatments_wizard_sbcheckbox.visibility = if (SP.getBoolean(R.string.key_usesuperbolus, false)) View.VISIBLE else View.GONE
+ treatments_wizard_notes_layout.visibility = if (SP.getBoolean(R.string.key_show_notes_entry_dialogs, false)) View.VISIBLE else View.GONE
+
+ val maxCarbs = MainApp.getConstraintChecker().maxCarbsAllowed.value()
+ val maxCorrection = MainApp.getConstraintChecker().maxBolusAllowed.value()
+
+ treatments_wizard_bg_input.setParams(savedInstanceState?.getDouble("treatments_wizard_bg_input")
+ ?: 0.0, 0.0, 500.0, 0.1, DecimalFormat("0.0"), false, ok, textWatcher)
+ treatments_wizard_carbs_input.setParams(savedInstanceState?.getDouble("treatments_wizard_carbs_input")
+ ?: 0.0, 0.0, maxCarbs.toDouble(), 1.0, DecimalFormat("0"), false, ok, textWatcher)
+ val bolusStep = ConfigBuilderPlugin.getPlugin().activePump?.pumpDescription?.bolusStep
+ ?: 0.1
+ treatments_wizard_correction_input.setParams(savedInstanceState?.getDouble("treatments_wizard_correction_input")
+ ?: 0.0, -maxCorrection, maxCorrection, bolusStep, DecimalFormatter.pumpSupportedBolusFormat(), false, ok, textWatcher)
+ treatments_wizard_carb_time_input.setParams(savedInstanceState?.getDouble("treatments_wizard_carb_time_input")
+ ?: 0.0, -60.0, 60.0, 5.0, DecimalFormat("0"), false, ok, textWatcher)
+ initDialog()
+
+ treatments_wizard_percent_used.text = MainApp.gs(R.string.format_percent, SP.getInt(R.string.key_boluswizard_percentage, 100))
+ // ok button
+ ok.setOnClickListener {
+ if (okClicked) {
+ log.debug("guarding: ok already clicked")
+ } else {
+ okClicked = true
+ parentContext?.let { context ->
+ wizard?.confirmAndExecute(context)
+ }
+ }
+ dismiss()
+ }
+ // cancel button
+ cancel.setOnClickListener { dismiss() }
+ // checkboxes
+ treatments_wizard_bgcheckbox.setOnCheckedChangeListener { buttonView, _ -> onCheckedChanged(buttonView) }
+ treatments_wizard_ttcheckbox.setOnCheckedChangeListener { buttonView, _ -> onCheckedChanged(buttonView) }
+ treatments_wizard_cobcheckbox.setOnCheckedChangeListener { buttonView, _ -> onCheckedChanged(buttonView) }
+ treatments_wizard_basaliobcheckbox.setOnCheckedChangeListener { buttonView, _ -> onCheckedChanged(buttonView) }
+ treatments_wizard_bolusiobcheckbox.setOnCheckedChangeListener { buttonView, _ -> onCheckedChanged(buttonView) }
+ treatments_wizard_bgtrendcheckbox.setOnCheckedChangeListener { buttonView, _ -> onCheckedChanged(buttonView) }
+ treatments_wizard_sbcheckbox.setOnCheckedChangeListener { buttonView, _ -> onCheckedChanged(buttonView) }
+
+ val showCalc = SP.getBoolean(MainApp.gs(R.string.key_wizard_calculation_visible), false)
+ treatments_wizard_delimiter.visibility = if (showCalc) View.VISIBLE else View.GONE
+ treatments_wizard_resulttable.visibility = if (showCalc) View.VISIBLE else View.GONE
+ treatments_wizard_calculationcheckbox.isChecked = showCalc
+ treatments_wizard_calculationcheckbox.setOnCheckedChangeListener { _, isChecked ->
+ run {
+ SP.putBoolean(MainApp.gs(R.string.key_wizard_calculation_visible), isChecked)
+ treatments_wizard_delimiter.visibility = if (isChecked) View.VISIBLE else View.GONE
+ treatments_wizard_resulttable.visibility = if (isChecked) View.VISIBLE else View.GONE
+ }
+ }
+ // profile spinner
+ treatments_wizard_profile.onItemSelectedListener = object : OnItemSelectedListener {
+ override fun onNothingSelected(parent: AdapterView<*>?) {
+ ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.noprofileselected))
+ ok.visibility = View.GONE
+ }
+
+ override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
+ calculateInsulin()
+ ok.visibility = View.VISIBLE
+ }
+ }
+ // bus
+ disposable.add(RxBus
+ .toObservable(EventAutosensCalculationFinished::class.java)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe({
+ activity?.runOnUiThread { calculateInsulin() }
+ }, {
+ FabricPrivacy.logException(it)
+ })
+ )
+
+ }
+
+ override fun onDestroyView() {
+ super.onDestroyView()
+ disposable.clear()
+ }
+
+ private fun onCheckedChanged(buttonView: CompoundButton) {
+ saveCheckedStates()
+ treatments_wizard_ttcheckbox.isEnabled = treatments_wizard_bgcheckbox.isChecked && TreatmentsPlugin.getPlugin().tempTargetFromHistory != null
+ if (buttonView.id == treatments_wizard_cobcheckbox.id)
+ processCobCheckBox()
+ calculateInsulin()
+ }
+
+ private fun processCobCheckBox() {
+ if (treatments_wizard_cobcheckbox.isChecked) {
+ treatments_wizard_bolusiobcheckbox.isEnabled = false
+ treatments_wizard_basaliobcheckbox.isEnabled = false
+ treatments_wizard_bolusiobcheckbox.isChecked = true
+ treatments_wizard_basaliobcheckbox.isChecked = true
+ } else {
+ treatments_wizard_bolusiobcheckbox.isEnabled = true
+ treatments_wizard_basaliobcheckbox.isEnabled = true
+ }
+ }
+
+ private fun saveCheckedStates() {
+ SP.putBoolean(MainApp.gs(R.string.key_wizard_include_cob), treatments_wizard_cobcheckbox.isChecked)
+ SP.putBoolean(MainApp.gs(R.string.key_wizard_include_trend_bg), treatments_wizard_bgtrendcheckbox.isChecked)
+ }
+
+ private fun loadCheckedStates() {
+ treatments_wizard_bgtrendcheckbox.isChecked = SP.getBoolean(MainApp.gs(R.string.key_wizard_include_trend_bg), false)
+ treatments_wizard_cobcheckbox.isChecked = SP.getBoolean(MainApp.gs(R.string.key_wizard_include_cob), false)
+ }
+
+ private fun initDialog() {
+ val profile = ProfileFunctions.getInstance().profile
+ val profileStore = ConfigBuilderPlugin.getPlugin().activeProfileInterface?.profile
+
+ if (profile == null || profileStore == null) {
+ ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.noprofile))
+ dismiss()
+ return
+ }
+
+ val profileList: ArrayList
+ profileList = profileStore.profileList
+ profileList.add(0, MainApp.gs(R.string.active))
+ context?.let { context ->
+ val adapter = ArrayAdapter(context, R.layout.spinner_centered, profileList)
+ treatments_wizard_profile.adapter = adapter
+ } ?: return
+
+
+ val units = profile.units
+ treatments_wizard_bgunits.text = units
+ if (units == Constants.MGDL)
+ treatments_wizard_bg_input.setStep(1.0)
+ else
+ treatments_wizard_bg_input.setStep(0.1)
+
+ // Set BG if not old
+ val lastBg = DatabaseHelper.actualBg()
+
+ if (lastBg != null) {
+ treatments_wizard_bg_input.value = lastBg.valueToUnits(units)
+ } else {
+ treatments_wizard_bg_input.value = 0.0
+ }
+ treatments_wizard_ttcheckbox.isEnabled = TreatmentsPlugin.getPlugin().tempTargetFromHistory != null
+
+ // IOB calculation
+ TreatmentsPlugin.getPlugin().updateTotalIOBTreatments()
+ val bolusIob = TreatmentsPlugin.getPlugin().lastCalculationTreatments.round()
+ TreatmentsPlugin.getPlugin().updateTotalIOBTempBasals()
+ val basalIob = TreatmentsPlugin.getPlugin().lastCalculationTempBasals.round()
+
+ treatments_wizard_bolusiobinsulin.text = StringUtils.formatInsulin(-bolusIob.iob)
+ treatments_wizard_basaliobinsulin.text = StringUtils.formatInsulin(-basalIob.basaliob)
+
+ calculateInsulin()
+
+ treatments_wizard_percent_used.visibility = if (SP.getInt(R.string.key_boluswizard_percentage, 100) != 100) View.VISIBLE else View.GONE
+ }
+
+ private fun calculateInsulin() {
+ val profileStore = ConfigBuilderPlugin.getPlugin().activeProfileInterface?.profile
+ if (treatments_wizard_profile.selectedItem == null || profileStore == null)
+ return // not initialized yet
+ var profileName = treatments_wizard_profile.selectedItem.toString()
+ val specificProfile: Profile?
+ if (profileName == MainApp.gs(R.string.active)) {
+ specificProfile = ProfileFunctions.getInstance().profile
+ profileName = ProfileFunctions.getInstance().profileName
+ } else
+ specificProfile = profileStore.getSpecificProfile(profileName)
+
+ if (specificProfile == null) return
+
+ // Entered values
+ var bg = SafeParse.stringToDouble(treatments_wizard_bg_input.text)
+ val carbs = SafeParse.stringToInt(treatments_wizard_carbs_input.text)
+ val correction = SafeParse.stringToDouble(treatments_wizard_correction_input.text)
+ val carbsAfterConstraint = MainApp.getConstraintChecker().applyCarbsConstraints(Constraint(carbs)).value()
+ if (abs(carbs - carbsAfterConstraint) > 0.01) {
+ treatments_wizard_carbs_input.value = 0.0
+ ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.carbsconstraintapplied))
+ return
+ }
+
+ bg = if (treatments_wizard_bgcheckbox.isChecked) bg else 0.0
+ val tempTarget = if (treatments_wizard_ttcheckbox.isChecked) TreatmentsPlugin.getPlugin().tempTargetFromHistory else null
+
+ // COB
+ var cob = 0.0
+ if (treatments_wizard_cobcheckbox.isChecked) {
+ val cobInfo = IobCobCalculatorPlugin.getPlugin().getCobInfo(false, "Wizard COB")
+ cobInfo.displayCob?.let { cob = it }
+ }
+
+ val carbTime = SafeParse.stringToInt(treatments_wizard_carb_time_input.text)
+
+ wizard = BolusWizard(specificProfile, profileName, tempTarget, carbsAfterConstraint, cob, bg, correction,
+ SP.getInt(R.string.key_boluswizard_percentage, 100).toDouble(),
+ treatments_wizard_bgcheckbox.isChecked,
+ treatments_wizard_cobcheckbox.isChecked,
+ treatments_wizard_bolusiobcheckbox.isChecked,
+ treatments_wizard_basaliobcheckbox.isChecked,
+ treatments_wizard_sbcheckbox.isChecked,
+ treatments_wizard_ttcheckbox.isChecked,
+ treatments_wizard_bgtrendcheckbox.isChecked,
+ treatment_wizard_notes.text.toString(), carbTime)
+
+ wizard?.let { wizard ->
+ treatments_wizard_bg.text = String.format(MainApp.gs(R.string.format_bg_isf), BgReading().value(Profile.toMgdl(bg, specificProfile.units)).valueToUnitsToString(specificProfile.units), wizard.sens)
+ treatments_wizard_bginsulin.text = StringUtils.formatInsulin(wizard.insulinFromBG)
+
+ treatments_wizard_carbs.text = String.format(MainApp.gs(R.string.format_carbs_ic), carbs.toDouble(), wizard.ic)
+ treatments_wizard_carbsinsulin.text = StringUtils.formatInsulin(wizard.insulinFromCarbs)
+
+ treatments_wizard_bolusiobinsulin.text = StringUtils.formatInsulin(wizard.insulinFromBolusIOB)
+ treatments_wizard_basaliobinsulin.text = StringUtils.formatInsulin(wizard.insulinFromBasalsIOB)
+
+ treatments_wizard_correctioninsulin.text = StringUtils.formatInsulin(wizard.insulinFromCorrection)
+
+ // Superbolus
+ treatments_wizard_sb.text = if (treatments_wizard_sbcheckbox.isChecked) MainApp.gs(R.string.twohours) else ""
+ treatments_wizard_sbinsulin.text = StringUtils.formatInsulin(wizard.insulinFromSuperBolus)
+
+ // Trend
+ if (treatments_wizard_bgtrendcheckbox.isChecked && wizard.glucoseStatus != null) {
+ treatments_wizard_bgtrend.text = ((if (wizard.trend > 0) "+" else "")
+ + Profile.toUnitsString(wizard.trend * 3, wizard.trend * 3 / Constants.MMOLL_TO_MGDL, specificProfile.units)
+ + " " + specificProfile.units)
+ } else {
+ treatments_wizard_bgtrend.text = ""
+ }
+ treatments_wizard_bgtrendinsulin.text = StringUtils.formatInsulin(wizard.insulinFromTrend)
+
+ // COB
+ if (treatments_wizard_cobcheckbox.isChecked) {
+ treatments_wizard_cob.text = String.format(MainApp.gs(R.string.format_cob_ic), cob, wizard.ic)
+ treatments_wizard_cobinsulin.text = StringUtils.formatInsulin(wizard.insulinFromCOB)
+ } else {
+ treatments_wizard_cob.text = ""
+ treatments_wizard_cobinsulin.text = ""
+ }
+
+ if (wizard.calculatedTotalInsulin > 0.0 || carbsAfterConstraint > 0.0) {
+ val insulinText = if (wizard.calculatedTotalInsulin > 0.0) MainApp.gs(R.string.formatinsulinunits, wizard.calculatedTotalInsulin) else ""
+ val carbsText = if (carbsAfterConstraint > 0.0) MainApp.gs(R.string.format_carbs, carbsAfterConstraint) else ""
+ treatments_wizard_total.text = MainApp.gs(R.string.result_insulin_carbs, insulinText, carbsText)
+ ok.visibility = View.VISIBLE
+ } else {
+ treatments_wizard_total.text = MainApp.gs(R.string.missing_carbs, wizard.carbsEquivalent.toInt())
+ ok.visibility = View.INVISIBLE
+ }
+ }
+
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/events/EventDismissBolusProgressIfRunning.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/events/EventDismissBolusProgressIfRunning.kt
new file mode 100644
index 0000000000..53ab699d9c
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/events/EventDismissBolusProgressIfRunning.kt
@@ -0,0 +1,6 @@
+package info.nightscout.androidaps.plugins.general.overview.events
+
+import info.nightscout.androidaps.data.PumpEnactResult
+import info.nightscout.androidaps.events.Event
+
+class EventDismissBolusProgressIfRunning(val result: PumpEnactResult?) : Event()
\ No newline at end of file
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/events/EventDismissBolusprogressIfRunning.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/events/EventDismissBolusprogressIfRunning.java
deleted file mode 100644
index 2022a4d74b..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/events/EventDismissBolusprogressIfRunning.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package info.nightscout.androidaps.plugins.general.overview.events;
-
-import info.nightscout.androidaps.data.PumpEnactResult;
-import info.nightscout.androidaps.events.Event;
-
-/**
- * Created by adrian on 20/02/17.
- */
-
-public class EventDismissBolusprogressIfRunning extends Event {
- public final PumpEnactResult result;
-
- public EventDismissBolusprogressIfRunning(PumpEnactResult result) {
- this.result = result;
- }
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/events/EventDismissNotification.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/events/EventDismissNotification.java
deleted file mode 100644
index bc13c93970..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/events/EventDismissNotification.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package info.nightscout.androidaps.plugins.general.overview.events;
-
-import info.nightscout.androidaps.events.Event;
-
-/**
- * Created by mike on 03.12.2016.
- */
-
-public class EventDismissNotification extends Event {
- public int id;
-
- public EventDismissNotification(int did) {
- id = did;
- }
-
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/events/EventDismissNotification.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/events/EventDismissNotification.kt
new file mode 100644
index 0000000000..bd719ecac8
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/events/EventDismissNotification.kt
@@ -0,0 +1,5 @@
+package info.nightscout.androidaps.plugins.general.overview.events
+
+import info.nightscout.androidaps.events.Event
+
+class EventDismissNotification(var id: Int) : Event()
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/events/EventNewNotification.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/events/EventNewNotification.java
deleted file mode 100644
index f6b62b7f83..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/events/EventNewNotification.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package info.nightscout.androidaps.plugins.general.overview.events;
-
-import info.nightscout.androidaps.events.Event;
-import info.nightscout.androidaps.plugins.general.overview.notifications.Notification;
-
-/**
- * Created by mike on 03.12.2016.
- */
-
-public class EventNewNotification extends Event {
- public Notification notification;
-
- public EventNewNotification(Notification n) {
- notification = n;
- }
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/events/EventNewNotification.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/events/EventNewNotification.kt
new file mode 100644
index 0000000000..b70af5bfe1
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/events/EventNewNotification.kt
@@ -0,0 +1,6 @@
+package info.nightscout.androidaps.plugins.general.overview.events
+
+import info.nightscout.androidaps.events.Event
+import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
+
+class EventNewNotification(var notification: Notification) : Event()
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/events/EventOverviewBolusProgress.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/events/EventOverviewBolusProgress.java
deleted file mode 100644
index 3a7c50faac..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/events/EventOverviewBolusProgress.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package info.nightscout.androidaps.plugins.general.overview.events;
-
-import info.nightscout.androidaps.plugins.treatments.Treatment;
-import info.nightscout.androidaps.events.Event;
-
-public class EventOverviewBolusProgress extends Event {
- public String status = "";
- public Treatment t = null;
- public int percent = 0;
- public int bolusId;
- private static EventOverviewBolusProgress eventOverviewBolusProgress = null;
-
- public EventOverviewBolusProgress() {
- }
-
- public boolean isSMB(){
- return (t != null) && t.isSMB;
- }
-
- public static EventOverviewBolusProgress getInstance() {
- if(eventOverviewBolusProgress == null) {
- eventOverviewBolusProgress = new EventOverviewBolusProgress();
- }
- return eventOverviewBolusProgress;
- }
-
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/events/EventOverviewBolusProgress.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/events/EventOverviewBolusProgress.kt
new file mode 100644
index 0000000000..52b62790da
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/events/EventOverviewBolusProgress.kt
@@ -0,0 +1,12 @@
+package info.nightscout.androidaps.plugins.general.overview.events
+
+import info.nightscout.androidaps.plugins.treatments.Treatment
+import info.nightscout.androidaps.events.Event
+
+object EventOverviewBolusProgress : Event() {
+ var status = ""
+ var t: Treatment? = null
+ var percent = 0
+
+ fun isSMB(): Boolean = t?.isSMB ?: false
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/events/EventQuickWizardChange.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/events/EventQuickWizardChange.java
deleted file mode 100644
index 7b070d160e..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/events/EventQuickWizardChange.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package info.nightscout.androidaps.plugins.general.overview.events;
-
-import info.nightscout.androidaps.events.Event;
-
-/**
- * Created by mike on 20.10.2016.
- */
-
-public class EventQuickWizardChange extends Event {
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/events/EventQuickWizardChange.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/events/EventQuickWizardChange.kt
new file mode 100644
index 0000000000..7cfa02f3ba
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/events/EventQuickWizardChange.kt
@@ -0,0 +1,5 @@
+package info.nightscout.androidaps.plugins.general.overview.events
+
+import info.nightscout.androidaps.events.Event
+
+class EventQuickWizardChange : Event()
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphData/GraphData.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphData/GraphData.java
index c081567a4c..6de3e2c335 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphData/GraphData.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphData/GraphData.java
@@ -21,6 +21,7 @@ import java.util.List;
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.CareportalEvent;
@@ -28,13 +29,11 @@ import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.ProfileSwitch;
import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.logging.L;
-import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
-import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
-import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensData;
-import info.nightscout.androidaps.plugins.iob.iobCobCalculator.BasalData;
-import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.aps.loop.APSResult;
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
+import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults;
+import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
+import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.AreaGraphSeries;
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface;
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DoubleDataPoint;
@@ -43,9 +42,15 @@ import info.nightscout.androidaps.plugins.general.overview.graphExtensions.Point
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.Scale;
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.ScaledDataPoint;
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.TimeAsXAxisLabelFormatter;
+import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensData;
+import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult;
+import info.nightscout.androidaps.plugins.iob.iobCobCalculator.BasalData;
+import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.treatments.Treatment;
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
+import info.nightscout.androidaps.utils.DecimalFormatter;
import info.nightscout.androidaps.utils.Round;
+import info.nightscout.androidaps.utils.SP;
/**
* Created by mike on 18.10.2017.
@@ -344,8 +349,62 @@ public class GraphData {
? Profile.fromMgdlToUnits(bgReadingsArray.get(0).value, units) : Profile.fromMgdlToUnits(100, units);
}
+ public void addActivity(long fromTime, long toTime, boolean useForScale, double scale) {
+ FixedLineGraphSeries actSeriesHist;
+ List actArrayHist = new ArrayList<>();
+ FixedLineGraphSeries actSeriesPred;
+ List actArrayPred = new ArrayList<>();
+
+ double now = System.currentTimeMillis();
+ Scale actScale = new Scale();
+ IobTotal total;
+ double maxIAValue = 0;
+
+ for (long time = fromTime; time <= toTime; time += 5 * 60 * 1000L) {
+ Profile profile = ProfileFunctions.getInstance().getProfile(time);
+ double act = 0d;
+ if (profile == null) continue;
+ total = iobCobCalculatorPlugin.calculateFromTreatmentsAndTempsSynchronized(time, profile);
+ act = total.activity;
+
+ if (time <= now)
+ actArrayHist.add(new ScaledDataPoint(time, act, actScale));
+ else
+ actArrayPred.add(new ScaledDataPoint(time, act, actScale));
+ if (act > maxIAValue) maxIAValue = act;
+ }
+
+ ScaledDataPoint[] actData = new ScaledDataPoint[actArrayHist.size()];
+ actData = actArrayHist.toArray(actData);
+ actSeriesHist = new FixedLineGraphSeries<>(actData);
+ actSeriesHist.setDrawBackground(false);
+ actSeriesHist.setColor(MainApp.gc(R.color.activity));
+ actSeriesHist.setThickness(3);
+
+ addSeries(actSeriesHist);
+
+ actData = new ScaledDataPoint[actArrayPred.size()];
+ actData = actArrayPred.toArray(actData);
+ actSeriesPred = new FixedLineGraphSeries<>(actData);
+
+ Paint paint = new Paint();
+ paint.setStyle(Paint.Style.STROKE);
+ paint.setStrokeWidth(3);
+ paint.setPathEffect(new DashPathEffect(new float[]{4, 4}, 0));
+ paint.setColor(MainApp.gc(R.color.activity));
+ actSeriesPred.setCustomPaint(paint);
+
+ if (useForScale) {
+ maxY = maxIAValue;
+ minY = -maxIAValue;
+ }
+ actScale.setMultiplier(maxY * scale / maxIAValue);
+
+ addSeries(actSeriesPred);
+ }
+
// scale in % of vertical size (like 0.3)
- public void addIob(long fromTime, long toTime, boolean useForScale, double scale) {
+ public void addIob(long fromTime, long toTime, boolean useForScale, double scale, boolean showPrediction) {
FixedLineGraphSeries iobSeries;
List iobArray = new ArrayList<>();
Double maxIobValueFound = Double.MIN_VALUE;
@@ -374,6 +433,42 @@ public class GraphData {
iobSeries.setColor(MainApp.gc(R.color.iob));
iobSeries.setThickness(3);
+ if (showPrediction) {
+ AutosensResult lastAutosensResult;
+ AutosensData autosensData = IobCobCalculatorPlugin.getPlugin().getLastAutosensDataSynchronized("GraphData");
+ if (autosensData == null)
+ lastAutosensResult = new AutosensResult();
+ else
+ lastAutosensResult = autosensData.autosensResult;
+ boolean isTempTarget = TreatmentsPlugin.getPlugin().getTempTargetFromHistory(System.currentTimeMillis()) != null;
+
+ List iobPred = new ArrayList<>();
+ IobTotal[] iobPredArray = IobCobCalculatorPlugin.getPlugin().calculateIobArrayForSMB(lastAutosensResult, SMBDefaults.exercise_mode, SMBDefaults.half_basal_exercise_target, isTempTarget);
+ for (IobTotal i : iobPredArray) {
+ iobPred.add(i.setColor(MainApp.gc(R.color.iobPredAS)));
+ maxIobValueFound = Math.max(maxIobValueFound, Math.abs(i.iob));
+ }
+ DataPointWithLabelInterface[] iobp = new DataPointWithLabelInterface[iobPred.size()];
+ iobp = iobPred.toArray(iobp);
+ addSeries(new PointsWithLabelGraphSeries<>(iobp));
+
+
+ List iobPred2 = new ArrayList<>();
+ IobTotal[] iobPredArray2 = IobCobCalculatorPlugin.getPlugin().calculateIobArrayForSMB(new AutosensResult(), SMBDefaults.exercise_mode, SMBDefaults.half_basal_exercise_target, isTempTarget);
+ for (IobTotal i : iobPredArray2) {
+ iobPred2.add(i.setColor(MainApp.gc(R.color.iobPred)));
+ maxIobValueFound = Math.max(maxIobValueFound, Math.abs(i.iob));
+ }
+ DataPointWithLabelInterface[] iobp2 = new DataPointWithLabelInterface[iobPred2.size()];
+ iobp2 = iobPred2.toArray(iobp2);
+ addSeries(new PointsWithLabelGraphSeries<>(iobp2));
+
+ if (L.isEnabled(L.AUTOSENS)) {
+ log.debug("IOB pred for AS=" + DecimalFormatter.to2Decimal(lastAutosensResult.ratio) + ": " + IobCobCalculatorPlugin.getPlugin().iobArrayToString(iobPredArray));
+ log.debug("IOB pred for AS=" + DecimalFormatter.to2Decimal(1) + ": " + IobCobCalculatorPlugin.getPlugin().iobArrayToString(iobPredArray2));
+ }
+ }
+
if (useForScale) {
maxY = maxIobValueFound;
minY = -maxIobValueFound;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphExtensions/PointsWithLabelGraphSeries.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphExtensions/PointsWithLabelGraphSeries.java
index aaa38359a0..eb981e9329 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphExtensions/PointsWithLabelGraphSeries.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphExtensions/PointsWithLabelGraphSeries.java
@@ -79,7 +79,8 @@ public class PointsWithLabelGraphSeries e
EXERCISE,
GENERAL,
GENERALWITHDURATION,
- COBFAILOVER
+ COBFAILOVER,
+ IOBPREDICTION
}
/**
@@ -206,6 +207,11 @@ public class PointsWithLabelGraphSeries e
mPaint.setStyle(Paint.Style.FILL);
mPaint.setStrokeWidth(0);
canvas.drawCircle(endX, endY, value.getSize() * scaledPxSize, mPaint);
+ } else if (value.getShape() == Shape.BG || value.getShape() == Shape.IOBPREDICTION) {
+ mPaint.setColor(value.getColor());
+ mPaint.setStyle(Paint.Style.FILL);
+ mPaint.setStrokeWidth(0);
+ canvas.drawCircle(endX, endY, value.getSize() * scaledPxSize, mPaint);
} else if (value.getShape() == Shape.PREDICTION) {
mPaint.setColor(value.getColor());
mPaint.setStyle(Paint.Style.FILL);
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/DismissNotificationService.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/DismissNotificationService.java
index a8d6fca1ba..3d1189de2b 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/DismissNotificationService.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/DismissNotificationService.java
@@ -3,9 +3,11 @@ package info.nightscout.androidaps.plugins.general.overview.notifications;
import android.app.IntentService;
import android.app.PendingIntent;
import android.content.Intent;
-import android.support.annotation.Nullable;
+
+import androidx.annotation.Nullable;
import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification;
public class DismissNotificationService extends IntentService {
@@ -19,16 +21,16 @@ public class DismissNotificationService extends IntentService {
super(name);
}
- public DismissNotificationService(){
+ public DismissNotificationService() {
super("DismissNotificationService");
- };
+ }
@Override
protected void onHandleIntent(@Nullable Intent intent) {
- MainApp.bus().post(new EventDismissNotification(intent.getIntExtra("alertID", -1)));
+ RxBus.INSTANCE.send(new EventDismissNotification(intent.getIntExtra("alertID", -1)));
}
- public static PendingIntent deleteIntent(int id){
+ public static PendingIntent deleteIntent(int id) {
Intent intent = new Intent(MainApp.instance(), DismissNotificationService.class);
intent.putExtra("alertID", id);
return PendingIntent.getService(MainApp.instance(), id, intent, PendingIntent.FLAG_UPDATE_CURRENT);
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/Notification.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/Notification.java
index f7a4c32360..28b0abd33d 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/Notification.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/Notification.java
@@ -1,4 +1,3 @@
-
package info.nightscout.androidaps.plugins.general.overview.notifications;
import java.util.Date;
@@ -34,11 +33,12 @@ public class Notification {
public static final int OLD_NSCLIENT = 8;
public static final int OLD_NS = 9;
public static final int INVALID_PHONE_NUMBER = 10;
- public static final int APPROACHING_DAILY_LIMIT = 11;
- public static final int NSCLIENT_NO_WRITE_PERMISSION = 12;
- public static final int MISSING_SMS_PERMISSION = 13;
- public static final int PUMPERROR = 14;
- public static final int WRONGSERIALNUMBER = 15;
+ public static final int INVALID_MESSAGE_BODY = 11;
+ public static final int APPROACHING_DAILY_LIMIT = 12;
+ public static final int NSCLIENT_NO_WRITE_PERMISSION = 13;
+ public static final int MISSING_SMS_PERMISSION = 14;
+ public static final int PUMPERROR = 15;
+ public static final int WRONGSERIALNUMBER = 16;
public static final int NSANNOUNCEMENT = 18;
public static final int NSALARM = 19;
@@ -75,6 +75,9 @@ public class Notification {
public static final int DST_IN_24H = 50;
public static final int DISKFULL = 51;
public static final int OLDVERSION = 52;
+ public static final int USERMESSAGE = 53;
+ public static final int OVER_24H_TIME_CHANGE_REQUESTED = 54;
+ public static final int INVALID_VERSION = 55;
public int id;
@@ -85,6 +88,7 @@ public class Notification {
public NSAlarm nsAlarm = null;
public Integer soundId = null;
+
public Notification() {
}
@@ -198,10 +202,10 @@ public class Notification {
return false;
}
- public static boolean isAlarmForStaleData(){
+ public static boolean isAlarmForStaleData() {
long snoozedTo = SP.getLong("snoozedTo", 0L);
- if(snoozedTo != 0L){
- if(System.currentTimeMillis() < SP.getLong("snoozedTo", 0L)) {
+ if (snoozedTo != 0L) {
+ if (System.currentTimeMillis() < SP.getLong("snoozedTo", 0L)) {
//log.debug("Alarm is snoozed for next "+(SP.getLong("snoozedTo", 0L)-System.currentTimeMillis())/1000+" seconds");
return false;
}
@@ -217,12 +221,12 @@ public class Notification {
//log.debug("bgReadingAgoMin value is:"+bgReadingAgoMin);
//log.debug("Stale alarm snoozed to: "+(System.currentTimeMillis() - snoozedTo)/60000L);
Double threshold = NSSettingsStatus.getInstance().getThreshold("alarmTimeagoWarnMins");
- //log.debug("OpenAPS Alerts enabled: "+openAPSEnabledAlerts);
- // if no thresshold from Ns get it loccally
- if(threshold == null) threshold = SP.getDouble(R.string.key_nsalarm_staledatavalue,15D);
- // No threshold of OpenAPS Alarm so using the one for BG
- // Added OpenAPSEnabledAlerts to alarm check
- if((bgReadingAgoMin > threshold && SP.getBoolean(R.string.key_nsalarm_staledata, false))||(bgReadingAgoMin > threshold && openAPSEnabledAlerts)){
+ //log.debug("OpenAPS Alerts enabled: "+openAPSEnabledAlerts);
+ // if no thresshold from Ns get it loccally
+ if (threshold == null) threshold = SP.getDouble(R.string.key_nsalarm_staledatavalue, 15D);
+ // No threshold of OpenAPS Alarm so using the one for BG
+ // Added OpenAPSEnabledAlerts to alarm check
+ if ((bgReadingAgoMin > threshold && SP.getBoolean(R.string.key_nsalarm_staledata, false)) || (bgReadingAgoMin > threshold && openAPSEnabledAlerts)) {
return true;
}
//snoozing for threshold
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/NotificationRecyclerViewAdapter.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/NotificationRecyclerViewAdapter.java
index de35e4bc8c..1e96b02be1 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/NotificationRecyclerViewAdapter.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/NotificationRecyclerViewAdapter.java
@@ -1,14 +1,16 @@
package info.nightscout.androidaps.plugins.general.overview.notifications;
-import android.support.v4.content.ContextCompat;
-import android.support.v7.widget.CardView;
-import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
+import androidx.annotation.NonNull;
+import androidx.cardview.widget.CardView;
+import androidx.core.content.ContextCompat;
+import androidx.recyclerview.widget.RecyclerView;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -18,6 +20,7 @@ import java.util.Objects;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.general.nsclient.broadcasts.BroadcastAckAlarm;
import info.nightscout.androidaps.plugins.general.overview.OverviewPlugin;
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification;
@@ -29,10 +32,11 @@ public class NotificationRecyclerViewAdapter extends RecyclerView.Adapter notificationsList;
- public NotificationRecyclerViewAdapter(List notificationsList) {
+ NotificationRecyclerViewAdapter(List notificationsList) {
this.notificationsList = notificationsList;
}
+ @NonNull
@Override
public NotificationsViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.overview_notification_item, viewGroup, false);
@@ -46,10 +50,9 @@ public class NotificationRecyclerViewAdapter extends RecyclerView.Adapter= Build.VERSION_CODES.O)
+ MainApp.instance().startForegroundService(alarm);
+ else
+ MainApp.instance().startService(alarm);
}
} else {
- if (n.soundId != null) {
+ if (n.soundId != null && n.soundId != 0) {
Intent alarm = new Intent(MainApp.instance().getApplicationContext(), AlarmSoundService.class);
alarm.putExtra("soundid", n.soundId);
- MainApp.instance().startService(alarm);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
+ MainApp.instance().startForegroundService(alarm);
+ else
+ MainApp.instance().startService(alarm);
}
}
@@ -97,7 +105,7 @@ public class NotificationStore {
return false;
}
- public synchronized void removeExpired() {
+ private synchronized void removeExpired() {
for (int i = 0; i < store.size(); i++) {
Notification n = store.get(i);
if (n.validTo.getTime() != 0 && n.validTo.getTime() < System.currentTimeMillis()) {
@@ -107,13 +115,13 @@ public class NotificationStore {
}
}
- public void snoozeTo(long timeToSnooze) {
+ void snoozeTo(long timeToSnooze) {
if (L.isEnabled(L.NOTIFICATION))
log.debug("Snoozing alarm until: " + timeToSnooze);
SP.putLong("snoozedTo", timeToSnooze);
}
- public void unSnooze() {
+ private void unSnooze() {
if (Notification.isAlarmForStaleData()) {
Notification notification = new Notification(Notification.NSALARM, MainApp.gs(R.string.nsalarm_staledata), Notification.URGENT);
SP.putLong("snoozedTo", System.currentTimeMillis());
@@ -139,7 +147,7 @@ public class NotificationStore {
if (n.level == Notification.URGENT) {
notificationBuilder.setVibrate(new long[]{1000, 1000, 1000, 1000})
.setContentTitle(MainApp.gs(R.string.urgent_alarm))
- .setSound(sound, AudioAttributes.USAGE_ALARM);
+ .setSound(sound, AudioManager.STREAM_ALARM);
} else {
notificationBuilder.setVibrate(new long[]{0, 100, 50, 100, 50})
.setContentTitle(MainApp.gs(R.string.info))
@@ -160,4 +168,21 @@ public class NotificationStore {
}
}
+ public synchronized void updateNotifications(RecyclerView notificationsView) {
+ removeExpired();
+ unSnooze();
+ if (store.size() > 0) {
+ NotificationRecyclerViewAdapter adapter = new NotificationRecyclerViewAdapter(cloneStore());
+ notificationsView.setAdapter(adapter);
+ notificationsView.setVisibility(View.VISIBLE);
+ } else {
+ notificationsView.setVisibility(View.GONE);
+ }
+ }
+
+ private synchronized List cloneStore() {
+ List clone = new ArrayList<>(store.size());
+ clone.addAll(store);
+ return clone;
+ }
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/NotificationWithAction.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/NotificationWithAction.java
index 2ff61b63c8..c117559a61 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/NotificationWithAction.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/NotificationWithAction.java
@@ -1,15 +1,17 @@
package info.nightscout.androidaps.plugins.general.overview.notifications;
+import androidx.annotation.IntegerRes;
+
public class NotificationWithAction extends Notification {
Runnable action;
- String buttonText;
+ int buttonText;
public NotificationWithAction(int id, String text, int level) {
super(id, text, level);
}
- public void action(String buttonText, Runnable action) {
+ public void action(int buttonText, Runnable action) {
this.buttonText = buttonText;
this.action = action;
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/DummyService.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/DummyService.java
index 863046c0c4..007298ac76 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/DummyService.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/DummyService.java
@@ -1,25 +1,27 @@
package info.nightscout.androidaps.plugins.general.persistentNotification;
-import android.app.Notification;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
-import android.support.annotation.Nullable;
-import com.squareup.otto.Subscribe;
+import androidx.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.events.EventAppExit;
import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.bus.RxBus;
+import info.nightscout.androidaps.utils.FabricPrivacy;
+import io.reactivex.disposables.CompositeDisposable;
+import io.reactivex.schedulers.Schedulers;
/**
* 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 {
private static Logger log = LoggerFactory.getLogger(L.CORE);
+ private CompositeDisposable disposable = new CompositeDisposable();
@Nullable
@Override
@@ -27,32 +29,35 @@ public class DummyService extends Service {
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;
- }
-
- @Subscribe
- public void onStatusEvent(EventAppExit event) {
- if (L.isEnabled(L.CORE))
- log.debug("EventAppExit received");
-
- stopSelf();
- }
-
@Override
public void onCreate() {
- MainApp.bus().register(this);
+ super.onCreate();
+ // TODO: I guess this was moved here in order to adhere to the 5 seconds rule to call "startForeground" after a Service was called as Foreground service?
+ // As onCreate() is not called every time a service is started, copied to onStartCommand().
+ startForeground(PersistentNotificationPlugin.ONGOING_NOTIFICATION_ID, PersistentNotificationPlugin.getPlugin().getLastNotification());
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventAppExit.class)
+ .observeOn(Schedulers.io())
+ .subscribe(event -> {
+ if (L.isEnabled(L.PUMP)) log.debug("EventAppExit received");
+ stopSelf();
+ }, FabricPrivacy::logException)
+ );
}
@Override
public void onDestroy() {
- if (L.isEnabled(L.CORE))
- log.debug("onDestroy");
- MainApp.bus().unregister(this);
+ if (L.isEnabled(L.CORE)) log.debug("onDestroy");
+ disposable.clear();
+ super.onDestroy();
stopForeground(true);
}
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ super.onStartCommand(intent, flags, startId);
+ startForeground(PersistentNotificationPlugin.ONGOING_NOTIFICATION_ID, PersistentNotificationPlugin.getPlugin().getLastNotification());
+ return START_STICKY;
+ }
+
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/PersistentNotificationPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/PersistentNotificationPlugin.java
index 987d9374bd..fdee040682 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/PersistentNotificationPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/PersistentNotificationPlugin.java
@@ -10,17 +10,15 @@ import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
-import android.support.v4.app.NotificationCompat;
-import android.support.v4.app.RemoteInput;
-import android.support.v4.app.TaskStackBuilder;
-import com.squareup.otto.Subscribe;
+import androidx.core.app.NotificationCompat;
+import androidx.core.app.RemoteInput;
+import androidx.core.app.TaskStackBuilder;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainActivity;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
-import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus;
import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.DatabaseHelper;
@@ -35,12 +33,17 @@ import info.nightscout.androidaps.events.EventTreatmentChange;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
+import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
+import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished;
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
import info.nightscout.androidaps.utils.DecimalFormatter;
+import info.nightscout.androidaps.utils.FabricPrivacy;
+import io.reactivex.disposables.CompositeDisposable;
+import io.reactivex.schedulers.Schedulers;
/**
* Created by adrian on 23/12/16.
@@ -48,17 +51,19 @@ import info.nightscout.androidaps.utils.DecimalFormatter;
public class PersistentNotificationPlugin extends PluginBase {
+ private CompositeDisposable disposable = new CompositeDisposable();
+
private static PersistentNotificationPlugin plugin;
+ private Notification notification;
public static PersistentNotificationPlugin getPlugin() {
- if (plugin == null) plugin = new PersistentNotificationPlugin(MainApp.instance());
+ if (plugin == null) plugin = new PersistentNotificationPlugin();
return plugin;
}
public static final String CHANNEL_ID = "AndroidAPS-Ongoing";
public static final int ONGOING_NOTIFICATION_ID = 4711;
- private final Context ctx;
/// For Android Auto
/// Intents are not declared in manifest and not consumed, this is intentionally because actually we can't do anything with
@@ -72,31 +77,78 @@ public class PersistentNotificationPlugin extends PluginBase {
/// End Android Auto
- public PersistentNotificationPlugin(Context ctx) {
+ private PersistentNotificationPlugin() {
super(new PluginDescription()
.mainType(PluginType.GENERAL)
.neverVisible(true)
.pluginName(R.string.ongoingnotificaction)
.enableByDefault(true)
- .alwaysEnabled(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
+ .alwaysEnabled(true)
+ .showInList(false)
.description(R.string.description_persistent_notification)
);
- this.ctx = ctx;
}
@Override
protected void onStart() {
- MainApp.bus().register(this);
- createNotificationChannel();
- triggerNotificationUpdate();
super.onStart();
+ createNotificationChannel(); // make sure channels exist before triggering updates through the bus
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventRefreshOverview.class)
+ .observeOn(Schedulers.io())
+ .subscribe(event -> triggerNotificationUpdate(false),
+ FabricPrivacy::logException
+ ));
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventExtendedBolusChange.class)
+ .observeOn(Schedulers.io())
+ .subscribe(event -> triggerNotificationUpdate(false),
+ FabricPrivacy::logException
+ ));
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventTempBasalChange.class)
+ .observeOn(Schedulers.io())
+ .subscribe(event -> triggerNotificationUpdate(false),
+ FabricPrivacy::logException
+ ));
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventTreatmentChange.class)
+ .observeOn(Schedulers.io())
+ .subscribe(event -> triggerNotificationUpdate(false),
+ FabricPrivacy::logException
+ ));
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventInitializationChanged.class)
+ .observeOn(Schedulers.io())
+ .subscribe(event -> triggerNotificationUpdate(false),
+ FabricPrivacy::logException
+ ));
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventNewBasalProfile.class)
+ .observeOn(Schedulers.io())
+ .subscribe(event -> triggerNotificationUpdate(false),
+ FabricPrivacy::logException
+ ));
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventAutosensCalculationFinished.class)
+ .observeOn(Schedulers.io())
+ .subscribe(event -> triggerNotificationUpdate(false),
+ FabricPrivacy::logException
+ ));
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventPreferenceChange.class)
+ .observeOn(Schedulers.io())
+ .subscribe(event -> triggerNotificationUpdate(false),
+ FabricPrivacy::logException
+ ));
+ triggerNotificationUpdate(true);
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager mNotificationManager =
- (NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE);
+ (NotificationManager) MainApp.instance().getSystemService(Context.NOTIFICATION_SERVICE);
@SuppressLint("WrongConstant") NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
CHANNEL_ID,
NotificationManager.IMPORTANCE_HIGH);
@@ -106,129 +158,138 @@ public class PersistentNotificationPlugin extends PluginBase {
@Override
protected void onStop() {
- MainApp.bus().unregister(this);
+ disposable.clear();
MainApp.instance().stopService(new Intent(MainApp.instance(), DummyService.class));
+ super.onStop();
}
- private void triggerNotificationUpdate() {
- MainApp.instance().startService(new Intent(MainApp.instance(), DummyService.class));
+ private void triggerNotificationUpdate(boolean boot) {
+ updateNotification(boot);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
+ MainApp.instance().startForegroundService(new Intent(MainApp.instance(), DummyService.class));
+ else
+ MainApp.instance().startService(new Intent(MainApp.instance(), DummyService.class));
}
- Notification updateNotification() {
- if (!isEnabled(PluginType.GENERAL)) {
- return null;
- }
-
+ private void updateNotification(boolean boot) {
String line1;
- String line1_aa;
+ String line2 = null;
+ String line3 = null;
+ NotificationCompat.CarExtender.UnreadConversation.Builder unreadConversationBuilder = null;
- if (ConfigBuilderPlugin.getPlugin().getActiveProfileInterface() == null || !ProfileFunctions.getInstance().isProfileValid("Notificiation"))
- return null;
- String units = ProfileFunctions.getInstance().getProfileUnits();
+ if (boot) {
+ line1 = MainApp.gs(R.string.loading);
+ } else if (ConfigBuilderPlugin.getPlugin().getActiveProfileInterface() != null && ProfileFunctions.getInstance().isProfileValid("Notification")) {
+ String line1_aa;
+ String units = ProfileFunctions.getInstance().getProfileUnits();
- BgReading lastBG = DatabaseHelper.lastBg();
- GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
+ BgReading lastBG = DatabaseHelper.lastBg();
+ GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
- if (lastBG != null) {
- line1 = line1_aa = lastBG.valueToUnitsToString(units);
- if (glucoseStatus != null) {
- line1 += " Δ" + deltastring(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units)
- + " avgΔ" + deltastring(glucoseStatus.avgdelta, glucoseStatus.avgdelta * Constants.MGDL_TO_MMOLL, units);
- line1_aa += " " + lastBG.directionToSymbol();
+ if (lastBG != null) {
+ line1 = line1_aa = lastBG.valueToUnitsToString(units);
+ if (glucoseStatus != null) {
+ line1 += " Δ" + deltastring(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units)
+ + " avgΔ" + deltastring(glucoseStatus.avgdelta, glucoseStatus.avgdelta * Constants.MGDL_TO_MMOLL, units);
+ line1_aa += " " + lastBG.directionToSymbol();
+ } else {
+ line1 += " " +
+ MainApp.gs(R.string.old_data) +
+ " ";
+ line1_aa += line1 + ".";
+ }
} else {
- line1 += " " +
- MainApp.gs(R.string.old_data) +
- " ";
- line1_aa += line1 + ".";
+ line1 = line1_aa = MainApp.gs(R.string.missed_bg_readings);
}
+
+ TemporaryBasal activeTemp = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(System.currentTimeMillis());
+ if (activeTemp != null) {
+ line1 += " " + activeTemp.toStringShort();
+ line1_aa += " " + activeTemp.toStringShort() + ".";
+ }
+
+ //IOB
+ TreatmentsPlugin.getPlugin().updateTotalIOBTreatments();
+ TreatmentsPlugin.getPlugin().updateTotalIOBTempBasals();
+ IobTotal bolusIob = TreatmentsPlugin.getPlugin().getLastCalculationTreatments().round();
+ IobTotal basalIob = TreatmentsPlugin.getPlugin().getLastCalculationTempBasals().round();
+
+
+ line2 = MainApp.gs(R.string.treatments_iob_label_string) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U " + MainApp.gs(R.string.cob) + ": " + IobCobCalculatorPlugin.getPlugin().getCobInfo(false, "PersistentNotificationPlugin").generateCOBString();
+ String line2_aa = MainApp.gs(R.string.treatments_iob_label_string) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U. " + MainApp.gs(R.string.cob) + ": " + IobCobCalculatorPlugin.getPlugin().getCobInfo(false, "PersistentNotificationPlugin").generateCOBString() + ".";
+
+
+ line3 = DecimalFormatter.to2Decimal(ConfigBuilderPlugin.getPlugin().getActivePump().getBaseBasalRate()) + " U/h";
+ String line3_aa = DecimalFormatter.to2Decimal(ConfigBuilderPlugin.getPlugin().getActivePump().getBaseBasalRate()) + " U/h.";
+
+
+ line3 += " - " + ProfileFunctions.getInstance().getProfileName();
+ line3_aa += " - " + ProfileFunctions.getInstance().getProfileName() + ".";
+
+ /// For Android Auto
+ Intent msgReadIntent = new Intent()
+ .addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
+ .setAction(READ_ACTION)
+ .putExtra(CONVERSATION_ID, ONGOING_NOTIFICATION_ID)
+ .setPackage(PACKAGE);
+
+ PendingIntent msgReadPendingIntent =
+ PendingIntent.getBroadcast(MainApp.instance(),
+ ONGOING_NOTIFICATION_ID,
+ msgReadIntent,
+ PendingIntent.FLAG_UPDATE_CURRENT);
+
+ Intent msgReplyIntent = new Intent()
+ .addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
+ .setAction(REPLY_ACTION)
+ .putExtra(CONVERSATION_ID, ONGOING_NOTIFICATION_ID)
+ .setPackage(PACKAGE);
+
+ PendingIntent msgReplyPendingIntent = PendingIntent.getBroadcast(
+ MainApp.instance(),
+ ONGOING_NOTIFICATION_ID,
+ msgReplyIntent,
+ PendingIntent.FLAG_UPDATE_CURRENT);
+
+ // Build a RemoteInput for receiving voice input from devices
+ RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY).build();
+
+ // Create the UnreadConversation
+ unreadConversationBuilder =
+ new NotificationCompat.CarExtender.UnreadConversation.Builder(line1_aa + "\n" + line2_aa)
+ .setLatestTimestamp(System.currentTimeMillis())
+ .setReadPendingIntent(msgReadPendingIntent)
+ .setReplyAction(msgReplyPendingIntent, remoteInput);
+
+ /// Add dot to produce a "more natural sounding result"
+ unreadConversationBuilder.addMessage(line3_aa);
+ /// End Android Auto
} else {
- line1 = line1_aa = MainApp.gs(R.string.missed_bg_readings);
+ line1 = MainApp.gs(R.string.noprofileset);
}
- TemporaryBasal activeTemp = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(System.currentTimeMillis());
- if (activeTemp != null) {
- line1 += " " + activeTemp.toStringShort();
- line1_aa += " " + activeTemp.toStringShort() + ".";
- }
-
- //IOB
- TreatmentsPlugin.getPlugin().updateTotalIOBTreatments();
- TreatmentsPlugin.getPlugin().updateTotalIOBTempBasals();
- IobTotal bolusIob = TreatmentsPlugin.getPlugin().getLastCalculationTreatments().round();
- IobTotal basalIob = TreatmentsPlugin.getPlugin().getLastCalculationTempBasals().round();
-
-
- String line2 = MainApp.gs(R.string.treatments_iob_label_string) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U " + MainApp.gs(R.string.cob) + ": " + IobCobCalculatorPlugin.getPlugin().getCobInfo(false, "PersistentNotificationPlugin").generateCOBString();
- String line2_aa = MainApp.gs(R.string.treatments_iob_label_string) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U. " + MainApp.gs(R.string.cob) + ": " + IobCobCalculatorPlugin.getPlugin().getCobInfo(false, "PersistentNotificationPlugin").generateCOBString() + ".";
-
-
- String line3 = DecimalFormatter.to2Decimal(ConfigBuilderPlugin.getPlugin().getActivePump().getBaseBasalRate()) + " U/h";
- String line3_aa = DecimalFormatter.to2Decimal(ConfigBuilderPlugin.getPlugin().getActivePump().getBaseBasalRate()) + " U/h.";
-
-
- line3 += " - " + ProfileFunctions.getInstance().getProfileName();
- line3_aa += " - " + ProfileFunctions.getInstance().getProfileName() + ".";
-
- /// For Android Auto
- Intent msgReadIntent = new Intent()
- .addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
- .setAction(READ_ACTION)
- .putExtra(CONVERSATION_ID, ONGOING_NOTIFICATION_ID)
- .setPackage(PACKAGE);
-
- PendingIntent msgReadPendingIntent =
- PendingIntent.getBroadcast(ctx,
- ONGOING_NOTIFICATION_ID,
- msgReadIntent,
- PendingIntent.FLAG_UPDATE_CURRENT);
-
- Intent msgReplyIntent = new Intent()
- .addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
- .setAction(REPLY_ACTION)
- .putExtra(CONVERSATION_ID, ONGOING_NOTIFICATION_ID)
- .setPackage(PACKAGE);
-
- PendingIntent msgReplyPendingIntent = PendingIntent.getBroadcast(
- ctx,
- ONGOING_NOTIFICATION_ID,
- msgReplyIntent,
- PendingIntent.FLAG_UPDATE_CURRENT);
-
- // Build a RemoteInput for receiving voice input from devices
- RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY).build();
-
- // Create the UnreadConversation
- NotificationCompat.CarExtender.UnreadConversation.Builder unreadConversationBuilder =
- new NotificationCompat.CarExtender.UnreadConversation.Builder(line1_aa + "\n" + line2_aa)
- .setLatestTimestamp(System.currentTimeMillis())
- .setReadPendingIntent(msgReadPendingIntent)
- .setReplyAction(msgReplyPendingIntent, remoteInput);
-
- /// Add dot to produce a "more natural sounding result"
- unreadConversationBuilder.addMessage(line3_aa);
- /// End Android Auto
-
-
- NotificationCompat.Builder builder = new NotificationCompat.Builder(ctx, CHANNEL_ID);
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(MainApp.instance(), CHANNEL_ID);
builder.setOngoing(true);
builder.setOnlyAlertOnce(true);
builder.setCategory(NotificationCompat.CATEGORY_STATUS);
builder.setSmallIcon(MainApp.getNotificationIcon());
- Bitmap largeIcon = BitmapFactory.decodeResource(ctx.getResources(), MainApp.getIcon());
+ Bitmap largeIcon = BitmapFactory.decodeResource(MainApp.instance().getResources(), MainApp.getIcon());
builder.setLargeIcon(largeIcon);
- builder.setContentTitle(line1);
- builder.setContentText(line2);
- builder.setSubText(line3);
+ if (line1 != null) builder.setContentTitle(line1);
+ if (line2 != null) builder.setContentText(line2);
+ if (line3 != null) builder.setSubText(line3);
/// Android Auto
- builder.extend(new NotificationCompat.CarExtender()
- .setUnreadConversation(unreadConversationBuilder.build()));
+ if (unreadConversationBuilder != null) {
+ builder.extend(new NotificationCompat.CarExtender()
+ .setUnreadConversation(unreadConversationBuilder.build()));
+ }
/// End Android Auto
- Intent resultIntent = new Intent(ctx, MainActivity.class);
+ Intent resultIntent = new Intent(MainApp.instance(), MainActivity.class);
- TaskStackBuilder stackBuilder = TaskStackBuilder.create(ctx);
+ TaskStackBuilder stackBuilder = TaskStackBuilder.create(MainApp.instance());
stackBuilder.addParentStack(MainActivity.class);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =
@@ -238,11 +299,11 @@ public class PersistentNotificationPlugin extends PluginBase {
);
builder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
- (NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE);
+ (NotificationManager) MainApp.instance().getSystemService(Context.NOTIFICATION_SERVICE);
android.app.Notification notification = builder.build();
mNotificationManager.notify(ONGOING_NOTIFICATION_ID, notification);
- return notification;
+ this.notification = notification;
}
private String deltastring(double deltaMGDL, double deltaMMOL, String units) {
@@ -261,45 +322,16 @@ public class PersistentNotificationPlugin extends PluginBase {
return deltastring;
}
+ /***
+ * returns the current ongoing notification.
+ *
+ * If it does not exist, return a dummy notification. This should only happen if onStart() wasn't called.
+ */
- @Subscribe
- public void onStatusEvent(final EventPreferenceChange ev) {
- triggerNotificationUpdate();
+ public Notification getLastNotification() {
+ if (notification != null) return notification;
+ else {
+ throw new IllegalStateException("Notification is null");
+ }
}
-
- @Subscribe
- public void onStatusEvent(final EventTreatmentChange ev) {
- triggerNotificationUpdate();
- }
-
- @Subscribe
- public void onStatusEvent(final EventTempBasalChange ev) {
- triggerNotificationUpdate();
- }
-
- @Subscribe
- public void onStatusEvent(final EventExtendedBolusChange ev) {
- triggerNotificationUpdate();
- }
-
- @Subscribe
- public void onStatusEvent(final EventAutosensCalculationFinished ev) {
- triggerNotificationUpdate();
- }
-
- @Subscribe
- public void onStatusEvent(final EventNewBasalProfile ev) {
- triggerNotificationUpdate();
- }
-
- @Subscribe
- public void onStatusEvent(final EventInitializationChanged ev) {
- triggerNotificationUpdate();
- }
-
- @Subscribe
- public void onStatusEvent(final EventRefreshOverview ev) {
- triggerNotificationUpdate();
- }
-
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorFragment.java
index d1c4adf5fe..31f335a7cf 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorFragment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorFragment.java
@@ -1,7 +1,6 @@
package info.nightscout.androidaps.plugins.general.smsCommunicator;
-import android.app.Activity;
import android.os.Bundle;
import android.text.Html;
import android.view.LayoutInflater;
@@ -9,17 +8,21 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
-import com.squareup.otto.Subscribe;
+import androidx.fragment.app.Fragment;
import java.util.Collections;
import java.util.Comparator;
import info.nightscout.androidaps.R;
-import info.nightscout.androidaps.plugins.common.SubscriberFragment;
+import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.general.smsCommunicator.events.EventSmsCommunicatorUpdateGui;
import info.nightscout.androidaps.utils.DateUtil;
+import info.nightscout.androidaps.utils.FabricPrivacy;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.disposables.CompositeDisposable;
-public class SmsCommunicatorFragment extends SubscriberFragment {
+public class SmsCommunicatorFragment extends Fragment {
+ private CompositeDisposable disposable = new CompositeDisposable();
TextView logView;
public SmsCommunicatorFragment() {
@@ -36,38 +39,45 @@ public class SmsCommunicatorFragment extends SubscriberFragment {
return view;
}
- @Subscribe
- public void onStatusEvent(final EventSmsCommunicatorUpdateGui ev) {
- updateGUI();
+ @Override
+ public synchronized void onResume() {
+ super.onResume();
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventSmsCommunicatorUpdateGui.class)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(event -> updateGui(), FabricPrivacy::logException)
+ );
+ updateGui();
}
@Override
- protected void updateGUI() {
- Activity activity = getActivity();
- if (activity != null)
- activity.runOnUiThread(() -> {
- class CustomComparator implements Comparator {
- public int compare(Sms object1, Sms object2) {
- return (int) (object1.date - object2.date);
- }
- }
- Collections.sort(SmsCommunicatorPlugin.getPlugin().messages, new CustomComparator());
- int messagesToShow = 40;
+ public synchronized void onPause() {
+ super.onPause();
+ disposable.clear();
+ }
- int start = Math.max(0, SmsCommunicatorPlugin.getPlugin().messages.size() - messagesToShow);
+ protected void updateGui() {
+ class CustomComparator implements Comparator {
+ public int compare(Sms object1, Sms object2) {
+ return (int) (object1.date - object2.date);
+ }
+ }
+ Collections.sort(SmsCommunicatorPlugin.getPlugin().messages, new CustomComparator());
+ int messagesToShow = 40;
- String logText = "";
- for (int x = start; x < SmsCommunicatorPlugin.getPlugin().messages.size(); x++) {
- Sms sms = SmsCommunicatorPlugin.getPlugin().messages.get(x);
- if (sms.ignored) {
- logText += DateUtil.timeString(sms.date) + " <<< " + "░ " + sms.phoneNumber + " " + sms.text + " ";
- } else if (sms.received) {
- logText += DateUtil.timeString(sms.date) + " <<< " + (sms.processed ? "● " : "○ ") + sms.phoneNumber + " " + sms.text + " ";
- } else if (sms.sent) {
- logText += DateUtil.timeString(sms.date) + " >>> " + (sms.processed ? "● " : "○ ") + sms.phoneNumber + " " + sms.text + " ";
- }
- }
- logView.setText(Html.fromHtml(logText));
- });
+ int start = Math.max(0, SmsCommunicatorPlugin.getPlugin().messages.size() - messagesToShow);
+
+ String logText = "";
+ for (int x = start; x < SmsCommunicatorPlugin.getPlugin().messages.size(); x++) {
+ Sms sms = SmsCommunicatorPlugin.getPlugin().messages.get(x);
+ if (sms.ignored) {
+ logText += DateUtil.timeString(sms.date) + " <<< " + "░ " + sms.phoneNumber + " " + sms.text + " ";
+ } else if (sms.received) {
+ logText += DateUtil.timeString(sms.date) + " <<< " + (sms.processed ? "● " : "○ ") + sms.phoneNumber + " " + sms.text + " ";
+ } else if (sms.sent) {
+ logText += DateUtil.timeString(sms.date) + " >>> " + (sms.processed ? "● " : "○ ") + sms.phoneNumber + " " + sms.text + " ";
+ }
+ }
+ logView.setText(Html.fromHtml(logText));
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.java
index 181bdd86d2..264d7c3e52 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.java
@@ -1,13 +1,10 @@
package info.nightscout.androidaps.plugins.general.smsCommunicator;
import android.content.Intent;
-import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
-import com.squareup.otto.Subscribe;
-
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -20,7 +17,6 @@ import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.DetailedBolusInfo;
-import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus;
import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.ProfileStore;
@@ -37,28 +33,34 @@ import info.nightscout.androidaps.interfaces.ProfileInterface;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
+import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
+import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart;
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification;
import info.nightscout.androidaps.plugins.general.smsCommunicator.events.EventSmsCommunicatorUpdateGui;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.CobInfo;
+import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
import info.nightscout.androidaps.queue.Callback;
-import info.nightscout.androidaps.services.Intents;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.DecimalFormatter;
+import info.nightscout.androidaps.utils.FabricPrivacy;
import info.nightscout.androidaps.utils.SP;
import info.nightscout.androidaps.utils.SafeParse;
import info.nightscout.androidaps.utils.XdripCalibrations;
+import io.reactivex.disposables.CompositeDisposable;
+import io.reactivex.schedulers.Schedulers;
/**
* Created by mike on 05.08.2016.
*/
public class SmsCommunicatorPlugin extends PluginBase {
private static Logger log = LoggerFactory.getLogger(L.SMS);
+ private CompositeDisposable disposable = new CompositeDisposable();
private static SmsCommunicatorPlugin smsCommunicatorPlugin;
@@ -92,23 +94,28 @@ public class SmsCommunicatorPlugin extends PluginBase {
@Override
protected void onStart() {
- MainApp.bus().register(this);
super.onStart();
+ disposable.add(RxBus.INSTANCE
+ .toObservable(EventPreferenceChange.class)
+ .observeOn(Schedulers.io())
+ .subscribe(event -> {
+ processSettings(event);
+ }, FabricPrivacy::logException)
+ );
}
@Override
protected void onStop() {
- MainApp.bus().unregister(this);
+ disposable.clear();
+ super.onStop();
}
- @Subscribe
- public void processSettings(final EventPreferenceChange ev) {
+ private void processSettings(final EventPreferenceChange ev) {
if (ev == null || ev.isChanged(R.string.key_smscommunicator_allowednumbers)) {
String settings = SP.getString(R.string.key_smscommunicator_allowednumbers, "");
- String pattern = ";";
-
- String[] substrings = settings.split(pattern);
+ allowedNumbers.clear();
+ String[] substrings = settings.split(";");
for (String number : substrings) {
String cleaned = number.replaceAll("\\s+", "");
allowedNumbers.add(cleaned);
@@ -166,7 +173,7 @@ public class SmsCommunicatorPlugin extends PluginBase {
log.debug("Ignoring SMS from: " + receivedSms.phoneNumber + ". Sender not allowed");
receivedSms.ignored = true;
messages.add(receivedSms);
- MainApp.bus().post(new EventSmsCommunicatorUpdateGui());
+ RxBus.INSTANCE.send(new EventSmsCommunicatorUpdateGui());
return;
}
@@ -258,7 +265,7 @@ public class SmsCommunicatorPlugin extends PluginBase {
}
}
- MainApp.bus().post(new EventSmsCommunicatorUpdateGui());
+ RxBus.INSTANCE.send(new EventSmsCommunicatorUpdateGui());
}
@SuppressWarnings("unused")
@@ -303,13 +310,13 @@ public class SmsCommunicatorPlugin extends PluginBase {
switch (splitted[1].toUpperCase()) {
case "DISABLE":
case "STOP":
- LoopPlugin loopPlugin = MainApp.getSpecificPlugin(LoopPlugin.class);
- if (loopPlugin != null && loopPlugin.isEnabled(PluginType.LOOP)) {
+ LoopPlugin loopPlugin = LoopPlugin.getPlugin();
+ if (loopPlugin.isEnabled(PluginType.LOOP)) {
loopPlugin.setPluginEnabled(PluginType.LOOP, false);
ConfigBuilderPlugin.getPlugin().getCommandQueue().cancelTempBasal(true, new Callback() {
@Override
public void run() {
- MainApp.bus().post(new EventRefreshOverview("SMS_LOOP_STOP"));
+ RxBus.INSTANCE.send(new EventRefreshOverview("SMS_LOOP_STOP"));
String reply = MainApp.gs(R.string.smscommunicator_loophasbeendisabled) + " " +
MainApp.gs(result.success ? R.string.smscommunicator_tempbasalcanceled : R.string.smscommunicator_tempbasalcancelfailed);
sendSMS(new Sms(receivedSms.phoneNumber, reply));
@@ -322,34 +329,32 @@ public class SmsCommunicatorPlugin extends PluginBase {
break;
case "ENABLE":
case "START":
- loopPlugin = MainApp.getSpecificPlugin(LoopPlugin.class);
- if (loopPlugin != null && !loopPlugin.isEnabled(PluginType.LOOP)) {
+ loopPlugin = LoopPlugin.getPlugin();
+ if (!loopPlugin.isEnabled(PluginType.LOOP)) {
loopPlugin.setPluginEnabled(PluginType.LOOP, true);
sendSMS(new Sms(receivedSms.phoneNumber, R.string.smscommunicator_loophasbeenenabled));
- MainApp.bus().post(new EventRefreshOverview("SMS_LOOP_START"));
+ RxBus.INSTANCE.send(new EventRefreshOverview("SMS_LOOP_START"));
} else {
sendSMS(new Sms(receivedSms.phoneNumber, R.string.smscommunicator_loopisenabled));
}
receivedSms.processed = true;
break;
case "STATUS":
- loopPlugin = MainApp.getSpecificPlugin(LoopPlugin.class);
- if (loopPlugin != null) {
- if (loopPlugin.isEnabled(PluginType.LOOP)) {
- if (loopPlugin.isSuspended())
- reply = String.format(MainApp.gs(R.string.loopsuspendedfor), loopPlugin.minutesToEndOfSuspend());
- else
- reply = MainApp.gs(R.string.smscommunicator_loopisenabled);
- } else {
- reply = MainApp.gs(R.string.smscommunicator_loopisdisabled);
- }
- sendSMS(new Sms(receivedSms.phoneNumber, reply));
+ loopPlugin = LoopPlugin.getPlugin();
+ if (loopPlugin.isEnabled(PluginType.LOOP)) {
+ if (loopPlugin.isSuspended())
+ reply = String.format(MainApp.gs(R.string.loopsuspendedfor), loopPlugin.minutesToEndOfSuspend());
+ else
+ reply = MainApp.gs(R.string.smscommunicator_loopisenabled);
+ } else {
+ reply = MainApp.gs(R.string.smscommunicator_loopisdisabled);
}
+ sendSMS(new Sms(receivedSms.phoneNumber, reply));
receivedSms.processed = true;
break;
case "RESUME":
LoopPlugin.getPlugin().suspendTo(0);
- MainApp.bus().post(new EventRefreshOverview("SMS_LOOP_RESUME"));
+ RxBus.INSTANCE.send(new EventRefreshOverview("SMS_LOOP_RESUME"));
NSUpload.uploadOpenAPSOffline(0);
sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, R.string.smscommunicator_loopresumed));
break;
@@ -376,7 +381,7 @@ public class SmsCommunicatorPlugin extends PluginBase {
if (result.success) {
LoopPlugin.getPlugin().suspendTo(System.currentTimeMillis() + anInteger * 60L * 1000);
NSUpload.uploadOpenAPSOffline(anInteger * 60);
- MainApp.bus().post(new EventRefreshOverview("SMS_LOOP_SUSPENDED"));
+ RxBus.INSTANCE.send(new EventRefreshOverview("SMS_LOOP_SUSPENDED"));
String reply = MainApp.gs(R.string.smscommunicator_loopsuspended) + " " +
MainApp.gs(result.success ? R.string.smscommunicator_tempbasalcanceled : R.string.smscommunicator_tempbasalcancelfailed);
sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply));
@@ -400,12 +405,9 @@ public class SmsCommunicatorPlugin extends PluginBase {
private void processTREATMENTS(String[] splitted, Sms receivedSms) {
if (splitted[1].toUpperCase().equals("REFRESH")) {
- Intent restartNSClient = new Intent(Intents.ACTION_RESTART);
TreatmentsPlugin.getPlugin().getService().resetTreatments();
- MainApp.instance().getApplicationContext().sendBroadcast(restartNSClient);
- List q = MainApp.instance().getApplicationContext().getPackageManager().queryBroadcastReceivers(restartNSClient, 0);
- String reply = "TREATMENTS REFRESH " + q.size() + " receivers";
- sendSMS(new Sms(receivedSms.phoneNumber, reply));
+ RxBus.INSTANCE.send(new EventNSClientRestart());
+ sendSMS(new Sms(receivedSms.phoneNumber, "TREATMENTS REFRESH SENT"));
receivedSms.processed = true;
} else
sendSMS(new Sms(receivedSms.phoneNumber, R.string.wrongformat));
@@ -413,11 +415,8 @@ public class SmsCommunicatorPlugin extends PluginBase {
private void processNSCLIENT(String[] splitted, Sms receivedSms) {
if (splitted[1].toUpperCase().equals("RESTART")) {
- Intent restartNSClient = new Intent(Intents.ACTION_RESTART);
- MainApp.instance().getApplicationContext().sendBroadcast(restartNSClient);
- List q = MainApp.instance().getApplicationContext().getPackageManager().queryBroadcastReceivers(restartNSClient, 0);
- String reply = "NSCLIENT RESTART " + q.size() + " receivers";
- sendSMS(new Sms(receivedSms.phoneNumber, reply));
+ RxBus.INSTANCE.send(new EventNSClientRestart());
+ sendSMS(new Sms(receivedSms.phoneNumber, "NSCLIENT RESTART SENT"));
receivedSms.processed = true;
} else
sendSMS(new Sms(receivedSms.phoneNumber, R.string.wrongformat));
@@ -743,11 +742,13 @@ public class SmsCommunicatorPlugin extends PluginBase {
sendSMS(new Sms(receivedSms.phoneNumber, R.string.wrongformat));
}
- public void sendNotificationToAllNumbers(String text) {
+ public boolean sendNotificationToAllNumbers(String text) {
+ boolean result = true;
for (int i = 0; i < allowedNumbers.size(); i++) {
Sms sms = new Sms(allowedNumbers.get(i), text);
- sendSMS(sms);
+ result = result && sendSMS(sms);
}
+ return result;
}
private void sendSMSToAllNumbers(Sms sms) {
@@ -757,7 +758,7 @@ public class SmsCommunicatorPlugin extends PluginBase {
}
}
- void sendSMS(Sms sms) {
+ boolean sendSMS(Sms sms) {
SmsManager smsManager = SmsManager.getDefault();
sms.text = stripAccents(sms.text);
@@ -774,13 +775,22 @@ public class SmsCommunicatorPlugin extends PluginBase {
messages.add(sms);
} catch (IllegalArgumentException e) {
- Notification notification = new Notification(Notification.INVALID_PHONE_NUMBER, MainApp.gs(R.string.smscommunicator_invalidphonennumber), Notification.NORMAL);
- MainApp.bus().post(new EventNewNotification(notification));
+ if (e.getMessage().equals("Invalid message body")) {
+ Notification notification = new Notification(Notification.INVALID_MESSAGE_BODY, MainApp.gs(R.string.smscommunicator_messagebody), Notification.NORMAL);
+ RxBus.INSTANCE.send(new EventNewNotification(notification));
+ return false;
+ } else {
+ Notification notification = new Notification(Notification.INVALID_PHONE_NUMBER, MainApp.gs(R.string.smscommunicator_invalidphonennumber), Notification.NORMAL);
+ RxBus.INSTANCE.send(new EventNewNotification(notification));
+ return false;
+ }
} catch (java.lang.SecurityException e) {
Notification notification = new Notification(Notification.MISSING_SMS_PERMISSION, MainApp.gs(R.string.smscommunicator_missingsmspermission), Notification.NORMAL);
- MainApp.bus().post(new EventNewNotification(notification));
+ RxBus.INSTANCE.send(new EventNewNotification(notification));
+ return false;
}
- MainApp.bus().post(new EventSmsCommunicatorUpdateGui());
+ RxBus.INSTANCE.send(new EventSmsCommunicatorUpdateGui());
+ return true;
}
private String generatePasscode() {
@@ -790,7 +800,7 @@ public class SmsCommunicatorPlugin extends PluginBase {
passCode += Character.toString((char) (startChar2 + Math.random() * ('z' - 'a' + 1)));
int startChar3 = Math.random() > 0.5 ? 'a' : 'A';
passCode += Character.toString((char) (startChar3 + Math.random() * ('z' - 'a' + 1)));
- passCode.replace('l', 'k').replace('I', 'J');
+ passCode = passCode.replace('l', 'k').replace('I', 'J');
return passCode;
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/events/EventSmsCommunicatorUpdateGui.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/events/EventSmsCommunicatorUpdateGui.java
deleted file mode 100644
index 7e50671c45..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/events/EventSmsCommunicatorUpdateGui.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package info.nightscout.androidaps.plugins.general.smsCommunicator.events;
-
-import info.nightscout.androidaps.events.EventUpdateGui;
-
-/**
- * Created by mike on 05.08.2016.
- */
-public class EventSmsCommunicatorUpdateGui extends EventUpdateGui {
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/events/EventSmsCommunicatorUpdateGui.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/events/EventSmsCommunicatorUpdateGui.kt
new file mode 100644
index 0000000000..4a0f95b244
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/events/EventSmsCommunicatorUpdateGui.kt
@@ -0,0 +1,5 @@
+package info.nightscout.androidaps.plugins.general.smsCommunicator.events
+
+import info.nightscout.androidaps.events.EventUpdateGui
+
+class EventSmsCommunicatorUpdateGui : EventUpdateGui()
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/TidepoolFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/TidepoolFragment.kt
new file mode 100644
index 0000000000..f83b9cc243
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/TidepoolFragment.kt
@@ -0,0 +1,60 @@
+package info.nightscout.androidaps.plugins.general.tidepool
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ScrollView
+import androidx.fragment.app.Fragment
+import info.nightscout.androidaps.R
+import info.nightscout.androidaps.plugins.bus.RxBus
+import info.nightscout.androidaps.plugins.general.tidepool.comm.TidepoolUploader
+import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolDoUpload
+import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolResetData
+import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolUpdateGUI
+import info.nightscout.androidaps.utils.FabricPrivacy
+import info.nightscout.androidaps.utils.SP
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.disposables.CompositeDisposable
+import kotlinx.android.synthetic.main.tidepool_fragment.*
+
+class TidepoolFragment : Fragment() {
+
+ private var disposable: CompositeDisposable = CompositeDisposable()
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ return inflater.inflate(R.layout.tidepool_fragment, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ tidepool_login.setOnClickListener { TidepoolUploader.doLogin(false) }
+ tidepool_uploadnow.setOnClickListener { RxBus.send(EventTidepoolDoUpload()) }
+ tidepool_removeall.setOnClickListener { RxBus.send(EventTidepoolResetData()) }
+ tidepool_resertstart.setOnClickListener { SP.putLong(R.string.key_tidepool_last_end, 0) }
+ }
+
+ @Synchronized
+ override fun onResume() {
+ super.onResume()
+ disposable.add(RxBus
+ .toObservable(EventTidepoolUpdateGUI::class.java)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe({
+ TidepoolPlugin.updateLog()
+ tidepool_log?.text = TidepoolPlugin.textLog
+ tidepool_status?.text = TidepoolUploader.connectionStatus.name
+ tidepool_log?.text = TidepoolPlugin.textLog
+ tidepool_logscrollview?.fullScroll(ScrollView.FOCUS_DOWN)
+ }, {
+ FabricPrivacy.logException(it)
+ })
+ )
+ }
+
+ @Synchronized
+ override fun onPause() {
+ super.onPause()
+ disposable.clear()
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/TidepoolPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/TidepoolPlugin.kt
new file mode 100644
index 0000000000..78ad0ab37d
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/TidepoolPlugin.kt
@@ -0,0 +1,149 @@
+package info.nightscout.androidaps.plugins.general.tidepool
+
+import android.text.Spanned
+import info.nightscout.androidaps.Constants
+import info.nightscout.androidaps.MainApp
+import info.nightscout.androidaps.R
+import info.nightscout.androidaps.events.EventNetworkChange
+import info.nightscout.androidaps.events.EventNewBG
+import info.nightscout.androidaps.events.EventPreferenceChange
+import info.nightscout.androidaps.interfaces.PluginBase
+import info.nightscout.androidaps.interfaces.PluginDescription
+import info.nightscout.androidaps.interfaces.PluginType
+import info.nightscout.androidaps.logging.L
+import info.nightscout.androidaps.plugins.bus.RxBus
+import info.nightscout.androidaps.plugins.general.tidepool.comm.TidepoolUploader
+import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolDoUpload
+import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolResetData
+import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolStatus
+import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolUpdateGUI
+import info.nightscout.androidaps.plugins.general.tidepool.utils.RateLimit
+import info.nightscout.androidaps.receivers.ChargingStateReceiver
+import info.nightscout.androidaps.receivers.NetworkChangeReceiver
+import info.nightscout.androidaps.utils.*
+import io.reactivex.disposables.CompositeDisposable
+import io.reactivex.schedulers.Schedulers
+import org.slf4j.LoggerFactory
+import java.util.*
+
+object TidepoolPlugin : PluginBase(PluginDescription()
+ .mainType(PluginType.GENERAL)
+ .pluginName(R.string.tidepool)
+ .shortName(R.string.tidepool_shortname)
+ .fragmentClass(TidepoolFragment::class.qualifiedName)
+ .preferencesId(R.xml.pref_tidepool)
+ .description(R.string.description_tidepool)
+) {
+
+ private val log = LoggerFactory.getLogger(L.TIDEPOOL)
+ private var disposable: CompositeDisposable = CompositeDisposable()
+
+ private val listLog = ArrayList()
+ var textLog: Spanned = HtmlHelper.fromHtml("")
+
+ override fun onStart() {
+ super.onStart()
+ disposable += RxBus
+ .toObservable(EventTidepoolDoUpload::class.java)
+ .observeOn(Schedulers.io())
+ .subscribe({ doUpload() }, {
+ FabricPrivacy.logException(it)
+ })
+ disposable += RxBus
+ .toObservable(EventTidepoolResetData::class.java)
+ .observeOn(Schedulers.io())
+ .subscribe({
+ if (TidepoolUploader.connectionStatus != TidepoolUploader.ConnectionStatus.CONNECTED) {
+ log.debug("Not connected for delete Dataset")
+ } else {
+ TidepoolUploader.deleteDataSet()
+ SP.putLong(R.string.key_tidepool_last_end, 0)
+ TidepoolUploader.doLogin()
+ }
+ }, {
+ FabricPrivacy.logException(it)
+ })
+ disposable += RxBus
+ .toObservable(EventTidepoolStatus::class.java)
+ .observeOn(Schedulers.io())
+ .subscribe({ event -> addToLog(event) }, {
+ FabricPrivacy.logException(it)
+ })
+ disposable += RxBus
+ .toObservable(EventNewBG::class.java)
+ .observeOn(Schedulers.io())
+ .filter { it.bgReading != null } // better would be optional in API level >24
+ .map { it.bgReading }
+ .subscribe({ bgReading ->
+ if (bgReading!!.date < TidepoolUploader.getLastEnd())
+ TidepoolUploader.setLastEnd(bgReading.date)
+ if (isEnabled(PluginType.GENERAL)
+ && (!SP.getBoolean(R.string.key_tidepool_only_while_charging, false) || ChargingStateReceiver.isCharging())
+ && (!SP.getBoolean(R.string.key_tidepool_only_while_unmetered, false) || NetworkChangeReceiver.isWifiConnected())
+ && RateLimit.rateLimit("tidepool-new-data-upload", T.mins(4).secs().toInt()))
+ doUpload()
+ }, {
+ FabricPrivacy.logException(it)
+ })
+ disposable += RxBus
+ .toObservable(EventPreferenceChange::class.java)
+ .observeOn(Schedulers.io())
+ .subscribe({ event ->
+ if (event.isChanged(R.string.key_tidepool_dev_servers)
+ || event.isChanged(R.string.key_tidepool_username)
+ || event.isChanged(R.string.key_tidepool_password)
+ )
+ TidepoolUploader.resetInstance()
+ }, {
+ FabricPrivacy.logException(it)
+ })
+ disposable += RxBus
+ .toObservable(EventNetworkChange::class.java)
+ .observeOn(Schedulers.io())
+ .subscribe({}, {
+ FabricPrivacy.logException(it)
+ }) // TODO start upload on wifi connect
+
+ }
+
+ override fun onStop() {
+ disposable.clear()
+ super.onStop()
+ }
+
+ private fun doUpload() =
+ when (TidepoolUploader.connectionStatus) {
+ TidepoolUploader.ConnectionStatus.FAILED -> {}
+ TidepoolUploader.ConnectionStatus.CONNECTING -> {}
+ TidepoolUploader.ConnectionStatus.DISCONNECTED -> TidepoolUploader.doLogin(true)
+ TidepoolUploader.ConnectionStatus.CONNECTED -> TidepoolUploader.doUpload()
+ }
+
+ @Synchronized
+ private fun addToLog(ev: EventTidepoolStatus) {
+ synchronized(listLog) {
+ listLog.add(ev)
+ // remove the first line if log is too large
+ if (listLog.size >= Constants.MAX_LOG_LINES) {
+ listLog.removeAt(0)
+ }
+ }
+ RxBus.send(EventTidepoolUpdateGUI())
+ }
+
+ @Synchronized
+ fun updateLog() {
+ try {
+ val newTextLog = StringBuilder()
+ synchronized(listLog) {
+ for (log in listLog) {
+ newTextLog.append(log.toPreparedHtml())
+ }
+ }
+ textLog = HtmlHelper.fromHtml(newTextLog.toString())
+ } catch (e: OutOfMemoryError) {
+ ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, "Out of memory!\nStop using this phone !!!", R.raw.error)
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/InfoInterceptor.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/InfoInterceptor.kt
new file mode 100644
index 0000000000..ca3c3e0483
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/InfoInterceptor.kt
@@ -0,0 +1,32 @@
+package info.nightscout.androidaps.plugins.general.tidepool.comm
+
+import info.nightscout.androidaps.logging.L
+import okhttp3.Interceptor
+import okhttp3.Response
+import okio.Buffer
+import org.slf4j.LoggerFactory
+import java.io.IOException
+
+class InfoInterceptor(tag: String) : Interceptor {
+
+ private val log = LoggerFactory.getLogger(L.TIDEPOOL)
+ private var tag = "interceptor"
+
+ init {
+ this.tag = tag
+ }
+
+ @Throws(IOException::class)
+ override fun intercept(chain: Interceptor.Chain): Response {
+ val request = chain.request()
+ request?.body()?.let {
+ if (L.isEnabled(L.TIDEPOOL)) {
+ log.debug("Interceptor Body size: " + it.contentLength())
+ val requestBuffer = Buffer()
+ it.writeTo(requestBuffer)
+ log.debug("Interceptor Body: " + requestBuffer.readUtf8())
+ }
+ }
+ return chain.proceed(request)
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/Session.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/Session.kt
new file mode 100644
index 0000000000..7067ddd073
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/Session.kt
@@ -0,0 +1,42 @@
+package info.nightscout.androidaps.plugins.general.tidepool.comm
+
+import info.nightscout.androidaps.plugins.general.tidepool.messages.AuthReplyMessage
+import info.nightscout.androidaps.plugins.general.tidepool.messages.DatasetReplyMessage
+import okhttp3.Headers
+
+class Session(val authHeader: String?,
+ private val sessionTokenHeader: String,
+ val service: TidepoolApiService?) {
+
+ internal var token: String? = null
+ internal var authReply: AuthReplyMessage? = null
+ internal var datasetReply: DatasetReplyMessage? = null
+ internal var start: Long = 0
+ internal var end: Long = 0
+ @Volatile
+ internal var iterations: Int = 0
+
+
+ fun populateHeaders(headers: Headers) {
+ if (this.token == null) {
+ this.token = headers.get(sessionTokenHeader)
+ }
+ }
+
+ fun populateBody(obj: Any?) {
+ if (obj == null) return
+ if (obj is AuthReplyMessage) {
+ authReply = obj
+ } else if (obj is List<*>) {
+ val list = obj as? List<*>?
+
+ list?.getOrNull(0)?.let {
+ if (it is DatasetReplyMessage) {
+ datasetReply = it
+ }
+ }
+ } else if (obj is DatasetReplyMessage) {
+ datasetReply = obj
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/TidepoolApiService.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/TidepoolApiService.kt
new file mode 100644
index 0000000000..52adf539c5
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/TidepoolApiService.kt
@@ -0,0 +1,48 @@
+package info.nightscout.androidaps.plugins.general.tidepool.comm
+
+import info.nightscout.androidaps.BuildConfig
+import info.nightscout.androidaps.plugins.general.tidepool.messages.AuthReplyMessage
+import info.nightscout.androidaps.plugins.general.tidepool.messages.DatasetReplyMessage
+import info.nightscout.androidaps.plugins.general.tidepool.messages.UploadReplyMessage
+import okhttp3.RequestBody
+import retrofit2.Call
+import retrofit2.http.*
+
+const val SESSION_TOKEN_HEADER: String = "x-tidepool-session-token"
+
+interface TidepoolApiService {
+
+ @Headers(
+ "User-Agent: AAPS- " + BuildConfig.VERSION_NAME,
+ "X-Tidepool-Client-Name: info.nightscout.androidaps" + BuildConfig.APPLICATION_ID,
+ "X-Tidepool-Client-Version: 0.1.0"
+ )
+
+ @POST("/auth/login")
+ fun getLogin(@Header("Authorization") secret: String): Call
+
+ @DELETE("/v1/users/{userId}/data")
+ fun deleteAllData(@Header(SESSION_TOKEN_HEADER) token: String, @Path("userId") id: String): Call